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