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