Home | History | Annotate | Download | only in FvbRuntimeDxe
      1 /** @file
      2   Firmware Volume Block Driver for Lakeport Platform.
      3 
      4   Firmware volume block driver for FWH or SPI device.
      5   It depends on which Flash Device Library to be linked with this driver.
      6 
      7 Copyright (c) 2006  - 2014, Intel Corporation. All rights reserved.<BR>
      8 
      9   This program and the accompanying materials are licensed and made available under
     11   the terms and conditions of the BSD License that accompanies this distribution.
     13   The full text of the license may be found at
     15   http://opensource.org/licenses/bsd-license.php.
     17 
     19   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     21   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     23 
     25 
     27 **/
     28 
     29 #include <PiDxe.h>
     30 #include <Library/UefiRuntimeLib.h>
     31 #include "FvbService.h"
     32 
     33 extern FWB_GLOBAL              mFvbModuleGlobal;
     34 
     35 /**
     36   Call back function on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
     37 
     38   Fixup internal data so that the driver is callable in EFI runtime
     39   in virtual mode. Convert the mFvbModuleGlobal date items to there
     40   virtual address.
     41 
     42   @param  Event     Event whose notification function is being invoked.
     43   @param  Context   The context of the Notification context. Not used in
     44                     this call back function.
     45 
     46 **/
     47 VOID
     48 EFIAPI
     49 FvbVirtualddressChangeEvent (
     50   IN EFI_EVENT                          Event,
     51   IN VOID                               *Context
     52   )
     53 {
     54   EFI_FW_VOL_INSTANCE                   *FwhInstance;
     55   UINTN                                 Index;
     56 
     57   //
     58   // Convert the base address of all the instances.
     59   //
     60   for (Index = 0; Index < mFvbModuleGlobal.NumFv; Index++) {
     61     FwhInstance = GetFvbInstance (Index);
     62     EfiConvertPointer (0, (VOID **) &FwhInstance->FvBase);
     63   }
     64 
     65   EfiConvertPointer (0, (VOID **) &mFvbModuleGlobal.FvInstance);
     66 }
     67 
     68 
     69 /**
     70   The function installs EFI_FIRMWARE_VOLUME_BLOCK protocol
     71   for each FV in the system.
     72 
     73   @param[in]  FwhInstance   The pointer to a FW volume instance structure,
     74                             which contains the information about one FV.
     75   @param[in]  InstanceNum   The instance number which can be used as a ID
     76                             to locate this FwhInstance in other functions.
     77 
     78   @retval     VOID
     79 
     80 **/
     81 VOID
     82 InstallFvbProtocol (
     83   IN  EFI_FW_VOL_INSTANCE               *FwhInstance,
     84   IN  UINTN                             InstanceNum
     85   )
     86 {
     87   EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;
     88   EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader;
     89   EFI_STATUS                            Status;
     90   EFI_HANDLE                            FwbHandle;
     91   EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *OldFwbInterface;
     92 
     93   FvbDevice = (EFI_FW_VOL_BLOCK_DEVICE *) AllocateRuntimeCopyPool (
     94                                             sizeof (EFI_FW_VOL_BLOCK_DEVICE),
     95                                             &mFvbDeviceTemplate
     96                                             );
     97   ASSERT (FvbDevice != NULL);
     98 
     99   FvbDevice->Instance = InstanceNum;
    100   FwVolHeader = &FwhInstance->VolumeHeader;
    101 
    102   //
    103   // Set up the devicepath.
    104   //
    105   DEBUG ((EFI_D_INFO, "FwBlockService.c: Setting up DevicePath for 0x%lx:\n", FwhInstance->FvBase));
    106   if (FwVolHeader->ExtHeaderOffset == 0) {
    107     //
    108     // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH.
    109     //
    110     FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate);
    111     ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.StartingAddress = FwhInstance->FvBase;
    112     ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.EndingAddress   = FwhInstance->FvBase + FwVolHeader->FvLength - 1;
    113   } else {
    114     FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate);
    115     CopyGuid (
    116       &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName,
    117       (GUID *)(UINTN)(FwhInstance->FvBase + FwVolHeader->ExtHeaderOffset)
    118       );
    119   }
    120 
    121   //
    122   // Find a handle with a matching device path that has supports FW Block protocol.
    123   //
    124   Status = gBS->LocateDevicePath (
    125                   &gEfiFirmwareVolumeBlockProtocolGuid,
    126                   &FvbDevice->DevicePath,
    127                   &FwbHandle
    128                   );
    129   if (EFI_ERROR (Status) ) {
    130     //
    131     // LocateDevicePath fails so install a new interface and device path.
    132     //
    133     DEBUG ((EFI_D_INFO, "FwBlockService.c: LocateDevicePath failed, install new interface 0x%lx:\n", FwhInstance->FvBase));
    134     FwbHandle = NULL;
    135     Status =  gBS->InstallMultipleProtocolInterfaces (
    136                      &FwbHandle,
    137                      &gEfiFirmwareVolumeBlockProtocolGuid,
    138                      &FvbDevice->FwVolBlockInstance,
    139                      &gEfiDevicePathProtocolGuid,
    140                      FvbDevice->DevicePath,
    141                      NULL
    142                      );
    143     ASSERT_EFI_ERROR (Status);
    144     DEBUG ((EFI_D_INFO, "FwBlockService.c: IMPI FirmwareVolBlockProt, DevPath 0x%lx: %r\n", FwhInstance->FvBase, Status));
    145 
    146   } else if (IsDevicePathEnd (FvbDevice->DevicePath)) {
    147     //
    148     // Device allready exists, so reinstall the FVB protocol.
    149     //
    150     DEBUG ((EFI_D_ERROR, "FwBlockService.c: LocateDevicePath succeeded, reinstall interface 0x%lx:\n", FwhInstance->FvBase));
    151     Status = gBS->HandleProtocol (
    152                     FwbHandle,
    153                     &gEfiFirmwareVolumeBlockProtocolGuid,
    154                     (VOID **) &OldFwbInterface
    155                     );
    156     ASSERT_EFI_ERROR (Status);
    157 
    158     Status =  gBS->ReinstallProtocolInterface (
    159                      FwbHandle,
    160                      &gEfiFirmwareVolumeBlockProtocolGuid,
    161                      OldFwbInterface,
    162                      &FvbDevice->FwVolBlockInstance
    163                      );
    164     ASSERT_EFI_ERROR (Status);
    165 
    166   } else {
    167     //
    168     // There was a FVB protocol on an End Device Path node.
    169     //
    170     ASSERT (FALSE);
    171   }
    172 
    173 }
    174 
    175 
    176 /**
    177   The driver entry point for Firmware Volume Block Driver.
    178 
    179   The function does the necessary initialization work for
    180   Firmware Volume Block Driver.
    181 
    182   @param[in]  ImageHandle       The firmware allocated handle for the UEFI image.
    183   @param[in]  SystemTable       A pointer to the EFI system table.
    184 
    185   @retval     EFI_SUCCESS       This funtion always return EFI_SUCCESS.
    186                                 It will ASSERT on errors.
    187 
    188 **/
    189 EFI_STATUS
    190 EFIAPI
    191 DxeFvbInitialize (
    192   IN EFI_HANDLE                         ImageHandle,
    193   IN EFI_SYSTEM_TABLE                   *SystemTable
    194   )
    195 {
    196   EFI_STATUS                            Status;
    197   EFI_EVENT                             Event;
    198 
    199   Status = gBS->CreateEventEx (
    200                   EVT_NOTIFY_SIGNAL,
    201                   TPL_NOTIFY,
    202                   FvbVirtualddressChangeEvent,
    203                   NULL,
    204                   &gEfiEventVirtualAddressChangeGuid,
    205                   &Event
    206                   );
    207   ASSERT_EFI_ERROR (Status);
    208 
    209   FvbInitialize ();
    210 
    211   return EFI_SUCCESS;
    212 }
    213 
    214