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