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