Roll back changes to apply GetBestLanguage() in HiiDataBase. Exact language match...
[mirror_edk2.git] / MdeModulePkg / Universal / HiiDatabaseDxe / String.c
1 /** @file
2 Implementation for EFI_HII_STRING_PROTOCOL.
3
4
5 Copyright (c) 2007, 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.
239 If StringId = 0, output the string id of last string block (EFI_HII_SIBT_END).
240
241 @param Private Hii database private structure.
242 @param StringPackage Hii string package instance.
243 @param StringId The string's id, which is unique within
244 PackageList.
245 @param BlockType Output the block type of found string block.
246 @param StringBlockAddr Output the block address of found string block.
247 @param StringTextOffset Offset, relative to the found block address, of
248 the string text information.
249 @param LastStringId Output the last string id when StringId = 0.
250
251 @retval EFI_SUCCESS The string text and font is retrieved
252 successfully.
253 @retval EFI_NOT_FOUND The specified text or font info can not be found
254 out.
255 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
256 task.
257
258 **/
259 EFI_STATUS
260 FindStringBlock (
261 IN HII_DATABASE_PRIVATE_DATA *Private,
262 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
263 IN EFI_STRING_ID StringId,
264 OUT UINT8 *BlockType, OPTIONAL
265 OUT UINT8 **StringBlockAddr, OPTIONAL
266 OUT UINTN *StringTextOffset, OPTIONAL
267 OUT EFI_STRING_ID *LastStringId OPTIONAL
268 )
269 {
270 UINT8 *BlockHdr;
271 EFI_STRING_ID CurrentStringId;
272 UINTN BlockSize;
273 UINTN Index;
274 UINT8 *StringTextPtr;
275 UINTN Offset;
276 HII_FONT_INFO *LocalFont;
277 EFI_FONT_INFO *FontInfo;
278 HII_GLOBAL_FONT_INFO *GlobalFont;
279 UINTN FontInfoSize;
280 UINT16 StringCount;
281 UINT16 SkipCount;
282 EFI_HII_FONT_STYLE FontStyle;
283 UINT16 FontSize;
284 UINT8 Length8;
285 EFI_HII_SIBT_EXT2_BLOCK Ext2;
286 UINT8 FontId;
287 UINT32 Length32;
288 UINTN StringSize;
289 CHAR16 Zero;
290
291 ASSERT (StringPackage != NULL);
292 ASSERT (StringPackage->Signature == HII_STRING_PACKAGE_SIGNATURE);
293
294 CurrentStringId = 1;
295
296 if (StringId != (EFI_STRING_ID) (-1) && StringId != 0) {
297 ASSERT (BlockType != NULL && StringBlockAddr != NULL && StringTextOffset != NULL);
298 } else {
299 ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
300 }
301
302 ZeroMem (&Zero, sizeof (CHAR16));
303
304 //
305 // Parse the string blocks to get the string text and font.
306 //
307 BlockHdr = StringPackage->StringBlock;
308 BlockSize = 0;
309 Offset = 0;
310 while (*BlockHdr != EFI_HII_SIBT_END) {
311 switch (*BlockHdr) {
312 case EFI_HII_SIBT_STRING_SCSU:
313 Offset = sizeof (EFI_HII_STRING_BLOCK);
314 StringTextPtr = BlockHdr + Offset;
315 BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);
316 CurrentStringId++;
317 break;
318
319 case EFI_HII_SIBT_STRING_SCSU_FONT:
320 Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8);
321 StringTextPtr = BlockHdr + Offset;
322 BlockSize += Offset + AsciiStrSize ((CHAR8 *) StringTextPtr);
323 CurrentStringId++;
324 break;
325
326 case EFI_HII_SIBT_STRINGS_SCSU:
327 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
328 StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8);
329 BlockSize += StringTextPtr - BlockHdr;
330
331 for (Index = 0; Index < StringCount; Index++) {
332 BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);
333 if (CurrentStringId == StringId) {
334 *BlockType = *BlockHdr;
335 *StringBlockAddr = BlockHdr;
336 *StringTextOffset = StringTextPtr - BlockHdr;
337 return EFI_SUCCESS;
338 }
339 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);
340 CurrentStringId++;
341 }
342 break;
343
344 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
345 CopyMem (
346 &StringCount,
347 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
348 sizeof (UINT16)
349 );
350 StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8);
351 BlockSize += StringTextPtr - BlockHdr;
352
353 for (Index = 0; Index < StringCount; Index++) {
354 BlockSize += AsciiStrSize ((CHAR8 *) StringTextPtr);
355 if (CurrentStringId == StringId) {
356 *BlockType = *BlockHdr;
357 *StringBlockAddr = BlockHdr;
358 *StringTextOffset = StringTextPtr - BlockHdr;
359 return EFI_SUCCESS;
360 }
361 StringTextPtr = StringTextPtr + AsciiStrSize ((CHAR8 *) StringTextPtr);
362 CurrentStringId++;
363 }
364 break;
365
366 case EFI_HII_SIBT_STRING_UCS2:
367 Offset = sizeof (EFI_HII_STRING_BLOCK);
368 StringTextPtr = BlockHdr + Offset;
369 //
370 // Use StringSize to store the size of the specified string, including the NULL
371 // terminator.
372 //
373 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
374 BlockSize += Offset + StringSize;
375 CurrentStringId++;
376 break;
377
378 case EFI_HII_SIBT_STRING_UCS2_FONT:
379 Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16);
380 StringTextPtr = BlockHdr + Offset;
381 //
382 // Use StrSize to store the size of the specified string, including the NULL
383 // terminator.
384 //
385 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
386 BlockSize += Offset + StringSize;
387 CurrentStringId++;
388 break;
389
390 case EFI_HII_SIBT_STRINGS_UCS2:
391 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16);
392 StringTextPtr = BlockHdr + Offset;
393 BlockSize += Offset;
394 CopyMem (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
395 for (Index = 0; Index < StringCount; Index++) {
396 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
397 BlockSize += StringSize;
398 if (CurrentStringId == StringId) {
399 *BlockType = *BlockHdr;
400 *StringBlockAddr = BlockHdr;
401 *StringTextOffset = StringTextPtr - BlockHdr;
402 return EFI_SUCCESS;
403 }
404 StringTextPtr = StringTextPtr + StringSize;
405 CurrentStringId++;
406 }
407 break;
408
409 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
410 Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16);
411 StringTextPtr = BlockHdr + Offset;
412 BlockSize += Offset;
413 CopyMem (
414 &StringCount,
415 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
416 sizeof (UINT16)
417 );
418 for (Index = 0; Index < StringCount; Index++) {
419 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
420 BlockSize += StringSize;
421 if (CurrentStringId == StringId) {
422 *BlockType = *BlockHdr;
423 *StringBlockAddr = BlockHdr;
424 *StringTextOffset = StringTextPtr - BlockHdr;
425 return EFI_SUCCESS;
426 }
427 StringTextPtr = StringTextPtr + StringSize;
428 CurrentStringId++;
429 }
430 break;
431
432 case EFI_HII_SIBT_DUPLICATE:
433 if (CurrentStringId == StringId) {
434 //
435 // Incoming StringId is an id of a duplicate string block.
436 // Update the StringId to be the previous string block.
437 // Go back to the header of string block to search.
438 //
439 CopyMem (
440 &StringId,
441 BlockHdr + sizeof (EFI_HII_STRING_BLOCK),
442 sizeof (EFI_STRING_ID)
443 );
444 ASSERT (StringId != CurrentStringId);
445 CurrentStringId = 1;
446 BlockSize = 0;
447 } else {
448 BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK);
449 CurrentStringId++;
450 }
451 break;
452
453 case EFI_HII_SIBT_SKIP1:
454 SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK)));
455 CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
456 BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK);
457 break;
458
459 case EFI_HII_SIBT_SKIP2:
460 CopyMem (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16));
461 CurrentStringId = (UINT16) (CurrentStringId + SkipCount);
462 BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK);
463 break;
464
465 case EFI_HII_SIBT_EXT1:
466 CopyMem (
467 &Length8,
468 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
469 sizeof (UINT8)
470 );
471 BlockSize += Length8;
472 break;
473
474 case EFI_HII_SIBT_EXT2:
475 CopyMem (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
476 if (Ext2.BlockType2 == EFI_HII_SIBT_FONT && StringId == (EFI_STRING_ID) (-1)) {
477 //
478 // Find the relationship between global font info and the font info of
479 // this EFI_HII_SIBT_FONT block then backup its information in local package.
480 //
481 BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
482 CopyMem (&FontId, BlockHdr, sizeof (UINT8));
483 BlockHdr += sizeof (UINT8);
484 CopyMem (&FontSize, BlockHdr, sizeof (UINT16));
485 BlockHdr += sizeof (UINT16);
486 CopyMem (&FontStyle, BlockHdr, sizeof (EFI_HII_FONT_STYLE));
487 BlockHdr += sizeof (EFI_HII_FONT_STYLE);
488 GetUnicodeStringTextOrSize (NULL, BlockHdr, &StringSize);
489
490 FontInfoSize = sizeof (EFI_FONT_INFO) - sizeof (CHAR16) + StringSize;
491 FontInfo = (EFI_FONT_INFO *) AllocateZeroPool (FontInfoSize);
492 if (FontInfo == NULL) {
493 return EFI_OUT_OF_RESOURCES;
494 }
495 FontInfo->FontStyle = FontStyle;
496 FontInfo->FontSize = FontSize;
497 CopyMem (FontInfo->FontName, BlockHdr, StringSize);
498
499 //
500 // If find the corresponding global font info, save the relationship.
501 // Otherwise ignore this EFI_HII_SIBT_FONT block.
502 //
503 if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {
504 ReferFontInfoLocally (Private, StringPackage, FontId, TRUE, GlobalFont, &LocalFont);
505 }
506
507 //
508 // Since string package tool set FontId initially to 0 and increases it
509 // progressively by one, StringPackage->FondId always represents an unique
510 // and available FontId.
511 //
512 StringPackage->FontId++;
513
514 FreePool (FontInfo);
515 }
516
517 BlockSize += Ext2.Length;
518
519 break;
520
521 case EFI_HII_SIBT_EXT4:
522 CopyMem (
523 &Length32,
524 BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8),
525 sizeof (UINT32)
526 );
527
528 BlockSize += Length32;
529 break;
530
531 default:
532 break;
533 }
534
535 if (StringId > 0) {
536 if (StringId == CurrentStringId - 1) {
537 *BlockType = *BlockHdr;
538 *StringBlockAddr = BlockHdr;
539 *StringTextOffset = Offset;
540 return EFI_SUCCESS;
541 }
542
543 if (StringId < CurrentStringId - 1) {
544 return EFI_NOT_FOUND;
545 }
546 }
547 BlockHdr = StringPackage->StringBlock + BlockSize;
548
549 }
550
551 if (StringId == (EFI_STRING_ID) (-1)) {
552 return EFI_SUCCESS;
553 }
554
555 if (StringId == 0 && LastStringId != NULL) {
556 *LastStringId = CurrentStringId;
557 return EFI_SUCCESS;
558 }
559
560 return EFI_NOT_FOUND;
561 }
562
563
564 /**
565 Parse all string blocks to get a string specified by StringId.
566
567 This is a internal function.
568
569 @param Private Hii database private structure.
570 @param StringPackage Hii string package instance.
571 @param StringId The string's id, which is unique within
572 PackageList.
573 @param String Points to retrieved null-terminated string.
574 @param StringSize On entry, points to the size of the buffer pointed
575 to by String, in bytes. On return, points to the
576 length of the string, in bytes.
577 @param StringFontInfo If not NULL, allocate a buffer to record the
578 output font info. It's caller's responsibility to
579 free this buffer.
580
581 @retval EFI_SUCCESS The string text and font is retrieved
582 successfully.
583 @retval EFI_NOT_FOUND The specified text or font info can not be found
584 out.
585 @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
586 hold the string.
587
588 **/
589 EFI_STATUS
590 GetStringWorker (
591 IN HII_DATABASE_PRIVATE_DATA *Private,
592 IN HII_STRING_PACKAGE_INSTANCE *StringPackage,
593 IN EFI_STRING_ID StringId,
594 OUT EFI_STRING String,
595 IN OUT UINTN *StringSize,
596 OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
597 )
598 {
599 UINT8 *StringTextPtr;
600 UINT8 BlockType;
601 UINT8 *StringBlockAddr;
602 UINTN StringTextOffset;
603 EFI_STATUS Status;
604 UINT8 FontId;
605
606 ASSERT (StringPackage != NULL && StringSize != NULL);
607 ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
608
609 //
610 // Find the specified string block
611 //
612 Status = FindStringBlock (
613 Private,
614 StringPackage,
615 StringId,
616 &BlockType,
617 &StringBlockAddr,
618 &StringTextOffset,
619 NULL
620 );
621 if (EFI_ERROR (Status)) {
622 return Status;
623 }
624
625 //
626 // Get the string text.
627 //
628 StringTextPtr = StringBlockAddr + StringTextOffset;
629 switch (BlockType) {
630 case EFI_HII_SIBT_STRING_SCSU:
631 case EFI_HII_SIBT_STRING_SCSU_FONT:
632 case EFI_HII_SIBT_STRINGS_SCSU:
633 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
634 Status = ConvertToUnicodeText (String, (CHAR8 *) StringTextPtr, StringSize);
635 break;
636 case EFI_HII_SIBT_STRING_UCS2:
637 case EFI_HII_SIBT_STRING_UCS2_FONT:
638 case EFI_HII_SIBT_STRINGS_UCS2:
639 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
640 Status = GetUnicodeStringTextOrSize (String, StringTextPtr, StringSize);
641 break;
642 default:
643 return EFI_NOT_FOUND;
644 }
645 if (EFI_ERROR (Status)) {
646 return Status;
647 }
648
649 //
650 // Get the string font. The FontId 0 is the default font for those string blocks which
651 // do not specify a font identifier. If default font is not specified, return NULL.
652 //
653 if (StringFontInfo != NULL) {
654 switch (BlockType) {
655 case EFI_HII_SIBT_STRING_SCSU_FONT:
656 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
657 case EFI_HII_SIBT_STRING_UCS2_FONT:
658 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
659 FontId = *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK));
660 break;
661 default:
662 FontId = 0;
663 }
664 Status = GetStringFontInfo (StringPackage, FontId, StringFontInfo);
665 if (Status == EFI_NOT_FOUND) {
666 *StringFontInfo = NULL;
667 }
668 }
669
670 return EFI_SUCCESS;
671 }
672
673
674 /**
675 Parse all string blocks to set a String specified by StringId.
676
677 This is a internal function.
678
679 @param Private HII database driver private structure.
680 @param StringPackage HII string package instance.
681 @param StringId The string's id, which is unique within
682 PackageList.
683 @param String Points to the new null-terminated string.
684 @param StringFontInfo Points to the input font info.
685
686 @retval EFI_SUCCESS The string was updated successfully.
687 @retval EFI_NOT_FOUND The string specified by StringId is not in the
688 database.
689 @retval EFI_INVALID_PARAMETER The String or Language was NULL.
690 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
691 current database.
692 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
693 task.
694
695 **/
696 EFI_STATUS
697 SetStringWorker (
698 IN HII_DATABASE_PRIVATE_DATA *Private,
699 IN OUT HII_STRING_PACKAGE_INSTANCE *StringPackage,
700 IN EFI_STRING_ID StringId,
701 IN EFI_STRING String,
702 IN EFI_FONT_INFO *StringFontInfo OPTIONAL
703 )
704 {
705 UINT8 *StringTextPtr;
706 UINT8 BlockType;
707 UINT8 *StringBlockAddr;
708 UINTN StringTextOffset;
709 EFI_STATUS Status;
710 UINT8 *Block;
711 UINT8 *BlockPtr;
712 UINTN BlockSize;
713 UINTN OldBlockSize;
714 HII_FONT_INFO *LocalFont;
715 HII_GLOBAL_FONT_INFO *GlobalFont;
716 BOOLEAN Referred;
717 EFI_HII_SIBT_EXT2_BLOCK Ext2;
718 UINTN StringSize;
719 UINTN TmpSize;
720
721
722 ASSERT (Private != NULL && StringPackage != NULL && String != NULL);
723 ASSERT (Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);
724 //
725 // Find the specified string block
726 //
727 Status = FindStringBlock (
728 Private,
729 StringPackage,
730 StringId,
731 &BlockType,
732 &StringBlockAddr,
733 &StringTextOffset,
734 NULL
735 );
736 if (EFI_ERROR (Status)) {
737 return Status;
738 }
739
740 LocalFont = NULL;
741 GlobalFont = NULL;
742 Referred = FALSE;
743
744 //
745 // The input StringFontInfo should exist in current database if specified.
746 //
747 if (StringFontInfo != NULL) {
748 if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) {
749 return EFI_INVALID_PARAMETER;
750 } else {
751 Referred = ReferFontInfoLocally (
752 Private,
753 StringPackage,
754 StringPackage->FontId,
755 FALSE,
756 GlobalFont,
757 &LocalFont
758 );
759 if (!Referred) {
760 StringPackage->FontId++;
761 }
762 }
763 //
764 // Update the FontId of the specified string block to input font info.
765 //
766 switch (BlockType) {
767 case EFI_HII_SIBT_STRING_SCSU_FONT:
768 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
769 case EFI_HII_SIBT_STRING_UCS2_FONT:
770 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
771 *(StringBlockAddr + sizeof (EFI_HII_STRING_BLOCK)) = LocalFont->FontId;
772 break;
773 default:
774 //
775 // When modify the font info of these blocks, the block type should be updated
776 // to contain font info thus the whole structure should be revised.
777 // It is recommended to use tool to modify the block type not in the code.
778 //
779 return EFI_UNSUPPORTED;
780 }
781 }
782
783 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
784
785 //
786 // Set the string text and font.
787 //
788 StringTextPtr = StringBlockAddr + StringTextOffset;
789 switch (BlockType) {
790 case EFI_HII_SIBT_STRING_SCSU:
791 case EFI_HII_SIBT_STRING_SCSU_FONT:
792 case EFI_HII_SIBT_STRINGS_SCSU:
793 case EFI_HII_SIBT_STRINGS_SCSU_FONT:
794 BlockSize = OldBlockSize + StrLen (String);
795 BlockSize -= AsciiStrLen ((CHAR8 *) StringTextPtr);
796 Block = AllocateZeroPool (BlockSize);
797 if (Block == NULL) {
798 return EFI_OUT_OF_RESOURCES;
799 }
800
801 CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
802 BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
803
804 while (*String != 0) {
805 *BlockPtr++ = (CHAR8) *String++;
806 }
807 *BlockPtr++ = 0;
808
809
810 TmpSize = OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - AsciiStrSize ((CHAR8 *) StringTextPtr);
811 CopyMem (
812 BlockPtr,
813 StringTextPtr + AsciiStrSize ((CHAR8 *)StringTextPtr),
814 TmpSize
815 );
816
817 FreePool (StringPackage->StringBlock);
818 StringPackage->StringBlock = Block;
819 StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);
820 break;
821
822 case EFI_HII_SIBT_STRING_UCS2:
823 case EFI_HII_SIBT_STRING_UCS2_FONT:
824 case EFI_HII_SIBT_STRINGS_UCS2:
825 case EFI_HII_SIBT_STRINGS_UCS2_FONT:
826 //
827 // Use StrSize to store the size of the specified string, including the NULL
828 // terminator.
829 //
830 GetUnicodeStringTextOrSize (NULL, StringTextPtr, &StringSize);
831
832 BlockSize = OldBlockSize + StrSize (String) - StringSize;
833 Block = AllocateZeroPool (BlockSize);
834 if (Block == NULL) {
835 return EFI_OUT_OF_RESOURCES;
836 }
837
838 CopyMem (Block, StringPackage->StringBlock, StringTextPtr - StringPackage->StringBlock);
839 BlockPtr = Block + (StringTextPtr - StringPackage->StringBlock);
840
841 CopyMem (BlockPtr, String, StrSize (String));
842 BlockPtr += StrSize (String);
843
844 CopyMem (
845 BlockPtr,
846 StringTextPtr + StringSize,
847 OldBlockSize - (StringTextPtr - StringPackage->StringBlock) - StringSize
848 );
849
850 FreePool (StringPackage->StringBlock);
851 StringPackage->StringBlock = Block;
852 StringPackage->StringPkgHdr->Header.Length += (UINT32) (BlockSize - OldBlockSize);
853 break;
854
855 default:
856 return EFI_NOT_FOUND;
857 }
858
859 //
860 // Insert a new EFI_HII_SIBT_FONT_BLOCK to the header of string block, if incoming
861 // StringFontInfo does not exist in current string package.
862 //
863 // This new block does not impact on the value of StringId.
864 //
865 //
866 if (StringFontInfo == NULL || Referred) {
867 return EFI_SUCCESS;
868 }
869
870 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
871 BlockSize = OldBlockSize + sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16) +
872 StrSize (GlobalFont->FontInfo->FontName);
873
874 Block = AllocateZeroPool (BlockSize);
875 if (Block == NULL) {
876 return EFI_OUT_OF_RESOURCES;
877 }
878
879 BlockPtr = Block;
880 Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
881 Ext2.BlockType2 = EFI_HII_SIBT_FONT;
882 Ext2.Length = (UINT16) (BlockSize - OldBlockSize);
883 CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
884 BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
885
886 *BlockPtr = LocalFont->FontId;
887 BlockPtr += sizeof (UINT8);
888 CopyMem (BlockPtr, &GlobalFont->FontInfo->FontSize, sizeof (UINT16));
889 BlockPtr += sizeof (UINT16);
890 CopyMem (BlockPtr, &GlobalFont->FontInfo->FontStyle, sizeof (UINT32));
891 BlockPtr += sizeof (UINT32);
892 CopyMem (
893 BlockPtr,
894 GlobalFont->FontInfo->FontName,
895 StrSize (GlobalFont->FontInfo->FontName)
896 );
897 BlockPtr += StrSize (GlobalFont->FontInfo->FontName);
898
899 CopyMem (BlockPtr, StringPackage->StringBlock, OldBlockSize);
900
901 FreePool (StringPackage->StringBlock);
902 StringPackage->StringBlock = Block;
903 StringPackage->StringPkgHdr->Header.Length += Ext2.Length;
904
905 return EFI_SUCCESS;
906
907 }
908
909
910 /**
911 This function adds the string String to the group of strings owned by PackageList, with the
912 specified font information StringFontInfo and returns a new string id.
913
914 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
915 @param PackageList Handle of the package list where this string will
916 be added.
917 @param StringId On return, contains the new strings id, which is
918 unique within PackageList.
919 @param Language Points to the language for the new string.
920 @param LanguageName Points to the printable language name to associate
921 with the passed in Language field.If LanguageName
922 is not NULL and the string package header's
923 LanguageName associated with a given Language is
924 not zero, the LanguageName being passed in will
925 be ignored.
926 @param String Points to the new null-terminated string.
927 @param StringFontInfo Points to the new string's font information or
928 NULL if the string should have the default system
929 font, size and style.
930
931 @retval EFI_SUCCESS The new string was added successfully.
932 @retval EFI_NOT_FOUND The specified PackageList could not be found in
933 database.
934 @retval EFI_OUT_OF_RESOURCES Could not add the string due to lack of resources.
935 @retval EFI_INVALID_PARAMETER String is NULL or StringId is NULL or Language is
936 NULL.
937 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
938 current database.
939
940 **/
941 EFI_STATUS
942 EFIAPI
943 HiiNewString (
944 IN CONST EFI_HII_STRING_PROTOCOL *This,
945 IN EFI_HII_HANDLE PackageList,
946 OUT EFI_STRING_ID *StringId,
947 IN CONST CHAR8 *Language,
948 IN CONST CHAR16 *LanguageName, OPTIONAL
949 IN CONST EFI_STRING String,
950 IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
951 )
952 {
953 EFI_STATUS Status;
954 LIST_ENTRY *Link;
955 BOOLEAN Matched;
956 HII_DATABASE_PRIVATE_DATA *Private;
957 HII_DATABASE_RECORD *DatabaseRecord;
958 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
959 HII_STRING_PACKAGE_INSTANCE *StringPackage;
960 UINT32 HeaderSize;
961 UINT32 BlockSize;
962 UINT32 OldBlockSize;
963 UINT8 *StringBlock;
964 UINT8 *BlockPtr;
965 UINT32 Ucs2BlockSize;
966 UINT32 FontBlockSize;
967 UINT32 Ucs2FontBlockSize;
968 EFI_HII_SIBT_EXT2_BLOCK Ext2;
969 HII_FONT_INFO *LocalFont;
970 HII_GLOBAL_FONT_INFO *GlobalFont;
971
972 if (This == NULL || String == NULL || StringId == NULL || Language == NULL || PackageList == NULL) {
973 return EFI_INVALID_PARAMETER;
974 }
975
976 if (!IsHiiHandleValid (PackageList)) {
977 return EFI_NOT_FOUND;
978 }
979
980 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
981 GlobalFont = NULL;
982
983 //
984 // If StringFontInfo specify a paritcular font, it should exist in current database.
985 //
986 if (StringFontInfo != NULL) {
987 if (!IsFontInfoExisted (Private, (EFI_FONT_INFO *) StringFontInfo, NULL, NULL, &GlobalFont)) {
988 return EFI_INVALID_PARAMETER;
989 }
990 }
991
992 //
993 // Get the matching package list.
994 //
995 PackageListNode = NULL;
996 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
997 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
998 if (DatabaseRecord->Handle == PackageList) {
999 PackageListNode = DatabaseRecord->PackageList;
1000 break;
1001 }
1002 }
1003 if (PackageListNode == NULL) {
1004 return EFI_NOT_FOUND;
1005 }
1006
1007 //
1008 // Try to get the matching string package. Create a new string package when failed.
1009 //
1010 StringPackage = NULL;
1011 Matched = FALSE;
1012 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1013 Link != &PackageListNode->StringPkgHdr;
1014 Link = Link->ForwardLink
1015 ) {
1016 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1017 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
1018 Matched = TRUE;
1019 break;
1020 }
1021 }
1022
1023 if (!Matched) {
1024 //
1025 // LanguageName is required to create a new string package.
1026 //
1027 if (LanguageName == NULL) {
1028 return EFI_INVALID_PARAMETER;
1029 }
1030
1031 StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));
1032 if (StringPackage == NULL) {
1033 return EFI_OUT_OF_RESOURCES;
1034 }
1035
1036 StringPackage->Signature = HII_STRING_PACKAGE_SIGNATURE;
1037 StringPackage->FontId = 0;
1038 InitializeListHead (&StringPackage->FontInfoList);
1039
1040 //
1041 // Fill in the string package header
1042 //
1043 HeaderSize = (UINT32) (AsciiStrSize ((CHAR8 *) Language) - 1 + sizeof (EFI_HII_STRING_PACKAGE_HDR));
1044 StringPackage->StringPkgHdr = AllocateZeroPool (HeaderSize);
1045 if (StringPackage->StringPkgHdr == NULL) {
1046 FreePool (StringPackage);
1047 return EFI_OUT_OF_RESOURCES;
1048 }
1049 StringPackage->StringPkgHdr->Header.Type = EFI_HII_PACKAGE_STRINGS;
1050 StringPackage->StringPkgHdr->HdrSize = HeaderSize;
1051 StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;
1052 CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));;
1053 StringPackage->StringPkgHdr->LanguageName = 1;
1054 AsciiStrCpy (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language);
1055
1056 //
1057 // Calculate the length of the string blocks, including string block to record
1058 // printable language full name and EFI_HII_SIBT_END_BLOCK.
1059 //
1060 Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) +
1061 sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));
1062
1063 BlockSize = Ucs2BlockSize + sizeof (EFI_HII_SIBT_END_BLOCK);
1064 StringPackage->StringBlock = (UINT8 *) AllocateZeroPool (BlockSize);
1065 if (StringPackage->StringBlock == NULL) {
1066 FreePool (StringPackage->StringPkgHdr);
1067 FreePool (StringPackage);
1068 return EFI_OUT_OF_RESOURCES;
1069 }
1070
1071 //
1072 // Insert the string block of printable language full name
1073 //
1074 BlockPtr = StringPackage->StringBlock;
1075 *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
1076 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1077 CopyMem (BlockPtr, (EFI_STRING) LanguageName, StrSize ((EFI_STRING) LanguageName));
1078 BlockPtr += StrSize ((EFI_STRING) LanguageName);
1079
1080 //
1081 // Insert the end block
1082 //
1083 *BlockPtr = EFI_HII_SIBT_END;
1084
1085 //
1086 // Append this string package node to string package array in this package list.
1087 //
1088 StringPackage->StringPkgHdr->Header.Length = HeaderSize + BlockSize;
1089 PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length;
1090 InsertTailList (&PackageListNode->StringPkgHdr, &StringPackage->StringEntry);
1091
1092 }
1093
1094 //
1095 // Create a string block and corresponding font block if exists, then append them
1096 // to the end of the string package.
1097 //
1098 Status = FindStringBlock (
1099 Private,
1100 StringPackage,
1101 0,
1102 NULL,
1103 NULL,
1104 NULL,
1105 StringId
1106 );
1107 if (EFI_ERROR (Status)) {
1108 return Status;
1109 }
1110
1111 OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;
1112
1113 if (StringFontInfo == NULL) {
1114 //
1115 // Create a EFI_HII_SIBT_STRING_UCS2_BLOCK since font info is not specified.
1116 //
1117
1118 Ucs2BlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK)
1119 - sizeof (CHAR16));
1120
1121 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2BlockSize);
1122 if (StringBlock == NULL) {
1123 return EFI_OUT_OF_RESOURCES;
1124 }
1125 //
1126 // Copy original string blocks, except the EFI_HII_SIBT_END.
1127 //
1128 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1129 //
1130 // Create a EFI_HII_SIBT_STRING_UCS2 block
1131 //
1132 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1133 *BlockPtr = EFI_HII_SIBT_STRING_UCS2;
1134 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1135 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
1136 BlockPtr += StrSize ((EFI_STRING) String);
1137
1138 //
1139 // Append a EFI_HII_SIBT_END block to the end.
1140 //
1141 *BlockPtr = EFI_HII_SIBT_END;
1142 FreePool (StringPackage->StringBlock);
1143 StringPackage->StringBlock = StringBlock;
1144 StringPackage->StringPkgHdr->Header.Length += Ucs2BlockSize;
1145 PackageListNode->PackageListHdr.PackageLength += Ucs2BlockSize;
1146
1147 } else {
1148 //
1149 // StringFontInfo is specified here. If there is a EFI_HII_SIBT_FONT_BLOCK
1150 // which refers to this font info, create a EFI_HII_SIBT_STRING_UCS2_FONT block
1151 // only. Otherwise create a EFI_HII_SIBT_FONT block with a EFI_HII_SIBT_STRING
1152 // _UCS2_FONT block.
1153 //
1154 Ucs2FontBlockSize = (UINT32) (StrSize (String) + sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) -
1155 sizeof (CHAR16));
1156 if (ReferFontInfoLocally (Private, StringPackage, StringPackage->FontId, FALSE, GlobalFont, &LocalFont)) {
1157 //
1158 // Create a EFI_HII_SIBT_STRING_UCS2_FONT block only.
1159 //
1160 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + Ucs2FontBlockSize);
1161 if (StringBlock == NULL) {
1162 return EFI_OUT_OF_RESOURCES;
1163 }
1164 //
1165 // Copy original string blocks, except the EFI_HII_SIBT_END.
1166 //
1167 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1168 //
1169 // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
1170 //
1171 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1172 *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
1173 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1174 *BlockPtr = LocalFont->FontId;
1175 BlockPtr += sizeof (UINT8);
1176 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
1177 BlockPtr += StrSize ((EFI_STRING) String);
1178
1179 //
1180 // Append a EFI_HII_SIBT_END block to the end.
1181 //
1182 *BlockPtr = EFI_HII_SIBT_END;
1183 FreePool (StringPackage->StringBlock);
1184 StringPackage->StringBlock = StringBlock;
1185 StringPackage->StringPkgHdr->Header.Length += Ucs2FontBlockSize;
1186 PackageListNode->PackageListHdr.PackageLength += Ucs2FontBlockSize;
1187
1188 } else {
1189 //
1190 // EFI_HII_SIBT_FONT_BLOCK does not exist in current string package, so
1191 // create a EFI_HII_SIBT_FONT block to record the font info, then generate
1192 // a EFI_HII_SIBT_STRING_UCS2_FONT block to record the incoming string.
1193 //
1194 FontBlockSize = (UINT32) (StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName) +
1195 sizeof (EFI_HII_SIBT_FONT_BLOCK) - sizeof (CHAR16));
1196 StringBlock = (UINT8 *) AllocateZeroPool (OldBlockSize + FontBlockSize + Ucs2FontBlockSize);
1197 if (StringBlock == NULL) {
1198 return EFI_OUT_OF_RESOURCES;
1199 }
1200 //
1201 // Copy original string blocks, except the EFI_HII_SIBT_END.
1202 //
1203 CopyMem (StringBlock, StringPackage->StringBlock, OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK));
1204
1205 //
1206 // Create a EFI_HII_SIBT_FONT block firstly and then backup its info in string
1207 // package instance for future reference.
1208 //
1209 BlockPtr = StringBlock + OldBlockSize - sizeof (EFI_HII_SIBT_END_BLOCK);
1210
1211 Ext2.Header.BlockType = EFI_HII_SIBT_EXT2;
1212 Ext2.BlockType2 = EFI_HII_SIBT_FONT;
1213 Ext2.Length = (UINT16) FontBlockSize;
1214 CopyMem (BlockPtr, &Ext2, sizeof (EFI_HII_SIBT_EXT2_BLOCK));
1215 BlockPtr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);
1216
1217 *BlockPtr = LocalFont->FontId;
1218 BlockPtr += sizeof (UINT8);
1219 CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontSize, sizeof (UINT16));
1220 BlockPtr += sizeof (UINT16);
1221 CopyMem (BlockPtr, &((EFI_FONT_INFO *) StringFontInfo)->FontStyle, sizeof (EFI_HII_FONT_STYLE));
1222 BlockPtr += sizeof (EFI_HII_FONT_STYLE);
1223 CopyMem (
1224 BlockPtr,
1225 &((EFI_FONT_INFO *) StringFontInfo)->FontName,
1226 StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName)
1227 );
1228
1229 //
1230 // Create a EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK
1231 //
1232 *BlockPtr = EFI_HII_SIBT_STRING_UCS2_FONT;
1233 BlockPtr += sizeof (EFI_HII_STRING_BLOCK);
1234 *BlockPtr = LocalFont->FontId;
1235 BlockPtr += sizeof (UINT8);
1236 CopyMem (BlockPtr, (EFI_STRING) String, StrSize ((EFI_STRING) String));
1237 BlockPtr += StrSize ((EFI_STRING) String);
1238
1239 //
1240 // Append a EFI_HII_SIBT_END block to the end.
1241 //
1242 *BlockPtr = EFI_HII_SIBT_END;
1243 FreePool (StringPackage->StringBlock);
1244 StringPackage->StringBlock = StringBlock;
1245 StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;
1246 PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;
1247
1248 //
1249 // Increase the FontId to make it unique since we already add
1250 // a EFI_HII_SIBT_FONT block to this string package.
1251 //
1252 StringPackage->FontId++;
1253 }
1254 }
1255
1256 //
1257 // Trigger any registered notification function
1258 //
1259 if (!Matched) {
1260 return InvokeRegisteredFunction (
1261 Private,
1262 EFI_HII_DATABASE_NOTIFY_NEW_PACK,
1263 (VOID *) StringPackage,
1264 EFI_HII_PACKAGE_STRINGS,
1265 PackageList
1266 );
1267 }
1268
1269 return EFI_SUCCESS;
1270 }
1271
1272
1273 /**
1274 This function retrieves the string specified by StringId which is associated
1275 with the specified PackageList in the language Language and copies it into
1276 the buffer specified by String.
1277
1278 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1279 @param Language Points to the language for the retrieved string.
1280 @param PackageList The package list in the HII database to search for
1281 the specified string.
1282 @param StringId The string's id, which is unique within
1283 PackageList.
1284 @param String Points to the new null-terminated string.
1285 @param StringSize On entry, points to the size of the buffer pointed
1286 to by String, in bytes. On return, points to the
1287 length of the string, in bytes.
1288 @param StringFontInfo If not NULL, points to the string's font
1289 information. It's caller's responsibility to free
1290 this buffer.
1291
1292 @retval EFI_SUCCESS The string was returned successfully.
1293 @retval EFI_NOT_FOUND The string specified by StringId is not available.
1294 @retval EFI_NOT_FOUND The string specified by StringId is available but
1295 not in the specified language.
1296 The specified PackageList is not in the database.
1297 @retval EFI_INVALID_LANGUAGE - The string specified by StringId is available but
1298 @retval EFI_BUFFER_TOO_SMALL The buffer specified by StringSize is too small to
1299 hold the string.
1300 @retval EFI_INVALID_PARAMETER The String or Language or StringSize was NULL.
1301 @retval EFI_OUT_OF_RESOURCES There were insufficient resources to complete the
1302 request.
1303
1304 **/
1305 EFI_STATUS
1306 EFIAPI
1307 HiiGetString (
1308 IN CONST EFI_HII_STRING_PROTOCOL *This,
1309 IN CONST CHAR8 *Language,
1310 IN EFI_HII_HANDLE PackageList,
1311 IN EFI_STRING_ID StringId,
1312 OUT EFI_STRING String,
1313 IN OUT UINTN *StringSize,
1314 OUT EFI_FONT_INFO **StringFontInfo OPTIONAL
1315 )
1316 {
1317 EFI_STATUS Status;
1318 LIST_ENTRY *Link;
1319 HII_DATABASE_PRIVATE_DATA *Private;
1320 HII_DATABASE_RECORD *DatabaseRecord;
1321 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1322 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1323
1324 if (This == NULL || Language == NULL || StringId < 1 || StringSize == NULL || PackageList == NULL) {
1325 return EFI_INVALID_PARAMETER;
1326 }
1327
1328 if (String == NULL && *StringSize != 0) {
1329 return EFI_INVALID_PARAMETER;
1330 }
1331
1332 if (!IsHiiHandleValid (PackageList)) {
1333 return EFI_NOT_FOUND;
1334 }
1335
1336 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1337 PackageListNode = NULL;
1338
1339 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1340 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1341 if (DatabaseRecord->Handle == PackageList) {
1342 PackageListNode = DatabaseRecord->PackageList;
1343 break;
1344 }
1345 }
1346
1347 if (PackageListNode != NULL) {
1348 //
1349 // First search: to match the StringId in the specified language.
1350 //
1351 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1352 Link != &PackageListNode->StringPkgHdr;
1353 Link = Link->ForwardLink
1354 ) {
1355 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1356 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
1357 Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);
1358 if (Status != EFI_NOT_FOUND) {
1359 return Status;
1360 }
1361 }
1362 }
1363 //
1364 // Second search: to match the StringId in other available languages if exist.
1365 //
1366 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1367 Link != &PackageListNode->StringPkgHdr;
1368 Link = Link->ForwardLink
1369 ) {
1370 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1371 Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);
1372 if (!EFI_ERROR (Status)) {
1373 return EFI_INVALID_LANGUAGE;
1374 }
1375 }
1376 }
1377
1378 return EFI_NOT_FOUND;
1379 }
1380
1381
1382
1383 /**
1384 This function updates the string specified by StringId in the specified PackageList to the text
1385 specified by String and, optionally, the font information specified by StringFontInfo.
1386
1387 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1388 @param PackageList The package list containing the strings.
1389 @param StringId The string's id, which is unique within
1390 PackageList.
1391 @param Language Points to the language for the updated string.
1392 @param String Points to the new null-terminated string.
1393 @param StringFontInfo Points to the string's font information or NULL if
1394 the string font information is not changed.
1395
1396 @retval EFI_SUCCESS The string was updated successfully.
1397 @retval EFI_NOT_FOUND The string specified by StringId is not in the
1398 database.
1399 @retval EFI_INVALID_PARAMETER The String or Language was NULL.
1400 @retval EFI_INVALID_PARAMETER The specified StringFontInfo does not exist in
1401 current database.
1402 @retval EFI_OUT_OF_RESOURCES The system is out of resources to accomplish the
1403 task.
1404
1405 **/
1406 EFI_STATUS
1407 EFIAPI
1408 HiiSetString (
1409 IN CONST EFI_HII_STRING_PROTOCOL *This,
1410 IN EFI_HII_HANDLE PackageList,
1411 IN EFI_STRING_ID StringId,
1412 IN CONST CHAR8 *Language,
1413 IN CONST EFI_STRING String,
1414 IN CONST EFI_FONT_INFO *StringFontInfo OPTIONAL
1415 )
1416 {
1417 EFI_STATUS Status;
1418 LIST_ENTRY *Link;
1419 HII_DATABASE_PRIVATE_DATA *Private;
1420 HII_DATABASE_RECORD *DatabaseRecord;
1421 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1422 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1423 UINT32 OldPackageLen;
1424
1425 if (This == NULL || Language == NULL || StringId < 1 || String == NULL || PackageList == NULL) {
1426 return EFI_INVALID_PARAMETER;
1427 }
1428
1429 if (!IsHiiHandleValid (PackageList)) {
1430 return EFI_NOT_FOUND;
1431 }
1432
1433 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1434 PackageListNode = NULL;
1435
1436 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1437 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1438 if (DatabaseRecord->Handle == PackageList) {
1439 PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);
1440 }
1441 }
1442
1443 if (PackageListNode != NULL) {
1444 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1445 Link != &PackageListNode->StringPkgHdr;
1446 Link = Link->ForwardLink
1447 ) {
1448 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1449 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {
1450 OldPackageLen = StringPackage->StringPkgHdr->Header.Length;
1451 Status = SetStringWorker (
1452 Private,
1453 StringPackage,
1454 StringId,
1455 (EFI_STRING) String,
1456 (EFI_FONT_INFO *) StringFontInfo
1457 );
1458 if (EFI_ERROR (Status)) {
1459 return Status;
1460 }
1461 PackageListNode->PackageListHdr.PackageLength += StringPackage->StringPkgHdr->Header.Length - OldPackageLen;
1462 return EFI_SUCCESS;
1463 }
1464 }
1465 }
1466
1467 return EFI_NOT_FOUND;
1468 }
1469
1470
1471
1472 /**
1473 This function returns the list of supported languages, in the format specified
1474 in Appendix M of UEFI 2.1 spec.
1475
1476 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1477 @param PackageList The package list to examine.
1478 @param Languages Points to the buffer to hold the returned string.
1479 @param LanguagesSize On entry, points to the size of the buffer pointed
1480 to by Languages, in bytes. On return, points to
1481 the length of Languages, in bytes.
1482
1483 @retval EFI_SUCCESS The languages were returned successfully.
1484 @retval EFI_INVALID_PARAMETER The Languages or LanguagesSize was NULL.
1485 @retval EFI_BUFFER_TOO_SMALL The LanguagesSize is too small to hold the list of
1486 supported languages. LanguageSize is updated to
1487 contain the required size.
1488 @retval EFI_NOT_FOUND Could not find string package in specified
1489 packagelist.
1490
1491 **/
1492 EFI_STATUS
1493 EFIAPI
1494 HiiGetLanguages (
1495 IN CONST EFI_HII_STRING_PROTOCOL *This,
1496 IN EFI_HII_HANDLE PackageList,
1497 IN OUT CHAR8 *Languages,
1498 IN OUT UINTN *LanguagesSize
1499 )
1500 {
1501 LIST_ENTRY *Link;
1502 HII_DATABASE_PRIVATE_DATA *Private;
1503 HII_DATABASE_RECORD *DatabaseRecord;
1504 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1505 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1506 UINTN ResultSize;
1507
1508 if (This == NULL || Languages == NULL || LanguagesSize == NULL || PackageList == NULL) {
1509 return EFI_INVALID_PARAMETER;
1510 }
1511 if (!IsHiiHandleValid (PackageList)) {
1512 return EFI_NOT_FOUND;
1513 }
1514
1515 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1516
1517 PackageListNode = NULL;
1518 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1519 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1520 if (DatabaseRecord->Handle == PackageList) {
1521 PackageListNode = DatabaseRecord->PackageList;
1522 break;
1523 }
1524 }
1525 if (PackageListNode == NULL) {
1526 return EFI_NOT_FOUND;
1527 }
1528
1529 //
1530 // Search the languages in the specified packagelist.
1531 //
1532 ResultSize = 0;
1533 for (Link = PackageListNode->StringPkgHdr.ForwardLink;
1534 Link != &PackageListNode->StringPkgHdr;
1535 Link = Link->ForwardLink
1536 ) {
1537 StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1538 ResultSize += AsciiStrSize (StringPackage->StringPkgHdr->Language);
1539 if (ResultSize <= *LanguagesSize) {
1540 AsciiStrCpy (Languages, StringPackage->StringPkgHdr->Language);
1541 Languages += AsciiStrSize (StringPackage->StringPkgHdr->Language);
1542 *(Languages - 1) = L';';
1543 }
1544 }
1545 if (ResultSize == 0) {
1546 return EFI_NOT_FOUND;
1547 }
1548
1549 if (*LanguagesSize < ResultSize) {
1550 *LanguagesSize = ResultSize;
1551 return EFI_BUFFER_TOO_SMALL;
1552 }
1553
1554 *(Languages - 1) = 0;
1555 return EFI_SUCCESS;
1556 }
1557
1558
1559 /**
1560 Each string package has associated with it a single primary language and zero
1561 or more secondary languages. This routine returns the secondary languages
1562 associated with a package list.
1563
1564 @param This A pointer to the EFI_HII_STRING_PROTOCOL instance.
1565 @param PackageList The package list to examine.
1566 @param FirstLanguage Points to the primary language.
1567 @param SecondaryLanguages Points to the buffer to hold the returned list of
1568 secondary languages for the specified
1569 FirstLanguage. If there are no secondary
1570 languages, the function returns successfully, but
1571 this is set to NULL.
1572 @param SecondaryLanguagesSize On entry, points to the size of the buffer pointed
1573 to by SecondaryLanguages, in bytes. On return,
1574 points to the length of SecondaryLanguages in bytes.
1575
1576 @retval EFI_SUCCESS Secondary languages were correctly returned.
1577 @retval EFI_INVALID_PARAMETER FirstLanguage or SecondaryLanguages or
1578 SecondaryLanguagesSize was NULL.
1579 @retval EFI_BUFFER_TOO_SMALL The buffer specified by SecondaryLanguagesSize is
1580 too small to hold the returned information.
1581 SecondLanguageSize is updated to hold the size of
1582 the buffer required.
1583 @retval EFI_INVALID_LANGUAGE The language specified by FirstLanguage is not
1584 present in the specified package list.
1585 @retval EFI_NOT_FOUND The specified PackageList is not in the Database.
1586
1587 **/
1588 EFI_STATUS
1589 EFIAPI
1590 HiiGetSecondaryLanguages (
1591 IN CONST EFI_HII_STRING_PROTOCOL *This,
1592 IN EFI_HII_HANDLE PackageList,
1593 IN CONST CHAR8 *FirstLanguage,
1594 IN OUT CHAR8 *SecondaryLanguages,
1595 IN OUT UINTN *SecondaryLanguagesSize
1596 )
1597 {
1598 LIST_ENTRY *Link;
1599 LIST_ENTRY *Link1;
1600 HII_DATABASE_PRIVATE_DATA *Private;
1601 HII_DATABASE_RECORD *DatabaseRecord;
1602 HII_DATABASE_PACKAGE_LIST_INSTANCE *PackageListNode;
1603 HII_STRING_PACKAGE_INSTANCE *StringPackage;
1604 CHAR8 *Languages;
1605 UINTN ResultSize;
1606
1607 if (This == NULL || PackageList == NULL || FirstLanguage == NULL) {
1608 return EFI_INVALID_PARAMETER;
1609 }
1610 if (SecondaryLanguages == NULL || SecondaryLanguagesSize == NULL) {
1611 return EFI_INVALID_PARAMETER;
1612 }
1613 if (!IsHiiHandleValid (PackageList)) {
1614 return EFI_NOT_FOUND;
1615 }
1616
1617 Private = HII_STRING_DATABASE_PRIVATE_DATA_FROM_THIS (This);
1618
1619 PackageListNode = NULL;
1620 for (Link = Private->DatabaseList.ForwardLink; Link != &Private->DatabaseList; Link = Link->ForwardLink) {
1621 DatabaseRecord = CR (Link, HII_DATABASE_RECORD, DatabaseEntry, HII_DATABASE_RECORD_SIGNATURE);
1622 if (DatabaseRecord->Handle == PackageList) {
1623 PackageListNode = (HII_DATABASE_PACKAGE_LIST_INSTANCE *) (DatabaseRecord->PackageList);
1624 break;
1625 }
1626 }
1627 if (PackageListNode == NULL) {
1628 return EFI_NOT_FOUND;
1629 }
1630
1631 Languages = NULL;
1632 ResultSize = 0;
1633 for (Link1 = PackageListNode->StringPkgHdr.ForwardLink;
1634 Link1 != &PackageListNode->StringPkgHdr;
1635 Link1 = Link1->ForwardLink
1636 ) {
1637 StringPackage = CR (Link1, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);
1638 if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) FirstLanguage)) {
1639 Languages = StringPackage->StringPkgHdr->Language;
1640 //
1641 // Language is a series of ';' terminated strings, first one is primary
1642 // language and following with other secondary languages or NULL if no
1643 // secondary languages any more.
1644 //
1645 Languages = AsciiStrStr (Languages, ";");
1646 if (Languages == NULL) {
1647 break;
1648 }
1649 Languages++;
1650
1651 ResultSize = AsciiStrSize (Languages);
1652 if (ResultSize <= *SecondaryLanguagesSize) {
1653 AsciiStrCpy (SecondaryLanguages, Languages);
1654 } else {
1655 *SecondaryLanguagesSize = ResultSize;
1656 return EFI_BUFFER_TOO_SMALL;
1657 }
1658
1659 return EFI_SUCCESS;
1660 }
1661 }
1662
1663 return EFI_INVALID_LANGUAGE;
1664 }
1665
1666 /**
1667 Compare whether two names of languages are identical.
1668
1669 @param Language1 Name of language 1
1670 @param Language2 Name of language 2
1671
1672 @retval TRUE same
1673 @retval FALSE not same
1674
1675 **/
1676 BOOLEAN
1677 HiiCompareLanguage (
1678 IN CHAR8 *Language1,
1679 IN CHAR8 *Language2
1680 )
1681 {
1682 //
1683 // Porting Guide:
1684 // This library interface is simply obsolete.
1685 // Include the source code to user code.
1686 //
1687 UINTN Index;
1688
1689 for (Index = 0; (Language1[Index] != 0) && (Language2[Index] != 0); Index++) {
1690 if (Language1[Index] != Language2[Index]) {
1691 return FALSE;
1692 }
1693 }
1694
1695 if (((Language1[Index] == 0) && (Language2[Index] == 0)) ||
1696 ((Language1[Index] == 0) && (Language2[Index] != ';')) ||
1697 ((Language1[Index] == ';') && (Language2[Index] != 0)) ||
1698 ((Language1[Index] == ';') && (Language2[Index] != ';'))) {
1699 return TRUE;
1700 }
1701
1702 return FALSE;
1703 }