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