1 /*++
2 
3 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
4 
5 
6   This program and the accompanying materials are licensed and made available under
7 
8   the terms and conditions of the BSD License that accompanies this distribution.
9 
10   The full text of the license may be found at
11 
12   http://opensource.org/licenses/bsd-license.php.
13 
14 
15 
16   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
17 
18   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 
20 
21 
22 
23 
24 Module Name:
25 
26   MiscNumberOfInstallableLanguagesFunction.c
27 
28 Abstract:
29 
30   This driver parses the mSmbiosMiscDataTable structure and reports
31   any generated data.
32 
33 --*/
34 
35 
36 #include "CommonHeader.h"
37 
38 #include "MiscSubclassDriver.h"
39 
40 /**
41   Check whether the language is supported for given HII handle
42 
43   @param   HiiHandle     The HII package list handle.
CurrentLanguageMatch(IN EFI_HII_HANDLE HiiHandle,OUT UINT16 * Offset,OUT CHAR8 * CurrentLang)44   @param   Offset        The offest of current lanague in the supported languages.
45   @param   CurrentLang   The language code.
46 
47   @retval  TRUE          Supported.
48   @retval  FALSE         Not Supported.
49 
50 **/
51 VOID
52 EFIAPI
53 CurrentLanguageMatch (
54   IN  EFI_HII_HANDLE                   HiiHandle,
55   OUT UINT16                           *Offset,
56   OUT CHAR8                            *CurrentLang
57   )
58 {
59   CHAR8     *DefaultLang;
60   CHAR8     *BestLanguage;
61   CHAR8     *Languages;
62   CHAR8     *MatchLang;
63   CHAR8     *EndMatchLang;
64   UINTN     CompareLength;
65 
66   Languages = HiiGetSupportedLanguages (HiiHandle);
67   if (Languages == NULL) {
68     return;
69   }
70 
71   CurrentLang  = GetEfiGlobalVariable (L"PlatformLang");
72   DefaultLang  = (CHAR8 *) PcdGetPtr (PcdUefiVariableDefaultPlatformLang);
73   BestLanguage = GetBestLanguage (
74                    Languages,
75                    FALSE,
76                    (CurrentLang != NULL) ? CurrentLang : "",
77                    DefaultLang,
78                    NULL
79                    );
80   if (BestLanguage != NULL) {
81     //
82     // Find the best matching RFC 4646 language, compute the offset.
83     //
84     CompareLength = AsciiStrLen (BestLanguage);
85     for (MatchLang = Languages, (*Offset) = 0; MatchLang != '\0'; (*Offset)++) {
86       //
87       // Seek to the end of current match language.
88       //
89       for (EndMatchLang = MatchLang; *EndMatchLang != '\0' && *EndMatchLang != ';'; EndMatchLang++);
90 
91       if ((EndMatchLang == MatchLang + CompareLength) && AsciiStrnCmp(MatchLang, BestLanguage, CompareLength) == 0) {
92         //
93         // Find the current best Language in the supported languages
94         //
95         break;
96       }
97       //
98       // best language match be in the supported language.
99       //
100       ASSERT (*EndMatchLang == ';');
101       MatchLang = EndMatchLang + 1;
102     }
103     FreePool (BestLanguage);
104   }
105 
106   FreePool (Languages);
107   if (CurrentLang != NULL) {
108     FreePool (CurrentLang);
109   }
110   return ;
111 }
112 
113 
114 /**
115   Get next language from language code list (with separator ';').
GetNextLanguage(IN OUT CHAR8 ** LangCode,OUT CHAR8 * Lang)116 
117   @param  LangCode       Input: point to first language in the list. On
118                          Otput: point to next language in the list, or
119                                 NULL if no more language in the list.
120   @param  Lang           The first language in the list.
121 
122 **/
123 VOID
124 EFIAPI
125 GetNextLanguage (
126   IN OUT CHAR8      **LangCode,
127   OUT CHAR8         *Lang
128   )
129 {
130   UINTN  Index;
131   CHAR8  *StringPtr;
132 
133   ASSERT (LangCode != NULL);
134   ASSERT (*LangCode != NULL);
135   ASSERT (Lang != NULL);
136 
137   Index     = 0;
138   StringPtr = *LangCode;
139   while (StringPtr[Index] != 0 && StringPtr[Index] != ';') {
140     Index++;
141   }
142 
143   CopyMem (Lang, StringPtr, Index);
144   Lang[Index] = 0;
145 
146   if (StringPtr[Index] == ';') {
147     Index++;
148   }
149   *LangCode = StringPtr + Index;
150 }
151 
152 /**
GetSupportedLanguageNumber(IN EFI_HII_HANDLE HiiHandle)153   This function returns the number of supported languages on HiiHandle.
154 
155   @param   HiiHandle    The HII package list handle.
156 
157   @retval  The number of supported languages.
158 
159 **/
160 UINT16
161 EFIAPI
162 GetSupportedLanguageNumber (
163   IN EFI_HII_HANDLE    HiiHandle
164   )
165 {
166   CHAR8   *Lang;
167   CHAR8   *Languages;
168   CHAR8   *LanguageString;
169   UINT16  LangNumber;
170 
171   Languages = HiiGetSupportedLanguages (HiiHandle);
172   if (Languages == NULL) {
173     return 0;
174   }
175 
176   LangNumber = 0;
177   Lang = AllocatePool (AsciiStrSize (Languages));
178   if (Lang != NULL) {
179     LanguageString = Languages;
180     while (*LanguageString != 0) {
181       GetNextLanguage (&LanguageString, Lang);
182       LangNumber++;
183     }
184     FreePool (Lang);
185   }
186   FreePool (Languages);
187   return LangNumber;
188 }
189 
190 
191 /**
192   This function makes boot time changes to the contents of the
MISC_SMBIOS_TABLE_FUNCTION(NumberOfInstallableLanguages)193   MiscNumberOfInstallableLanguages (Type 13).
194 
195   @param  RecordData                 Pointer to copy of RecordData from the Data Table.
196 
197   @retval EFI_SUCCESS                All parameters were valid.
198   @retval EFI_UNSUPPORTED            Unexpected RecordType value.
199   @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
200 
201 **/
202 MISC_SMBIOS_TABLE_FUNCTION(NumberOfInstallableLanguages)
203 {
204   UINTN                                     LangStrLen;
205   CHAR8                                     CurrentLang[SMBIOS_STRING_MAX_LENGTH + 1];
206   CHAR8                                     *OptionalStrStart;
207   UINT16                                    Offset;
208   EFI_STATUS                                Status;
209   EFI_SMBIOS_HANDLE                         SmbiosHandle;
210   SMBIOS_TABLE_TYPE13                       *SmbiosRecord;
211   EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES  *ForType13InputData;
212 
213   ForType13InputData = (EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES *)RecordData;
214 
215   //
216   // First check for invalid parameters.
217   //
218   if (RecordData == NULL) {
219     return EFI_INVALID_PARAMETER;
220   }
221 
222   ForType13InputData->NumberOfInstallableLanguages = GetSupportedLanguageNumber (mHiiHandle);
223 
224   //
225   // Try to check if current langcode matches with the langcodes in installed languages
226   //
227   ZeroMem(CurrentLang, SMBIOS_STRING_MAX_LENGTH + 1);
228   CurrentLanguageMatch (mHiiHandle, &Offset, CurrentLang);
229   LangStrLen = AsciiStrLen(CurrentLang);
230 
231   //
232   // Two zeros following the last string.
233   //
234   SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE13) + LangStrLen + 1 + 1);
235   ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE13) + LangStrLen + 1 + 1);
236 
237   SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_BIOS_LANGUAGE_INFORMATION;
238   SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE13);
239 
240   //
241   // Make handle chosen by smbios protocol.add automatically.
242   //
243   SmbiosRecord->Hdr.Handle = 0;
244 
245   SmbiosRecord->InstallableLanguages = (UINT8)ForType13InputData->NumberOfInstallableLanguages;
246   SmbiosRecord->Flags = (UINT8)ForType13InputData->LanguageFlags.AbbreviatedLanguageFormat;
247   SmbiosRecord->CurrentLanguages = 1;
248   OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
249   AsciiStrCpy(OptionalStrStart, CurrentLang);
250 
251   //
252   // Now we have got the full smbios record, call smbios protocol to add this record.
253   //
254   SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
255   Status = Smbios-> Add(
256                       Smbios,
257                       NULL,
258                       &SmbiosHandle,
259                       (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
260                       );
261   FreePool(SmbiosRecord);
262   return Status;
263 }
264