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  MiscBiosVendorFunction.c
27
28Abstract:
29
30  BIOS vendor information boot time changes.
31  Misc. subclass type 2.
32  SMBIOS type 0.
33
34--*/
35
36
37#include "CommonHeader.h"
38
39#include "MiscSubclassDriver.h"
40#include <Library/BiosIdLib.h>
41#include <Library/SpiFlash.H>
42
43EFI_SPI_PROTOCOL  *mSpiProtocol = NULL;
44
45
46/**
47  This function read the data from Spi Rom.
48
49  @param BaseAddress                The starting address of the read.
50  @param Byte                       The pointer to the destination buffer.
51  @param Length                     The number of bytes.
52  @param SpiRegionType              Spi Region Type.
53
54  @retval Status
55
56**/
57EFI_STATUS
58FlashRead (
59  IN  UINTN             BaseAddress,
60  IN  UINT8             *Byte,
61  IN  UINTN             Length,
62  IN  SPI_REGION_TYPE   SpiRegionType
63  )
64{
65  EFI_STATUS            Status = EFI_SUCCESS;
66  UINT32                SectorSize;
67  UINT32                SpiAddress;
68  UINT8                 Buffer[SECTOR_SIZE_4KB];
69
70  SpiAddress = (UINT32)(UINTN)(BaseAddress);
71  SectorSize = SECTOR_SIZE_4KB;
72
73  Status = mSpiProtocol->Execute (
74                           mSpiProtocol,
75                           SPI_READ,
76                           SPI_WREN,
77                           TRUE,
78                           TRUE,
79                           FALSE,
80                           (UINT32) SpiAddress,
81                           SectorSize,
82                           Buffer,
83                           SpiRegionType
84                           );
85
86  if (EFI_ERROR (Status)) {
87#ifdef _SHOW_LOG_
88    Print(L"Read SPI ROM Failed [%08x]\n", SpiAddress);
89#endif
90    return Status;
91  }
92
93  CopyMem (Byte, (void *)Buffer, Length);
94
95  return Status;
96}
97
98/**
99  This function returns the value & exponent to Base2 for a given
100  Hex value. This is used to calculate the BiosPhysicalDeviceSize.
101
102  @param Value                      The hex value which is to be converted into value-exponent form
103  @param Exponent                   The exponent out of the conversion
104
105  @retval EFI_SUCCESS               All parameters were valid and *Value & *Exponent have been set.
106  @retval EFI_INVALID_PARAMETER     Invalid parameter was found.
107
108**/
109EFI_STATUS
110GetValueExponentBase2(
111  IN OUT UINTN        *Value,
112  OUT    UINTN        *Exponent
113  )
114{
115  if ((Value == NULL) || (Exponent == NULL)) {
116    return EFI_INVALID_PARAMETER;
117  }
118
119  while ((*Value % 2) == 0) {
120    *Value=*Value/2;
121    (*Exponent)++;
122  }
123
124  return EFI_SUCCESS;
125}
126
127/**
128  Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a byte, with '64k'
129  as the unit.
130
131  @param  Base2Data              Pointer to Base2_Data
132
133  @retval EFI_SUCCESS            Transform successfully.
134  @retval EFI_INVALID_PARAMETER  Invalid parameter was found.
135
136**/
137UINT16
138Base2ToByteWith64KUnit (
139  IN      EFI_EXP_BASE2_DATA  *Base2Data
140  )
141{
142  UINT16              Value;
143  UINT16              Exponent;
144
145  Value     = Base2Data->Value;
146  Exponent  = Base2Data->Exponent;
147  Exponent -= 16;
148  Value <<= Exponent;
149
150  return Value;
151}
152
153
154/**
155  This function makes boot time changes to the contents of the
156  MiscBiosVendor (Type 0).
157
158  @param  RecordData                 Pointer to copy of RecordData from the Data Table.
159
160  @retval EFI_SUCCESS                All parameters were valid.
161  @retval EFI_UNSUPPORTED            Unexpected RecordType value.
162  @retval EFI_INVALID_PARAMETER      Invalid parameter was found.
163
164**/
165MISC_SMBIOS_TABLE_FUNCTION(MiscBiosVendor)
166{
167  CHAR8                 *OptionalStrStart;
168  UINTN                 VendorStrLen;
169  UINTN                 VerStrLen;
170  UINTN                 DateStrLen;
171  CHAR16                *Version;
172  CHAR16                *ReleaseDate;
173  CHAR16                BiosVersion[100];         //Assuming that strings are < 100 UCHAR
174  CHAR16                BiosReleaseDate[100];     //Assuming that strings are < 100 UCHAR
175  CHAR16                BiosReleaseTime[100];     //Assuming that strings are < 100 UCHAR
176  EFI_STATUS            Status;
177  EFI_STRING            Char16String;
178  STRING_REF            TokenToGet;
179  STRING_REF            TokenToUpdate;
180  SMBIOS_TABLE_TYPE0    *SmbiosRecord;
181  EFI_SMBIOS_HANDLE     SmbiosHandle;
182  EFI_MISC_BIOS_VENDOR *ForType0InputData;
183  BIOS_ID_IMAGE         BiosIdImage;
184  UINT16                UVerStr[32];
185  UINTN                 LoopIndex;
186  UINTN                 CopyIndex;
187  MANIFEST_OEM_DATA     *IFWIVerStruct;
188  UINT8                 *Data8 = NULL;
189  UINT16                SpaceVer[2]={0x0020,0x0000};
190  UINT16                BIOSVersionTemp[100];
191
192  ForType0InputData        = (EFI_MISC_BIOS_VENDOR *)RecordData;
193
194  //
195  // First check for invalid parameters.
196  //
197  if (RecordData == NULL) {
198    return EFI_INVALID_PARAMETER;
199  }
200  GetBiosId (&BiosIdImage);
201
202  //
203  //  Add VLV2 BIOS Version and Release data
204  //
205  SetMem(BiosVersion, sizeof(BiosVersion), 0);
206  SetMem(BiosReleaseDate, sizeof(BiosReleaseDate), 0);
207  SetMem(BiosReleaseTime, sizeof(BiosReleaseTime), 0);
208  Status = GetBiosVersionDateTime (BiosVersion, BiosReleaseDate, BiosReleaseTime);
209  DEBUG ((EFI_D_ERROR, "GetBiosVersionDateTime :%s %s %s \n", BiosVersion, BiosReleaseDate, BiosReleaseTime));
210  if (StrLen (BiosVersion) > 0) {
211    TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION);
212    HiiSetString (mHiiHandle, TokenToUpdate, BiosVersion, NULL);
213  }
214
215  if (StrLen(BiosReleaseDate) > 0) {
216    TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);
217    HiiSetString (mHiiHandle, TokenToUpdate, BiosReleaseDate, NULL);
218  }
219
220  TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VENDOR);
221  Char16String = SmbiosMiscGetString (TokenToGet);
222  VendorStrLen = StrLen(Char16String);
223  if (VendorStrLen > SMBIOS_STRING_MAX_LENGTH) {
224    return EFI_UNSUPPORTED;
225  }
226
227  TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VERSION);
228  Version = SmbiosMiscGetString (TokenToGet);
229
230  ZeroMem (UVerStr, 2*32);
231  ZeroMem (BIOSVersionTemp, 2*100);
232  StrCat (BIOSVersionTemp,Version);
233  Data8 = AllocatePool (SECTOR_SIZE_4KB);
234  ZeroMem (Data8, SECTOR_SIZE_4KB);
235
236  Status = gBS->LocateProtocol (
237                  &gEfiSpiProtocolGuid,
238                  NULL,
239                 (VOID **)&mSpiProtocol
240                 );
241  if (!EFI_ERROR(Status)) {
242    //
243    // Get data form SPI ROM.
244    //
245    Status = FlashRead (
246               MEM_IFWIVER_START,
247               Data8,
248               SECTOR_SIZE_4KB,
249               EnumSpiRegionAll
250               );
251    if (!EFI_ERROR(Status)) {
252      for(LoopIndex = 0; LoopIndex <= SECTOR_SIZE_4KB; LoopIndex++) {
253        IFWIVerStruct = (MANIFEST_OEM_DATA *)(Data8 + LoopIndex);
254        if(IFWIVerStruct->Signature == SIGNATURE_32('$','F','U','D')) {
255          DEBUG ((EFI_D_ERROR, "the IFWI Length is:%d\n", IFWIVerStruct->IFWIVersionLen));
256          if(IFWIVerStruct->IFWIVersionLen < 32) {
257            for(CopyIndex = 0; CopyIndex < IFWIVerStruct->IFWIVersionLen; CopyIndex++) {
258              UVerStr[CopyIndex] = (UINT16)IFWIVerStruct->IFWIVersion[CopyIndex];
259            }
260            UVerStr[CopyIndex] = 0x0000;
261            DEBUG ((EFI_D_ERROR, "The IFWI Version is :%s,the IFWI Length is:%d\n", UVerStr,IFWIVerStruct->IFWIVersionLen));
262            StrCat(BIOSVersionTemp,SpaceVer);
263            StrCat(BIOSVersionTemp,UVerStr);
264            DEBUG ((EFI_D_ERROR, "The BIOS and IFWI Version is :%s\n", BIOSVersionTemp));
265          }
266          break;
267        }
268      }
269    }
270  }
271  FreePool(Data8);
272
273  VerStrLen = StrLen(BIOSVersionTemp);
274  if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) {
275    return EFI_UNSUPPORTED;
276  }
277
278  TokenToGet = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);
279  ReleaseDate = SmbiosMiscGetString (TokenToGet);
280  DateStrLen = StrLen(ReleaseDate);
281  if (DateStrLen > SMBIOS_STRING_MAX_LENGTH) {
282    return EFI_UNSUPPORTED;
283  }
284
285  //
286  // Two zeros following the last string.
287  //
288  SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE0) + VendorStrLen + 1 + VerStrLen + 1 + DateStrLen + 1 + 1);
289  ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE0) + VendorStrLen + 1 + VerStrLen + 1 + DateStrLen + 1 + 1);
290
291  SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_BIOS_INFORMATION;
292  SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE0);
293
294  //
295  // Make handle chosen by smbios protocol.add automatically.
296  //
297  SmbiosRecord->Hdr.Handle = 0;
298
299  //
300  // Vendor will be the 1st optional string following the formatted structure.
301  //
302  SmbiosRecord->Vendor = 1;
303
304  //
305  // Version will be the 2nd optional string following the formatted structure.
306  //
307  SmbiosRecord->BiosVersion = 2;
308  SmbiosRecord->BiosSegment = (UINT16)ForType0InputData->BiosStartingAddress;
309
310  //
311  // ReleaseDate will be the 3rd optional string following the formatted structure.
312  //
313  SmbiosRecord->BiosReleaseDate = 3;
314
315  //
316  // Tiger has no PCD value to indicate BIOS Size, just fill 0 for simply.
317  //
318  SmbiosRecord->BiosSize = 0;
319  SmbiosRecord->BiosCharacteristics = *(MISC_BIOS_CHARACTERISTICS*)(&ForType0InputData->BiosCharacteristics1);
320
321  //
322  // CharacterExtensionBytes also store in ForType0InputData->BiosCharacteristics1 later two bytes to save size.
323  //
324  SmbiosRecord->BIOSCharacteristicsExtensionBytes[0] = *((UINT8 *) &ForType0InputData->BiosCharacteristics1 + 4);
325  SmbiosRecord->BIOSCharacteristicsExtensionBytes[1] = *((UINT8 *) &ForType0InputData->BiosCharacteristics1 + 5);
326
327  SmbiosRecord->SystemBiosMajorRelease =  ForType0InputData->BiosMajorRelease;
328  SmbiosRecord->SystemBiosMinorRelease =  ForType0InputData->BiosMinorRelease;
329  SmbiosRecord->EmbeddedControllerFirmwareMajorRelease = ForType0InputData->BiosEmbeddedFirmwareMajorRelease;
330  SmbiosRecord->EmbeddedControllerFirmwareMinorRelease = ForType0InputData->BiosEmbeddedFirmwareMinorRelease;
331
332  OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);
333  UnicodeStrToAsciiStr(Char16String, OptionalStrStart);
334  UnicodeStrToAsciiStr(BIOSVersionTemp, OptionalStrStart + VendorStrLen + 1);
335  UnicodeStrToAsciiStr(ReleaseDate, OptionalStrStart + VendorStrLen + 1 + VerStrLen + 1);
336
337  //
338  // Now we have got the full smbios record, call smbios protocol to add this record.
339  //
340  SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
341  Status = Smbios-> Add(
342                      Smbios,
343                      NULL,
344                      &SmbiosHandle,
345                      (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord
346                      );
347
348  FreePool(SmbiosRecord);
349  return Status;
350}
351