+/**\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