Fix ICC build break by do data conversion.
[efi/edk2/.git] / edk2 / MdeModulePkg / Universal / HiiDatabaseDxe / String.c
1 /** @file\r
2 Implementation for EFI_HII_STRING_PROTOCOL.\r
3 \r
4 \r
5 Copyright (c) 2007 - 2010, Intel Corporation\r
6 All rights reserved. This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution.  The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10 \r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 \r
14 **/\r
15 \r
16 \r
17 #include "HiiDatabase.h"\r
18 \r
19 CHAR16 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
32   This is a internal function.\r
33 \r
34 \r
35   @param  Private                Hii database private structure.\r
36   @param  StringPackage          HII string package instance.\r
37   @param  FontId                Font identifer, which must be unique within the string package.\r
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
50 BOOLEAN\r
51 ReferFontInfoLocally (\r
52   IN  HII_DATABASE_PRIVATE_DATA   *Private,\r
53   IN  HII_STRING_PACKAGE_INSTANCE *StringPackage,\r
54   IN  UINT8                       FontId,\r
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
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
88   LocalFont->FontId      = FontId;\r
89   LocalFont->GlobalEntry = &GlobalFontInfo->Entry;\r
90   InsertTailList (&StringPackage->FontInfoList, &LocalFont->Entry);\r
91 \r
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
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
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
114 EFI_STATUS\r
115 ConvertToUnicodeText (\r
116   OUT EFI_STRING       StringDest,\r
117   IN  CHAR8            *StringSrc,\r
118   IN  OUT UINTN        *BufferSize\r
119   )\r
120 {\r
121   UINTN  StringSize;\r
122   UINTN  Index;\r
123 \r
124   ASSERT (StringSrc != NULL && BufferSize != NULL);\r
125 \r
126   StringSize = AsciiStrSize (StringSrc) * 2;\r
127   if (*BufferSize < StringSize || StringDest == NULL) {\r
128     *BufferSize = StringSize;\r
129     return EFI_BUFFER_TOO_SMALL;\r
130   }\r
131 \r
132   for (Index = 0; Index < AsciiStrLen (StringSrc); Index++) {\r
133     StringDest[Index] = (CHAR16) StringSrc[Index];\r
134   }\r
135 \r
136   StringDest[Index] = 0;\r
137   return EFI_SUCCESS;\r
138 }\r
139 \r
140 \r
141 /**\r
142   Calculate the size of StringSrc and output it. If StringDest is not NULL,\r
143   copy string text from src to dest.\r
144 \r
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
149   @param  StringSrc              Points to current null-terminated string.\r
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
158 EFI_STATUS\r
159 GetUnicodeStringTextOrSize (\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
166   UINT8  *StringPtr;\r
167 \r
168   ASSERT (StringSrc != NULL && BufferSize != NULL);\r
169 \r
170   StringSize = sizeof (CHAR16);\r
171   StringPtr  = StringSrc;\r
172   while (ReadUnaligned16 ((UINT16 *) StringPtr) != 0) {\r
173     StringSize += sizeof (CHAR16);\r
174     StringPtr += sizeof (CHAR16);\r
175   }\r
176 \r
177   if (*BufferSize < StringSize) {\r
178     *BufferSize = StringSize;\r
179     return EFI_BUFFER_TOO_SMALL;\r
180   }\r
181   if (StringDest != NULL) {\r
182     CopyMem (StringDest, StringSrc, StringSize);\r
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
193   This is a internal function.\r
194 \r
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
205 EFI_STATUS\r
206 GetStringFontInfo (\r
207   IN  HII_STRING_PACKAGE_INSTANCE     *StringPackage,\r
208   IN  UINT8                           FontId,\r
209   OUT EFI_FONT_INFO                   **StringFontInfo\r
210   )\r
211 {\r
212   LIST_ENTRY                           *Link;\r
213   HII_FONT_INFO                        *FontInfo;\r
214   HII_GLOBAL_FONT_INFO                 *GlobalFont;\r
215 \r
216   ASSERT (StringFontInfo != NULL && StringPackage != NULL);\r
217 \r
218   for (Link = StringPackage->FontInfoList.ForwardLink; Link != &StringPackage->FontInfoList; Link = Link->ForwardLink) {\r
219     FontInfo = CR (Link, HII_FONT_INFO, Entry, HII_FONT_INFO_SIGNATURE);\r
220     if (FontInfo->FontId == FontId) {\r
221       GlobalFont = CR (FontInfo->GlobalEntry, HII_GLOBAL_FONT_INFO, Entry, HII_GLOBAL_FONT_INFO_SIGNATURE);\r
222       *StringFontInfo = (EFI_FONT_INFO *) AllocateZeroPool (GlobalFont->FontInfoSize);\r
223       if (*StringFontInfo == NULL) {\r
224         return EFI_OUT_OF_RESOURCES;\r
225       }\r
226       CopyMem (*StringFontInfo, GlobalFont->FontInfo, GlobalFont->FontInfoSize);\r
227       return EFI_SUCCESS;\r
228     }\r
229   }\r
230 \r
231   return EFI_NOT_FOUND;\r
232 }\r
233 \r
234 \r
235 /**\r
236   Parse all string blocks to find a String block specified by StringId.\r
237   If StringId = (EFI_STRING_ID) (-1), find out all EFI_HII_SIBT_FONT blocks\r
238   within this string package and backup its information. 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
258 \r
259 **/\r
260 EFI_STATUS\r
261 FindStringBlock (\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
287   UINT8                                FontId;\r
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
299     if (StringId > StringPackage->MaxStringId) {\r
300       return EFI_NOT_FOUND;\r
301     }\r
302   } else {\r
303     ASSERT (Private != NULL && Private->Signature == HII_DATABASE_PRIVATE_DATA_SIGNATURE);\r
304     if (StringId == 0 && LastStringId != NULL) {\r
305       *LastStringId = StringPackage->MaxStringId;\r
306       return EFI_SUCCESS;\r
307     }\r
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
489         BlockHdr += sizeof (EFI_HII_SIBT_EXT2_BLOCK);\r
490         CopyMem (&FontId, BlockHdr, sizeof (UINT8));\r
491         BlockHdr += sizeof (UINT8);\r
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
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
511         if (IsFontInfoExisted (Private, FontInfo, NULL, NULL, &GlobalFont)) {\r
512           ReferFontInfoLocally (Private, StringPackage, FontId, TRUE, GlobalFont, &LocalFont);\r
513         }\r
514 \r
515         //\r
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
522         FreePool (FontInfo);\r
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
558   \r
559   //\r
560   // Get last string ID\r
561   //\r
562   if (StringId == (EFI_STRING_ID) (-1)) {\r
563     *LastStringId = (EFI_STRING_ID) (CurrentStringId - 1);\r
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
574   This is a internal function.\r
575 \r
576   @param  Private                Hii database private structure.\r
577   @param  StringPackage          Hii string package instance.\r
578   @param  StringId               The string's id, which is unique within\r
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
596 EFI_STATUS\r
597 GetStringWorker (\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
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
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
667       break;\r
668     default:\r
669       FontId = 0;\r
670     }\r
671     Status = GetStringFontInfo (StringPackage, FontId, StringFontInfo);\r
672     if (Status == EFI_NOT_FOUND) {\r
673         *StringFontInfo = NULL;\r
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
684   This is a internal function.\r
685 \r
686   @param  Private                HII database driver private structure.\r
687   @param  StringPackage          HII string package instance.\r
688   @param  StringId               The string's id, which is unique within\r
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
703 EFI_STATUS\r
704 SetStringWorker (\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
752   // The input StringFontInfo should exist in current database if specified.\r
753   //\r
754   if (StringFontInfo != NULL) {\r
755     if (!IsFontInfoExisted (Private, StringFontInfo, NULL, NULL, &GlobalFont)) {\r
756       return EFI_INVALID_PARAMETER;\r
757     } else {\r
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
769     }\r
770     //\r
771     // Update the FontId of the specified string block to input font info.\r
772     //\r
773     switch (BlockType) {\r
774     case EFI_HII_SIBT_STRING_SCSU_FONT:  \r
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
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
787     }\r
788   }\r
789 \r
790   OldBlockSize = StringPackage->StringPkgHdr->Header.Length - StringPackage->StringPkgHdr->HdrSize;\r
791 \r
792   //\r
793   // Set the string text and font.\r
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
824     FreePool (StringPackage->StringBlock);\r
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
857     FreePool (StringPackage->StringBlock);\r
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
908   FreePool (StringPackage->StringBlock);\r
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
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
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
937   @param  StringFontInfo         Points to the new string's font information or\r
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
951 EFI_STATUS\r
952 EFIAPI\r
953 HiiNewString (\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
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
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
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
1022   Status = EFI_SUCCESS;\r
1023   NewStringPackageCreated = FALSE;\r
1024   NewStringId   = 0;\r
1025   NextStringId  = 0;\r
1026   StringPackage = NULL;\r
1027   MatchStringPackage = NULL;\r
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
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
1061     if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
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
1094     }\r
1095   }\r
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
1106     *StringId = (EFI_STRING_ID) (NewStringId + 1);\r
1107   }\r
1108 \r
1109   if (MatchStringPackage != NULL) {\r
1110     StringPackage = MatchStringPackage;\r
1111   } else {\r
1112     //\r
1113     // LanguageName is required to create a new string package.\r
1114     //\r
1115     if (LanguageName == NULL) {\r
1116       Status = EFI_INVALID_PARAMETER;\r
1117       goto Done;\r
1118     }\r
1119 \r
1120     StringPackage = AllocateZeroPool (sizeof (HII_STRING_PACKAGE_INSTANCE));\r
1121     if (StringPackage == NULL) {\r
1122       Status = EFI_OUT_OF_RESOURCES;\r
1123       goto Done;\r
1124     }\r
1125 \r
1126     StringPackage->Signature   = HII_STRING_PACKAGE_SIGNATURE;\r
1127     StringPackage->MaxStringId = *StringId;\r
1128     StringPackage->FontId      = 0;\r
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
1137       FreePool (StringPackage);\r
1138       Status = EFI_OUT_OF_RESOURCES;\r
1139       goto Done;\r
1140     }\r
1141     StringPackage->StringPkgHdr->Header.Type      = EFI_HII_PACKAGE_STRINGS;\r
1142     StringPackage->StringPkgHdr->HdrSize          = HeaderSize;\r
1143     StringPackage->StringPkgHdr->StringInfoOffset = HeaderSize;\r
1144     CopyMem (StringPackage->StringPkgHdr->LanguageWindow, mLanguageWindow, 16 * sizeof (CHAR16));\r
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
1152     Ucs2BlockSize = (UINT32) (StrSize ((CHAR16 *) LanguageName) + \r
1153                               (*StringId - 1) * sizeof (EFI_HII_SIBT_STRING_UCS2_BLOCK) - sizeof (CHAR16));\r
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
1158       FreePool (StringPackage->StringPkgHdr);\r
1159       FreePool (StringPackage);\r
1160       Status = EFI_OUT_OF_RESOURCES;\r
1161       goto Done;\r
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
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
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
1187     NewStringPackageCreated = TRUE;\r
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
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
1201       Status = EFI_OUT_OF_RESOURCES;\r
1202       goto Done;\r
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
1221     FreePool (StringPackage->StringBlock);\r
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
1235     if (ReferFontInfoLocally (Private, StringPackage, StringPackage->FontId, FALSE, GlobalFont, &LocalFont)) {\r
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
1241         Status = EFI_OUT_OF_RESOURCES;\r
1242         goto Done;\r
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
1263       FreePool (StringPackage->StringBlock);\r
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
1278         Status = EFI_OUT_OF_RESOURCES;\r
1279         goto Done;\r
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
1309       BlockPtr += StrSize (((EFI_FONT_INFO *) StringFontInfo)->FontName);\r
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
1324       FreePool (StringPackage->StringBlock);\r
1325       StringPackage->StringBlock = StringBlock;\r
1326       StringPackage->StringPkgHdr->Header.Length += FontBlockSize + Ucs2FontBlockSize;\r
1327       PackageListNode->PackageListHdr.PackageLength += FontBlockSize + Ucs2FontBlockSize;\r
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
1334     }\r
1335   }\r
1336 \r
1337 Done:\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
1349   }\r
1350 \r
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
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
1391   @param  StringFontInfo         If not NULL, points to the string's font\r
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
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
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
1408 EFI_STATUS\r
1409 EFIAPI\r
1410 HiiGetString (\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
1451     //\r
1452     // First search: to match the StringId in the specified language.\r
1453     //\r
1454     for (Link =  PackageListNode->StringPkgHdr.ForwardLink;\r
1455          Link != &PackageListNode->StringPkgHdr;\r
1456          Link =  Link->ForwardLink\r
1457         ) {\r
1458         StringPackage = CR (Link, HII_STRING_PACKAGE_INSTANCE, StringEntry, HII_STRING_PACKAGE_SIGNATURE);\r
1459         if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
1460           Status = GetStringWorker (Private, StringPackage, StringId, String, StringSize, StringFontInfo);\r
1461           if (Status != EFI_NOT_FOUND) {\r
1462             return Status;\r
1463           }\r
1464         }\r
1465       }\r
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
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
1492   @param  StringId               The string's id, which is unique within\r
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
1496   @param  StringFontInfo         Points to the string's font information or NULL if\r
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
1509 EFI_STATUS\r
1510 EFIAPI\r
1511 HiiSetString (\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
1552       if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) Language)) {\r
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
1595 EFI_STATUS\r
1596 EFIAPI\r
1597 HiiGetLanguages (\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
1642     if (ResultSize <= *LanguagesSize) {\r
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
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
1678 \r
1679   @retval EFI_SUCCESS            Secondary languages were correctly returned.\r
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
1683                                  too small to hold the returned information.\r
1684                                  SecondLanguageSize is updated to hold the size of\r
1685                                  the buffer required.\r
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
1689 \r
1690 **/\r
1691 EFI_STATUS\r
1692 EFIAPI\r
1693 HiiGetSecondaryLanguages (\r
1694   IN CONST EFI_HII_STRING_PROTOCOL   *This,\r
1695   IN EFI_HII_HANDLE                  PackageList,\r
1696   IN CONST CHAR8                     *FirstLanguage,\r
1697   IN OUT CHAR8                       *SecondaryLanguages,\r
1698   IN OUT UINTN                       *SecondaryLanguagesSize\r
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
1713   if (SecondaryLanguages == NULL || SecondaryLanguagesSize == NULL) {\r
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
1721 \r
1722   PackageListNode = NULL;     \r
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
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
1741     if (HiiCompareLanguage (StringPackage->StringPkgHdr->Language, (CHAR8 *) FirstLanguage)) {\r
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
1753 \r
1754       ResultSize = AsciiStrSize (Languages);\r
1755       if (ResultSize <= *SecondaryLanguagesSize) {\r
1756         AsciiStrCpy (SecondaryLanguages, Languages);\r
1757       } else {\r
1758         *SecondaryLanguagesSize = ResultSize;\r
1759         return EFI_BUFFER_TOO_SMALL;\r
1760       }\r
1761 \r
1762       return EFI_SUCCESS;\r
1763     }\r
1764   }\r
1765 \r
1766   return EFI_INVALID_LANGUAGE;\r
1767 }\r
1768 \r
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
1779 BOOLEAN\r
1780 HiiCompareLanguage (\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