--- /dev/null
+/** @file\r
+ Firmware Volume Block Driver for Lakeport Platform.\r
+\r
+ Firmware volume block driver for FWH or SPI device.\r
+ It depends on which Flash Device Library to be linked with this driver.\r
+\r
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
+ \r\r
+ This program and the accompanying materials are licensed and made available under\r\r
+ the terms and conditions of the BSD License that accompanies this distribution. \r\r
+ The full text of the license may be found at \r\r
+ http://opensource.org/licenses/bsd-license.php. \r\r
+ \r\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r\r
+ \r\r
+\r
+**/\r
+\r
+#include <PiDxe.h>\r
+#include <Library/UefiRuntimeLib.h>\r
+#include "FvbService.h"\r
+\r
+extern FWB_GLOBAL mFvbModuleGlobal;\r
+\r
+/**\r
+ Call back function on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.\r
+\r
+ Fixup internal data so that the driver is callable in EFI runtime\r
+ in virtual mode. Convert the mFvbModuleGlobal date items to there\r
+ virtual address.\r
+\r
+ @param Event Event whose notification function is being invoked.\r
+ @param Context The context of the Notification context. Not used in\r
+ this call back function.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+FvbVirtualddressChangeEvent (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_FW_VOL_INSTANCE *FwhInstance;\r
+ UINTN Index;\r
+\r
+ //\r
+ // Convert the base address of all the instances.\r
+ //\r
+ for (Index = 0; Index < mFvbModuleGlobal.NumFv; Index++) {\r
+ FwhInstance = GetFvbInstance (Index);\r
+ EfiConvertPointer (0, (VOID **) &FwhInstance->FvBase);\r
+ }\r
+\r
+ EfiConvertPointer (0, (VOID **) &mFvbModuleGlobal.FvInstance);\r
+}\r
+\r
+\r
+/**\r
+ The function installs EFI_FIRMWARE_VOLUME_BLOCK protocol\r
+ for each FV in the system.\r
+\r
+ @param[in] FwhInstance The pointer to a FW volume instance structure,\r
+ which contains the information about one FV.\r
+ @param[in] InstanceNum The instance number which can be used as a ID\r
+ to locate this FwhInstance in other functions.\r
+\r
+ @retval VOID\r
+\r
+**/\r
+VOID\r
+InstallFvbProtocol (\r
+ IN EFI_FW_VOL_INSTANCE *FwhInstance,\r
+ IN UINTN InstanceNum\r
+ )\r
+{\r
+ EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE FwbHandle;\r
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface;\r
+\r
+ FvbDevice = (EFI_FW_VOL_BLOCK_DEVICE *) AllocateRuntimeCopyPool (\r
+ sizeof (EFI_FW_VOL_BLOCK_DEVICE),\r
+ &mFvbDeviceTemplate\r
+ );\r
+ ASSERT (FvbDevice != NULL);\r
+\r
+ FvbDevice->Instance = InstanceNum;\r
+ FwVolHeader = &FwhInstance->VolumeHeader;\r
+\r
+ //\r
+ // Set up the devicepath.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "FwBlockService.c: Setting up DevicePath for 0x%lx:\n", FwhInstance->FvBase));\r
+ if (FwVolHeader->ExtHeaderOffset == 0) {\r
+ //\r
+ // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH.\r
+ //\r
+ FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate);\r
+ ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.StartingAddress = FwhInstance->FvBase;\r
+ ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.EndingAddress = FwhInstance->FvBase + FwVolHeader->FvLength - 1;\r
+ } else {\r
+ FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateRuntimeCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate);\r
+ CopyGuid (\r
+ &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName,\r
+ (GUID *)(UINTN)(FwhInstance->FvBase + FwVolHeader->ExtHeaderOffset)\r
+ );\r
+ }\r
+\r
+ //\r
+ // Find a handle with a matching device path that has supports FW Block protocol.\r
+ //\r
+ Status = gBS->LocateDevicePath (\r
+ &gEfiFirmwareVolumeBlockProtocolGuid,\r
+ &FvbDevice->DevicePath,\r
+ &FwbHandle\r
+ );\r
+ if (EFI_ERROR (Status) ) {\r
+ //\r
+ // LocateDevicePath fails so install a new interface and device path.\r
+ //\r
+ DEBUG ((EFI_D_INFO, "FwBlockService.c: LocateDevicePath failed, install new interface 0x%lx:\n", FwhInstance->FvBase));\r
+ FwbHandle = NULL;\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &FwbHandle,\r
+ &gEfiFirmwareVolumeBlockProtocolGuid,\r
+ &FvbDevice->FwVolBlockInstance,\r
+ &gEfiDevicePathProtocolGuid,\r
+ FvbDevice->DevicePath,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ DEBUG ((EFI_D_INFO, "FwBlockService.c: IMPI FirmwareVolBlockProt, DevPath 0x%lx: %r\n", FwhInstance->FvBase, Status));\r
+\r
+ } else if (IsDevicePathEnd (FvbDevice->DevicePath)) {\r
+ //\r
+ // Device allready exists, so reinstall the FVB protocol.\r
+ //\r
+ DEBUG ((EFI_D_ERROR, "FwBlockService.c: LocateDevicePath succeeded, reinstall interface 0x%lx:\n", FwhInstance->FvBase));\r
+ Status = gBS->HandleProtocol (\r
+ FwbHandle,\r
+ &gEfiFirmwareVolumeBlockProtocolGuid,\r
+ (VOID **) &OldFwbInterface\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = gBS->ReinstallProtocolInterface (\r
+ FwbHandle,\r
+ &gEfiFirmwareVolumeBlockProtocolGuid,\r
+ OldFwbInterface,\r
+ &FvbDevice->FwVolBlockInstance\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ } else {\r
+ //\r
+ // There was a FVB protocol on an End Device Path node.\r
+ //\r
+ ASSERT (FALSE);\r
+ }\r
+\r
+}\r
+\r
+\r
+/**\r
+ The driver entry point for Firmware Volume Block Driver.\r
+\r
+ The function does the necessary initialization work for\r
+ Firmware Volume Block Driver.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
+ @param[in] SystemTable A pointer to the EFI system table.\r
+\r
+ @retval EFI_SUCCESS This funtion always return EFI_SUCCESS.\r
+ It will ASSERT on errors.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeFvbInitialize (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_EVENT Event;\r
+\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ FvbVirtualddressChangeEvent,\r
+ NULL,\r
+ &gEfiEventVirtualAddressChangeGuid,\r
+ &Event\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ FvbInitialize ();\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r