2 Functions related to the Firmware Volume Block service whose
3 implementation is specific to the runtime DXE driver build.
5 Copyright (C) 2015, Red Hat, Inc.
6 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Guid/EventGroup.h>
12 #include <Library/DebugLib.h>
13 #include <Library/DevicePathLib.h>
14 #include <Library/DxeServicesTableLib.h>
15 #include <Library/MemEncryptSevLib.h>
16 #include <Library/PcdLib.h>
17 #include <Library/UefiBootServicesTableLib.h>
18 #include <Library/UefiRuntimeLib.h>
19 #include <Protocol/DevicePath.h>
20 #include <Protocol/FirmwareVolumeBlock.h>
22 #include "FwBlockService.h"
23 #include "QemuFlash.h"
26 InstallProtocolInterfaces (
27 IN EFI_FW_VOL_BLOCK_DEVICE
*FvbDevice
32 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*OldFwbInterface
;
34 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire
));
37 // Find a handle with a matching device path that has supports FW Block
40 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid
,
41 &FvbDevice
->DevicePath
, &FwbHandle
);
42 if (EFI_ERROR (Status
)) {
44 // LocateDevicePath fails so install a new interface and device path
47 DEBUG ((EFI_D_INFO
, "Installing QEMU flash FVB\n"));
48 Status
= gBS
->InstallMultipleProtocolInterfaces (
50 &gEfiFirmwareVolumeBlockProtocolGuid
,
51 &FvbDevice
->FwVolBlockInstance
,
52 &gEfiDevicePathProtocolGuid
,
53 FvbDevice
->DevicePath
,
56 ASSERT_EFI_ERROR (Status
);
57 } else if (IsDevicePathEnd (FvbDevice
->DevicePath
)) {
59 // Device already exists, so reinstall the FVB protocol
61 Status
= gBS
->HandleProtocol (
63 &gEfiFirmwareVolumeBlockProtocolGuid
,
64 (VOID
**)&OldFwbInterface
66 ASSERT_EFI_ERROR (Status
);
68 DEBUG ((EFI_D_INFO
, "Reinstalling FVB for QEMU flash region\n"));
69 Status
= gBS
->ReinstallProtocolInterface (
71 &gEfiFirmwareVolumeBlockProtocolGuid
,
73 &FvbDevice
->FwVolBlockInstance
75 ASSERT_EFI_ERROR (Status
);
78 // There was a FVB protocol on an End Device Path node
88 FvbVirtualAddressChangeEvent (
96 Fixup internal data so that EFI and SAL can be call in virtual mode.
97 Call the passed in Child Notify event and convert the mFvbModuleGlobal
98 date items to there virtual address.
102 (Standard EFI notify event - EFI_EVENT_NOTIFY)
110 EFI_FW_VOL_INSTANCE
*FwhInstance
;
113 FwhInstance
= mFvbModuleGlobal
->FvInstance
;
114 EfiConvertPointer (0x0, (VOID
**) &mFvbModuleGlobal
->FvInstance
);
117 // Convert the base address of all the instances
120 while (Index
< mFvbModuleGlobal
->NumFv
) {
121 EfiConvertPointer (0x0, (VOID
**) &FwhInstance
->FvBase
);
122 FwhInstance
= (EFI_FW_VOL_INSTANCE
*)
124 (UINTN
) ((UINT8
*) FwhInstance
) +
125 FwhInstance
->VolumeHeader
.HeaderLength
+
126 (sizeof (EFI_FW_VOL_INSTANCE
) - sizeof (EFI_FIRMWARE_VOLUME_HEADER
))
131 EfiConvertPointer (0x0, (VOID
**) &mFvbModuleGlobal
);
132 QemuFlashConvertPointers ();
137 InstallVirtualAddressChangeHandler (
142 EFI_EVENT VirtualAddressChangeEvent
;
144 Status
= gBS
->CreateEventEx (
147 FvbVirtualAddressChangeEvent
,
149 &gEfiEventVirtualAddressChangeGuid
,
150 &VirtualAddressChangeEvent
152 ASSERT_EFI_ERROR (Status
);
156 MarkIoMemoryRangeForRuntimeAccess (
157 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
162 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
165 // Mark flash region as runtime memory
167 Status
= gDS
->RemoveMemorySpace (
172 Status
= gDS
->AddMemorySpace (
173 EfiGcdMemoryTypeMemoryMappedIo
,
176 EFI_MEMORY_UC
| EFI_MEMORY_RUNTIME
178 ASSERT_EFI_ERROR (Status
);
180 Status
= gDS
->AllocateMemorySpace (
181 EfiGcdAllocateAddress
,
182 EfiGcdMemoryTypeMemoryMappedIo
,
189 ASSERT_EFI_ERROR (Status
);
191 Status
= gDS
->GetMemorySpaceDescriptor (BaseAddress
, &GcdDescriptor
);
192 ASSERT_EFI_ERROR (Status
);
194 Status
= gDS
->SetMemorySpaceAttributes (
197 GcdDescriptor
.Attributes
| EFI_MEMORY_RUNTIME
199 ASSERT_EFI_ERROR (Status
);
202 // When SEV is active, AmdSevDxe mapped the BaseAddress with C=0 but
203 // SetMemorySpaceAttributes() remaps the range with C=1. Let's restore
204 // the mapping so that both guest and hyervisor can access the flash
207 if (MemEncryptSevIsEnabled ()) {
208 Status
= MemEncryptSevClearPageEncMask (
211 EFI_SIZE_TO_PAGES (Length
),
214 ASSERT_EFI_ERROR (Status
);