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