]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Compatibility/FrameworkHiiOnUefiHiiThunk/Strings.c
Replace references to RFC 3066 with RFC 4646.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / FrameworkHiiOnUefiHiiThunk / Strings.c
index 6e966192ac2243f4671dff44a0b4bbddd315ceb2..daf652c1ab7b460293b99a13f9606d135163271c 100644 (file)
@@ -17,16 +17,160 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 typedef struct {\r
   CHAR8 *Iso639;\r
-  CHAR8 *Rfc3066;\r
-} ISO639TORFC3066MAP;\r
+  CHAR8 *Rfc4646;\r
+} ISO639TORFC4646MAP;\r
 \r
-ISO639TORFC3066MAP Iso639ToRfc3066Map [] = {\r
+ISO639TORFC4646MAP Iso639ToRfc4646Map [] = {\r
     {"eng", "en-US"},\r
     {"fra", "fr-FR"},\r
 };\r
 \r
+//\r
+// Lookup table of ISO639-2 3 character language codes to ISO 639-1 2 character language codes\r
+// Each entry is 5 CHAR8 values long.  The first 3 CHAR8 values are the ISO 639-2 code.\r
+// The last 2 CHAR8 values are the ISO 639-1 code.\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 Iso639ToRfc4646ConversionTable[] =\r
+"\\r
+aaraa\\r
+abkab\\r
+afraf\\r
+amham\\r
+araar\\r
+asmas\\r
+aymay\\r
+azeaz\\r
+bakba\\r
+belbe\\r
+benbn\\r
+bihbh\\r
+bisbi\\r
+bodbo\\r
+brebr\\r
+bulbg\\r
+catca\\r
+cescs\\r
+corkw\\r
+cosco\\r
+cymcy\\r
+danda\\r
+deude\\r
+dzodz\\r
+ellel\\r
+engen\\r
+epoeo\\r
+estet\\r
+euseu\\r
+faofo\\r
+fasfa\\r
+fijfj\\r
+finfi\\r
+frafr\\r
+fryfy\\r
+gaiga\\r
+gdhgd\\r
+glggl\\r
+grngn\\r
+gujgu\\r
+hauha\\r
+hebhe\\r
+hinhi\\r
+hrvhr\\r
+hunhu\\r
+hyehy\\r
+ikuiu\\r
+ileie\\r
+inaia\\r
+indid\\r
+ipkik\\r
+islis\\r
+itait\\r
+jawjw\\r
+jpnja\\r
+kalkl\\r
+kankn\\r
+kasks\\r
+katka\\r
+kazkk\\r
+khmkm\\r
+kinrw\\r
+kirky\\r
+korko\\r
+kurku\\r
+laolo\\r
+latla\\r
+lavlv\\r
+linln\\r
+litlt\\r
+ltzlb\\r
+malml\\r
+marmr\\r
+mkdmk\\r
+mlgmg\\r
+mltmt\\r
+molmo\\r
+monmn\\r
+mrimi\\r
+msams\\r
+myamy\\r
+nauna\\r
+nepne\\r
+nldnl\\r
+norno\\r
+ocioc\\r
+ormom\\r
+panpa\\r
+polpl\\r
+porpt\\r
+pusps\\r
+quequ\\r
+rohrm\\r
+ronro\\r
+runrn\\r
+rusru\\r
+sagsg\\r
+sansa\\r
+sinsi\\r
+slksk\\r
+slvsl\\r
+smise\\r
+smosm\\r
+snasn\\r
+sndsd\\r
+somso\\r
+sotst\\r
+spaes\\r
+sqisq\\r
+srpsr\\r
+sswss\\r
+sunsu\\r
+swasw\\r
+swesv\\r
+tamta\\r
+tattt\\r
+telte\\r
+tgktg\\r
+tgltl\\r
+thath\\r
+tsnts\\r
+tuktk\\r
+twitw\\r
+uigug\\r
+ukruk\\r
+urdur\\r
+uzbuz\\r
+vievi\\r
+volvo\\r
+wolwo\\r
+xhoxh\\r
+yidyi\\r
+zhaza\\r
+zhozh\\r
+zulzu\\r
+";\r
+\r
 CHAR8 *\r
-ConvertIso639ToRfc3066 (\r
+ConvertIso639ToRfc4646 (\r
   CHAR8 *Iso638Lang\r
   )\r
 {\r
@@ -42,15 +186,128 @@ ConvertIso639ToRfc3066 (
        }\r
   }\r
 \r
-  for (Index = 0; Index < sizeof (Iso639ToRfc3066Map) / sizeof (Iso639ToRfc3066Map[0]); Index++) {\r
-    if (AsciiStrnCmp (AsciiLanguage, Iso639ToRfc3066Map[Index].Iso639, AsciiStrSize (AsciiLanguage)) == 0) {\r
-      return Iso639ToRfc3066Map[Index].Rfc3066;\r
+  for (Index = 0; Index < sizeof (Iso639ToRfc4646Map) / sizeof (Iso639ToRfc4646Map[0]); Index++) {\r
+    if (AsciiStrnCmp (AsciiLanguage, Iso639ToRfc4646Map[Index].Iso639, AsciiStrSize (AsciiLanguage)) == 0) {\r
+      return Iso639ToRfc4646Map[Index].Rfc4646;\r
     }\r
   }\r
 \r
   return (CHAR8 *) NULL;\r
 }\r
 \r
+/**\r
+  Convert language code from RFC4646 to ISO639-2.\r
+\r
+  @param  LanguageRfc4646        RFC4646 language code.\r
+  @param  LanguageIso639         ISO639-2 language code.\r
+\r
+  @retval EFI_SUCCESS            Language code converted.\r
+  @retval EFI_NOT_FOUND          Language code not found.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ConvertRfc4646LanguageToIso639Language (\r
+  IN  CHAR8   *LanguageRfc4646,\r
+  OUT CHAR8   *LanguageIso639\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  if ((LanguageRfc4646[2] != '-') && (LanguageRfc4646[2] != 0)) {\r
+    CopyMem (LanguageIso639, LanguageRfc4646, 3);\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  for (Index = 0; Iso639ToRfc4646ConversionTable[Index] != 0; Index += 5) {\r
+    if (CompareMem (LanguageRfc4646, &Iso639ToRfc4646ConversionTable[Index + 3], 2) == 0) {\r
+      CopyMem (LanguageIso639, &Iso639ToRfc4646ConversionTable[Index], 3);\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+  Convert language code from ISO639-2 to RFC4646 and return the converted language.\r
+  Caller is responsible for freeing the allocated buffer.\r
+\r
+  LanguageIso639 contain a single ISO639-2 code such as\r
+  "eng" or "fra".\r
+\r
+  If LanguageIso639 is NULL, then ASSERT.\r
+  If LanguageRfc4646 is NULL, then ASSERT.\r
+\r
+  @param  LanguageIso639         ISO639-2 language code.\r
+\r
+  @return the allocated buffer or NULL, if the language is not found.\r
+\r
+**/\r
+CHAR8*\r
+EFIAPI\r
+ConvertIso639LanguageToRfc4646Language (\r
+  IN  CONST CHAR8   *LanguageIso639\r
+  )\r
+{\r
+  UINTN Index;\r
+  CHAR8 *Rfc4646Language;\r
+  \r
+  for (Index = 0; Iso639ToRfc4646ConversionTable[Index] != 0; Index += 5) {\r
+    if (CompareMem (LanguageIso639, &Iso639ToRfc4646ConversionTable[Index], 3) == 0) {\r
+      Rfc4646Language = AllocateZeroPool (3);\r
+      if (Rfc4646Language != NULL) {\r
+        Rfc4646Language = CopyMem (Rfc4646Language, &Iso639ToRfc4646ConversionTable[Index + 3], 2);\r
+      }\r
+      return Rfc4646Language;\r
+    }\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+/**\r
+  Get next language from language code list (with separator ';').\r
+\r
+  If LangCode is NULL, then ASSERT.\r
+  If Lang is NULL, then ASSERT.\r
+\r
+  @param  LangCode    On input: point to first language in the list. On\r
+                                 output: point to next language in the list, or\r
+                                 NULL if no more language in the list.\r
+  @param  Lang           The first language in the list.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+GetNextLanguage (\r
+  IN OUT CHAR8      **LangCode,\r
+  OUT CHAR8         *Lang\r
+  )\r
+{\r
+  UINTN  Index;\r
+  CHAR8  *StringPtr;\r
+\r
+  ASSERT (LangCode != NULL);\r
+  ASSERT (*LangCode != NULL);\r
+  ASSERT (Lang != NULL);\r
+\r
+  Index = 0;\r
+  StringPtr = *LangCode;\r
+  while (StringPtr[Index] != 0 && StringPtr[Index] != ';') {\r
+    Index++;\r
+  }\r
+\r
+  CopyMem (Lang, StringPtr, Index);\r
+  Lang[Index] = 0;\r
+\r
+  if (StringPtr[Index] == ';') {\r
+    Index++;\r
+  }\r
+  *LangCode = StringPtr + Index;\r
+}\r
+\r
 /**\r
   Test if all of the characters in a string have corresponding font characters.\r
 \r
@@ -65,7 +322,7 @@ ConvertIso639ToRfc3066 (
                          If all glyphs in the string are available, the index is the index of the terminator \r
                          of the string. \r
   @param GlyphBufferSize A pointer to a value. On output, if the function returns EFI_SUCCESS, \r
-                         it contains the amount of memory that is required to store the string¡¯s glyph equivalent.\r
+                         it contains the amount of memory that is required to store the string? glyph equivalent.\r
 \r
   @retval EFI_UNSUPPORTED  The function performs nothing and return EFI_UNSUPPORTED.\r
 **/\r
@@ -126,7 +383,7 @@ GetTagGuidByFwHiiHandle (
   Create or update the String given a new string and String ID.\r
 \r
   @param ThunkContext           The Thunk Context.\r
-  @param Rfc3066AsciiLanguage   The RFC 3066 Language code in ASCII string format.\r
+  @param Rfc4646AsciiLanguage   The RFC 4646 Language code in ASCII string format.\r
   @param NewString              The new string.\r
   @param StringId               The String ID. If StringId is 0, a new String Token\r
                                 is created. Otherwise, the String Token StringId is \r
@@ -142,79 +399,23 @@ GetTagGuidByFwHiiHandle (
 EFI_STATUS\r
 UpdateString (\r
   IN CONST HII_THUNK_CONTEXT        *ThunkContext,\r
-  IN CONST CHAR8                    *Rfc3066AsciiLanguage,\r
+  IN CONST CHAR8                    *Rfc4646AsciiLanguage,\r
   IN       CHAR16                   *NewString,\r
   IN OUT STRING_REF                 *StringId\r
   )\r
 {\r
   EFI_STRING_ID                             NewStringId;\r
-  EFI_STATUS                                Status;\r
-\r
 \r
-  NewStringId = 0;\r
-  \r
-  if (*StringId == 0) {\r
-    //\r
-    // Create a new string token.\r
-    //\r
-    if (Rfc3066AsciiLanguage == NULL) {\r
-      //\r
-      // For all languages in the package list.\r
-      //\r
-      Status = HiiLibNewString (ThunkContext->UefiHiiHandle, &NewStringId, NewString);\r
-    } else {\r
-      //\r
-      // For specified language.\r
-      //\r
-      Status = mHiiStringProtocol->NewString (\r
-                                     mHiiStringProtocol,\r
-                                     ThunkContext->UefiHiiHandle,\r
-                                     &NewStringId,\r
-                                     Rfc3066AsciiLanguage,\r
-                                     NULL,\r
-                                     NewString,\r
-                                     NULL\r
-                                     );\r
-    }\r
-  } else {\r
-    //\r
-    // Update the existing string token.\r
-    //\r
-    if (Rfc3066AsciiLanguage == NULL) {\r
-      //\r
-      // For all languages in the package list.\r
-      //\r
-      Status = HiiLibSetString (ThunkContext->UefiHiiHandle, *StringId, NewString);\r
-    } else {\r
-      //\r
-      // For specified language.\r
-      //\r
-      Status = mHiiStringProtocol->SetString (\r
-                                   mHiiStringProtocol,\r
-                                   ThunkContext->UefiHiiHandle,\r
-                                   *StringId,\r
-                                   Rfc3066AsciiLanguage,\r
-                                   NewString,\r
-                                   NULL\r
-                                   );\r
-    }\r
-  }\r
-  \r
-  if (!EFI_ERROR (Status)) {\r
-    if (*StringId == 0) {\r
-      //\r
-      // When creating new string, return the newly created String Token.\r
-      //\r
-      *StringId = NewStringId;\r
-    }\r
-  } else {\r
+  NewStringId = HiiSetString (ThunkContext->UefiHiiHandle, *StringId, NewString, Rfc4646AsciiLanguage);\r
+  *StringId = NewStringId;\r
+  if (NewStringId == 0) {\r
     //\r
     // Only EFI_INVALID_PARAMETER is defined in HII 0.92 specification.\r
     //\r
-    *StringId = 0;\r
+    return EFI_INVALID_PARAMETER;\r
+  } else {\r
+    return EFI_SUCCESS;\r
   }\r
-\r
-  return Status;\r
 }\r
 \r
 /**\r
@@ -256,19 +457,19 @@ HiiNewString (
   EFI_STRING_ID                             LastStringId;\r
   CHAR8                                     AsciiLanguage[ISO_639_2_ENTRY_SIZE + 1];\r
   CHAR16                                    LanguageCopy[ISO_639_2_ENTRY_SIZE + 1];\r
-  CHAR8                                     *Rfc3066AsciiLanguage;\r
+  CHAR8                                     *Rfc4646AsciiLanguage;\r
 \r
   LastStringId      = (EFI_STRING_ID) 0;\r
   StringId          = (EFI_STRING_ID) 0;\r
-  Rfc3066AsciiLanguage = NULL;\r
+  Rfc4646AsciiLanguage = NULL;\r
 \r
   if (Language != NULL) {\r
     ZeroMem (AsciiLanguage, sizeof (AsciiLanguage));;\r
     ZeroMem (LanguageCopy, sizeof (LanguageCopy));\r
     CopyMem (LanguageCopy, Language, ISO_639_2_ENTRY_SIZE * sizeof (CHAR16));\r
     UnicodeStrToAsciiStr (LanguageCopy, AsciiLanguage);\r
-    Rfc3066AsciiLanguage = ConvertIso639ToRfc3066 (AsciiLanguage);\r
-    ASSERT (Rfc3066AsciiLanguage != NULL);\r
+    Rfc4646AsciiLanguage = ConvertIso639ToRfc4646 (AsciiLanguage);\r
+    ASSERT (Rfc4646AsciiLanguage != NULL);\r
   }\r
 \r
   Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);\r
@@ -289,7 +490,7 @@ HiiNewString (
       if (CompareGuid (&TagGuid, &ThunkContext->TagGuid)) {\r
         if (ThunkContext->SharingStringPack) {\r
           StringId = *Reference;\r
-          Status = UpdateString (ThunkContext, Rfc3066AsciiLanguage, NewString, &StringId);\r
+          Status = UpdateString (ThunkContext, Rfc4646AsciiLanguage, NewString, &StringId);\r
           if (EFI_ERROR (Status)) {\r
             break;\r
           }\r
@@ -317,7 +518,7 @@ HiiNewString (
     }\r
   } else {\r
     StringId = *Reference;\r
-    Status = UpdateString (StringPackThunkContext, Rfc3066AsciiLanguage, NewString, &StringId);\r
+    Status = UpdateString (StringPackThunkContext, Rfc4646AsciiLanguage, NewString, &StringId);\r
   }\r
 \r
   if (!EFI_ERROR (Status)) {\r
@@ -378,7 +579,7 @@ HiiResetStrings (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-HiiGetString (\r
+HiiThunkGetString (\r
   IN     EFI_HII_PROTOCOL           *This,\r
   IN     FRAMEWORK_EFI_HII_HANDLE   Handle,\r
   IN     STRING_REF                 Token,\r
@@ -388,16 +589,19 @@ HiiGetString (
   OUT    EFI_STRING                 StringBuffer\r
   )\r
 {\r
-  CHAR8                                 *Iso639AsciiLanguage;\r
   HII_THUNK_PRIVATE_DATA                *Private;\r
-  CHAR8                                 *Rfc3066AsciiLanguage;\r
+  CHAR8                                 *Iso639AsciiLanguage;\r
+  CHAR8                                 *Rfc4646AsciiLanguage;\r
+  CHAR8                                 *SupportedLanguages;\r
+  CHAR8                                 *PlatformLanguage;\r
+  CHAR8                                 *BestLanguage;\r
   EFI_HII_HANDLE                        UefiHiiHandle;\r
   EFI_STATUS                            Status;\r
 \r
   Private = HII_THUNK_PRIVATE_DATA_FROM_THIS(This);\r
 \r
   Iso639AsciiLanguage = NULL;\r
-  Rfc3066AsciiLanguage = NULL;\r
+  Rfc4646AsciiLanguage = NULL;\r
 \r
   if (LanguageString != NULL) {\r
     Iso639AsciiLanguage = AllocateZeroPool (StrLen (LanguageString) + 1);\r
@@ -408,15 +612,15 @@ HiiGetString (
 \r
     //\r
     // Caller of Framework HII Interface uses the Language Identification String defined \r
-    // in Iso639. So map it to the Language Identifier defined in RFC3066.\r
+    // in Iso639. So map it to the Language Identifier defined in RFC4646.\r
     //\r
-    Rfc3066AsciiLanguage = ConvertIso639ToRfc3066 (Iso639AsciiLanguage);\r
+    Rfc4646AsciiLanguage = ConvertIso639ToRfc4646 (Iso639AsciiLanguage);\r
 \r
     //\r
-    // If Rfc3066AsciiLanguage is NULL, more language mapping must be added to \r
-    // Iso639ToRfc3066Map.\r
+    // If Rfc4646AsciiLanguage is NULL, more language mapping must be added to \r
+    // Iso639ToRfc4646Map.\r
     //\r
-    ASSERT (Rfc3066AsciiLanguage != NULL);\r
+    ASSERT (Rfc4646AsciiLanguage != NULL);\r
     \r
   }\r
 \r
@@ -426,12 +630,56 @@ HiiGetString (
     goto Done;\r
   }\r
 \r
-  if (Rfc3066AsciiLanguage == NULL) {\r
-    Status =  HiiLibGetString (UefiHiiHandle, Token, StringBuffer, BufferLengthTemp);\r
+  if (Rfc4646AsciiLanguage == NULL) {\r
+    //\r
+    // Get the languages that the package specified by HiiHandle supports\r
+    //\r
+    SupportedLanguages = HiiGetSupportedLanguages (UefiHiiHandle);\r
+    if (SupportedLanguages == NULL) {\r
+      goto Error2;\r
+    }\r
+\r
+    //\r
+    // Get the current platform language setting\r
+    //\r
+    PlatformLanguage = GetEfiGlobalVariable (L"PlatformLang");\r
+    if (PlatformLanguage == NULL) {\r
+      goto Error1;\r
+    }\r
+\r
+    //\r
+    // Get the best matching language from SupportedLanguages\r
+    //\r
+    BestLanguage = GetBestLanguage (\r
+                     SupportedLanguages, \r
+                     FALSE,                // RFC 4646 mode\r
+                     PlatformLanguage,     // Next highest priority\r
+                     SupportedLanguages,   // Lowest priority \r
+                     NULL\r
+                     );\r
+    if (BestLanguage == NULL) {\r
+      FreePool (PlatformLanguage);\r
+Error1:\r
+      FreePool (SupportedLanguages);\r
+Error2:\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+\r
+    Status = mHiiStringProtocol->GetString (\r
+                                 mHiiStringProtocol,\r
+                                 BestLanguage,\r
+                                 UefiHiiHandle,\r
+                                 Token,\r
+                                 StringBuffer,\r
+                                 BufferLengthTemp,\r
+                                 NULL\r
+                                 );\r
+    FreePool (BestLanguage);\r
   } else {\r
     Status = mHiiStringProtocol->GetString (\r
                                  mHiiStringProtocol,\r
-                                 Rfc3066AsciiLanguage,\r
+                                 Rfc4646AsciiLanguage,\r
                                  UefiHiiHandle,\r
                                  Token,\r
                                  StringBuffer,\r