]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/HiiDatabaseDxe/String.c
Update HiiString Protocol and HiiSetString Api in HiiLib
[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 = 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,
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 && StringSize != 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 //
633 // Get the string text.
634 //
635 StringTextPtr = StringBlockAddr + StringTextOffset;
636 switch (BlockType) {
637 case EFI_HII_SIBT_STRING_SCSU:
638 case EFI_HII_SIBT_STRING_SCSU_FONT:
639 case EFI_HII_SIBT_STRINGS_SCSU:
640 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
641 Status = ConvertToUnicodeText (String, (CHAR8 *) StringTextPtr, StringSize);
642 break;
643 case EFI_HII_SIBT_STRING_UCS2:
644 case EFI_HII_SIBT_STRING_UCS2_FONT:
645 case EFI_HII_SIBT_STRINGS_UCS2:
646 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
647 Status = GetUnicodeStringTextOrSize (String, StringTextPtr, StringSize);
648 break;
649 default:
650 return EFI_NOT_FOUND;
651 }
652 if (EFI_ERROR (Status)) {
653 return Status;
654 }
655
656 //
657 // Get the string font. The FontId 0 is the default font for those string blocks which
658 // do not specify a font identifier. If default font is not specified, return NULL.
659 //
660 if (StringFontInfo != NULL) {
661 switch (BlockType) {
662 case EFI_HII_SIBT_STRING_SCSU_FONT:
663 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
664 case EFI_HII_SIBT_STRING_UCS2_FONT:
665 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
666 FontId = *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK));
667 break;
668 default:
669 FontId = 0;
670 }
671 Status = GetStringFontInfo (StringPackage, FontId, StringFontInfo);
672 if (Status == EFI_NOT_FOUND) {
673 *StringFontInfo = NULL;
674 }
675 }
676
677 return EFI_SUCCESS;
678 }
679
680
681 /**
682 Parse all string blocks to set a String specified by StringId.
683
684 This is a internal function.
685
686 @param Private HII database driver private structure.
687 @param StringPackage HII string package instance.
688 @param StringId The string's id, which is unique within
689 PackageList.
690 @param String Points to the new null-terminated string.
691 @param StringFontInfo Points to the input font info.
692
693 @retval EFI_SUCCESS The string was updated successfully.
694 @retval EFI_NOT_FOUND The string specified by StringId is not in the
695 database.
696 @retval EFI_INVALID_PARAMETER The String or Language was NULL.
697 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
698 current database.
699 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
700 task.
701
702 **/
703 EFI_STATUS
704 SetStringWorker (
705 IN HII_DATABASE_PRIVATE_DATA *Private,
706 IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage,
707 IN EFI_STRING_ID StringId,
708 IN EFI_STRING String,
709 IN EFI_FONT_INFO *StringFontInfo OPTIONAL
710 )
711 {
712 UINT8 *StringTextPtr;
713 UINT8 BlockType;
714 UINT8 *StringBlockAddr;
715 UINTN StringTextOffset;
716 EFI_STATUS Status;
717 UINT8 *Block;
718 UINT8 *BlockPtr;
719 UINTN BlockSize;
720 UINTN OldBlockSize;
721 HII_FONT_INFO *LocalFont;
722 HII_GLOBAL_FONT_INFO *GlobalFont;
723 BOOLEAN Referred;
724 EFI_HII_SIBT_EXT2_BLOCK Ext2;
725 UINTN StringSize;
726 UINTN TmpSize;
727
728
729 ASSERT (Private != NULL && StringPackage != NULL && String != NULL);
730 ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
731 //
732 // Find the specified string block
733 //
734 Status = FindStringBlock (
735 Private,
736 StringPackage,
737 StringId,
738 &BlockType,
739 &StringBlockAddr,
740 &StringTextOffset,
741 NULL
742 );
743 if (EFI_ERROR (Status)) {
744 return Status;
745 }
746
747 LocalFont = NULL;
748 GlobalFont = NULL;
749 Referred = FALSE;
750
751 //
752 // The input StringFontInfo should exist in current database if specified.
753 //
754 if (StringFontInfo != NULL) {
755 if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) {
756 return EFI_INVALID_PARAMETER;
757 } else {
758 Referred = ReferFontInfoLocally (
759 Private,
760 StringPackage,
761 StringPackage->FontId,
762 FALSE,
763 GlobalFont,
764 &LocalFont
765 );
766 if (!Referred) {
767 StringPackage->FontId++;
768 }
769 }
770 //
771 // Update the FontId of the specified string block to input font info.
772 //
773 switch (BlockType) {
774 case EFI_HII_SIBT_STRING_SCSU_FONT:
775 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
776 case EFI_HII_SIBT_STRING_UCS2_FONT:
777 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
778 *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)) = LocalFont->FontId;
779 break;
780 default:
781 //
782 // When modify the font info of these blocks, the block type should be updated
783 // to contain font info thus the whole structure should be revised.
784 // It is recommended to use tool to modify the block type not in the code.
785 //
786 return EFI_UNSUPPORTED;
787 }
788 }
789
790 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
791
792 //
793 // Set the string text and font.
794 //
795 StringTextPtr = StringBlockAddr + StringTextOffset;
796 switch (BlockType) {
797 case EFI_HII_SIBT_STRING_SCSU:
798 case EFI_HII_SIBT_STRING_SCSU_FONT:
799 case EFI_HII_SIBT_STRINGS_SCSU:
800 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
801 BlockSize = OldBlockSize + StrLen (String);
802 BlockSize -= AsciiStrLen ((CHAR8 *) StringTextPtr);
803 Block = AllocateZeroPool (BlockSize);
804 if (Block == NULL) {
805 return EFI_OUT_OF_RESOURCES;
806 }
807
808 CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
809 BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
810
811 while (*String != 0) {
812 *BlockPtr++ = (CHAR8) *String++;
813 }
814 *BlockPtr++ = 0;
815
816
817 TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *) StringTextPtr);
818 CopyMem (
819 BlockPtr,
820 StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr),
821 TmpSize
822 );
823
824 FreePool (StringPackage->StringBlock);
825 StringPackage->StringBlock = Block;
826 StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);
827 break;
828
829 case EFI_HII_SIBT_STRING_UCS2:
830 case EFI_HII_SIBT_STRING_UCS2_FONT:
831 case EFI_HII_SIBT_STRINGS_UCS2:
832 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
833 //
834 // Use StrSize to store the size of the specified string, including the NULL
835 // terminator.
836 //
837 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
838
839 BlockSize = OldBlockSize + StrSize (String) - StringSize;
840 Block = AllocateZeroPool (BlockSize);
841 if (Block == NULL) {
842 return EFI_OUT_OF_RESOURCES;
843 }
844
845 CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
846 BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
847
848 CopyMem (BlockPtr, String, StrSize (String));
849 BlockPtr += StrSize (String);
850
851 CopyMem (
852 BlockPtr,
853 StringTextPtr + StringSize,
854 OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize
855 );
856
857 FreePool (StringPackage->StringBlock);
858 StringPackage->StringBlock = Block;
859 StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);
860 break;
861
862 default:
863 return EFI_NOT_FOUND;
864 }
865
866 //
867 // Insert a new EFI_HII_SIBT_FONT_BLOCK to the header of string block, if incoming
868 // StringFontInfo does not exist in current string package.
869 //
870 // This new block does not impact on the value of StringId.
871 //
872 //
873 if (StringFontInfo == NULL || Referred) {
874 return EFI_SUCCESS;
875 }
876
877 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
878 BlockSize = OldBlockSize + sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16) +
879 StrSize (GlobalFont->FontInfo->FontName);
880
881 Block = AllocateZeroPool (BlockSize);
882 if (Block == NULL) {
883 return EFI_OUT_OF_RESOURCES;
884 }
885
886 BlockPtr = Block;
887 Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
888 Ext2.BlockType2 = EFI_HII_SIBT_FONT;
889 Ext2.Length = (UINT16) (BlockSize - OldBlockSize);
890 CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
891 BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
892
893 *BlockPtr = LocalFont->FontId;
894 BlockPtr += sizeof (UINT8);
895 CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16));
896 BlockPtr += sizeof (UINT16);
897 CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32));
898 BlockPtr += sizeof (UINT32);
899 CopyMem (
900 BlockPtr,
901 GlobalFont->FontInfo->FontName,
902 StrSize (GlobalFont->FontInfo->FontName)
903 );
904 BlockPtr += StrSize (GlobalFont->FontInfo->FontName);
905
906 CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize);
907
908 FreePool (StringPackage->StringBlock);
909 StringPackage->StringBlock = Block;
910 StringPackage->StringPkgHdr->Header.Length += Ext2.Length;
911
912 return EFI_SUCCESS;
913
914 }
915
916
917 /**
918 This function adds the string String to the group of strings owned by PackageList, with the
919 specified font information StringFontInfo and returns a new string id.
920 The new string identifier is guaranteed to be unique within the package list.
921 That new string identifier is reserved for all languages in the package list.
922
923
924 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
925 @param PackageList Handle of the package list where this string will
926 be added.
927 @param StringId On return, contains the new strings id, which is
928 unique within PackageList.
929 @param Language Points to the language for the new string.
930 @param LanguageName Points to the printable language name to associate
931 with the passed in Language field.If LanguageName
932 is not NULL and the string package header's
933 LanguageName associated with a given Language is
934 not zero, the LanguageName being passed in will
935 be ignored.
936 @param String Points to the new null-terminated string.
937 @param StringFontInfo Points to the new string's font information or
938 NULL if the string should have the default system
939 font, size and style.
940
941 @retval EFI_SUCCESS The new string was added successfully.
942 @retval EFI_NOT_FOUND The specified PackageList could not be found in
943 database.
944 @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources.
945 @retval EFI_INVALID_PARAMETER String is NULL or StringId is NULL or Language is
946 NULL.
947 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
948 current database.
949
950 **/
951 EFI_STATUS
952 EFIAPI
953 HiiNewString (
954 IN CONST EFI_HII_STRING_PROTOCOL *This,
955 IN EFI_HII_HANDLE PackageList,
956 OUT EFI_STRING_ID *StringId,
957 IN CONST CHAR8 *Language,
958 IN CONST CHAR16 *LanguageName, OPTIONAL
959 IN CONST EFI_STRING String,
960 IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
961 )
962 {
963 EFI_STATUS Status;
964 LIST_ENTRY *Link;
965 HII_DATABASE_PRIVATE_DATA *Private;
966 HII_DATABASE_RECORD *DatabaseRecord;
967 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
968 HII_STRING_PACKAGE_INSTANCE *StringPackage;
969 UINT32 HeaderSize;
970 UINT32 BlockSize;
971 UINT32 OldBlockSize;
972 UINT8 *StringBlock;
973 UINT8 *BlockPtr;
974 UINT32 Ucs2BlockSize;
975 UINT32 FontBlockSize;
976 UINT32 Ucs2FontBlockSize;
977 EFI_HII_SIBT_EXT2_BLOCK Ext2;
978 HII_FONT_INFO *LocalFont;
979 HII_GLOBAL_FONT_INFO *GlobalFont;
980 EFI_STRING_ID NewStringId;
981 EFI_STRING_ID NextStringId;
982 EFI_STRING_ID Index;
983 HII_STRING_PACKAGE_INSTANCE *MatchStringPackage;
984 BOOLEAN NewStringPackageCreated;
985
986
987 if (This == NULL || String == NULL || StringId == NULL || Language == NULL || PackageList == NULL) {
988 return EFI_INVALID_PARAMETER;
989 }
990
991 if (!IsHiiHandleValid (PackageList)) {
992 return EFI_NOT_FOUND;
993 }
994
995 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
996 GlobalFont = NULL;
997
998 //
999 // If StringFontInfo specify a paritcular font, it should exist in current database.
1000 //
1001 if (StringFontInfo != NULL) {
1002 if (!IsFontInfoExisted (Private, (EFI_FONT_INFO *) StringFontInfo, NULL, NULL, &GlobalFont)) {
1003 return EFI_INVALID_PARAMETER;
1004 }
1005 }
1006
1007 //
1008 // Get the matching package list.
1009 //
1010 PackageListNode = NULL;
1011 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1012 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1013 if (DatabaseRecord->Handle == PackageList) {
1014 PackageListNode = DatabaseRecord->PackageList;
1015 break;
1016 }
1017 }
1018 if (PackageListNode == NULL) {
1019 return EFI_NOT_FOUND;
1020 }
1021
1022 Status = EFI_SUCCESS;
1023 NewStringPackageCreated = FALSE;
1024 NewStringId = 0;
1025 NextStringId = 0;
1026 StringPackage = NULL;
1027 MatchStringPackage = NULL;
1028 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1029 Link != &PackageListNode->StringPkgHdr;
1030 Link = Link->ForwardLink
1031 ) {
1032 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1033 //
1034 // Create a string block and corresponding font block if exists, then append them
1035 // to the end of the string package.
1036 //
1037 Status = FindStringBlock (
1038 Private,
1039 StringPackage,
1040 0,
1041 NULL,
1042 NULL,
1043 NULL,
1044 &NextStringId
1045 );
1046 if (EFI_ERROR (Status)) {
1047 goto Done;
1048 }
1049 //
1050 // Make sure that new StringId is same in all String Packages for the different language.
1051 //
1052 if (NewStringId != 0 && NewStringId != NextStringId) {
1053 ASSERT (FALSE);
1054 Status = EFI_INVALID_PARAMETER;
1055 goto Done;
1056 }
1057 NewStringId = NextStringId;
1058 //
1059 // Get the matched string package with language.
1060 //
1061 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
1062 MatchStringPackage = StringPackage;
1063 } else {
1064 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
1065 //
1066 // Create a blank EFI_HII_SIBT_STRING_UCS2_BLOCK to reserve new string ID.
1067 //
1068 Ucs2BlockSize = (UINT32) sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
1069
1070 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize);
1071 if (StringBlock == NULL) {
1072 Status = EFI_OUT_OF_RESOURCES;
1073 goto Done;
1074 }
1075 //
1076 // Copy original string blocks, except the EFI_HII_SIBT_END.
1077 //
1078 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1079 //
1080 // Create a blank EFI_HII_SIBT_STRING_UCS2 block
1081 //
1082 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1083 *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
1084 BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
1085
1086 //
1087 // Append a EFI_HII_SIBT_END block to the end.
1088 //
1089 *BlockPtr = EFI_HII_SIBT_END;
1090 FreePool (StringPackage->StringBlock);
1091 StringPackage->StringBlock = StringBlock;
1092 StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;
1093 PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;
1094 }
1095 }
1096 if (NewStringId == 0) {
1097 //
1098 // No string package is found.
1099 // Create new string package. StringId 1 is reserved for Language Name string.
1100 //
1101 *StringId = 2;
1102 } else {
1103 //
1104 // Set new StringId
1105 //
1106 *StringId = NewStringId + 1;
1107 }
1108
1109 if (MatchStringPackage != NULL) {
1110 StringPackage = MatchStringPackage;
1111 } else {
1112 //
1113 // LanguageName is required to create a new string package.
1114 //
1115 if (LanguageName == NULL) {
1116 Status = EFI_INVALID_PARAMETER;
1117 goto Done;
1118 }
1119
1120 StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
1121 if (StringPackage == NULL) {
1122 Status = EFI_OUT_OF_RESOURCES;
1123 goto Done;
1124 }
1125
1126 StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
1127 StringPackage->MaxStringId = *StringId;
1128 StringPackage->FontId = 0;
1129 InitializeListHead (&StringPackage->FontInfoList);
1130
1131 //
1132 // Fill in the string package header
1133 //
1134 HeaderSize = (UINT32) (AsciiStrSize ((CHAR8 *) Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR));
1135 StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize);
1136 if (StringPackage->StringPkgHdr == NULL) {
1137 FreePool (StringPackage);
1138 Status = EFI_OUT_OF_RESOURCES;
1139 goto Done;
1140 }
1141 StringPackage->StringPkgHdr->Header.Type = EFI_HII_PACKAGE_STRINGS;
1142 StringPackage->StringPkgHdr->HdrSize = HeaderSize;
1143 StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;
1144 CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));
1145 StringPackage->StringPkgHdr->LanguageName = 1;
1146 AsciiStrCpy (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language);
1147
1148 //
1149 // Calculate the length of the string blocks, including string block to record
1150 // printable language full name and EFI_HII_SIBT_END_BLOCK.
1151 //
1152 Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) +
1153 (*StringId - 1) * sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));
1154
1155 BlockSize = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK);
1156 StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (BlockSize);
1157 if (StringPackage->StringBlock == NULL) {
1158 FreePool (StringPackage->StringPkgHdr);
1159 FreePool (StringPackage);
1160 Status = EFI_OUT_OF_RESOURCES;
1161 goto Done;
1162 }
1163
1164 //
1165 // Insert the string block of printable language full name
1166 //
1167 BlockPtr = StringPackage->StringBlock;
1168 *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
1169 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1170 CopyMem (BlockPtr, (EFI_STRING) LanguageName, StrSize ((EFI_STRING) LanguageName));
1171 BlockPtr += StrSize ((EFI_STRING) LanguageName);
1172 for (Index = 2; Index <= *StringId - 1; Index ++) {
1173 *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
1174 BlockPtr += sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK);
1175 }
1176 //
1177 // Insert the end block
1178 //
1179 *BlockPtr = EFI_HII_SIBT_END;
1180
1181 //
1182 // Append this string package node to string package array in this package list.
1183 //
1184 StringPackage->StringPkgHdr->Header.Length = HeaderSize + BlockSize;
1185 PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
1186 InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry);
1187 NewStringPackageCreated = TRUE;
1188 }
1189
1190 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
1191
1192 if (StringFontInfo == NULL) {
1193 //
1194 // Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified.
1195 //
1196 Ucs2BlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK)
1197 - sizeof (CHAR16));
1198
1199 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize);
1200 if (StringBlock == NULL) {
1201 Status = EFI_OUT_OF_RESOURCES;
1202 goto Done;
1203 }
1204 //
1205 // Copy original string blocks, except the EFI_HII_SIBT_END.
1206 //
1207 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1208 //
1209 // Create a EFI_HII_SIBT_STRING_UCS2 block
1210 //
1211 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1212 *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
1213 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1214 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
1215 BlockPtr += StrSize ((EFI_STRING) String);
1216
1217 //
1218 // Append a EFI_HII_SIBT_END block to the end.
1219 //
1220 *BlockPtr = EFI_HII_SIBT_END;
1221 FreePool (StringPackage->StringBlock);
1222 StringPackage->StringBlock = StringBlock;
1223 StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;
1224 PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;
1225
1226 } else {
1227 //
1228 // StringFontInfo is specified here. If there is a EFI_HII_SIBT_FONT_BLOCK
1229 // which refers to this font info, create a EFI_HII_SIBT_STRING_UCS2_FONT block
1230 // only. Otherwise create a EFI_HII_SIBT_FONT block with a EFI_HII_SIBT_STRING
1231 // _UCS2_FONT block.
1232 //
1233 Ucs2FontBlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) -
1234 sizeof (CHAR16));
1235 if (ReferFontInfoLocally (Private, StringPackage, StringPackage->FontId, FALSE, GlobalFont, &LocalFont)) {
1236 //
1237 // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only.
1238 //
1239 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize);
1240 if (StringBlock == NULL) {
1241 Status = EFI_OUT_OF_RESOURCES;
1242 goto Done;
1243 }
1244 //
1245 // Copy original string blocks, except the EFI_HII_SIBT_END.
1246 //
1247 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1248 //
1249 // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
1250 //
1251 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1252 *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
1253 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1254 *BlockPtr = LocalFont->FontId;
1255 BlockPtr += sizeof (UINT8);
1256 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
1257 BlockPtr += StrSize ((EFI_STRING) String);
1258
1259 //
1260 // Append a EFI_HII_SIBT_END block to the end.
1261 //
1262 *BlockPtr = EFI_HII_SIBT_END;
1263 FreePool (StringPackage->StringBlock);
1264 StringPackage->StringBlock = StringBlock;
1265 StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize;
1266 PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize;
1267
1268 } else {
1269 //
1270 // EFI_HII_SIBT_FONT_BLOCK does not exist in current string package, so
1271 // create a EFI_HII_SIBT_FONT block to record the font info, then generate
1272 // a EFI_HII_SIBT_STRING_UCS2_FONT block to record the incoming string.
1273 //
1274 FontBlockSize = (UINT32) (StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName) +
1275 sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16));
1276 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize);
1277 if (StringBlock == NULL) {
1278 Status = EFI_OUT_OF_RESOURCES;
1279 goto Done;
1280 }
1281 //
1282 // Copy original string blocks, except the EFI_HII_SIBT_END.
1283 //
1284 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1285
1286 //
1287 // Create a EFI_HII_SIBT_FONT block firstly and then backup its info in string
1288 // package instance for future reference.
1289 //
1290 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1291
1292 Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
1293 Ext2.BlockType2 = EFI_HII_SIBT_FONT;
1294 Ext2.Length = (UINT16) FontBlockSize;
1295 CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
1296 BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
1297
1298 *BlockPtr = LocalFont->FontId;
1299 BlockPtr += sizeof (UINT8);
1300 CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontSize, sizeof (UINT16));
1301 BlockPtr += sizeof (UINT16);
1302 CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE));
1303 BlockPtr += sizeof (EFI_HII_FONT_STYLE);
1304 CopyMem (
1305 BlockPtr,
1306 &((EFI_FONT_INFO *) StringFontInfo)->FontName,
1307 StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName)
1308 );
1309 BlockPtr += StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName);
1310 //
1311 // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
1312 //
1313 *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
1314 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1315 *BlockPtr = LocalFont->FontId;
1316 BlockPtr += sizeof (UINT8);
1317 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
1318 BlockPtr += StrSize ((EFI_STRING) String);
1319
1320 //
1321 // Append a EFI_HII_SIBT_END block to the end.
1322 //
1323 *BlockPtr = EFI_HII_SIBT_END;
1324 FreePool (StringPackage->StringBlock);
1325 StringPackage->StringBlock = StringBlock;
1326 StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;
1327 PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;
1328
1329 //
1330 // Increase the FontId to make it unique since we already add
1331 // a EFI_HII_SIBT_FONT block to this string package.
1332 //
1333 StringPackage->FontId++;
1334 }
1335 }
1336
1337 Done:
1338 if (!EFI_ERROR (Status) && NewStringPackageCreated) {
1339 //
1340 // Trigger any registered notification function for new string package
1341 //
1342 Status = InvokeRegisteredFunction (
1343 Private,
1344 EFI_HII_DATABASE_NOTIFY_NEW_PACK,
1345 (VOID *) StringPackage,
1346 EFI_HII_PACKAGE_STRINGS,
1347 PackageList
1348 );
1349 }
1350
1351 if (!EFI_ERROR (Status)) {
1352 //
1353 // Update MaxString Id to new StringId
1354 //
1355 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1356 Link != &PackageListNode->StringPkgHdr;
1357 Link = Link->ForwardLink
1358 ) {
1359 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1360 StringPackage->MaxStringId = *StringId;
1361 }
1362 } else if (NewStringPackageCreated) {
1363 //
1364 // Free the allocated new string Package when new string can't be added.
1365 //
1366 RemoveEntryList (&StringPackage->StringEntry);
1367 FreePool (StringPackage->StringBlock);
1368 FreePool (StringPackage->StringPkgHdr);
1369 FreePool (StringPackage);
1370 }
1371
1372 return Status;
1373 }
1374
1375
1376 /**
1377 This function retrieves the string specified by StringId which is associated
1378 with the specified PackageList in the language Language and copies it into
1379 the buffer specified by String.
1380
1381 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1382 @param Language Points to the language for the retrieved string.
1383 @param PackageList The package list in the HII database to search for
1384 the specified string.
1385 @param StringId The string's id, which is unique within
1386 PackageList.
1387 @param String Points to the new null-terminated string.
1388 @param StringSize On entry, points to the size of the buffer pointed
1389 to by String, in bytes. On return, points to the
1390 length of the string, in bytes.
1391 @param StringFontInfo If not NULL, points to the string's font
1392 information. It's caller's responsibility to free
1393 this buffer.
1394
1395 @retval EFI_SUCCESS The string was returned successfully.
1396 @retval EFI_NOT_FOUND The string specified by StringId is not available.
1397 @retval EFI_NOT_FOUND The string specified by StringId is available but
1398 not in the specified language.
1399 The specified PackageList is not in the database.
1400 @retval EFI_INVALID_LANGUAGE - The string specified by StringId is available but
1401 @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
1402 hold the string.
1403 @retval EFI_INVALID_PARAMETER The String or Language or StringSize was NULL.
1404 @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
1405 request.
1406
1407 **/
1408 EFI_STATUS
1409 EFIAPI
1410 HiiGetString (
1411 IN CONST EFI_HII_STRING_PROTOCOL *This,
1412 IN CONST CHAR8 *Language,
1413 IN EFI_HII_HANDLE PackageList,
1414 IN EFI_STRING_ID StringId,
1415 OUT EFI_STRING String,
1416 IN OUT UINTN *StringSize,
1417 OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
1418 )
1419 {
1420 EFI_STATUS Status;
1421 LIST_ENTRY *Link;
1422 HII_DATABASE_PRIVATE_DATA *Private;
1423 HII_DATABASE_RECORD *DatabaseRecord;
1424 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1425 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1426
1427 if (This == NULL || Language == NULL || StringId < 1 || StringSize == NULL || PackageList == NULL) {
1428 return EFI_INVALID_PARAMETER;
1429 }
1430
1431 if (String == NULL && *StringSize != 0) {
1432 return EFI_INVALID_PARAMETER;
1433 }
1434
1435 if (!IsHiiHandleValid (PackageList)) {
1436 return EFI_NOT_FOUND;
1437 }
1438
1439 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1440 PackageListNode = NULL;
1441
1442 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1443 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1444 if (DatabaseRecord->Handle == PackageList) {
1445 PackageListNode = DatabaseRecord->PackageList;
1446 break;
1447 }
1448 }
1449
1450 if (PackageListNode != NULL) {
1451 //
1452 // First search: to match the StringId in the specified language.
1453 //
1454 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1455 Link != &PackageListNode->StringPkgHdr;
1456 Link = Link->ForwardLink
1457 ) {
1458 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1459 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
1460 Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);
1461 if (Status != EFI_NOT_FOUND) {
1462 return Status;
1463 }
1464 }
1465 }
1466 //
1467 // Second search: to match the StringId in other available languages if exist.
1468 //
1469 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1470 Link != &PackageListNode->StringPkgHdr;
1471 Link = Link->ForwardLink
1472 ) {
1473 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1474 Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);
1475 if (!EFI_ERROR (Status)) {
1476 return EFI_INVALID_LANGUAGE;
1477 }
1478 }
1479 }
1480
1481 return EFI_NOT_FOUND;
1482 }
1483
1484
1485
1486 /**
1487 This function updates the string specified by StringId in the specified PackageList to the text
1488 specified by String and, optionally, the font information specified by StringFontInfo.
1489
1490 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1491 @param PackageList The package list containing the strings.
1492 @param StringId The string's id, which is unique within
1493 PackageList.
1494 @param Language Points to the language for the updated string.
1495 @param String Points to the new null-terminated string.
1496 @param StringFontInfo Points to the string's font information or NULL if
1497 the string font information is not changed.
1498
1499 @retval EFI_SUCCESS The string was updated successfully.
1500 @retval EFI_NOT_FOUND The string specified by StringId is not in the
1501 database.
1502 @retval EFI_INVALID_PARAMETER The String or Language was NULL.
1503 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
1504 current database.
1505 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
1506 task.
1507
1508 **/
1509 EFI_STATUS
1510 EFIAPI
1511 HiiSetString (
1512 IN CONST EFI_HII_STRING_PROTOCOL *This,
1513 IN EFI_HII_HANDLE PackageList,
1514 IN EFI_STRING_ID StringId,
1515 IN CONST CHAR8 *Language,
1516 IN CONST EFI_STRING String,
1517 IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
1518 )
1519 {
1520 EFI_STATUS Status;
1521 LIST_ENTRY *Link;
1522 HII_DATABASE_PRIVATE_DATA *Private;
1523 HII_DATABASE_RECORD *DatabaseRecord;
1524 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1525 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1526 UINT32 OldPackageLen;
1527
1528 if (This == NULL || Language == NULL || StringId < 1 || String == NULL || PackageList == NULL) {
1529 return EFI_INVALID_PARAMETER;
1530 }
1531
1532 if (!IsHiiHandleValid (PackageList)) {
1533 return EFI_NOT_FOUND;
1534 }
1535
1536 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1537 PackageListNode = NULL;
1538
1539 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1540 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1541 if (DatabaseRecord->Handle == PackageList) {
1542 PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);
1543 }
1544 }
1545
1546 if (PackageListNode != NULL) {
1547 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1548 Link != &PackageListNode->StringPkgHdr;
1549 Link = Link->ForwardLink
1550 ) {
1551 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1552 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
1553 OldPackageLen = StringPackage->StringPkgHdr->Header.Length;
1554 Status = SetStringWorker (
1555 Private,
1556 StringPackage,
1557 StringId,
1558 (EFI_STRING) String,
1559 (EFI_FONT_INFO *) StringFontInfo
1560 );
1561 if (EFI_ERROR (Status)) {
1562 return Status;
1563 }
1564 PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen;
1565 return EFI_SUCCESS;
1566 }
1567 }
1568 }
1569
1570 return EFI_NOT_FOUND;
1571 }
1572
1573
1574
1575 /**
1576 This function returns the list of supported languages, in the format specified
1577 in Appendix M of UEFI 2.1 spec.
1578
1579 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1580 @param PackageList The package list to examine.
1581 @param Languages Points to the buffer to hold the returned string.
1582 @param LanguagesSize On entry, points to the size of the buffer pointed
1583 to by Languages, in bytes. On return, points to
1584 the length of Languages, in bytes.
1585
1586 @retval EFI_SUCCESS The languages were returned successfully.
1587 @retval EFI_INVALID_PARAMETER The Languages or LanguagesSize was NULL.
1588 @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of
1589 supported languages. LanguageSize is updated to
1590 contain the required size.
1591 @retval EFI_NOT_FOUND Could not find string package in specified
1592 packagelist.
1593
1594 **/
1595 EFI_STATUS
1596 EFIAPI
1597 HiiGetLanguages (
1598 IN CONST EFI_HII_STRING_PROTOCOL *This,
1599 IN EFI_HII_HANDLE PackageList,
1600 IN OUT CHAR8 *Languages,
1601 IN OUT UINTN *LanguagesSize
1602 )
1603 {
1604 LIST_ENTRY *Link;
1605 HII_DATABASE_PRIVATE_DATA *Private;
1606 HII_DATABASE_RECORD *DatabaseRecord;
1607 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1608 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1609 UINTN ResultSize;
1610
1611 if (This == NULL || Languages == NULL || LanguagesSize == NULL || PackageList == NULL) {
1612 return EFI_INVALID_PARAMETER;
1613 }
1614 if (!IsHiiHandleValid (PackageList)) {
1615 return EFI_NOT_FOUND;
1616 }
1617
1618 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1619
1620 PackageListNode = NULL;
1621 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1622 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1623 if (DatabaseRecord->Handle == PackageList) {
1624 PackageListNode = DatabaseRecord->PackageList;
1625 break;
1626 }
1627 }
1628 if (PackageListNode == NULL) {
1629 return EFI_NOT_FOUND;
1630 }
1631
1632 //
1633 // Search the languages in the specified packagelist.
1634 //
1635 ResultSize = 0;
1636 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1637 Link != &PackageListNode->StringPkgHdr;
1638 Link = Link->ForwardLink
1639 ) {
1640 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1641 ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language);
1642 if (ResultSize <= *LanguagesSize) {
1643 AsciiStrCpy (Languages, StringPackage->StringPkgHdr->Language);
1644 Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language);
1645 *(Languages - 1) = L';';
1646 }
1647 }
1648 if (ResultSize == 0) {
1649 return EFI_NOT_FOUND;
1650 }
1651
1652 if (*LanguagesSize < ResultSize) {
1653 *LanguagesSize = ResultSize;
1654 return EFI_BUFFER_TOO_SMALL;
1655 }
1656
1657 *(Languages - 1) = 0;
1658 return EFI_SUCCESS;
1659 }
1660
1661
1662 /**
1663 Each string package has associated with it a single primary language and zero
1664 or more secondary languages. This routine returns the secondary languages
1665 associated with a package list.
1666
1667 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1668 @param PackageList The package list to examine.
1669 @param FirstLanguage Points to the primary language.
1670 @param SecondaryLanguages Points to the buffer to hold the returned list of
1671 secondary languages for the specified
1672 FirstLanguage. If there are no secondary
1673 languages, the function returns successfully, but
1674 this is set to NULL.
1675 @param SecondaryLanguagesSize On entry, points to the size of the buffer pointed
1676 to by SecondaryLanguages, in bytes. On return,
1677 points to the length of SecondaryLanguages in bytes.
1678
1679 @retval EFI_SUCCESS Secondary languages were correctly returned.
1680 @retval EFI_INVALID_PARAMETER FirstLanguage or SecondaryLanguages or
1681 SecondaryLanguagesSize was NULL.
1682 @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is
1683 too small to hold the returned information.
1684 SecondLanguageSize is updated to hold the size of
1685 the buffer required.
1686 @retval EFI_INVALID_LANGUAGE The language specified by FirstLanguage is not
1687 present in the specified package list.
1688 @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
1689
1690 **/
1691 EFI_STATUS
1692 EFIAPI
1693 HiiGetSecondaryLanguages (
1694 IN CONST EFI_HII_STRING_PROTOCOL *This,
1695 IN EFI_HII_HANDLE PackageList,
1696 IN CONST CHAR8 *FirstLanguage,
1697 IN OUT CHAR8 *SecondaryLanguages,
1698 IN OUT UINTN *SecondaryLanguagesSize
1699 )
1700 {
1701 LIST_ENTRY *Link;
1702 LIST_ENTRY *Link1;
1703 HII_DATABASE_PRIVATE_DATA *Private;
1704 HII_DATABASE_RECORD *DatabaseRecord;
1705 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1706 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1707 CHAR8 *Languages;
1708 UINTN ResultSize;
1709
1710 if (This == NULL || PackageList == NULL || FirstLanguage == NULL) {
1711 return EFI_INVALID_PARAMETER;
1712 }
1713 if (SecondaryLanguages == NULL || SecondaryLanguagesSize == NULL) {
1714 return EFI_INVALID_PARAMETER;
1715 }
1716 if (!IsHiiHandleValid (PackageList)) {
1717 return EFI_NOT_FOUND;
1718 }
1719
1720 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1721
1722 PackageListNode = NULL;
1723 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1724 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1725 if (DatabaseRecord->Handle == PackageList) {
1726 PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);
1727 break;
1728 }
1729 }
1730 if (PackageListNode == NULL) {
1731 return EFI_NOT_FOUND;
1732 }
1733
1734 Languages = NULL;
1735 ResultSize = 0;
1736 for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;
1737 Link1 != &PackageListNode->StringPkgHdr;
1738 Link1 = Link1->ForwardLink
1739 ) {
1740 StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1741 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) FirstLanguage)) {
1742 Languages = StringPackage->StringPkgHdr->Language;
1743 //
1744 // Language is a series of ';' terminated strings, first one is primary
1745 // language and following with other secondary languages or NULL if no
1746 // secondary languages any more.
1747 //
1748 Languages = AsciiStrStr (Languages, ";");
1749 if (Languages == NULL) {
1750 break;
1751 }
1752 Languages++;
1753
1754 ResultSize = AsciiStrSize (Languages);
1755 if (ResultSize <= *SecondaryLanguagesSize) {
1756 AsciiStrCpy (SecondaryLanguages, Languages);
1757 } else {
1758 *SecondaryLanguagesSize = ResultSize;
1759 return EFI_BUFFER_TOO_SMALL;
1760 }
1761
1762 return EFI_SUCCESS;
1763 }
1764 }
1765
1766 return EFI_INVALID_LANGUAGE;
1767 }
1768
1769 /**
1770 Compare whether two names of languages are identical.
1771
1772 @param Language1 Name of language 1
1773 @param Language2 Name of language 2
1774
1775 @retval TRUE same
1776 @retval FALSE not same
1777
1778 **/
1779 BOOLEAN
1780 HiiCompareLanguage (
1781 IN CHAR8 *Language1,
1782 IN CHAR8 *Language2
1783 )
1784 {
1785 //
1786 // Porting Guide:
1787 // This library interface is simply obsolete.
1788 // Include the source code to user code.
1789 //
1790 UINTN Index;
1791
1792 for (Index = 0; (Language1[Index] != 0) && (Language2[Index] != 0); Index++) {
1793 if (Language1[Index] != Language2[Index]) {
1794 return FALSE;
1795 }
1796 }
1797
1798 if (((Language1[Index] == 0) && (Language2[Index] == 0)) ||
1799 ((Language1[Index] == 0) && (Language2[Index] != ';')) ||
1800 ((Language1[Index] == ';') && (Language2[Index] != 0)) ||
1801 ((Language1[Index] == ';') && (Language2[Index] != ';'))) {
1802 return TRUE;
1803 }
1804
1805 return FALSE;
1806 }