]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
OvmfPkg/QemuFlashFvbServices: factor out SetPcdFlashNvStorageBaseAddresses
[mirror_edk2.git] / OvmfPkg / QemuFlashFvbServicesRuntimeDxe / FwBlockServiceDxe.c
CommitLineData
1767877a
LE
1/**@file\r
2 Functions related to the Firmware Volume Block service whose\r
3 implementation is specific to the runtime DXE driver build.\r
4\r
5 Copyright (C) 2015, Red Hat, Inc.\r
6 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
7\r
b26f0cf9 8 SPDX-License-Identifier: BSD-2-Clause-Patent\r
1767877a
LE
9**/\r
10\r
11#include <Guid/EventGroup.h>\r
12#include <Library/DebugLib.h>\r
13#include <Library/DevicePathLib.h>\r
3b3d016b 14#include <Library/DxeServicesTableLib.h>\r
75b7aa95 15#include <Library/MemEncryptSevLib.h>\r
b963ec49 16#include <Library/PcdLib.h>\r
1767877a
LE
17#include <Library/UefiBootServicesTableLib.h>\r
18#include <Library/UefiRuntimeLib.h>\r
19#include <Protocol/DevicePath.h>\r
20#include <Protocol/FirmwareVolumeBlock.h>\r
21\r
22#include "FwBlockService.h"\r
23#include "QemuFlash.h"\r
24\r
25VOID\r
26InstallProtocolInterfaces (\r
27 IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice\r
28 )\r
29{\r
30 EFI_STATUS Status;\r
31 EFI_HANDLE FwbHandle;\r
32 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface;\r
33\r
b963ec49
LE
34 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));\r
35\r
1767877a
LE
36 //\r
37 // Find a handle with a matching device path that has supports FW Block\r
38 // protocol\r
39 //\r
40 Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid,\r
41 &FvbDevice->DevicePath, &FwbHandle);\r
42 if (EFI_ERROR (Status)) {\r
43 //\r
44 // LocateDevicePath fails so install a new interface and device path\r
45 //\r
46 FwbHandle = NULL;\r
47 DEBUG ((EFI_D_INFO, "Installing QEMU flash FVB\n"));\r
48 Status = gBS->InstallMultipleProtocolInterfaces (\r
49 &FwbHandle,\r
50 &gEfiFirmwareVolumeBlockProtocolGuid,\r
51 &FvbDevice->FwVolBlockInstance,\r
52 &gEfiDevicePathProtocolGuid,\r
53 FvbDevice->DevicePath,\r
54 NULL\r
55 );\r
56 ASSERT_EFI_ERROR (Status);\r
57 } else if (IsDevicePathEnd (FvbDevice->DevicePath)) {\r
58 //\r
59 // Device already exists, so reinstall the FVB protocol\r
60 //\r
61 Status = gBS->HandleProtocol (\r
62 FwbHandle,\r
63 &gEfiFirmwareVolumeBlockProtocolGuid,\r
64 (VOID**)&OldFwbInterface\r
65 );\r
66 ASSERT_EFI_ERROR (Status);\r
67\r
68 DEBUG ((EFI_D_INFO, "Reinstalling FVB for QEMU flash region\n"));\r
69 Status = gBS->ReinstallProtocolInterface (\r
70 FwbHandle,\r
71 &gEfiFirmwareVolumeBlockProtocolGuid,\r
72 OldFwbInterface,\r
73 &FvbDevice->FwVolBlockInstance\r
74 );\r
75 ASSERT_EFI_ERROR (Status);\r
76 } else {\r
77 //\r
78 // There was a FVB protocol on an End Device Path node\r
79 //\r
80 ASSERT (FALSE);\r
81 }\r
82}\r
83\r
84\r
85STATIC\r
86VOID\r
87EFIAPI\r
88FvbVirtualAddressChangeEvent (\r
89 IN EFI_EVENT Event,\r
90 IN VOID *Context\r
91 )\r
92/*++\r
93\r
94 Routine Description:\r
95\r
96 Fixup internal data so that EFI and SAL can be call in virtual mode.\r
97 Call the passed in Child Notify event and convert the mFvbModuleGlobal\r
98 date items to there virtual address.\r
99\r
100 Arguments:\r
101\r
102 (Standard EFI notify event - EFI_EVENT_NOTIFY)\r
103\r
104 Returns:\r
105\r
106 None\r
107\r
108--*/\r
109{\r
110 EFI_FW_VOL_INSTANCE *FwhInstance;\r
111 UINTN Index;\r
112\r
113 FwhInstance = mFvbModuleGlobal->FvInstance;\r
114 EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal->FvInstance);\r
115\r
116 //\r
117 // Convert the base address of all the instances\r
118 //\r
119 Index = 0;\r
120 while (Index < mFvbModuleGlobal->NumFv) {\r
121 EfiConvertPointer (0x0, (VOID **) &FwhInstance->FvBase);\r
122 FwhInstance = (EFI_FW_VOL_INSTANCE *)\r
123 (\r
124 (UINTN) ((UINT8 *) FwhInstance) +\r
125 FwhInstance->VolumeHeader.HeaderLength +\r
126 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))\r
127 );\r
128 Index++;\r
129 }\r
130\r
131 EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal);\r
132 QemuFlashConvertPointers ();\r
133}\r
134\r
135\r
136VOID\r
137InstallVirtualAddressChangeHandler (\r
138 VOID\r
139 )\r
140{\r
141 EFI_STATUS Status;\r
142 EFI_EVENT VirtualAddressChangeEvent;\r
143\r
144 Status = gBS->CreateEventEx (\r
145 EVT_NOTIFY_SIGNAL,\r
146 TPL_NOTIFY,\r
147 FvbVirtualAddressChangeEvent,\r
148 NULL,\r
149 &gEfiEventVirtualAddressChangeGuid,\r
150 &VirtualAddressChangeEvent\r
151 );\r
152 ASSERT_EFI_ERROR (Status);\r
153}\r
3b3d016b
BS
154\r
155EFI_STATUS\r
156MarkIoMemoryRangeForRuntimeAccess (\r
157 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
158 IN UINTN Length\r
159 )\r
160{\r
161 EFI_STATUS Status;\r
162 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
163\r
164 //\r
165 // Mark flash region as runtime memory\r
166 //\r
167 Status = gDS->RemoveMemorySpace (\r
168 BaseAddress,\r
169 Length\r
170 );\r
171\r
172 Status = gDS->AddMemorySpace (\r
173 EfiGcdMemoryTypeMemoryMappedIo,\r
174 BaseAddress,\r
175 Length,\r
176 EFI_MEMORY_UC | EFI_MEMORY_RUNTIME\r
177 );\r
178 ASSERT_EFI_ERROR (Status);\r
179\r
180 Status = gDS->AllocateMemorySpace (\r
181 EfiGcdAllocateAddress,\r
182 EfiGcdMemoryTypeMemoryMappedIo,\r
183 0,\r
184 Length,\r
185 &BaseAddress,\r
186 gImageHandle,\r
187 NULL\r
188 );\r
189 ASSERT_EFI_ERROR (Status);\r
190\r
191 Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);\r
192 ASSERT_EFI_ERROR (Status);\r
193\r
194 Status = gDS->SetMemorySpaceAttributes (\r
195 BaseAddress,\r
196 Length,\r
197 GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME\r
198 );\r
199 ASSERT_EFI_ERROR (Status);\r
200\r
75b7aa95
BS
201 //\r
202 // When SEV is active, AmdSevDxe mapped the BaseAddress with C=0 but\r
203 // SetMemorySpaceAttributes() remaps the range with C=1. Let's restore\r
204 // the mapping so that both guest and hyervisor can access the flash\r
205 // memory range.\r
206 //\r
207 if (MemEncryptSevIsEnabled ()) {\r
208 Status = MemEncryptSevClearPageEncMask (\r
209 0,\r
210 BaseAddress,\r
211 EFI_SIZE_TO_PAGES (Length),\r
212 FALSE\r
213 );\r
214 ASSERT_EFI_ERROR (Status);\r
215 }\r
216\r
3b3d016b
BS
217 return Status;\r
218}\r
cd99d07d
LE
219\r
220VOID\r
221SetPcdFlashNvStorageBaseAddresses (\r
222 VOID\r
223 )\r
224{\r
225 RETURN_STATUS PcdStatus;\r
226\r
227 //\r
228 // Set several PCD values to point to flash\r
229 //\r
230 PcdStatus = PcdSet64S (\r
231 PcdFlashNvStorageVariableBase64,\r
232 (UINTN) PcdGet32 (PcdOvmfFlashNvStorageVariableBase)\r
233 );\r
234 ASSERT_RETURN_ERROR (PcdStatus);\r
235 PcdStatus = PcdSet32S (\r
236 PcdFlashNvStorageFtwWorkingBase,\r
237 PcdGet32 (PcdOvmfFlashNvStorageFtwWorkingBase)\r
238 );\r
239 ASSERT_RETURN_ERROR (PcdStatus);\r
240 PcdStatus = PcdSet32S (\r
241 PcdFlashNvStorageFtwSpareBase,\r
242 PcdGet32 (PcdOvmfFlashNvStorageFtwSpareBase)\r
243 );\r
244 ASSERT_RETURN_ERROR (PcdStatus);\r
245}\r