]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/String.c
321b2f704035dd65c4be08e0f4350f3526e254b5
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / String.c
1 /** @file
2 Implementation for EFI_HII_STRING_PROTOCOL.
3
4
5 Copyright (c) 2007 - 2010, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16
17 #include "HiiDatabase.h"
18
19 CHAR16 mLanguageWindow[16] = {
20 0x0000, 0x0080, 0x0100, 0x0300,
21 0x2000, 0x2080, 0x2100, 0x3000,
22 0x0080, 0x00C0, 0x0400, 0x0600,
23 0x0900, 0x3040, 0x30A0, 0xFF00
24 };
25
26
27 /**
28 This function checks whether a global font info is referred by local
29 font info list or not. (i.e. HII_FONT_INFO is generated.) If not, create
30 a HII_FONT_INFO to refer it locally.
31
32 This is a internal function.
33
34
35 @param Private Hii database private structure.
36 @param StringPackage HII string package instance.
37 @param FontId Font identifer, which must be unique within the string package.
38 @param DuplicateEnable If true, duplicate HII_FONT_INFO which refers to
39 the same EFI_FONT_INFO is permitted. Otherwise it
40 is not allowed.
41 @param GlobalFontInfo Input a global font info which specify a
42 EFI_FONT_INFO.
43 @param LocalFontInfo Output a local font info which refers to a
44 EFI_FONT_INFO.
45
46 @retval TRUE Already referred before calling this function.
47 @retval FALSE Not referred before calling this function.
48
49 **/
50 BOOLEAN
51 ReferFontInfoLocally (
52 IN HII_DATABASE_PRIVATE_DATA *Private,
53 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
54 IN UINT8 FontId,
55 IN BOOLEAN DuplicateEnable,
56 IN HII_GLOBAL_FONT_INFO *GlobalFontInfo,
57 OUT HII_FONT_INFO **LocalFontInfo
58 )
59 {
60 HII_FONT_INFO *LocalFont;
61 LIST_ENTRY *Link;
62
63 ASSERT (Private != NULL && StringPackage != NULL && GlobalFontInfo != NULL && LocalFontInfo != NULL);
64
65 if (!DuplicateEnable) {
66 for (Link = StringPackage->FontInfoList.ForwardLink;
67 Link != &StringPackage->FontInfoList;
68 Link = Link->ForwardLink
69 ) {
70 LocalFont = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);
71 if (LocalFont->GlobalEntry == &GlobalFontInfo->Entry) {
72 //
73 // Already referred by local font info list, return directly.
74 //
75 *LocalFontInfo = LocalFont;
76 return TRUE;
77 }
78 }
79 }
80 // FontId identifies EFI_FONT_INFO in local string package uniquely.
81 // GlobalEntry points to a HII_GLOBAL_FONT_INFO which identifies
82 // EFI_FONT_INFO uniquely in whole hii database.
83 //
84 LocalFont = (HII_FONT_INFO *) AllocateZeroPool (sizeof (HII_FONT_INFO));
85 ASSERT (LocalFont != NULL);
86
87 LocalFont->Signature = HII_FONT_INFO_SIGNATURE;
88 LocalFont->FontId = FontId;
89 LocalFont->GlobalEntry = &GlobalFontInfo->Entry;
90 InsertTailList (&StringPackage->FontInfoList, &LocalFont->Entry);
91
92 *LocalFontInfo = LocalFont;
93 return FALSE;
94 }
95
96
97 /**
98 Convert Ascii string text to unicode string test.
99
100 This is a internal function.
101
102
103 @param StringDest Buffer to store the string text. If it is NULL,
104 only the size will be returned.
105 @param StringSrc Points to current null-terminated string.
106 @param BufferSize Length of the buffer.
107
108 @retval EFI_SUCCESS The string text was outputed successfully.
109 @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string
110 text. BufferSize is updated to the required buffer
111 size.
112
113 **/
114 EFI_STATUS
115 ConvertToUnicodeText (
116 OUT EFI_STRING StringDest,
117 IN CHAR8 *StringSrc,
118 IN OUT UINTN *BufferSize
119 )
120 {
121 UINTN StringSize;
122 UINTN Index;
123
124 ASSERT (StringSrc != NULL && BufferSize != NULL);
125
126 StringSize = AsciiStrSize (StringSrc) * 2;
127 if (*BufferSize < StringSize || StringDest == NULL) {
128 *BufferSize = StringSize;
129 return EFI_BUFFER_TOO_SMALL;
130 }
131
132 for (Index = 0; Index < AsciiStrLen (StringSrc); Index++) {
133 StringDest[Index] = (CHAR16) StringSrc[Index];
134 }
135
136 StringDest[Index] = 0;
137 return EFI_SUCCESS;
138 }
139
140
141 /**
142 Calculate the size of StringSrc and output it. If StringDest is not NULL,
143 copy string text from src to dest.
144
145 This is a internal function.
146
147 @param StringDest Buffer to store the string text. If it is NULL,
148 only the size will be returned.
149 @param StringSrc Points to current null-terminated string.
150 @param BufferSize Length of the buffer.
151
152 @retval EFI_SUCCESS The string text was outputed successfully.
153 @retval EFI_BUFFER_TOO_SMALL Buffer is insufficient to store the found string
154 text. BufferSize is updated to the required buffer
155 size.
156
157 **/
158 EFI_STATUS
159 GetUnicodeStringTextOrSize (
160 OUT EFI_STRING StringDest, OPTIONAL
161 IN UINT8 *StringSrc,
162 IN OUT UINTN *BufferSize
163 )
164 {
165 UINTN StringSize;
166 UINT8 *StringPtr;
167
168 ASSERT (StringSrc != NULL && BufferSize != NULL);
169
170 StringSize = sizeof (CHAR16);
171 StringPtr = StringSrc;
172 while (ReadUnaligned16 ((UINT16 *) StringPtr) != 0) {
173 StringSize += sizeof (CHAR16);
174 StringPtr += sizeof (CHAR16);
175 }
176
177 if (*BufferSize < StringSize) {
178 *BufferSize = StringSize;
179 return EFI_BUFFER_TOO_SMALL;
180 }
181 if (StringDest != NULL) {
182 CopyMem (StringDest, StringSrc, StringSize);
183 }
184
185 *BufferSize = StringSize;
186 return EFI_SUCCESS;
187 }
188
189
190 /**
191 Copy string font info to a buffer.
192
193 This is a internal function.
194
195 @param StringPackage Hii string package instance.
196 @param FontId Font identifier which is unique in a string
197 package.
198 @param StringFontInfo Buffer to record the output font info. It's
199 caller's responsibility to free this buffer.
200
201 @retval EFI_SUCCESS The string font is outputed successfully.
202 @retval EFI_NOT_FOUND The specified font id does not exist.
203
204 **/
205 EFI_STATUS
206 GetStringFontInfo (
207 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
208 IN UINT8 FontId,
209 OUT EFI_FONT_INFO **StringFontInfo
210 )
211 {
212 LIST_ENTRY *Link;
213 HII_FONT_INFO *FontInfo;
214 HII_GLOBAL_FONT_INFO *GlobalFont;
215
216 ASSERT (StringFontInfo != NULL && StringPackage != NULL);
217
218 for (Link = StringPackage->FontInfoList.ForwardLink; Link != &StringPackage->FontInfoList; Link = Link->ForwardLink) {
219 FontInfo = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);
220 if (FontInfo->FontId == FontId) {
221 GlobalFont = CR (FontInfo->GlobalEntry, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);
222 *StringFontInfo = (EFI_FONT_INFO *) AllocateZeroPool (GlobalFont->FontInfoSize);
223 if (*StringFontInfo == NULL) {
224 return EFI_OUT_OF_RESOURCES;
225 }
226 CopyMem (*StringFontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);
227 return EFI_SUCCESS;
228 }
229 }
230
231 return EFI_NOT_FOUND;
232 }
233
234
235 /**
236 Parse all string blocks to find a String block specified by StringId.
237 If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks
238 within this string package and backup its information. If LastStringId is
239 specified, the string id of last string block will also be output.
240 If StringId = 0, output the string id of last string block (EFI_HII_SIBT_STRING).
241
242 @param Private Hii database private structure.
243 @param StringPackage Hii string package instance.
244 @param StringId The string's id, which is unique within
245 PackageList.
246 @param BlockType Output the block type of found string block.
247 @param StringBlockAddr Output the block address of found string block.
248 @param StringTextOffset Offset, relative to the found block address, of
249 the string text information.
250 @param LastStringId Output the last string id when StringId = 0 or StringId = -1.
251
252 @retval EFI_SUCCESS The string text and font is retrieved
253 successfully.
254 @retval EFI_NOT_FOUND The specified text or font info can not be found
255 out.
256 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
257 task.
258
259 **/
260 EFI_STATUS
261 FindStringBlock (
262 IN HII_DATABASE_PRIVATE_DATA *Private,
263 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
264 IN EFI_STRING_ID StringId,
265 OUT UINT8 *BlockType, OPTIONAL
266 OUT UINT8 **StringBlockAddr, OPTIONAL
267 OUT UINTN *StringTextOffset, OPTIONAL
268 OUT EFI_STRING_ID *LastStringId OPTIONAL
269 )
270 {
271 UINT8 *BlockHdr;
272 EFI_STRING_ID CurrentStringId;
273 UINTN BlockSize;
274 UINTN Index;
275 UINT8 *StringTextPtr;
276 UINTN Offset;
277 HII_FONT_INFO *LocalFont;
278 EFI_FONT_INFO *FontInfo;
279 HII_GLOBAL_FONT_INFO *GlobalFont;
280 UINTN FontInfoSize;
281 UINT16 StringCount;
282 UINT16 SkipCount;
283 EFI_HII_FONT_STYLE FontStyle;
284 UINT16 FontSize;
285 UINT8 Length8;
286 EFI_HII_SIBT_EXT2_BLOCK Ext2;
287 UINT8 FontId;
288 UINT32 Length32;
289 UINTN StringSize;
290 CHAR16 Zero;
291
292 ASSERT (StringPackage != NULL);
293 ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
294
295 CurrentStringId = 1;
296
297 if (StringId != (EFI_STRING_ID) (-1) && StringId != 0) {
298 ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
299 if (StringId > StringPackage->MaxStringId) {
300 return EFI_NOT_FOUND;
301 }
302 } else {
303 ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
304 if (StringId == 0 && LastStringId != NULL) {
305 *LastStringId = StringPackage->MaxStringId;
306 return EFI_SUCCESS;
307 }
308 }
309
310 ZeroMem (&Zero, sizeof (CHAR16));
311
312 //
313 // Parse the string blocks to get the string text and font.
314 //
315 BlockHdr = StringPackage->StringBlock;
316 BlockSize = 0;
317 Offset = 0;
318 while (*BlockHdr != EFI_HII_SIBT_END) {
319 switch (*BlockHdr) {
320 case EFI_HII_SIBT_STRING_SCSU:
321 Offset = sizeof (EFI_HII_STRING_BLOCK);
322 StringTextPtr = BlockHdr + Offset;
323 BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);
324 CurrentStringId++;
325 break;
326
327 case EFI_HII_SIBT_STRING_SCSU_FONT:
328 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
329 StringTextPtr = BlockHdr + Offset;
330 BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);
331 CurrentStringId++;
332 break;
333
334 case EFI_HII_SIBT_STRINGS_SCSU:
335 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
336 StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);
337 BlockSize += StringTextPtr - BlockHdr;
338
339 for (Index = 0; Index < StringCount; Index++) {
340 BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);
341 if (CurrentStringId == StringId) {
342 *BlockType = *BlockHdr;
343 *StringBlockAddr = BlockHdr;
344 *StringTextOffset = StringTextPtr - BlockHdr;
345 return EFI_SUCCESS;
346 }
347 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);
348 CurrentStringId++;
349 }
350 break;
351
352 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
353 CopyMem (
354 &StringCount,
355 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
356 sizeof (UINT16)
357 );
358 StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8);
359 BlockSize += StringTextPtr - BlockHdr;
360
361 for (Index = 0; Index < StringCount; Index++) {
362 BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);
363 if (CurrentStringId == StringId) {
364 *BlockType = *BlockHdr;
365 *StringBlockAddr = BlockHdr;
366 *StringTextOffset = StringTextPtr - BlockHdr;
367 return EFI_SUCCESS;
368 }
369 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);
370 CurrentStringId++;
371 }
372 break;
373
374 case EFI_HII_SIBT_STRING_UCS2:
375 Offset = sizeof (EFI_HII_STRING_BLOCK);
376 StringTextPtr = BlockHdr + Offset;
377 //
378 // Use StringSize to store the size of the specified string, including the NULL
379 // terminator.
380 //
381 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
382 BlockSize += Offset + StringSize;
383 CurrentStringId++;
384 break;
385
386 case EFI_HII_SIBT_STRING_UCS2_FONT:
387 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
388 StringTextPtr = BlockHdr + Offset;
389 //
390 // Use StrSize to store the size of the specified string, including the NULL
391 // terminator.
392 //
393 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
394 BlockSize += Offset + StringSize;
395 CurrentStringId++;
396 break;
397
398 case EFI_HII_SIBT_STRINGS_UCS2:
399 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
400 StringTextPtr = BlockHdr + Offset;
401 BlockSize += Offset;
402 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
403 for (Index = 0; Index < StringCount; Index++) {
404 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
405 BlockSize += StringSize;
406 if (CurrentStringId == StringId) {
407 *BlockType = *BlockHdr;
408 *StringBlockAddr = BlockHdr;
409 *StringTextOffset = StringTextPtr - BlockHdr;
410 return EFI_SUCCESS;
411 }
412 StringTextPtr = StringTextPtr + StringSize;
413 CurrentStringId++;
414 }
415 break;
416
417 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
418 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
419 StringTextPtr = BlockHdr + Offset;
420 BlockSize += Offset;
421 CopyMem (
422 &StringCount,
423 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
424 sizeof (UINT16)
425 );
426 for (Index = 0; Index < StringCount; Index++) {
427 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
428 BlockSize += StringSize;
429 if (CurrentStringId == StringId) {
430 *BlockType = *BlockHdr;
431 *StringBlockAddr = BlockHdr;
432 *StringTextOffset = StringTextPtr - BlockHdr;
433 return EFI_SUCCESS;
434 }
435 StringTextPtr = StringTextPtr + StringSize;
436 CurrentStringId++;
437 }
438 break;
439
440 case EFI_HII_SIBT_DUPLICATE:
441 if (CurrentStringId == StringId) {
442 //
443 // Incoming StringId is an id of a duplicate string block.
444 // Update the StringId to be the previous string block.
445 // Go back to the header of string block to search.
446 //
447 CopyMem (
448 &StringId,
449 BlockHdr + sizeof (EFI_HII_STRING_BLOCK),
450 sizeof (EFI_STRING_ID)
451 );
452 ASSERT (StringId != CurrentStringId);
453 CurrentStringId = 1;
454 BlockSize = 0;
455 } else {
456 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
457 CurrentStringId++;
458 }
459 break;
460
461 case EFI_HII_SIBT_SKIP1:
462 SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
463 CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
464 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
465 break;
466
467 case EFI_HII_SIBT_SKIP2:
468 CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
469 CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
470 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
471 break;
472
473 case EFI_HII_SIBT_EXT1:
474 CopyMem (
475 &Length8,
476 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
477 sizeof (UINT8)
478 );
479 BlockSize += Length8;
480 break;
481
482 case EFI_HII_SIBT_EXT2:
483 CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
484 if (Ext2.BlockType2 == EFI_HII_SIBT_FONT && StringId == (EFI_STRING_ID) (-1)) {
485 //
486 // Find the relationship between global font info and the font info of
487 // this EFI_HII_SIBT_FONT block then backup its information in local package.
488 //
489 BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
490 CopyMem (&FontId, BlockHdr, sizeof (UINT8));
491 BlockHdr += sizeof (UINT8);
492 CopyMem (&FontSize, BlockHdr, sizeof (UINT16));
493 BlockHdr += sizeof (UINT16);
494 CopyMem (&FontStyle, BlockHdr, sizeof (EFI_HII_FONT_STYLE));
495 BlockHdr += sizeof (EFI_HII_FONT_STYLE);
496 GetUnicodeStringTextOrSize (NULL, BlockHdr, &StringSize);
497
498 FontInfoSize = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StringSize;
499 FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);
500 if (FontInfo == NULL) {
501 return EFI_OUT_OF_RESOURCES;
502 }
503 FontInfo->FontStyle = FontStyle;
504 FontInfo->FontSize = FontSize;
505 CopyMem (FontInfo->FontName, BlockHdr, StringSize);
506
507 //
508 // If find the corresponding global font info, save the relationship.
509 // Otherwise ignore this EFI_HII_SIBT_FONT block.
510 //
511 if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {
512 ReferFontInfoLocally (Private, StringPackage, FontId, TRUE, GlobalFont, &LocalFont);
513 }
514
515 //
516 // Since string package tool set FontId initially to 0 and increases it
517 // progressively by one, StringPackage->FondId always represents an unique
518 // and available FontId.
519 //
520 StringPackage->FontId++;
521
522 FreePool (FontInfo);
523 }
524
525 BlockSize += Ext2.Length;
526
527 break;
528
529 case EFI_HII_SIBT_EXT4:
530 CopyMem (
531 &Length32,
532 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
533 sizeof (UINT32)
534 );
535
536 BlockSize += Length32;
537 break;
538
539 default:
540 break;
541 }
542
543 if (StringId > 0) {
544 if (StringId == CurrentStringId - 1) {
545 *BlockType = *BlockHdr;
546 *StringBlockAddr = BlockHdr;
547 *StringTextOffset = Offset;
548 return EFI_SUCCESS;
549 }
550
551 if (StringId < CurrentStringId - 1) {
552 return EFI_NOT_FOUND;
553 }
554 }
555 BlockHdr = StringPackage->StringBlock + BlockSize;
556
557 }
558
559 //
560 // Get last string ID
561 //
562 if (StringId == (EFI_STRING_ID) (-1)) {
563 *LastStringId = (EFI_STRING_ID) (CurrentStringId - 1);
564 return EFI_SUCCESS;
565 }
566
567 return EFI_NOT_FOUND;
568 }
569
570
571 /**
572 Parse all string blocks to get a string specified by StringId.
573
574 This is a internal function.
575
576 @param Private Hii database private structure.
577 @param StringPackage Hii string package instance.
578 @param StringId The string's id, which is unique within
579 PackageList.
580 @param String Points to retrieved null-terminated string.
581 @param StringSize On entry, points to the size of the buffer pointed
582 to by String, in bytes. On return, points to the
583 length of the string, in bytes.
584 @param StringFontInfo If not NULL, allocate a buffer to record the
585 output font info. It's caller's responsibility to
586 free this buffer.
587
588 @retval EFI_SUCCESS The string text and font is retrieved
589 successfully.
590 @retval EFI_NOT_FOUND The specified text or font info can not be found
591 out.
592 @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
593 hold the string.
594
595 **/
596 EFI_STATUS
597 GetStringWorker (
598 IN HII_DATABASE_PRIVATE_DATA *Private,
599 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
600 IN EFI_STRING_ID StringId,
601 OUT EFI_STRING String,
602 IN OUT UINTN *StringSize, OPTIONAL
603 OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
604 )
605 {
606 UINT8 *StringTextPtr;
607 UINT8 BlockType;
608 UINT8 *StringBlockAddr;
609 UINTN StringTextOffset;
610 EFI_STATUS Status;
611 UINT8 FontId;
612
613 ASSERT (StringPackage != NULL);
614 ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
615
616 //
617 // Find the specified string block
618 //
619 Status = FindStringBlock (
620 Private,
621 StringPackage,
622 StringId,
623 &BlockType,
624 &StringBlockAddr,
625 &StringTextOffset,
626 NULL
627 );
628 if (EFI_ERROR (Status)) {
629 return Status;
630 }
631
632 if (StringSize == NULL) {
633 //
634 // String text buffer is not requested
635 //
636 return EFI_SUCCESS;
637 }
638
639 //
640 // Get the string text.
641 //
642 StringTextPtr = StringBlockAddr + StringTextOffset;
643 switch (BlockType) {
644 case EFI_HII_SIBT_STRING_SCSU:
645 case EFI_HII_SIBT_STRING_SCSU_FONT:
646 case EFI_HII_SIBT_STRINGS_SCSU:
647 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
648 Status = ConvertToUnicodeText (String, (CHAR8 *) StringTextPtr, StringSize);
649 break;
650 case EFI_HII_SIBT_STRING_UCS2:
651 case EFI_HII_SIBT_STRING_UCS2_FONT:
652 case EFI_HII_SIBT_STRINGS_UCS2:
653 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
654 Status = GetUnicodeStringTextOrSize (String, StringTextPtr, StringSize);
655 break;
656 default:
657 return EFI_NOT_FOUND;
658 }
659 if (EFI_ERROR (Status)) {
660 return Status;
661 }
662
663 //
664 // Get the string font. The FontId 0 is the default font for those string blocks which
665 // do not specify a font identifier. If default font is not specified, return NULL.
666 //
667 if (StringFontInfo != NULL) {
668 switch (BlockType) {
669 case EFI_HII_SIBT_STRING_SCSU_FONT:
670 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
671 case EFI_HII_SIBT_STRING_UCS2_FONT:
672 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
673 FontId = *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK));
674 break;
675 default:
676 FontId = 0;
677 }
678 Status = GetStringFontInfo (StringPackage, FontId, StringFontInfo);
679 if (Status == EFI_NOT_FOUND) {
680 *StringFontInfo = NULL;
681 }
682 }
683
684 return EFI_SUCCESS;
685 }
686
687
688 /**
689 Parse all string blocks to set a String specified by StringId.
690
691 This is a internal function.
692
693 @param Private HII database driver private structure.
694 @param StringPackage HII string package instance.
695 @param StringId The string's id, which is unique within
696 PackageList.
697 @param String Points to the new null-terminated string.
698 @param StringFontInfo Points to the input font info.
699
700 @retval EFI_SUCCESS The string was updated successfully.
701 @retval EFI_NOT_FOUND The string specified by StringId is not in the
702 database.
703 @retval EFI_INVALID_PARAMETER The String or Language was NULL.
704 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
705 current database.
706 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
707 task.
708
709 **/
710 EFI_STATUS
711 SetStringWorker (
712 IN HII_DATABASE_PRIVATE_DATA *Private,
713 IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage,
714 IN EFI_STRING_ID StringId,
715 IN EFI_STRING String,
716 IN EFI_FONT_INFO *StringFontInfo OPTIONAL
717 )
718 {
719 UINT8 *StringTextPtr;
720 UINT8 BlockType;
721 UINT8 *StringBlockAddr;
722 UINTN StringTextOffset;
723 EFI_STATUS Status;
724 UINT8 *Block;
725 UINT8 *BlockPtr;
726 UINTN BlockSize;
727 UINTN OldBlockSize;
728 HII_FONT_INFO *LocalFont;
729 HII_GLOBAL_FONT_INFO *GlobalFont;
730 BOOLEAN Referred;
731 EFI_HII_SIBT_EXT2_BLOCK Ext2;
732 UINTN StringSize;
733 UINTN TmpSize;
734
735
736 ASSERT (Private != NULL && StringPackage != NULL && String != NULL);
737 ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
738 //
739 // Find the specified string block
740 //
741 Status = FindStringBlock (
742 Private,
743 StringPackage,
744 StringId,
745 &BlockType,
746 &StringBlockAddr,
747 &StringTextOffset,
748 NULL
749 );
750 if (EFI_ERROR (Status)) {
751 return Status;
752 }
753
754 LocalFont = NULL;
755 GlobalFont = NULL;
756 Referred = FALSE;
757
758 //
759 // The input StringFontInfo should exist in current database if specified.
760 //
761 if (StringFontInfo != NULL) {
762 if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) {
763 return EFI_INVALID_PARAMETER;
764 } else {
765 Referred = ReferFontInfoLocally (
766 Private,
767 StringPackage,
768 StringPackage->FontId,
769 FALSE,
770 GlobalFont,
771 &LocalFont
772 );
773 if (!Referred) {
774 StringPackage->FontId++;
775 }
776 }
777 //
778 // Update the FontId of the specified string block to input font info.
779 //
780 switch (BlockType) {
781 case EFI_HII_SIBT_STRING_SCSU_FONT:
782 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
783 case EFI_HII_SIBT_STRING_UCS2_FONT:
784 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
785 *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)) = LocalFont->FontId;
786 break;
787 default:
788 //
789 // When modify the font info of these blocks, the block type should be updated
790 // to contain font info thus the whole structure should be revised.
791 // It is recommended to use tool to modify the block type not in the code.
792 //
793 return EFI_UNSUPPORTED;
794 }
795 }
796
797 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
798
799 //
800 // Set the string text and font.
801 //
802 StringTextPtr = StringBlockAddr + StringTextOffset;
803 switch (BlockType) {
804 case EFI_HII_SIBT_STRING_SCSU:
805 case EFI_HII_SIBT_STRING_SCSU_FONT:
806 case EFI_HII_SIBT_STRINGS_SCSU:
807 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
808 BlockSize = OldBlockSize + StrLen (String);
809 BlockSize -= AsciiStrLen ((CHAR8 *) StringTextPtr);
810 Block = AllocateZeroPool (BlockSize);
811 if (Block == NULL) {
812 return EFI_OUT_OF_RESOURCES;
813 }
814
815 CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
816 BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
817
818 while (*String != 0) {
819 *BlockPtr++ = (CHAR8) *String++;
820 }
821 *BlockPtr++ = 0;
822
823
824 TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *) StringTextPtr);
825 CopyMem (
826 BlockPtr,
827 StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr),
828 TmpSize
829 );
830
831 FreePool (StringPackage->StringBlock);
832 StringPackage->StringBlock = Block;
833 StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);
834 break;
835
836 case EFI_HII_SIBT_STRING_UCS2:
837 case EFI_HII_SIBT_STRING_UCS2_FONT:
838 case EFI_HII_SIBT_STRINGS_UCS2:
839 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
840 //
841 // Use StrSize to store the size of the specified string, including the NULL
842 // terminator.
843 //
844 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
845
846 BlockSize = OldBlockSize + StrSize (String) - StringSize;
847 Block = AllocateZeroPool (BlockSize);
848 if (Block == NULL) {
849 return EFI_OUT_OF_RESOURCES;
850 }
851
852 CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
853 BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
854
855 CopyMem (BlockPtr, String, StrSize (String));
856 BlockPtr += StrSize (String);
857
858 CopyMem (
859 BlockPtr,
860 StringTextPtr + StringSize,
861 OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize
862 );
863
864 FreePool (StringPackage->StringBlock);
865 StringPackage->StringBlock = Block;
866 StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);
867 break;
868
869 default:
870 return EFI_NOT_FOUND;
871 }
872
873 //
874 // Insert a new EFI_HII_SIBT_FONT_BLOCK to the header of string block, if incoming
875 // StringFontInfo does not exist in current string package.
876 //
877 // This new block does not impact on the value of StringId.
878 //
879 //
880 if (StringFontInfo == NULL || Referred) {
881 return EFI_SUCCESS;
882 }
883
884 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
885 BlockSize = OldBlockSize + sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16) +
886 StrSize (GlobalFont->FontInfo->FontName);
887
888 Block = AllocateZeroPool (BlockSize);
889 if (Block == NULL) {
890 return EFI_OUT_OF_RESOURCES;
891 }
892
893 BlockPtr = Block;
894 Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
895 Ext2.BlockType2 = EFI_HII_SIBT_FONT;
896 Ext2.Length = (UINT16) (BlockSize - OldBlockSize);
897 CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
898 BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
899
900 *BlockPtr = LocalFont->FontId;
901 BlockPtr += sizeof (UINT8);
902 CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16));
903 BlockPtr += sizeof (UINT16);
904 CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32));
905 BlockPtr += sizeof (UINT32);
906 CopyMem (
907 BlockPtr,
908 GlobalFont->FontInfo->FontName,
909 StrSize (GlobalFont->FontInfo->FontName)
910 );
911 BlockPtr += StrSize (GlobalFont->FontInfo->FontName);
912
913 CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize);
914
915 FreePool (StringPackage->StringBlock);
916 StringPackage->StringBlock = Block;
917 StringPackage->StringPkgHdr->Header.Length += Ext2.Length;
918
919 return EFI_SUCCESS;
920
921 }
922
923
924 /**
925 This function adds the string String to the group of strings owned by PackageList, with the
926 specified font information StringFontInfo and returns a new string id.
927 The new string identifier is guaranteed to be unique within the package list.
928 That new string identifier is reserved for all languages in the package list.
929
930
931 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
932 @param PackageList Handle of the package list where this string will
933 be added.
934 @param StringId On return, contains the new strings id, which is
935 unique within PackageList.
936 @param Language Points to the language for the new string.
937 @param LanguageName Points to the printable language name to associate
938 with the passed in Language field.If LanguageName
939 is not NULL and the string package header's
940 LanguageName associated with a given Language is
941 not zero, the LanguageName being passed in will
942 be ignored.
943 @param String Points to the new null-terminated string.
944 @param StringFontInfo Points to the new string's font information or
945 NULL if the string should have the default system
946 font, size and style.
947
948 @retval EFI_SUCCESS The new string was added successfully.
949 @retval EFI_NOT_FOUND The specified PackageList could not be found in
950 database.
951 @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources.
952 @retval EFI_INVALID_PARAMETER String is NULL or StringId is NULL or Language is
953 NULL.
954 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
955 current database.
956
957 **/
958 EFI_STATUS
959 EFIAPI
960 HiiNewString (
961 IN CONST EFI_HII_STRING_PROTOCOL *This,
962 IN EFI_HII_HANDLE PackageList,
963 OUT EFI_STRING_ID *StringId,
964 IN CONST CHAR8 *Language,
965 IN CONST CHAR16 *LanguageName, OPTIONAL
966 IN CONST EFI_STRING String,
967 IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
968 )
969 {
970 EFI_STATUS Status;
971 LIST_ENTRY *Link;
972 HII_DATABASE_PRIVATE_DATA *Private;
973 HII_DATABASE_RECORD *DatabaseRecord;
974 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
975 HII_STRING_PACKAGE_INSTANCE *StringPackage;
976 UINT32 HeaderSize;
977 UINT32 BlockSize;
978 UINT32 OldBlockSize;
979 UINT8 *StringBlock;
980 UINT8 *BlockPtr;
981 UINT32 Ucs2BlockSize;
982 UINT32 FontBlockSize;
983 UINT32 Ucs2FontBlockSize;
984 EFI_HII_SIBT_EXT2_BLOCK Ext2;
985 HII_FONT_INFO *LocalFont;
986 HII_GLOBAL_FONT_INFO *GlobalFont;
987 EFI_STRING_ID NewStringId;
988 EFI_STRING_ID NextStringId;
989 EFI_STRING_ID Index;
990 HII_STRING_PACKAGE_INSTANCE *MatchStringPackage;
991 BOOLEAN NewStringPackageCreated;
992
993
994 if (This == NULL || String == NULL || StringId == NULL || Language == NULL || PackageList == NULL) {
995 return EFI_INVALID_PARAMETER;
996 }
997
998 if (!IsHiiHandleValid (PackageList)) {
999 return EFI_NOT_FOUND;
1000 }
1001
1002 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1003 GlobalFont = NULL;
1004
1005 //
1006 // If StringFontInfo specify a paritcular font, it should exist in current database.
1007 //
1008 if (StringFontInfo != NULL) {
1009 if (!IsFontInfoExisted (Private, (EFI_FONT_INFO *) StringFontInfo, NULL, NULL, &GlobalFont)) {
1010 return EFI_INVALID_PARAMETER;
1011 }
1012 }
1013
1014 //
1015 // Get the matching package list.
1016 //
1017 PackageListNode = NULL;
1018 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1019 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1020 if (DatabaseRecord->Handle == PackageList) {
1021 PackageListNode = DatabaseRecord->PackageList;
1022 break;
1023 }
1024 }
1025 if (PackageListNode == NULL) {
1026 return EFI_NOT_FOUND;
1027 }
1028
1029 Status = EFI_SUCCESS;
1030 NewStringPackageCreated = FALSE;
1031 NewStringId = 0;
1032 NextStringId = 0;
1033 StringPackage = NULL;
1034 MatchStringPackage = NULL;
1035 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1036 Link != &PackageListNode->StringPkgHdr;
1037 Link = Link->ForwardLink
1038 ) {
1039 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1040 //
1041 // Create a string block and corresponding font block if exists, then append them
1042 // to the end of the string package.
1043 //
1044 Status = FindStringBlock (
1045 Private,
1046 StringPackage,
1047 0,
1048 NULL,
1049 NULL,
1050 NULL,
1051 &NextStringId
1052 );
1053 if (EFI_ERROR (Status)) {
1054 goto Done;
1055 }
1056 //
1057 // Make sure that new StringId is same in all String Packages for the different language.
1058 //
1059 if (NewStringId != 0 && NewStringId != NextStringId) {
1060 ASSERT (FALSE);
1061 Status = EFI_INVALID_PARAMETER;
1062 goto Done;
1063 }
1064 NewStringId = NextStringId;
1065 //
1066 // Get the matched string package with language.
1067 //
1068 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
1069 MatchStringPackage = StringPackage;
1070 } else {
1071 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
1072 //
1073 // Create a blank EFI_HII_SIBT_STRING_UCS2_BLOCK to reserve new string ID.
1074 //
1075 Ucs2BlockSize = (UINT32) sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
1076
1077 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize);
1078 if (StringBlock == NULL) {
1079 Status = EFI_OUT_OF_RESOURCES;
1080 goto Done;
1081 }
1082 //
1083 // Copy original string blocks, except the EFI_HII_SIBT_END.
1084 //
1085 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1086 //
1087 // Create a blank EFI_HII_SIBT_STRING_UCS2 block
1088 //
1089 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1090 *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
1091 BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
1092
1093 //
1094 // Append a EFI_HII_SIBT_END block to the end.
1095 //
1096 *BlockPtr = EFI_HII_SIBT_END;
1097 FreePool (StringPackage->StringBlock);
1098 StringPackage->StringBlock = StringBlock;
1099 StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;
1100 PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;
1101 }
1102 }
1103 if (NewStringId == 0) {
1104 //
1105 // No string package is found.
1106 // Create new string package. StringId 1 is reserved for Language Name string.
1107 //
1108 *StringId = 2;
1109 } else {
1110 //
1111 // Set new StringId
1112 //
1113 *StringId = (EFI_STRING_ID) (NewStringId + 1);
1114 }
1115
1116 if (MatchStringPackage != NULL) {
1117 StringPackage = MatchStringPackage;
1118 } else {
1119 //
1120 // LanguageName is required to create a new string package.
1121 //
1122 if (LanguageName == NULL) {
1123 Status = EFI_INVALID_PARAMETER;
1124 goto Done;
1125 }
1126
1127 StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
1128 if (StringPackage == NULL) {
1129 Status = EFI_OUT_OF_RESOURCES;
1130 goto Done;
1131 }
1132
1133 StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
1134 StringPackage->MaxStringId = *StringId;
1135 StringPackage->FontId = 0;
1136 InitializeListHead (&StringPackage->FontInfoList);
1137
1138 //
1139 // Fill in the string package header
1140 //
1141 HeaderSize = (UINT32) (AsciiStrSize ((CHAR8 *) Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR));
1142 StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize);
1143 if (StringPackage->StringPkgHdr == NULL) {
1144 FreePool (StringPackage);
1145 Status = EFI_OUT_OF_RESOURCES;
1146 goto Done;
1147 }
1148 StringPackage->StringPkgHdr->Header.Type = EFI_HII_PACKAGE_STRINGS;
1149 StringPackage->StringPkgHdr->HdrSize = HeaderSize;
1150 StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;
1151 CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));
1152 StringPackage->StringPkgHdr->LanguageName = 1;
1153 AsciiStrCpy (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language);
1154
1155 //
1156 // Calculate the length of the string blocks, including string block to record
1157 // printable language full name and EFI_HII_SIBT_END_BLOCK.
1158 //
1159 Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) +
1160 (*StringId - 1) * sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));
1161
1162 BlockSize = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK);
1163 StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (BlockSize);
1164 if (StringPackage->StringBlock == NULL) {
1165 FreePool (StringPackage->StringPkgHdr);
1166 FreePool (StringPackage);
1167 Status = EFI_OUT_OF_RESOURCES;
1168 goto Done;
1169 }
1170
1171 //
1172 // Insert the string block of printable language full name
1173 //
1174 BlockPtr = StringPackage->StringBlock;
1175 *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
1176 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1177 CopyMem (BlockPtr, (EFI_STRING) LanguageName, StrSize ((EFI_STRING) LanguageName));
1178 BlockPtr += StrSize ((EFI_STRING) LanguageName);
1179 for (Index = 2; Index <= *StringId - 1; Index ++) {
1180 *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
1181 BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
1182 }
1183 //
1184 // Insert the end block
1185 //
1186 *BlockPtr = EFI_HII_SIBT_END;
1187
1188 //
1189 // Append this string package node to string package array in this package list.
1190 //
1191 StringPackage->StringPkgHdr->Header.Length = HeaderSize + BlockSize;
1192 PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
1193 InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry);
1194 NewStringPackageCreated = TRUE;
1195 }
1196
1197 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
1198
1199 if (StringFontInfo == NULL) {
1200 //
1201 // Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified.
1202 //
1203 Ucs2BlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK)
1204 - sizeof (CHAR16));
1205
1206 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize);
1207 if (StringBlock == NULL) {
1208 Status = EFI_OUT_OF_RESOURCES;
1209 goto Done;
1210 }
1211 //
1212 // Copy original string blocks, except the EFI_HII_SIBT_END.
1213 //
1214 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1215 //
1216 // Create a EFI_HII_SIBT_STRING_UCS2 block
1217 //
1218 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1219 *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
1220 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1221 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
1222 BlockPtr += StrSize ((EFI_STRING) String);
1223
1224 //
1225 // Append a EFI_HII_SIBT_END block to the end.
1226 //
1227 *BlockPtr = EFI_HII_SIBT_END;
1228 FreePool (StringPackage->StringBlock);
1229 StringPackage->StringBlock = StringBlock;
1230 StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;
1231 PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;
1232
1233 } else {
1234 //
1235 // StringFontInfo is specified here. If there is a EFI_HII_SIBT_FONT_BLOCK
1236 // which refers to this font info, create a EFI_HII_SIBT_STRING_UCS2_FONT block
1237 // only. Otherwise create a EFI_HII_SIBT_FONT block with a EFI_HII_SIBT_STRING
1238 // _UCS2_FONT block.
1239 //
1240 Ucs2FontBlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) -
1241 sizeof (CHAR16));
1242 if (ReferFontInfoLocally (Private, StringPackage, StringPackage->FontId, FALSE, GlobalFont, &LocalFont)) {
1243 //
1244 // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only.
1245 //
1246 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize);
1247 if (StringBlock == NULL) {
1248 Status = EFI_OUT_OF_RESOURCES;
1249 goto Done;
1250 }
1251 //
1252 // Copy original string blocks, except the EFI_HII_SIBT_END.
1253 //
1254 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1255 //
1256 // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
1257 //
1258 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1259 *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
1260 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1261 *BlockPtr = LocalFont->FontId;
1262 BlockPtr += sizeof (UINT8);
1263 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
1264 BlockPtr += StrSize ((EFI_STRING) String);
1265
1266 //
1267 // Append a EFI_HII_SIBT_END block to the end.
1268 //
1269 *BlockPtr = EFI_HII_SIBT_END;
1270 FreePool (StringPackage->StringBlock);
1271 StringPackage->StringBlock = StringBlock;
1272 StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize;
1273 PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize;
1274
1275 } else {
1276 //
1277 // EFI_HII_SIBT_FONT_BLOCK does not exist in current string package, so
1278 // create a EFI_HII_SIBT_FONT block to record the font info, then generate
1279 // a EFI_HII_SIBT_STRING_UCS2_FONT block to record the incoming string.
1280 //
1281 FontBlockSize = (UINT32) (StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName) +
1282 sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16));
1283 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize);
1284 if (StringBlock == NULL) {
1285 Status = EFI_OUT_OF_RESOURCES;
1286 goto Done;
1287 }
1288 //
1289 // Copy original string blocks, except the EFI_HII_SIBT_END.
1290 //
1291 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1292
1293 //
1294 // Create a EFI_HII_SIBT_FONT block firstly and then backup its info in string
1295 // package instance for future reference.
1296 //
1297 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1298
1299 Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
1300 Ext2.BlockType2 = EFI_HII_SIBT_FONT;
1301 Ext2.Length = (UINT16) FontBlockSize;
1302 CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
1303 BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
1304
1305 *BlockPtr = LocalFont->FontId;
1306 BlockPtr += sizeof (UINT8);
1307 CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontSize, sizeof (UINT16));
1308 BlockPtr += sizeof (UINT16);
1309 CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE));
1310 BlockPtr += sizeof (EFI_HII_FONT_STYLE);
1311 CopyMem (
1312 BlockPtr,
1313 &((EFI_FONT_INFO *) StringFontInfo)->FontName,
1314 StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName)
1315 );
1316 BlockPtr += StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName);
1317 //
1318 // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
1319 //
1320 *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
1321 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1322 *BlockPtr = LocalFont->FontId;
1323 BlockPtr += sizeof (UINT8);
1324 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
1325 BlockPtr += StrSize ((EFI_STRING) String);
1326
1327 //
1328 // Append a EFI_HII_SIBT_END block to the end.
1329 //
1330 *BlockPtr = EFI_HII_SIBT_END;
1331 FreePool (StringPackage->StringBlock);
1332 StringPackage->StringBlock = StringBlock;
1333 StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;
1334 PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;
1335
1336 //
1337 // Increase the FontId to make it unique since we already add
1338 // a EFI_HII_SIBT_FONT block to this string package.
1339 //
1340 StringPackage->FontId++;
1341 }
1342 }
1343
1344 Done:
1345 if (!EFI_ERROR (Status) && NewStringPackageCreated) {
1346 //
1347 // Trigger any registered notification function for new string package
1348 //
1349 Status = InvokeRegisteredFunction (
1350 Private,
1351 EFI_HII_DATABASE_NOTIFY_NEW_PACK,
1352 (VOID *) StringPackage,
1353 EFI_HII_PACKAGE_STRINGS,
1354 PackageList
1355 );
1356 }
1357
1358 if (!EFI_ERROR (Status)) {
1359 //
1360 // Update MaxString Id to new StringId
1361 //
1362 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1363 Link != &PackageListNode->StringPkgHdr;
1364 Link = Link->ForwardLink
1365 ) {
1366 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1367 StringPackage->MaxStringId = *StringId;
1368 }
1369 } else if (NewStringPackageCreated) {
1370 //
1371 // Free the allocated new string Package when new string can't be added.
1372 //
1373 RemoveEntryList (&StringPackage->StringEntry);
1374 FreePool (StringPackage->StringBlock);
1375 FreePool (StringPackage->StringPkgHdr);
1376 FreePool (StringPackage);
1377 }
1378
1379 return Status;
1380 }
1381
1382
1383 /**
1384 This function retrieves the string specified by StringId which is associated
1385 with the specified PackageList in the language Language and copies it into
1386 the buffer specified by String.
1387
1388 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1389 @param Language Points to the language for the retrieved string.
1390 @param PackageList The package list in the HII database to search for
1391 the specified string.
1392 @param StringId The string's id, which is unique within
1393 PackageList.
1394 @param String Points to the new null-terminated string.
1395 @param StringSize On entry, points to the size of the buffer pointed
1396 to by String, in bytes. On return, points to the
1397 length of the string, in bytes.
1398 @param StringFontInfo If not NULL, points to the string's font
1399 information. It's caller's responsibility to free
1400 this buffer.
1401
1402 @retval EFI_SUCCESS The string was returned successfully.
1403 @retval EFI_NOT_FOUND The string specified by StringId is not available.
1404 @retval EFI_NOT_FOUND The string specified by StringId is available but
1405 not in the specified language.
1406 The specified PackageList is not in the database.
1407 @retval EFI_INVALID_LANGUAGE - The string specified by StringId is available but
1408 @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
1409 hold the string.
1410 @retval EFI_INVALID_PARAMETER The String or Language or StringSize was NULL.
1411 @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
1412 request.
1413
1414 **/
1415 EFI_STATUS
1416 EFIAPI
1417 HiiGetString (
1418 IN CONST EFI_HII_STRING_PROTOCOL *This,
1419 IN CONST CHAR8 *Language,
1420 IN EFI_HII_HANDLE PackageList,
1421 IN EFI_STRING_ID StringId,
1422 OUT EFI_STRING String,
1423 IN OUT UINTN *StringSize,
1424 OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
1425 )
1426 {
1427 EFI_STATUS Status;
1428 LIST_ENTRY *Link;
1429 HII_DATABASE_PRIVATE_DATA *Private;
1430 HII_DATABASE_RECORD *DatabaseRecord;
1431 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1432 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1433
1434 if (This == NULL || Language == NULL || StringId < 1 || StringSize == NULL || PackageList == NULL) {
1435 return EFI_INVALID_PARAMETER;
1436 }
1437
1438 if (String == NULL && *StringSize != 0) {
1439 return EFI_INVALID_PARAMETER;
1440 }
1441
1442 if (!IsHiiHandleValid (PackageList)) {
1443 return EFI_NOT_FOUND;
1444 }
1445
1446 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1447 PackageListNode = NULL;
1448
1449 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1450 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1451 if (DatabaseRecord->Handle == PackageList) {
1452 PackageListNode = DatabaseRecord->PackageList;
1453 break;
1454 }
1455 }
1456
1457 if (PackageListNode != NULL) {
1458 //
1459 // First search: to match the StringId in the specified language.
1460 //
1461 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1462 Link != &PackageListNode->StringPkgHdr;
1463 Link = Link->ForwardLink
1464 ) {
1465 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1466 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
1467 Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);
1468 if (Status != EFI_NOT_FOUND) {
1469 return Status;
1470 }
1471 }
1472 }
1473 //
1474 // Second search: to match the StringId in other available languages if exist.
1475 //
1476 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1477 Link != &PackageListNode->StringPkgHdr;
1478 Link = Link->ForwardLink
1479 ) {
1480 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1481 Status = GetStringWorker (Private, StringPackage, StringId, NULL, NULL, NULL);
1482 if (!EFI_ERROR (Status)) {
1483 return EFI_INVALID_LANGUAGE;
1484 }
1485 }
1486 }
1487
1488 return EFI_NOT_FOUND;
1489 }
1490
1491
1492
1493 /**
1494 This function updates the string specified by StringId in the specified PackageList to the text
1495 specified by String and, optionally, the font information specified by StringFontInfo.
1496
1497 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1498 @param PackageList The package list containing the strings.
1499 @param StringId The string's id, which is unique within
1500 PackageList.
1501 @param Language Points to the language for the updated string.
1502 @param String Points to the new null-terminated string.
1503 @param StringFontInfo Points to the string's font information or NULL if
1504 the string font information is not changed.
1505
1506 @retval EFI_SUCCESS The string was updated successfully.
1507 @retval EFI_NOT_FOUND The string specified by StringId is not in the
1508 database.
1509 @retval EFI_INVALID_PARAMETER The String or Language was NULL.
1510 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
1511 current database.
1512 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
1513 task.
1514
1515 **/
1516 EFI_STATUS
1517 EFIAPI
1518 HiiSetString (
1519 IN CONST EFI_HII_STRING_PROTOCOL *This,
1520 IN EFI_HII_HANDLE PackageList,
1521 IN EFI_STRING_ID StringId,
1522 IN CONST CHAR8 *Language,
1523 IN CONST EFI_STRING String,
1524 IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
1525 )
1526 {
1527 EFI_STATUS Status;
1528 LIST_ENTRY *Link;
1529 HII_DATABASE_PRIVATE_DATA *Private;
1530 HII_DATABASE_RECORD *DatabaseRecord;
1531 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1532 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1533 UINT32 OldPackageLen;
1534
1535 if (This == NULL || Language == NULL || StringId < 1 || String == NULL || PackageList == NULL) {
1536 return EFI_INVALID_PARAMETER;
1537 }
1538
1539 if (!IsHiiHandleValid (PackageList)) {
1540 return EFI_NOT_FOUND;
1541 }
1542
1543 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1544 PackageListNode = NULL;
1545
1546 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1547 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1548 if (DatabaseRecord->Handle == PackageList) {
1549 PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);
1550 }
1551 }
1552
1553 if (PackageListNode != NULL) {
1554 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1555 Link != &PackageListNode->StringPkgHdr;
1556 Link = Link->ForwardLink
1557 ) {
1558 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1559 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
1560 OldPackageLen = StringPackage->StringPkgHdr->Header.Length;
1561 Status = SetStringWorker (
1562 Private,
1563 StringPackage,
1564 StringId,
1565 (EFI_STRING) String,
1566 (EFI_FONT_INFO *) StringFontInfo
1567 );
1568 if (EFI_ERROR (Status)) {
1569 return Status;
1570 }
1571 PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen;
1572 return EFI_SUCCESS;
1573 }
1574 }
1575 }
1576
1577 return EFI_NOT_FOUND;
1578 }
1579
1580
1581
1582 /**
1583 This function returns the list of supported languages, in the format specified
1584 in Appendix M of UEFI 2.1 spec.
1585
1586 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1587 @param PackageList The package list to examine.
1588 @param Languages Points to the buffer to hold the returned string.
1589 @param LanguagesSize On entry, points to the size of the buffer pointed
1590 to by Languages, in bytes. On return, points to
1591 the length of Languages, in bytes.
1592
1593 @retval EFI_SUCCESS The languages were returned successfully.
1594 @retval EFI_INVALID_PARAMETER The Languages or LanguagesSize was NULL.
1595 @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of
1596 supported languages. LanguageSize is updated to
1597 contain the required size.
1598 @retval EFI_NOT_FOUND Could not find string package in specified
1599 packagelist.
1600
1601 **/
1602 EFI_STATUS
1603 EFIAPI
1604 HiiGetLanguages (
1605 IN CONST EFI_HII_STRING_PROTOCOL *This,
1606 IN EFI_HII_HANDLE PackageList,
1607 IN OUT CHAR8 *Languages,
1608 IN OUT UINTN *LanguagesSize
1609 )
1610 {
1611 LIST_ENTRY *Link;
1612 HII_DATABASE_PRIVATE_DATA *Private;
1613 HII_DATABASE_RECORD *DatabaseRecord;
1614 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1615 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1616 UINTN ResultSize;
1617
1618 if (This == NULL || Languages == NULL || LanguagesSize == NULL || PackageList == NULL) {
1619 return EFI_INVALID_PARAMETER;
1620 }
1621 if (!IsHiiHandleValid (PackageList)) {
1622 return EFI_NOT_FOUND;
1623 }
1624
1625 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1626
1627 PackageListNode = NULL;
1628 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1629 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1630 if (DatabaseRecord->Handle == PackageList) {
1631 PackageListNode = DatabaseRecord->PackageList;
1632 break;
1633 }
1634 }
1635 if (PackageListNode == NULL) {
1636 return EFI_NOT_FOUND;
1637 }
1638
1639 //
1640 // Search the languages in the specified packagelist.
1641 //
1642 ResultSize = 0;
1643 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1644 Link != &PackageListNode->StringPkgHdr;
1645 Link = Link->ForwardLink
1646 ) {
1647 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1648 ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language);
1649 if (ResultSize <= *LanguagesSize) {
1650 AsciiStrCpy (Languages, StringPackage->StringPkgHdr->Language);
1651 Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language);
1652 *(Languages - 1) = L';';
1653 }
1654 }
1655 if (ResultSize == 0) {
1656 return EFI_NOT_FOUND;
1657 }
1658
1659 if (*LanguagesSize < ResultSize) {
1660 *LanguagesSize = ResultSize;
1661 return EFI_BUFFER_TOO_SMALL;
1662 }
1663
1664 *(Languages - 1) = 0;
1665 return EFI_SUCCESS;
1666 }
1667
1668
1669 /**
1670 Each string package has associated with it a single primary language and zero
1671 or more secondary languages. This routine returns the secondary languages
1672 associated with a package list.
1673
1674 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1675 @param PackageList The package list to examine.
1676 @param FirstLanguage Points to the primary language.
1677 @param SecondaryLanguages Points to the buffer to hold the returned list of
1678 secondary languages for the specified
1679 FirstLanguage. If there are no secondary
1680 languages, the function returns successfully, but
1681 this is set to NULL.
1682 @param SecondaryLanguagesSize On entry, points to the size of the buffer pointed
1683 to by SecondaryLanguages, in bytes. On return,
1684 points to the length of SecondaryLanguages in bytes.
1685
1686 @retval EFI_SUCCESS Secondary languages were correctly returned.
1687 @retval EFI_INVALID_PARAMETER FirstLanguage or SecondaryLanguages or
1688 SecondaryLanguagesSize was NULL.
1689 @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is
1690 too small to hold the returned information.
1691 SecondLanguageSize is updated to hold the size of
1692 the buffer required.
1693 @retval EFI_INVALID_LANGUAGE The language specified by FirstLanguage is not
1694 present in the specified package list.
1695 @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
1696
1697 **/
1698 EFI_STATUS
1699 EFIAPI
1700 HiiGetSecondaryLanguages (
1701 IN CONST EFI_HII_STRING_PROTOCOL *This,
1702 IN EFI_HII_HANDLE PackageList,
1703 IN CONST CHAR8 *FirstLanguage,
1704 IN OUT CHAR8 *SecondaryLanguages,
1705 IN OUT UINTN *SecondaryLanguagesSize
1706 )
1707 {
1708 LIST_ENTRY *Link;
1709 LIST_ENTRY *Link1;
1710 HII_DATABASE_PRIVATE_DATA *Private;
1711 HII_DATABASE_RECORD *DatabaseRecord;
1712 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1713 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1714 CHAR8 *Languages;
1715 UINTN ResultSize;
1716
1717 if (This == NULL || PackageList == NULL || FirstLanguage == NULL) {
1718 return EFI_INVALID_PARAMETER;
1719 }
1720 if (SecondaryLanguages == NULL || SecondaryLanguagesSize == NULL) {
1721 return EFI_INVALID_PARAMETER;
1722 }
1723 if (!IsHiiHandleValid (PackageList)) {
1724 return EFI_NOT_FOUND;
1725 }
1726
1727 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1728
1729 PackageListNode = NULL;
1730 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1731 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1732 if (DatabaseRecord->Handle == PackageList) {
1733 PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);
1734 break;
1735 }
1736 }
1737 if (PackageListNode == NULL) {
1738 return EFI_NOT_FOUND;
1739 }
1740
1741 Languages = NULL;
1742 ResultSize = 0;
1743 for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;
1744 Link1 != &PackageListNode->StringPkgHdr;
1745 Link1 = Link1->ForwardLink
1746 ) {
1747 StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1748 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) FirstLanguage)) {
1749 Languages = StringPackage->StringPkgHdr->Language;
1750 //
1751 // Language is a series of ';' terminated strings, first one is primary
1752 // language and following with other secondary languages or NULL if no
1753 // secondary languages any more.
1754 //
1755 Languages = AsciiStrStr (Languages, ";");
1756 if (Languages == NULL) {
1757 break;
1758 }
1759 Languages++;
1760
1761 ResultSize = AsciiStrSize (Languages);
1762 if (ResultSize <= *SecondaryLanguagesSize) {
1763 AsciiStrCpy (SecondaryLanguages, Languages);
1764 } else {
1765 *SecondaryLanguagesSize = ResultSize;
1766 return EFI_BUFFER_TOO_SMALL;
1767 }
1768
1769 return EFI_SUCCESS;
1770 }
1771 }
1772
1773 return EFI_INVALID_LANGUAGE;
1774 }
1775
1776 /**
1777 Compare whether two names of languages are identical.
1778
1779 @param Language1 Name of language 1
1780 @param Language2 Name of language 2
1781
1782 @retval TRUE same
1783 @retval FALSE not same
1784
1785 **/
1786 BOOLEAN
1787 HiiCompareLanguage (
1788 IN CHAR8 *Language1,
1789 IN CHAR8 *Language2
1790 )
1791 {
1792 //
1793 // Porting Guide:
1794 // This library interface is simply obsolete.
1795 // Include the source code to user code.
1796 //
1797 UINTN Index;
1798
1799 for (Index = 0; (Language1[Index] != 0) && (Language2[Index] != 0); Index++) {
1800 if (Language1[Index] != Language2[Index]) {
1801 return FALSE;
1802 }
1803 }
1804
1805 if (((Language1[Index] == 0) && (Language2[Index] == 0)) ||
1806 ((Language1[Index] == 0) && (Language2[Index] != ';')) ||
1807 ((Language1[Index] == ';') && (Language2[Index] != 0)) ||
1808 ((Language1[Index] == ';') && (Language2[Index] != ';'))) {
1809 return TRUE;
1810 }
1811
1812 return FALSE;
1813 }