Home | History | Annotate | Download | only in FlashDeviceLib
      1 /** @file
      2 
      3   Copyright (c) 2004  - 2016, Intel Corporation. All rights reserved.<BR>
      4 
      5   This program and the accompanying materials are licensed and made available under
      6   the terms and conditions of the BSD License that accompanies this distribution.
      7   The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php.
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 
     14 
     15 **/
     16 
     17 #include <PiDxe.h>
     18 
     19 #include <Library/FlashDeviceLib.h>
     20 #include <Library/DebugLib.h>
     21 #include <Library/BaseLib.h>
     22 #include <Library/UefiBootServicesTableLib.h>
     23 #include <Library/UefiRuntimeServicesTableLib.h>
     24 #include <Library/BaseMemoryLib.h>
     25 #include <Library/UefiRuntimeLib.h>
     26 #include <Protocol/SmmBase2.h>
     27 #include <Guid/EventGroup.h>
     28 #include "SpiChipDefinitions.h"
     29 
     30 extern UINTN FlashDeviceBase;
     31 
     32 extern EFI_SPI_PROTOCOL *mSpiProtocol;
     33 
     34 VOID
     35 EFIAPI
     36 LibFvbFlashDeviceVirtualAddressChangeNotifyEvent (
     37   IN EFI_EVENT        Event,
     38   IN VOID             *Context
     39   )
     40 {
     41   gRT->ConvertPointer (0, (VOID **) &mSpiProtocol);
     42   gRT->ConvertPointer (0, (VOID **) &FlashDeviceBase);
     43 }
     44 
     45 
     46 /**
     47   The library constructuor.
     48 
     49   The function does the necessary initialization work for this library
     50   instance. Please put all initialization works in it.
     51 
     52   @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
     53   @param[in]  SystemTable       A pointer to the EFI system table.
     54 
     55   @retval     EFI_SUCCESS       The function always return EFI_SUCCESS for now.
     56                                 It will ASSERT on error for debug version.
     57   @retval     EFI_ERROR         Please reference LocateProtocol for error code details.
     58 
     59 **/
     60 EFI_STATUS
     61 EFIAPI
     62 LibFvbFlashDeviceSupportInit (
     63   IN EFI_HANDLE         ImageHandle,
     64   IN EFI_SYSTEM_TABLE   *SystemTable
     65   )
     66 {
     67   EFI_STATUS Status;
     68   EFI_EVENT  Event;
     69   UINT8                         SfId[3];
     70   UINT8                         FlashIndex;
     71   UINT8                         SpiReadError;
     72   UINT8                         SpiNotMatchError;
     73   EFI_SMM_BASE2_PROTOCOL       *SmmBase;
     74   BOOLEAN                       InSmm;
     75 
     76   SpiReadError     = 0x00;
     77   SpiNotMatchError = 0x00;
     78 
     79   InSmm = FALSE;
     80   Status = gBS->LocateProtocol (
     81                   &gEfiSmmBase2ProtocolGuid,
     82                   NULL,
     83                   (void **)&SmmBase
     84                   );
     85   if (!EFI_ERROR(Status)) {
     86     Status = SmmBase->InSmm(SmmBase, &InSmm);
     87     if (EFI_ERROR(Status)) {
     88       InSmm = FALSE;
     89     }
     90   }
     91 
     92   if (!InSmm) {
     93     Status = gBS->LocateProtocol (
     94                   &gEfiSpiProtocolGuid,
     95                   NULL,
     96                   (VOID **)&mSpiProtocol
     97                   );
     98     ASSERT_EFI_ERROR (Status);
     99 
    100     Status = gBS->CreateEventEx (
    101                   EVT_NOTIFY_SIGNAL,
    102                   TPL_NOTIFY,
    103                   LibFvbFlashDeviceVirtualAddressChangeNotifyEvent,
    104                   NULL,
    105                   &gEfiEventVirtualAddressChangeGuid,
    106                   &Event
    107                   );
    108     ASSERT_EFI_ERROR (Status);
    109 
    110   } else {
    111     Status = gBS->LocateProtocol (
    112                     &gEfiSmmSpiProtocolGuid,
    113                     NULL,
    114                     (VOID **)&mSpiProtocol
    115                     );
    116     ASSERT_EFI_ERROR (Status);
    117   }
    118 
    119 
    120   for (FlashIndex = EnumSpiFlashW25Q64; FlashIndex < EnumSpiFlashMax; FlashIndex++) {
    121     Status = mSpiProtocol->Init (mSpiProtocol, &(mInitTable[FlashIndex]));
    122     if (!EFI_ERROR (Status)) {
    123       //
    124       // Read Vendor/Device IDs to check if the driver supports the Serial Flash device.
    125       //
    126       Status = mSpiProtocol->Execute (
    127                                mSpiProtocol,
    128                                SPI_READ_ID,
    129                                SPI_WREN,
    130                                TRUE,
    131                                FALSE,
    132                                FALSE,
    133                                0,
    134                                3,
    135                                SfId,
    136                                EnumSpiRegionAll
    137                                );
    138       if (!EFI_ERROR (Status)) {
    139         if ((SfId[0] == mInitTable[FlashIndex].VendorId)  &&
    140             (SfId[1] == mInitTable[FlashIndex].DeviceId0) &&
    141             (SfId[2] == mInitTable[FlashIndex].DeviceId1)) {
    142             //
    143             // Found a matching SPI device, FlashIndex now contains flash device.
    144             //
    145             DEBUG ((EFI_D_ERROR, "OK - Found SPI Flash Type in SPI Flash Driver, Device Type ID 0 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId0));
    146             DEBUG ((EFI_D_ERROR, "Device Type ID 1 = 0x%02x!\n", mInitTable[FlashIndex].DeviceId1));
    147 
    148             if (mInitTable[FlashIndex].BiosStartOffset == (UINTN) (-1)) {
    149               DEBUG ((EFI_D_ERROR, "ERROR - The size of BIOS image is bigger than SPI Flash device!\n"));
    150               CpuDeadLoop ();
    151             }
    152             break;
    153         } else {
    154           SpiNotMatchError++;
    155         }
    156       } else {
    157         SpiReadError++;
    158       }
    159     }
    160   }
    161 
    162   DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
    163 
    164   if (FlashIndex < EnumSpiFlashMax)  {
    165     return EFI_SUCCESS;
    166   } else {
    167   if (SpiReadError != 0) {
    168       DEBUG ((EFI_D_ERROR, "ERROR - SPI Read ID execution failed! Error Count = %d\n", SpiReadError));
    169    }
    170     else {
    171       if (SpiNotMatchError != 0) {
    172         DEBUG ((EFI_D_ERROR, "ERROR - No supported SPI flash chip found! Error Count = %d\n", SpiNotMatchError));
    173         DEBUG ((EFI_D_ERROR, "SPI flash chip VID = 0x%X, DID0 = 0x%X, DID1 = 0x%X\n", SfId[0], SfId[1], SfId[2]));
    174       }
    175     }
    176     return EFI_UNSUPPORTED;
    177   }
    178 }
    179 
    180