1 /*++ 2 3 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR> 4 5 This program and the accompanying materials are licensed and made available under 7 the terms and conditions of the BSD License that accompanies this distribution. 9 The full text of the license may be found at 11 http://opensource.org/licenses/bsd-license.php. 13 15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 17 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 19 21 23 24 Module Name: 25 26 MiscBiosVendorFunction.c 27 28 Abstract: 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 43 EFI_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 **/ 57 EFI_STATUS 58 FlashRead ( 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 **/ 109 EFI_STATUS 110 GetValueExponentBase2( 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 **/ 137 UINT16 138 Base2ToByteWith64KUnit ( 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 **/ 165 MISC_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