--- /dev/null
+/*++\r
+\r
+Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
+ \r\r
+ This program and the accompanying materials are licensed and made available under\r\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r\r
+ The full text of the license may be found at \r\r
+ http://opensource.org/licenses/bsd-license.php. \r\r
+ \r\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r\r
+ \r\r
+\r
+\r
+Module Name:\r
+\r
+ MiscBiosVendorFunction.c\r
+\r
+Abstract:\r
+\r
+ BIOS vendor information boot time changes.\r
+ Misc. subclass type 2.\r
+ SMBIOS type 0.\r
+\r
+--*/\r
+\r
+\r
+#include "CommonHeader.h"\r
+\r
+#include "MiscSubclassDriver.h"\r
+#include <Library/BiosIdLib.h>\r
+#include <Library/SpiFlash.H>\r
+\r
+EFI_SPI_PROTOCOL *mSpiProtocol = NULL;\r
+\r
+\r
+/**\r
+ This function read the data from Spi Rom.\r
+\r
+ @param BaseAddress The starting address of the read.\r
+ @param Byte The pointer to the destination buffer.\r
+ @param Length The number of bytes.\r
+ @param SpiRegionType Spi Region Type.\r
+\r
+ @retval Status\r
+\r
+**/\r
+EFI_STATUS\r
+FlashRead (\r
+ IN UINTN BaseAddress,\r
+ IN UINT8 *Byte,\r
+ IN UINTN Length,\r
+ IN SPI_REGION_TYPE SpiRegionType\r
+ )\r
+{\r
+ EFI_STATUS Status = EFI_SUCCESS;\r
+ UINT32 SectorSize;\r
+ UINT32 SpiAddress;\r
+ UINT8 Buffer[SECTOR_SIZE_4KB];\r
+\r
+ SpiAddress = (UINT32)(UINTN)(BaseAddress);\r
+ SectorSize = SECTOR_SIZE_4KB;\r
+\r
+ Status = mSpiProtocol->Execute (\r
+ mSpiProtocol,\r
+ SPI_READ,\r
+ SPI_WREN,\r
+ TRUE,\r
+ TRUE,\r
+ FALSE,\r
+ (UINT32) SpiAddress,\r
+ SectorSize,\r
+ Buffer,\r
+ SpiRegionType\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+#ifdef _SHOW_LOG_\r
+ Print(L"Read SPI ROM Failed [%08x]\n", SpiAddress);\r
+#endif\r
+ return Status;\r
+ }\r
+\r
+ CopyMem (Byte, (void *)Buffer, Length);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function returns the value & exponent to Base2 for a given\r
+ Hex value. This is used to calculate the BiosPhysicalDeviceSize.\r
+\r
+ @param Value The hex value which is to be converted into value-exponent form\r
+ @param Exponent The exponent out of the conversion\r
+\r
+ @retval EFI_SUCCESS All parameters were valid and *Value & *Exponent have been set.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.\r
+\r
+**/\r
+EFI_STATUS\r
+GetValueExponentBase2(\r
+ IN OUT UINTN *Value,\r
+ OUT UINTN *Exponent\r
+ )\r
+{\r
+ if ((Value == NULL) || (Exponent == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ while ((*Value % 2) == 0) {\r
+ *Value=*Value/2;\r
+ (*Exponent)++;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Field Filling Function. Transform an EFI_EXP_BASE2_DATA to a byte, with '64k'\r
+ as the unit.\r
+\r
+ @param Base2Data Pointer to Base2_Data\r
+\r
+ @retval EFI_SUCCESS Transform successfully.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.\r
+\r
+**/\r
+UINT16\r
+Base2ToByteWith64KUnit (\r
+ IN EFI_EXP_BASE2_DATA *Base2Data\r
+ )\r
+{\r
+ UINT16 Value;\r
+ UINT16 Exponent;\r
+\r
+ Value = Base2Data->Value;\r
+ Exponent = Base2Data->Exponent;\r
+ Exponent -= 16;\r
+ Value <<= Exponent;\r
+\r
+ return Value;\r
+}\r
+\r
+\r
+/**\r
+ This function makes boot time changes to the contents of the\r
+ MiscBiosVendor (Type 0).\r
+\r
+ @param RecordData Pointer to copy of RecordData from the Data Table.\r
+\r
+ @retval EFI_SUCCESS All parameters were valid.\r
+ @retval EFI_UNSUPPORTED Unexpected RecordType value.\r
+ @retval EFI_INVALID_PARAMETER Invalid parameter was found.\r
+\r
+**/\r
+MISC_SMBIOS_TABLE_FUNCTION(MiscBiosVendor)\r
+{\r
+ CHAR8 *OptionalStrStart;\r
+ UINTN VendorStrLen;\r
+ UINTN VerStrLen;\r
+ UINTN DateStrLen;\r
+ CHAR16 *Version;\r
+ CHAR16 *ReleaseDate;\r
+ CHAR16 BiosVersion[100]; //Assuming that strings are < 100 UCHAR\r
+ CHAR16 BiosReleaseDate[100]; //Assuming that strings are < 100 UCHAR\r
+ CHAR16 BiosReleaseTime[100]; //Assuming that strings are < 100 UCHAR\r
+ EFI_STATUS Status;\r
+ EFI_STRING Char16String;\r
+ STRING_REF TokenToGet;\r
+ STRING_REF TokenToUpdate;\r
+ SMBIOS_TABLE_TYPE0 *SmbiosRecord;\r
+ EFI_SMBIOS_HANDLE SmbiosHandle;\r
+ EFI_MISC_BIOS_VENDOR *ForType0InputData;\r
+ BIOS_ID_IMAGE BiosIdImage;\r
+ UINT16 UVerStr[32];\r
+ UINTN LoopIndex;\r
+ UINTN CopyIndex;\r
+ MANIFEST_OEM_DATA *IFWIVerStruct;\r
+ UINT8 *Data8 = NULL;\r
+ UINT16 SpaceVer[2]={0x0020,0x0000};\r
+ UINT16 BIOSVersionTemp[100];\r
+\r
+ ForType0InputData = (EFI_MISC_BIOS_VENDOR *)RecordData;\r
+\r
+ //\r
+ // First check for invalid parameters.\r
+ //\r
+ if (RecordData == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ GetBiosId (&BiosIdImage);\r
+\r
+ //\r
+ // Add VLV2 BIOS Version and Release data\r
+ //\r
+ SetMem(BiosVersion, sizeof(BiosVersion), 0);\r
+ SetMem(BiosReleaseDate, sizeof(BiosReleaseDate), 0);\r
+ SetMem(BiosReleaseTime, sizeof(BiosReleaseTime), 0);\r
+ Status = GetBiosVersionDateTime (BiosVersion, BiosReleaseDate, BiosReleaseTime);\r
+ DEBUG ((EFI_D_ERROR, "GetBiosVersionDateTime :%s %s %s \n", BiosVersion, BiosReleaseDate, BiosReleaseTime));\r
+ if (StrLen (BiosVersion) > 0) {\r
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_VERSION);\r
+ HiiSetString (mHiiHandle, TokenToUpdate, BiosVersion, NULL);\r
+ }\r
+\r
+ if (StrLen(BiosReleaseDate) > 0) {\r
+ TokenToUpdate = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);\r
+ HiiSetString (mHiiHandle, TokenToUpdate, BiosReleaseDate, NULL);\r
+ }\r
+\r
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VENDOR);\r
+ Char16String = SmbiosMiscGetString (TokenToGet);\r
+ VendorStrLen = StrLen(Char16String);\r
+ if (VendorStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_VERSION);\r
+ Version = SmbiosMiscGetString (TokenToGet);\r
+\r
+ ZeroMem (UVerStr, 2*32);\r
+ ZeroMem (BIOSVersionTemp, 2*100);\r
+ StrCat (BIOSVersionTemp,Version);\r
+ Data8 = AllocatePool (SECTOR_SIZE_4KB);\r
+ ZeroMem (Data8, SECTOR_SIZE_4KB);\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiSpiProtocolGuid,\r
+ NULL,\r
+ (VOID **)&mSpiProtocol\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ //\r
+ // Get data form SPI ROM.\r
+ //\r
+ Status = FlashRead (\r
+ MEM_IFWIVER_START,\r
+ Data8,\r
+ SECTOR_SIZE_4KB,\r
+ EnumSpiRegionAll\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ for(LoopIndex = 0; LoopIndex <= SECTOR_SIZE_4KB; LoopIndex++) {\r
+ IFWIVerStruct = (MANIFEST_OEM_DATA *)(Data8 + LoopIndex);\r
+ if(IFWIVerStruct->Signature == SIGNATURE_32('$','F','U','D')) {\r
+ DEBUG ((EFI_D_ERROR, "the IFWI Length is:%d\n", IFWIVerStruct->IFWIVersionLen));\r
+ if(IFWIVerStruct->IFWIVersionLen < 32) {\r
+ for(CopyIndex = 0; CopyIndex < IFWIVerStruct->IFWIVersionLen; CopyIndex++) {\r
+ UVerStr[CopyIndex] = (UINT16)IFWIVerStruct->IFWIVersion[CopyIndex];\r
+ }\r
+ UVerStr[CopyIndex] = 0x0000;\r
+ DEBUG ((EFI_D_ERROR, "The IFWI Version is :%s,the IFWI Length is:%d\n", UVerStr,IFWIVerStruct->IFWIVersionLen));\r
+ StrCat(BIOSVersionTemp,SpaceVer);\r
+ StrCat(BIOSVersionTemp,UVerStr);\r
+ DEBUG ((EFI_D_ERROR, "The BIOS and IFWI Version is :%s\n", BIOSVersionTemp));\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ FreePool(Data8);\r
+\r
+ VerStrLen = StrLen(BIOSVersionTemp);\r
+ if (VerStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ TokenToGet = STRING_TOKEN (STR_MISC_BIOS_RELEASE_DATE);\r
+ ReleaseDate = SmbiosMiscGetString (TokenToGet);\r
+ DateStrLen = StrLen(ReleaseDate);\r
+ if (DateStrLen > SMBIOS_STRING_MAX_LENGTH) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Two zeros following the last string.\r
+ //\r
+ SmbiosRecord = AllocatePool(sizeof (SMBIOS_TABLE_TYPE0) + VendorStrLen + 1 + VerStrLen + 1 + DateStrLen + 1 + 1);\r
+ ZeroMem(SmbiosRecord, sizeof (SMBIOS_TABLE_TYPE0) + VendorStrLen + 1 + VerStrLen + 1 + DateStrLen + 1 + 1);\r
+\r
+ SmbiosRecord->Hdr.Type = EFI_SMBIOS_TYPE_BIOS_INFORMATION;\r
+ SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE0);\r
+\r
+ //\r
+ // Make handle chosen by smbios protocol.add automatically.\r
+ //\r
+ SmbiosRecord->Hdr.Handle = 0;\r
+\r
+ //\r
+ // Vendor will be the 1st optional string following the formatted structure.\r
+ //\r
+ SmbiosRecord->Vendor = 1;\r
+\r
+ //\r
+ // Version will be the 2nd optional string following the formatted structure.\r
+ //\r
+ SmbiosRecord->BiosVersion = 2;\r
+ SmbiosRecord->BiosSegment = (UINT16)ForType0InputData->BiosStartingAddress;\r
+\r
+ //\r
+ // ReleaseDate will be the 3rd optional string following the formatted structure.\r
+ //\r
+ SmbiosRecord->BiosReleaseDate = 3;\r
+\r
+ //\r
+ // Tiger has no PCD value to indicate BIOS Size, just fill 0 for simply.\r
+ //\r
+ SmbiosRecord->BiosSize = 0;\r
+ SmbiosRecord->BiosCharacteristics = *(MISC_BIOS_CHARACTERISTICS*)(&ForType0InputData->BiosCharacteristics1);\r
+\r
+ //\r
+ // CharacterExtensionBytes also store in ForType0InputData->BiosCharacteristics1 later two bytes to save size.\r
+ //\r
+ SmbiosRecord->BIOSCharacteristicsExtensionBytes[0] = *((UINT8 *) &ForType0InputData->BiosCharacteristics1 + 4);\r
+ SmbiosRecord->BIOSCharacteristicsExtensionBytes[1] = *((UINT8 *) &ForType0InputData->BiosCharacteristics1 + 5);\r
+\r
+ SmbiosRecord->SystemBiosMajorRelease = ForType0InputData->BiosMajorRelease;\r
+ SmbiosRecord->SystemBiosMinorRelease = ForType0InputData->BiosMinorRelease;\r
+ SmbiosRecord->EmbeddedControllerFirmwareMajorRelease = ForType0InputData->BiosEmbeddedFirmwareMajorRelease;\r
+ SmbiosRecord->EmbeddedControllerFirmwareMinorRelease = ForType0InputData->BiosEmbeddedFirmwareMinorRelease;\r
+\r
+ OptionalStrStart = (CHAR8 *)(SmbiosRecord + 1);\r
+ UnicodeStrToAsciiStr(Char16String, OptionalStrStart);\r
+ UnicodeStrToAsciiStr(BIOSVersionTemp, OptionalStrStart + VendorStrLen + 1);\r
+ UnicodeStrToAsciiStr(ReleaseDate, OptionalStrStart + VendorStrLen + 1 + VerStrLen + 1);\r
+\r
+ //\r
+ // Now we have got the full smbios record, call smbios protocol to add this record.\r
+ //\r
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;\r
+ Status = Smbios-> Add(\r
+ Smbios,\r
+ NULL,\r
+ &SmbiosHandle,\r
+ (EFI_SMBIOS_TABLE_HEADER *) SmbiosRecord\r
+ );\r
+\r
+ FreePool(SmbiosRecord);\r
+ return Status;\r
+}\r