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