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