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