1/*++
2
3Copyright (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
24Module Name:
25
26  MiscNumberOfInstallableLanguagesFunction.c
27
28Abstract:
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.
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**/
51VOID
52EFIAPI
53CurrentLanguageMatch (
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 ';').
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**/
123VOID
124EFIAPI
125GetNextLanguage (
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/**
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**/
160UINT16
161EFIAPI
162GetSupportedLanguageNumber (
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
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**/
202MISC_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