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