Home | History | Annotate | Download | only in BiosIdLib
      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