1 /*++
2 
3 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13 
14   UefiIfrString.c
15 
16 Abstract:
17 
18   Common Library Routines to assist to handle String and Language.
19 
20 --*/
21 
22 #include "UefiIfrLibrary.h"
23 
24 //
25 // Lookup table of ISO639-2 3 character language codes to ISO 639-1 2 character language codes
26 // Each entry is 5 CHAR8 values long.  The first 3 CHAR8 values are the ISO 639-2 code.
27 // The last 2 CHAR8 values are the ISO 639-1 code.
28 //
29 CHAR8 Iso639ToRfc3066ConversionTable[] =
30 "\
31 aaraa\
32 abkab\
33 afraf\
34 amham\
35 araar\
36 asmas\
37 aymay\
38 azeaz\
39 bakba\
40 belbe\
41 benbn\
42 bihbh\
43 bisbi\
44 bodbo\
45 brebr\
46 bulbg\
47 catca\
48 cescs\
49 corkw\
50 cosco\
51 cymcy\
52 danda\
53 deude\
54 dzodz\
55 ellel\
56 engen\
57 epoeo\
58 estet\
59 euseu\
60 faofo\
61 fasfa\
62 fijfj\
63 finfi\
64 frafr\
65 fryfy\
66 gaiga\
67 gdhgd\
68 glggl\
69 grngn\
70 gujgu\
71 hauha\
72 hebhe\
73 hinhi\
74 hrvhr\
75 hunhu\
76 hyehy\
77 ikuiu\
78 ileie\
79 inaia\
80 indid\
81 ipkik\
82 islis\
83 itait\
84 jawjw\
85 jpnja\
86 kalkl\
87 kankn\
88 kasks\
89 katka\
90 kazkk\
91 khmkm\
92 kinrw\
93 kirky\
94 korko\
95 kurku\
96 laolo\
97 latla\
98 lavlv\
99 linln\
100 litlt\
101 ltzlb\
102 malml\
103 marmr\
104 mkdmk\
105 mlgmg\
106 mltmt\
107 molmo\
108 monmn\
109 mrimi\
110 msams\
111 myamy\
112 nauna\
113 nepne\
114 nldnl\
115 norno\
116 ocioc\
117 ormom\
118 panpa\
119 polpl\
120 porpt\
121 pusps\
122 quequ\
123 rohrm\
124 ronro\
125 runrn\
126 rusru\
127 sagsg\
128 sansa\
129 sinsi\
130 slksk\
131 slvsl\
132 smise\
133 smosm\
134 snasn\
135 sndsd\
136 somso\
137 sotst\
138 spaes\
139 sqisq\
140 srpsr\
141 sswss\
142 sunsu\
143 swasw\
144 swesv\
145 tamta\
146 tattt\
147 telte\
148 tgktg\
149 tgltl\
150 thath\
151 tsnts\
152 tuktk\
153 twitw\
154 uigug\
155 ukruk\
156 urdur\
157 uzbuz\
158 vievi\
159 volvo\
160 wolwo\
161 xhoxh\
162 yidyi\
163 zhaza\
164 zhozh\
165 zulzu\
166 ";
167 
168 EFI_STATUS
ConvertRfc3066LanguageToIso639Language(CHAR8 * LanguageRfc3066,CHAR8 * LanguageIso639)169 ConvertRfc3066LanguageToIso639Language (
170   CHAR8   *LanguageRfc3066,
171   CHAR8   *LanguageIso639
172   )
173 /*++
174 
175 Routine Description:
176   Convert language code from RFC3066 to ISO639-2.
177 
178 Arguments:
179   LanguageRfc3066 - RFC3066 language code.
180   LanguageIso639  - ISO639-2 language code.
181 
182 Returns:
183   EFI_SUCCESS   - Language code converted.
184   EFI_NOT_FOUND - Language code not found.
185 
186 --*/
187 {
188   UINTN  Index;
189 
190   if ((LanguageRfc3066[2] != '-') && (LanguageRfc3066[2] != 0)) {
191     EfiCopyMem (LanguageIso639, LanguageRfc3066, 3);
192     return EFI_SUCCESS;
193   }
194 
195   for (Index = 0; Iso639ToRfc3066ConversionTable[Index] != 0; Index += 5) {
196     if (EfiCompareMem (LanguageRfc3066, &Iso639ToRfc3066ConversionTable[Index + 3], 2) == 0) {
197       EfiCopyMem (LanguageIso639, &Iso639ToRfc3066ConversionTable[Index], 3);
198       return EFI_SUCCESS;
199     }
200   }
201 
202   return EFI_NOT_FOUND;
203 }
204 
205 CHAR8 *
Rfc3066ToIso639(CHAR8 * SupportedLanguages)206 Rfc3066ToIso639 (
207   CHAR8  *SupportedLanguages
208   )
209 /*++
210 
211 Routine Description:
212   Convert language code list from RFC3066 to ISO639-2, e.g. "en-US;fr-FR" will
213   be converted to "engfra".
214 
215 Arguments:
216   SupportedLanguages - The RFC3066 language list.
217 
218 Returns:
219   The ISO639-2 language list.
220 
221 --*/
222 {
223   CHAR8       *Languages;
224   CHAR8       *ReturnValue;
225   CHAR8       *LangCodes;
226   CHAR8       LangRfc3066[RFC_3066_ENTRY_SIZE];
227   CHAR8       LangIso639[ISO_639_2_ENTRY_SIZE];
228   EFI_STATUS  Status;
229 
230   ReturnValue = EfiLibAllocateZeroPool (EfiAsciiStrSize (SupportedLanguages));
231   if (ReturnValue == NULL) {
232     return ReturnValue;
233   }
234 
235   Languages = ReturnValue;
236   LangCodes = SupportedLanguages;
237   while (*LangCodes != 0) {
238     GetNextLanguage (&LangCodes, LangRfc3066);
239 
240     Status = ConvertRfc3066LanguageToIso639Language (LangRfc3066, LangIso639);
241     if (!EFI_ERROR (Status)) {
242       EfiCopyMem (Languages, LangIso639, 3);
243       Languages = Languages + 3;
244     }
245   }
246 
247   return ReturnValue;
248 }
249 
250 EFI_STATUS
GetCurrentLanguage(OUT CHAR8 * Lang)251 GetCurrentLanguage (
252   OUT     CHAR8               *Lang
253   )
254 /*++
255 
256 Routine Description:
257   Determine what is the current language setting
258 
259 Arguments:
260   Lang      - Pointer of system language
261 
262 Returns:
263   Status code
264 
265 --*/
266 {
267   EFI_STATUS  Status;
268   UINTN       Size;
269 
270   //
271   // Get current language setting
272   //
273   Size = RFC_3066_ENTRY_SIZE;
274   Status = gRT->GetVariable (
275                   L"PlatformLang",
276                   &gEfiGlobalVariableGuid,
277                   NULL,
278                   &Size,
279                   Lang
280                   );
281 
282   if (EFI_ERROR (Status)) {
283     EfiAsciiStrCpy (Lang, (CHAR8 *) "en-US");
284   }
285 
286   return Status;
287 }
288 
289 VOID
GetNextLanguage(IN OUT CHAR8 ** LangCode,OUT CHAR8 * Lang)290 GetNextLanguage (
291   IN OUT CHAR8      **LangCode,
292   OUT CHAR8         *Lang
293   )
294 /*++
295 
296 Routine Description:
297   Get next language from language code list (with separator ';').
298 
299 Arguments:
300   LangCode - On input: point to first language in the list. On output: point to
301              next language in the list, or NULL if no more language in the list.
302   Lang     - The first language in the list.
303 
304 Returns:
305   None.
306 
307 --*/
308 {
309   UINTN  Index;
310   CHAR8  *StringPtr;
311 
312   if (LangCode == NULL || *LangCode == NULL) {
313     *Lang = 0;
314     return;
315   }
316 
317   Index = 0;
318   StringPtr = *LangCode;
319   while (StringPtr[Index] != 0 && StringPtr[Index] != ';') {
320     Index++;
321   }
322 
323   EfiCopyMem (Lang, StringPtr, Index);
324   Lang[Index] = 0;
325 
326   if (StringPtr[Index] == ';') {
327     Index++;
328   }
329   *LangCode = StringPtr + Index;
330 }
331 
332 CHAR8 *
GetSupportedLanguages(IN EFI_HII_HANDLE HiiHandle)333 GetSupportedLanguages (
334   IN EFI_HII_HANDLE           HiiHandle
335   )
336 /*++
337 
338 Routine Description:
339   This function returns the list of supported languages, in the format specified
340   in UEFI specification Appendix M.
341 
342 Arguments:
343   HiiHandle  - The HII package list handle.
344 
345 Returns:
346   The supported languages.
347 
348 --*/
349 {
350   EFI_STATUS  Status;
351   UINTN       BufferSize;
352   CHAR8       *LanguageString;
353 
354   LocateHiiProtocols ();
355 
356   //
357   // Collect current supported Languages for given HII handle
358   //
359   BufferSize = 0x1000;
360   LanguageString = EfiLibAllocatePool (BufferSize);
361   Status = gIfrLibHiiString->GetLanguages (gIfrLibHiiString, HiiHandle, LanguageString, &BufferSize);
362   if (Status == EFI_BUFFER_TOO_SMALL) {
363     gBS->FreePool (LanguageString);
364     LanguageString = EfiLibAllocatePool (BufferSize);
365     Status = gIfrLibHiiString->GetLanguages (gIfrLibHiiString, HiiHandle, LanguageString, &BufferSize);
366   }
367 
368   if (EFI_ERROR (Status)) {
369     LanguageString = NULL;
370   }
371 
372   return LanguageString;
373 }
374 
375 UINT16
GetSupportedLanguageNumber(IN EFI_HII_HANDLE HiiHandle)376 GetSupportedLanguageNumber (
377   IN EFI_HII_HANDLE           HiiHandle
378   )
379 /*++
380 
381 Routine Description:
382   This function returns the number of supported languages
383 
384 Arguments:
385   HiiHandle  - The HII package list handle.
386 
387 Returns:
388   The  number of supported languages.
389 
390 --*/
391 {
392   CHAR8   *Languages;
393   CHAR8   *LanguageString;
394   UINT16  LangNumber;
395   CHAR8   Lang[RFC_3066_ENTRY_SIZE];
396 
397   Languages = GetSupportedLanguages (HiiHandle);
398   if (Languages == NULL) {
399     return 0;
400   }
401 
402   LangNumber = 0;
403   LanguageString = Languages;
404   while (*LanguageString != 0) {
405     GetNextLanguage (&LanguageString, Lang);
406     LangNumber++;
407   }
408   gBS->FreePool (Languages);
409 
410   return LangNumber;
411 }
412 
413 EFI_STATUS
GetStringFromHandle(IN EFI_HII_HANDLE HiiHandle,IN EFI_STRING_ID StringId,OUT EFI_STRING * String)414 GetStringFromHandle (
415   IN  EFI_HII_HANDLE                  HiiHandle,
416   IN  EFI_STRING_ID                   StringId,
417   OUT EFI_STRING                      *String
418   )
419 /*++
420 
421 Routine Description:
422   Get string specified by StringId form the HiiHandle.
423 
424 Arguments:
425   HiiHandle     - The HII handle of package list.
426   StringId      - The String ID.
427   String        - The output string.
428 
429 Returns:
430   EFI_NOT_FOUND         - String is not found.
431   EFI_SUCCESS           - Operation is successful.
432   EFI_OUT_OF_RESOURCES  - There is not enought memory in the system.
433   EFI_INVALID_PARAMETER - The String is NULL.
434 
435 --*/
436 {
437   EFI_STATUS                          Status;
438   UINTN                               StringSize;
439 
440   if (String == NULL) {
441     return EFI_INVALID_PARAMETER;
442   }
443 
444   StringSize = IFR_LIB_DEFAULT_STRING_SIZE;
445   *String    = EfiLibAllocateZeroPool (StringSize);
446   if (*String == NULL) {
447     return EFI_OUT_OF_RESOURCES;
448   }
449 
450   Status = IfrLibGetString (HiiHandle, StringId, *String, &StringSize);
451   if (Status == EFI_BUFFER_TOO_SMALL) {
452     gBS->FreePool (*String);
453     *String = EfiLibAllocateZeroPool (StringSize);
454     if (*String == NULL) {
455       return EFI_OUT_OF_RESOURCES;
456     }
457     Status = IfrLibGetString (HiiHandle, StringId, *String, &StringSize);
458   }
459 
460   return Status;
461 }
462 
463 EFI_STATUS
GetStringFromToken(IN EFI_GUID * ProducerGuid,IN EFI_STRING_ID StringId,OUT EFI_STRING * String)464 GetStringFromToken (
465   IN  EFI_GUID                        *ProducerGuid,
466   IN  EFI_STRING_ID                   StringId,
467   OUT EFI_STRING                      *String
468   )
469 /*++
470 
471 Routine Description:
472   Get the string given the StringId and String package Producer's Guid.
473 
474 Arguments:
475   ProducerGuid  - The Guid of String package list.
476   StringId      - The String ID.
477   String        - The output string.
478 
479 Returns:
480   EFI_NOT_FOUND         - String is not found.
481   EFI_SUCCESS           - Operation is successful.
482   EFI_OUT_OF_RESOURCES  - There is not enought memory in the system.
483 
484 --*/
485 {
486   EFI_STATUS      Status;
487   UINTN           Index;
488   UINTN           HandleBufferLen;
489   EFI_HII_HANDLE  *HiiHandleBuffer;
490   EFI_GUID        Guid;
491 
492   HiiHandleBuffer = NULL;
493   Status = GetHiiHandles (&HandleBufferLen, &HiiHandleBuffer);
494   if (EFI_ERROR(Status)) {
495     return Status;
496   }
497   for (Index = 0; Index < (HandleBufferLen / sizeof (EFI_HII_HANDLE)); Index++) {
498     Status = ExtractGuidFromHiiHandle (HiiHandleBuffer[Index], &Guid);
499     if (EFI_ERROR(Status)) {
500       return Status;
501     }
502     if (EfiCompareGuid (&Guid, ProducerGuid) == TRUE) {
503       break;
504     }
505   }
506 
507   if (Index >= (HandleBufferLen / sizeof (EFI_HII_HANDLE))) {
508     Status = EFI_NOT_FOUND;
509     goto Out;
510   }
511 
512   Status = GetStringFromHandle (HiiHandleBuffer[Index], StringId, String);
513 
514 Out:
515   if (HiiHandleBuffer != NULL) {
516     gBS->FreePool (HiiHandleBuffer);
517   }
518   return Status;
519 }
520 
521 EFI_STATUS
IfrLibNewString(IN EFI_HII_HANDLE PackageList,OUT EFI_STRING_ID * StringId,IN CONST EFI_STRING String)522 IfrLibNewString (
523   IN  EFI_HII_HANDLE                  PackageList,
524   OUT EFI_STRING_ID                   *StringId,
525   IN  CONST EFI_STRING                String
526   )
527 /*++
528 
529   Routine Description:
530     This function adds the string into String Package of each language.
531 
532   Arguments:
533     PackageList       - Handle of the package list where this string will be added.
534     StringId          - On return, contains the new strings id, which is unique within PackageList.
535     String            - Points to the new null-terminated string.
536 
537   Returns:
538     EFI_SUCCESS            - The new string was added successfully.
539     EFI_NOT_FOUND          - The specified PackageList could not be found in database.
540     EFI_OUT_OF_RESOURCES   - Could not add the string due to lack of resources.
541     EFI_INVALID_PARAMETER  - String is NULL or StringId is NULL is NULL.
542 
543 --*/
544 {
545   EFI_STATUS  Status;
546   CHAR8       *Languages;
547   CHAR8       *LangStrings;
548   CHAR8       Lang[RFC_3066_ENTRY_SIZE];
549 
550   Status = EFI_SUCCESS;
551 
552   LocateHiiProtocols ();
553 
554   Languages = GetSupportedLanguages (PackageList);
555   if (Languages == NULL) {
556     return EFI_NOT_FOUND;
557   }
558 
559   if (StringId == NULL) {
560     return EFI_INVALID_PARAMETER;
561   }
562   *StringId = 0;
563 
564   LangStrings = Languages;
565   while (*LangStrings != 0) {
566     GetNextLanguage (&LangStrings, Lang);
567 
568     if (*StringId == 0) {
569       Status = gIfrLibHiiString->NewString (
570                                    gIfrLibHiiString,
571                                    PackageList,
572                                    StringId,
573                                    Lang,
574                                    NULL,
575                                    String,
576                                    NULL
577                                    );
578     } else {
579       Status = gIfrLibHiiString->SetString (
580                                    gIfrLibHiiString,
581                                    PackageList,
582                                    *StringId,
583                                    Lang,
584                                    String,
585                                    NULL
586                                    );
587     }
588 
589     if (EFI_ERROR (Status)) {
590       break;
591     }
592   }
593 
594   gBS->FreePool (Languages);
595 
596   return Status;
597 }
598 
599 EFI_STATUS
IfrLibGetString(IN EFI_HII_HANDLE PackageList,IN EFI_STRING_ID StringId,OUT EFI_STRING String,IN OUT UINTN * StringSize)600 IfrLibGetString (
601   IN  EFI_HII_HANDLE                  PackageList,
602   IN  EFI_STRING_ID                   StringId,
603   OUT EFI_STRING                      String,
604   IN  OUT UINTN                       *StringSize
605   )
606 /*++
607 
608   Routine Description:
609     This function try to retrieve string from String package of current language.
610     If fail, it try to retrieve string from String package of first language it support.
611 
612   Arguments:
613     PackageList       - The package list in the HII database to search for the specified string.
614     StringId          - The string's id, which is unique within PackageList.
615     String            - Points to the new null-terminated string.
616     StringSize        - On entry, points to the size of the buffer pointed to by String, in bytes. On return,
617                         points to the length of the string, in bytes.
618 
619   Returns:
620     EFI_SUCCESS            - The string was returned successfully.
621     EFI_NOT_FOUND          - The string specified by StringId is not available.
622     EFI_BUFFER_TOO_SMALL   - The buffer specified by StringLength is too small to hold the string.
623     EFI_INVALID_PARAMETER  - The String or StringSize was NULL.
624 
625 --*/
626 {
627   EFI_STATUS  Status;
628   CHAR8       *Languages;
629   CHAR8       *LangStrings;
630   CHAR8       Lang[RFC_3066_ENTRY_SIZE];
631   CHAR8       CurrentLang[RFC_3066_ENTRY_SIZE];
632 
633   LocateHiiProtocols ();
634 
635   GetCurrentLanguage (CurrentLang);
636 
637   Status = gIfrLibHiiString->GetString (
638                                gIfrLibHiiString,
639                                CurrentLang,
640                                PackageList,
641                                StringId,
642                                String,
643                                StringSize,
644                                NULL
645                                );
646 
647   if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
648     Languages = GetSupportedLanguages (PackageList);
649     LangStrings = Languages;
650     GetNextLanguage (&LangStrings, Lang);
651     gBS->FreePool (Languages);
652 
653     Status = gIfrLibHiiString->GetString (
654                                  gIfrLibHiiString,
655                                  Lang,
656                                  PackageList,
657                                  StringId,
658                                  String,
659                                  StringSize,
660                                  NULL
661                                  );
662   }
663 
664   return Status;
665 }
666 
667 EFI_STATUS
IfrLibSetString(IN EFI_HII_HANDLE PackageList,IN EFI_STRING_ID StringId,IN CONST EFI_STRING String)668 IfrLibSetString (
669   IN EFI_HII_HANDLE                   PackageList,
670   IN EFI_STRING_ID                    StringId,
671   IN CONST EFI_STRING                 String
672   )
673 /*++
674 
675   Routine Description:
676     This function updates the string in String package of each language.
677 
678   Arguments:
679     PackageList       - The package list containing the strings.
680     StringId          - The string's id, which is unique within PackageList.
681     String            - Points to the new null-terminated string.
682 
683   Returns:
684     EFI_SUCCESS            - The string was updated successfully.
685     EFI_NOT_FOUND          - The string specified by StringId is not in the database.
686     EFI_INVALID_PARAMETER  - The String was NULL.
687     EFI_OUT_OF_RESOURCES   - The system is out of resources to accomplish the task.
688 
689 --*/
690 {
691   EFI_STATUS  Status;
692   CHAR8       *Languages;
693   CHAR8       *LangStrings;
694   CHAR8       Lang[RFC_3066_ENTRY_SIZE];
695 
696   Status = EFI_SUCCESS;
697 
698   LocateHiiProtocols ();
699 
700   Languages = GetSupportedLanguages (PackageList);
701   if (Languages == NULL) {
702     return EFI_NOT_FOUND;
703   }
704 
705   LangStrings = Languages;
706   while (*LangStrings != 0) {
707     GetNextLanguage (&LangStrings, Lang);
708 
709     Status = gIfrLibHiiString->SetString (
710                                  gIfrLibHiiString,
711                                  PackageList,
712                                  StringId,
713                                  Lang,
714                                  String,
715                                  NULL
716                                  );
717     if (EFI_ERROR (Status)) {
718       break;
719     }
720   }
721 
722   gBS->FreePool (Languages);
723 
724   return Status;
725 }
726 
727