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