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