1 /** @file
2 
3 Copyright (c) 2009 - 2012, 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 **/
13 
14 #include "MiscSubclassDriver.h"
15 /*++
16   Check whether the language is supported for given HII handle
17 
18   @param   HiiHandle     The HII package list handle.
19   @param   Offset        The offest of current lanague in the supported languages.
20   @param   CurrentLang   The language code.
21 
22   @retval  TRUE          Supported.
23   @retval  FALSE         Not Supported.
24 
25 --*/
26 VOID
27 EFIAPI
CurrentLanguageMatch(IN EFI_HII_HANDLE HiiHandle,OUT UINT16 * Offset,OUT CHAR8 * CurrentLang)28 CurrentLanguageMatch (
29   IN  EFI_HII_HANDLE                   HiiHandle,
30   OUT UINT16                           *Offset,
31   OUT CHAR8                            *CurrentLang
32   )
33 {
34   CHAR8     *DefaultLang;
35   CHAR8     *BestLanguage;
36   CHAR8     *Languages;
37   CHAR8     *MatchLang;
38   CHAR8     *EndMatchLang;
39   UINTN     CompareLength;
40 
41   Languages = HiiGetSupportedLanguages (HiiHandle);
42   if (Languages == NULL) {
43     return;
44   }
45 
46   GetEfiGlobalVariable2 (L"PlatformLang", (VOID**)&CurrentLang, NULL);
47   DefaultLang  = (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang);
48   BestLanguage = GetBestLanguage (
49                    Languages,
50                    FALSE,
51                    (CurrentLang != NULL) ? CurrentLang : "",
52                    DefaultLang,
53                    NULL
54                    );
55   if (BestLanguage != NULL) {
56     //
57     // Find the best matching RFC 4646 language, compute the offset.
58     //
59     CompareLength = AsciiStrLen (BestLanguage);
60     for (MatchLang = Languages, (*Offset) = 0; MatchLang != '\0'; (*Offset)++) {
61       //
62       // Seek to the end of current match language.
63       //
64       for (EndMatchLang = MatchLang; *EndMatchLang != '\0' && *EndMatchLang != ';'; EndMatchLang++);
65 
66       if ((EndMatchLang == MatchLang + CompareLength) && AsciiStrnCmp(MatchLang, BestLanguage, CompareLength) == 0) {
67         //
68         // Find the current best Language in the supported languages
69         //
70         break;
71       }
72       //
73       // best language match be in the supported language.
74       //
75       ASSERT (*EndMatchLang == ';');
76       MatchLang = EndMatchLang + 1;
77     }
78     FreePool (BestLanguage);
79   }
80 
81   FreePool (Languages);
82   if (CurrentLang != NULL) {
83     FreePool (CurrentLang);
84   }
85   return ;
86 }
87 
88 
89 /**
90   Get next language from language code list (with separator ';').
91 
92   @param  LangCode       Input: point to first language in the list. On
93                          Otput: point to next language in the list, or
94                                 NULL if no more language in the list.
95   @param  Lang           The first language in the list.
96 
97 **/
98 VOID
99 EFIAPI
GetNextLanguage(IN OUT CHAR8 ** LangCode,OUT CHAR8 * Lang)100 GetNextLanguage (
101   IN OUT CHAR8      **LangCode,
102   OUT CHAR8         *Lang
103   )
104 {
105   UINTN  Index;
106   CHAR8  *StringPtr;
107 
108   ASSERT (LangCode != NULL);
109   ASSERT (*LangCode != NULL);
110   ASSERT (Lang != NULL);
111 
112   Index     = 0;
113   StringPtr = *LangCode;
114   while (StringPtr[Index] != 0 && StringPtr[Index] != ';') {
115     Index++;
116   }
117 
118   CopyMem (Lang, StringPtr, Index);
119   Lang[Index] = 0;
120 
121   if (StringPtr[Index] == ';') {
122     Index++;
123   }
124   *LangCode = StringPtr + Index;
125 }
126 
127 /**
128   This function returns the number of supported languages on HiiHandle.
129 
130   @param   HiiHandle    The HII package list handle.
131 
132   @retval  The number of supported languages.
133 
134 **/
135 UINT16
136 EFIAPI
GetSupportedLanguageNumber(IN EFI_HII_HANDLE HiiHandle)137 GetSupportedLanguageNumber (
138   IN EFI_HII_HANDLE    HiiHandle
139   )
140 {
141   CHAR8   *Lang;
142   CHAR8   *Languages;
143   CHAR8   *LanguageString;
144   UINT16  LangNumber;
145 
146   Languages = HiiGetSupportedLanguages (HiiHandle);
147   if (Languages == NULL) {
148     return 0;
149   }
150 
151   LangNumber = 0;
152   Lang = AllocatePool (AsciiStrSize (Languages));
153   if (Lang != NULL) {
154     LanguageString = Languages;
155     while (*LanguageString != 0) {
156       GetNextLanguage (&LanguageString, Lang);
157       LangNumber++;
158     }
159     FreePool (Lang);
160   }
161   FreePool (Languages);
162   return LangNumber;
163 }
164 
165 
166 /**
167   This function makes boot time changes to the contents of the
168   MiscNumberOfInstallableLanguages (Type 13).
169 
170   @param  RecordData                 Pointer to copy of RecordData from the Data Table.
171 
172   @retval EFI_SUCCESS                All parameters were valid.
173   @retval EFI_UNSUPPORTED            Unexpected RecordType value.
174   @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
175 
176 **/
MISC_SMBIOS_TABLE_FUNCTION(NumberOfInstallableLanguages)177 MISC_SMBIOS_TABLE_FUNCTION(NumberOfInstallableLanguages)
178 {
179   UINTN                                     LangStrLen;
180   CHAR8                                     CurrentLang[SMBIOS_STRING_MAX_LENGTH + 1];
181   CHAR8                                     *OptionalStrStart;
182   UINT16                                    Offset;
183   EFI_STATUS                                Status;
184   EFI_SMBIOS_HANDLE                         SmbiosHandle;
185   SMBIOS_TABLE_TYPE13                       *SmbiosRecord;
186   EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES  *ForType13InputData;
187 
188   ForType13InputData = (EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES *)RecordData;
189 
190   //
191   // First check for invalid parameters.
192   //
193   if (RecordData == NULL) {
194     return EFI_INVALID_PARAMETER;
195   }
196 
197   ForType13InputData->NumberOfInstallableLanguages = GetSupportedLanguageNumber (mHiiHandle);
198 
199   //
200   // Try to check if current langcode matches with the langcodes in installed languages
201   //
202   ZeroMem(CurrentLang, SMBIOS_STRING_MAX_LENGTH + 1);
203   CurrentLanguageMatch (mHiiHandle, &Offset, CurrentLang);
204   LangStrLen = AsciiStrLen(CurrentLang);
205 
206   //
207   // Two zeros following the last string.
208   //
209   SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE13) + LangStrLen + 1 + 1);
210   ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE13) + LangStrLen + 1 + 1);
211 
212   SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION;
213   SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE13);
214   //
215   // Make handle chosen by smbios protocol.add automatically.
216   //
217   SmbiosRecord->Hdr.Handle = 0;
218 
219   SmbiosRecord->InstallableLanguages = (UINT8)ForType13InputData->NumberOfInstallableLanguages;
220   SmbiosRecord->Flags = (UINT8)ForType13InputData->LanguageFlags.AbbreviatedLanguageFormat;
221   SmbiosRecord->CurrentLanguages = 1;
222   OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
223   AsciiStrCpy(OptionalStrStart, CurrentLang);
224   //
225   // Now we have got the full smbios record, call smbios protocol to add this record.
226   //
227   Status = AddSmbiosRecord (Smbios, &SmbiosHandle, (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord);
228 
229   FreePool(SmbiosRecord);
230   return Status;
231 }
232