+\r
+/**\r
+ \r
+ This function adds a Unicode string to UnicodeStringTable.\r
+ If Language is a member of SupportedLanguages then\r
+ UnicodeString is added to UnicodeStringTable. New buffers are\r
+ allocated for both Language and UnicodeString. The contents\r
+ of Language and UnicodeString are copied into these new\r
+ buffers. These buffers are automatically freed when\r
+ FreeUnicodeStringTable() is called.\r
+\r
+ @param Language A pointer to the ISO 639-2 or\r
+ RFC 3066 language code for the\r
+ Unicode string to add.\r
+ \r
+ @param SupportedLanguages A pointer to the set of ISO\r
+ 639-2 or RFC 3.66 language\r
+ codes that the Unicode string\r
+ table supports. Language must\r
+ be a member of this set.\r
+ \r
+ @param UnicodeStringTable A pointer to the table of\r
+ Unicode strings.\r
+ \r
+ @param UnicodeString A pointer to the Unicode\r
+ string to add.\r
+ \r
+ @param Iso639Language Specify the language code\r
+ format supported. If true,\r
+ then the format follow ISO\r
+ 639-2. If false, then it\r
+ follows RFC3066.\r
+\r
+ @retval EFI_SUCCESS The Unicode string that\r
+ matches the language specified\r
+ by Language was found in the\r
+ table of Unicode strings\r
+ UnicodeStringTable, and it was\r
+ returned in UnicodeString.\r
+ \r
+ @retval EFI_INVALID_PARAMETER Language is NULL.\r
+ \r
+ @retval EFI_INVALID_PARAMETER UnicodeString is NULL.\r
+ \r
+ @retval EFI_INVALID_PARAMETER UnicodeString is an empty string.\r
+ \r
+ @retval EFI_UNSUPPORTED SupportedLanguages is NULL.\r
+ \r
+ @retval EFI_ALREADY_STARTED A Unicode string with language\r
+ Language is already present in\r
+ UnicodeStringTable.\r
+ \r
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory to\r
+ add another Unicode string to\r
+ UnicodeStringTable.\r
+ \r
+ @retval EFI_UNSUPPORTED The language specified by\r
+ Language is not a member of\r
+ SupportedLanguages.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+AddUnicodeString2 (\r
+ IN CONST CHAR8 *Language,\r
+ IN CONST CHAR8 *SupportedLanguages,\r
+ IN EFI_UNICODE_STRING_TABLE **UnicodeStringTable,\r
+ IN CONST CHAR16 *UnicodeString,\r
+ IN BOOLEAN Iso639Language\r
+ )\r
+{\r
+ UINTN NumberOfEntries;\r
+ EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable;\r
+ EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable;\r
+ UINTN UnicodeStringLength;\r
+ BOOLEAN Found;\r
+ UINTN Index;\r
+ CHAR8 *LanguageString;\r
+\r
+ //\r
+ // Make sure the parameter are valid\r
+ //\r
+ if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // If there are no supported languages, then a Unicode String can not be added\r
+ //\r
+ if (SupportedLanguages == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // If the Unicode String is empty, then a Unicode String can not be added\r
+ //\r
+ if (UnicodeString[0] == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Make sure Language is a member of SupportedLanguages\r
+ //\r
+ Found = FALSE;\r
+ while (*SupportedLanguages != 0) {\r
+ if (Iso639Language) {\r
+ if (CompareIso639LanguageCode (Language, SupportedLanguages)) {\r
+ Found = TRUE;\r
+ break;\r
+ }\r
+ SupportedLanguages += 3;\r
+ } else {\r
+ for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);\r
+ if (AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) {\r
+ Found = TRUE;\r
+ break;\r
+ }\r
+ SupportedLanguages += Index;\r
+ for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);\r
+ }\r
+ }\r
+\r
+ //\r
+ // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED\r
+ //\r
+ if (!Found) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Determine the size of the Unicode String Table by looking for a NULL Language entry\r
+ //\r
+ NumberOfEntries = 0;\r
+ if (*UnicodeStringTable != NULL) {\r
+ OldUnicodeStringTable = *UnicodeStringTable;\r
+ while (OldUnicodeStringTable->Language != NULL) {\r
+ LanguageString = OldUnicodeStringTable->Language;\r
+\r
+ while (*LanguageString) {\r
+ for (Index = 0; LanguageString[Index] != 0 && LanguageString[Index] != ';'; Index++);\r
+\r
+ if (AsciiStrnCmp (Language, LanguageString, Index) == 0) { \r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+ LanguageString += Index;\r
+ for (; *LanguageString != 0 && *LanguageString == ';'; LanguageString++);\r
+ }\r
+ OldUnicodeStringTable++;\r
+ NumberOfEntries++;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Allocate space for a new Unicode String Table. It must hold the current number of\r
+ // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table\r
+ // marker\r
+ //\r
+ NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE));\r
+ if (NewUnicodeStringTable == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // If the current Unicode String Table contains any entries, then copy them to the\r
+ // newly allocated Unicode String Table.\r
+ //\r
+ if (*UnicodeStringTable != NULL) {\r
+ CopyMem (\r
+ NewUnicodeStringTable,\r
+ *UnicodeStringTable,\r
+ NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE)\r
+ );\r
+ }\r
+\r
+ //\r
+ // Allocate space for a copy of the Language specifier\r
+ //\r
+ NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (AsciiStrSize(Language), Language);\r
+ if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) {\r
+ gBS->FreePool (NewUnicodeStringTable);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Compute the length of the Unicode String\r
+ //\r
+ for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++);\r
+\r
+ //\r
+ // Allocate space for a copy of the Unicode String\r
+ //\r
+ NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool (StrSize (UnicodeString), UnicodeString);\r
+ if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) {\r
+ gBS->FreePool (NewUnicodeStringTable[NumberOfEntries].Language);\r
+ gBS->FreePool (NewUnicodeStringTable);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Mark the end of the Unicode String Table\r
+ //\r
+ NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL;\r
+ NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL;\r
+\r
+ //\r
+ // Free the old Unicode String Table\r
+ //\r
+ if (*UnicodeStringTable != NULL) {\r
+ gBS->FreePool (*UnicodeStringTable);\r
+ }\r
+\r
+ //\r
+ // Point UnicodeStringTable at the newly allocated Unicode String Table\r
+ //\r
+ *UnicodeStringTable = NewUnicodeStringTable;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r