1 /*++ 2 3 Copyright (c) 2011 - 2014, Intel Corporation. All rights reserved 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 Module Name: 24 25 BiosIdLib.c 26 27 Abstract: 28 29 Boot service DXE BIOS ID library implementation. 30 31 These functions in this file can be called during DXE and cannot be called during runtime 32 or in SMM which should use a RT or SMM library. 33 34 --*/ 35 36 #include <PiDxe.h> 37 #include <Library/BaseLib.h> 38 #include <Library/HobLib.h> 39 #include <Library/UefiBootServicesTableLib.h> 40 #include <Library/BaseMemoryLib.h> 41 #include <Library/DebugLib.h> 42 43 #include <Library/BiosIdLib.h> 44 #include <Guid/BiosId.h> 45 #include <Protocol/FirmwareVolume2.h> 46 #include <Protocol/LoadedImage.h> 47 48 49 EFI_STATUS 50 GetImageFromFv ( 51 IN EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv, 52 IN EFI_GUID *NameGuid, 53 IN EFI_SECTION_TYPE SectionType, 54 OUT VOID **Buffer, 55 OUT UINTN *Size 56 ) 57 { 58 EFI_STATUS Status; 59 EFI_FV_FILETYPE FileType; 60 EFI_FV_FILE_ATTRIBUTES Attributes; 61 UINT32 AuthenticationStatus; 62 63 // 64 // Read desired section content in NameGuid file 65 // 66 *Buffer = NULL; 67 *Size = 0; 68 Status = Fv->ReadSection ( 69 Fv, 70 NameGuid, 71 SectionType, 72 0, 73 Buffer, 74 Size, 75 &AuthenticationStatus 76 ); 77 78 if (EFI_ERROR (Status) && (SectionType == EFI_SECTION_TE)) { 79 // 80 // Try reading PE32 section, since the TE section does not exist 81 // 82 *Buffer = NULL; 83 *Size = 0; 84 Status = Fv->ReadSection ( 85 Fv, 86 NameGuid, 87 EFI_SECTION_PE32, 88 0, 89 Buffer, 90 Size, 91 &AuthenticationStatus 92 ); 93 } 94 95 if (EFI_ERROR (Status) && 96 ((SectionType == EFI_SECTION_TE) || (SectionType == EFI_SECTION_PE32))) { 97 // 98 // Try reading raw file, since the desired section does not exist 99 // 100 *Buffer = NULL; 101 *Size = 0; 102 Status = Fv->ReadFile ( 103 Fv, 104 NameGuid, 105 Buffer, 106 Size, 107 &FileType, 108 &Attributes, 109 &AuthenticationStatus 110 ); 111 } 112 113 return Status; 114 } 115 116 117 EFI_STATUS 118 GetImageEx ( 119 IN EFI_HANDLE ImageHandle, 120 IN EFI_GUID *NameGuid, 121 IN EFI_SECTION_TYPE SectionType, 122 OUT VOID **Buffer, 123 OUT UINTN *Size, 124 BOOLEAN WithinImageFv 125 ) 126 { 127 EFI_STATUS Status; 128 EFI_HANDLE *HandleBuffer; 129 UINTN HandleCount; 130 UINTN Index; 131 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; 132 133 EFI_FIRMWARE_VOLUME2_PROTOCOL *ImageFv; 134 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; 135 136 137 if (ImageHandle == NULL && WithinImageFv) { 138 return EFI_INVALID_PARAMETER; 139 } 140 141 Status = EFI_NOT_FOUND; 142 ImageFv = NULL; 143 if (ImageHandle != NULL) { 144 Status = gBS->HandleProtocol ( 145 ImageHandle, 146 &gEfiLoadedImageProtocolGuid, 147 (VOID **) &LoadedImage 148 ); 149 if (EFI_ERROR (Status)) { 150 return Status; 151 } 152 Status = gBS->HandleProtocol ( 153 LoadedImage->DeviceHandle, 154 &gEfiFirmwareVolume2ProtocolGuid, 155 (VOID **) &ImageFv 156 ); 157 if (!EFI_ERROR (Status)) { 158 Status = GetImageFromFv (ImageFv, NameGuid, SectionType, Buffer, Size); 159 } 160 } 161 162 if (Status == EFI_SUCCESS || WithinImageFv) { 163 return Status; 164 } 165 166 Status = gBS->LocateHandleBuffer ( 167 ByProtocol, 168 &gEfiFirmwareVolume2ProtocolGuid, 169 NULL, 170 &HandleCount, 171 &HandleBuffer 172 ); 173 if (EFI_ERROR (Status)) { 174 return Status; 175 } 176 177 // 178 // Find desired image in all Fvs 179 // 180 for (Index = 0; Index < HandleCount; ++Index) { 181 Status = gBS->HandleProtocol ( 182 HandleBuffer[Index], 183 &gEfiFirmwareVolume2ProtocolGuid, 184 (VOID**)&Fv 185 ); 186 187 if (EFI_ERROR (Status)) { 188 gBS->FreePool(HandleBuffer); 189 return Status; 190 } 191 192 if (ImageFv != NULL && Fv == ImageFv) { 193 continue; 194 } 195 196 Status = GetImageFromFv (Fv, NameGuid, SectionType, Buffer, Size); 197 198 if (!EFI_ERROR (Status)) { 199 break; 200 } 201 } 202 gBS->FreePool(HandleBuffer); 203 204 // 205 // Not found image 206 // 207 if (Index == HandleCount) { 208 return EFI_NOT_FOUND; 209 } 210 211 return EFI_SUCCESS; 212 } 213 214 /** 215 This function returns BIOS ID by searching HOB or FV. 216 217 @param BiosIdImage The BIOS ID got from HOB or FV. 218 219 @retval EFI_SUCCESS All parameters were valid and BIOS ID has been got. 220 @retval EFI_NOT_FOUND BiosId image is not found, and no parameter will be modified. 221 @retval EFI_INVALID_PARAMETER The parameter is NULL. 222 223 **/ 224 EFI_STATUS 225 GetBiosId ( 226 OUT BIOS_ID_IMAGE *BiosIdImage 227 ) 228 229 { 230 EFI_STATUS Status; 231 VOID *Address = NULL; 232 UINTN Size = 0; 233 234 DEBUG ((EFI_D_INFO, "Get BIOS ID from FV\n")); 235 236 Status = GetImageEx ( 237 NULL, 238 &gEfiBiosIdGuid, 239 EFI_SECTION_RAW, 240 &Address, 241 &Size, 242 FALSE 243 ); 244 245 if (Status == EFI_SUCCESS) { 246 // 247 // BiosId image is present in FV 248 // 249 if (Address != NULL) { 250 Size = sizeof (BIOS_ID_IMAGE); 251 gBS->CopyMem ( 252 (void *) BiosIdImage, 253 Address, 254 Size 255 ); 256 // 257 // GetImage () allocated buffer for Address, now clear it. 258 // 259 gBS->FreePool (Address); 260 261 DEBUG ((EFI_D_INFO, "Get BIOS ID from FV successfully\n")); 262 DEBUG ((EFI_D_INFO, "BIOS ID: %s\n", (CHAR16 *) (&(BiosIdImage->BiosIdString)))); 263 264 return EFI_SUCCESS; 265 } 266 } 267 return EFI_NOT_FOUND; 268 } 269 270 /** 271 This function returns the Version & Release Date and Time by getting and converting 272 BIOS ID. 273 274 @param BiosVersion The Bios Version out of the conversion. 275 @param BiosReleaseDate The Bios Release Date out of the conversion. 276 @param BiosReleaseTime - The Bios Release Time out of the conversion. 277 278 @retval EFI_SUCCESS - BIOS Version & Release Date and Time have been got successfully. 279 @retval EFI_NOT_FOUND - BiosId image is not found, and no parameter will be modified. 280 @retval EFI_INVALID_PARAMETER - All the parameters are NULL. 281 282 **/ 283 EFI_STATUS 284 GetBiosVersionDateTime ( 285 OUT CHAR16 *BiosVersion, OPTIONAL 286 OUT CHAR16 *BiosReleaseDate, OPTIONAL 287 OUT CHAR16 *BiosReleaseTime OPTIONAL 288 ) 289 { 290 EFI_STATUS Status; 291 BIOS_ID_IMAGE BiosIdImage; 292 293 if ((BiosVersion == NULL) && (BiosReleaseDate == NULL) && (BiosReleaseTime == NULL)) { 294 return EFI_INVALID_PARAMETER; 295 } 296 297 Status = GetBiosId (&BiosIdImage); 298 if (EFI_ERROR (Status)) { 299 return EFI_NOT_FOUND; 300 } 301 302 if (BiosVersion != NULL) { 303 // 304 // Fill the BiosVersion data from the BIOS ID. 305 // 306 StrCpy (BiosVersion, (CHAR16 *) (&(BiosIdImage.BiosIdString))); 307 } 308 309 if (BiosReleaseDate != NULL) { 310 // 311 // Fill the build timestamp date from the BIOS ID in the "MM/DD/YY" format. 312 // 313 BiosReleaseDate[0] = BiosIdImage.BiosIdString.TimeStamp[2]; 314 BiosReleaseDate[1] = BiosIdImage.BiosIdString.TimeStamp[3]; 315 BiosReleaseDate[2] = (CHAR16) ((UINT8) ('/')); 316 317 BiosReleaseDate[3] = BiosIdImage.BiosIdString.TimeStamp[4]; 318 BiosReleaseDate[4] = BiosIdImage.BiosIdString.TimeStamp[5]; 319 BiosReleaseDate[5] = (CHAR16) ((UINT8) ('/')); 320 321 // 322 // Add 20 for SMBIOS table 323 // Current Linux kernel will misjudge 09 as year 0, so using 2009 for SMBIOS table 324 // 325 BiosReleaseDate[6] = '2'; 326 BiosReleaseDate[7] = '0'; 327 BiosReleaseDate[8] = BiosIdImage.BiosIdString.TimeStamp[0]; 328 BiosReleaseDate[9] = BiosIdImage.BiosIdString.TimeStamp[1]; 329 330 BiosReleaseDate[10] = (CHAR16) ((UINT8) ('\0')); 331 } 332 333 if (BiosReleaseTime != NULL) { 334 335 // 336 // Fill the build timestamp time from the BIOS ID in the "HH:MM" format. 337 // 338 339 BiosReleaseTime[0] = BiosIdImage.BiosIdString.TimeStamp[6]; 340 BiosReleaseTime[1] = BiosIdImage.BiosIdString.TimeStamp[7]; 341 BiosReleaseTime[2] = (CHAR16) ((UINT8) (':')); 342 343 BiosReleaseTime[3] = BiosIdImage.BiosIdString.TimeStamp[8]; 344 BiosReleaseTime[4] = BiosIdImage.BiosIdString.TimeStamp[9]; 345 346 BiosReleaseTime[5] = (CHAR16) ((UINT8) ('\0')); 347 } 348 349 return EFI_SUCCESS; 350 } 351 352