• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10   This program and the accompanying materials are licensed and made available under
11 
12   the terms and conditions of the BSD License that accompanies this distribution.
13 
14   The full text of the license may be found at
15 
16   http://opensource.org/licenses/bsd-license.php.
17 
18 
19 
20   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
21 
22   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 
24 
25 
26 
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
FvbVirtualddressChangeEvent(IN EFI_EVENT Event,IN VOID * Context)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 
InstallFvbProtocol(IN EFI_FW_VOL_INSTANCE * FwhInstance,IN UINTN InstanceNum)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 
DxeFvbInitialize(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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