]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
ac0a286f 27 IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice\r
1767877a
LE
28 )\r
29{\r
ac0a286f
MK
30 EFI_STATUS Status;\r
31 EFI_HANDLE FwbHandle;\r
32 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface;\r
1767877a 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
ac0a286f
MK
40 Status = gBS->LocateDevicePath (\r
41 &gEfiFirmwareVolumeBlockProtocolGuid,\r
42 &FvbDevice->DevicePath,\r
43 &FwbHandle\r
44 );\r
1767877a
LE
45 if (EFI_ERROR (Status)) {\r
46 //\r
47 // LocateDevicePath fails so install a new interface and device path\r
48 //\r
49 FwbHandle = NULL;\r
70d5086c 50 DEBUG ((DEBUG_INFO, "Installing QEMU flash FVB\n"));\r
1767877a
LE
51 Status = gBS->InstallMultipleProtocolInterfaces (\r
52 &FwbHandle,\r
53 &gEfiFirmwareVolumeBlockProtocolGuid,\r
54 &FvbDevice->FwVolBlockInstance,\r
55 &gEfiDevicePathProtocolGuid,\r
56 FvbDevice->DevicePath,\r
57 NULL\r
58 );\r
59 ASSERT_EFI_ERROR (Status);\r
60 } else if (IsDevicePathEnd (FvbDevice->DevicePath)) {\r
61 //\r
62 // Device already exists, so reinstall the FVB protocol\r
63 //\r
64 Status = gBS->HandleProtocol (\r
65 FwbHandle,\r
66 &gEfiFirmwareVolumeBlockProtocolGuid,\r
ac0a286f 67 (VOID **)&OldFwbInterface\r
1767877a
LE
68 );\r
69 ASSERT_EFI_ERROR (Status);\r
70\r
70d5086c 71 DEBUG ((DEBUG_INFO, "Reinstalling FVB for QEMU flash region\n"));\r
1767877a
LE
72 Status = gBS->ReinstallProtocolInterface (\r
73 FwbHandle,\r
74 &gEfiFirmwareVolumeBlockProtocolGuid,\r
75 OldFwbInterface,\r
76 &FvbDevice->FwVolBlockInstance\r
77 );\r
78 ASSERT_EFI_ERROR (Status);\r
79 } else {\r
80 //\r
81 // There was a FVB protocol on an End Device Path node\r
82 //\r
83 ASSERT (FALSE);\r
84 }\r
85}\r
86\r
1767877a
LE
87STATIC\r
88VOID\r
89EFIAPI\r
90FvbVirtualAddressChangeEvent (\r
ac0a286f
MK
91 IN EFI_EVENT Event,\r
92 IN VOID *Context\r
1767877a 93 )\r
ac0a286f 94\r
1767877a
LE
95/*++\r
96\r
97 Routine Description:\r
98\r
99 Fixup internal data so that EFI and SAL can be call in virtual mode.\r
100 Call the passed in Child Notify event and convert the mFvbModuleGlobal\r
101 date items to there virtual address.\r
102\r
103 Arguments:\r
104\r
105 (Standard EFI notify event - EFI_EVENT_NOTIFY)\r
106\r
107 Returns:\r
108\r
109 None\r
110\r
111--*/\r
112{\r
ac0a286f
MK
113 EFI_FW_VOL_INSTANCE *FwhInstance;\r
114 UINTN Index;\r
1767877a
LE
115\r
116 FwhInstance = mFvbModuleGlobal->FvInstance;\r
ac0a286f 117 EfiConvertPointer (0x0, (VOID **)&mFvbModuleGlobal->FvInstance);\r
1767877a
LE
118\r
119 //\r
120 // Convert the base address of all the instances\r
121 //\r
ac0a286f 122 Index = 0;\r
1767877a 123 while (Index < mFvbModuleGlobal->NumFv) {\r
ac0a286f 124 EfiConvertPointer (0x0, (VOID **)&FwhInstance->FvBase);\r
1767877a 125 FwhInstance = (EFI_FW_VOL_INSTANCE *)\r
ac0a286f
MK
126 (\r
127 (UINTN)((UINT8 *)FwhInstance) +\r
128 FwhInstance->VolumeHeader.HeaderLength +\r
129 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))\r
130 );\r
1767877a
LE
131 Index++;\r
132 }\r
133\r
ac0a286f 134 EfiConvertPointer (0x0, (VOID **)&mFvbModuleGlobal);\r
1767877a
LE
135 QemuFlashConvertPointers ();\r
136}\r
137\r
1767877a
LE
138VOID\r
139InstallVirtualAddressChangeHandler (\r
140 VOID\r
141 )\r
142{\r
ac0a286f
MK
143 EFI_STATUS Status;\r
144 EFI_EVENT VirtualAddressChangeEvent;\r
1767877a
LE
145\r
146 Status = gBS->CreateEventEx (\r
147 EVT_NOTIFY_SIGNAL,\r
148 TPL_NOTIFY,\r
149 FvbVirtualAddressChangeEvent,\r
150 NULL,\r
151 &gEfiEventVirtualAddressChangeGuid,\r
152 &VirtualAddressChangeEvent\r
153 );\r
154 ASSERT_EFI_ERROR (Status);\r
155}\r
3b3d016b
BS
156\r
157EFI_STATUS\r
158MarkIoMemoryRangeForRuntimeAccess (\r
ac0a286f
MK
159 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
160 IN UINTN Length\r
3b3d016b
BS
161 )\r
162{\r
ac0a286f
MK
163 EFI_STATUS Status;\r
164 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;\r
3b3d016b
BS
165\r
166 //\r
167 // Mark flash region as runtime memory\r
168 //\r
169 Status = gDS->RemoveMemorySpace (\r
170 BaseAddress,\r
171 Length\r
172 );\r
173\r
174 Status = gDS->AddMemorySpace (\r
175 EfiGcdMemoryTypeMemoryMappedIo,\r
176 BaseAddress,\r
177 Length,\r
178 EFI_MEMORY_UC | EFI_MEMORY_RUNTIME\r
179 );\r
180 ASSERT_EFI_ERROR (Status);\r
181\r
182 Status = gDS->AllocateMemorySpace (\r
183 EfiGcdAllocateAddress,\r
184 EfiGcdMemoryTypeMemoryMappedIo,\r
185 0,\r
186 Length,\r
187 &BaseAddress,\r
188 gImageHandle,\r
189 NULL\r
190 );\r
191 ASSERT_EFI_ERROR (Status);\r
192\r
193 Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);\r
194 ASSERT_EFI_ERROR (Status);\r
195\r
196 Status = gDS->SetMemorySpaceAttributes (\r
197 BaseAddress,\r
198 Length,\r
199 GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME\r
200 );\r
201 ASSERT_EFI_ERROR (Status);\r
202\r
75b7aa95
BS
203 //\r
204 // When SEV is active, AmdSevDxe mapped the BaseAddress with C=0 but\r
205 // SetMemorySpaceAttributes() remaps the range with C=1. Let's restore\r
206 // the mapping so that both guest and hyervisor can access the flash\r
207 // memory range.\r
208 //\r
209 if (MemEncryptSevIsEnabled ()) {\r
8ee4e52b 210 Status = MemEncryptSevClearMmioPageEncMask (\r
75b7aa95
BS
211 0,\r
212 BaseAddress,\r
8ee4e52b 213 EFI_SIZE_TO_PAGES (Length)\r
75b7aa95
BS
214 );\r
215 ASSERT_EFI_ERROR (Status);\r
216 }\r
217\r
3b3d016b
BS
218 return Status;\r
219}\r
cd99d07d
LE
220\r
221VOID\r
222SetPcdFlashNvStorageBaseAddresses (\r
223 VOID\r
224 )\r
225{\r
ac0a286f 226 RETURN_STATUS PcdStatus;\r
cd99d07d
LE
227\r
228 //\r
229 // Set several PCD values to point to flash\r
230 //\r
231 PcdStatus = PcdSet64S (\r
ac0a286f
MK
232 PcdFlashNvStorageVariableBase64,\r
233 (UINTN)PcdGet32 (PcdOvmfFlashNvStorageVariableBase)\r
234 );\r
cd99d07d
LE
235 ASSERT_RETURN_ERROR (PcdStatus);\r
236 PcdStatus = PcdSet32S (\r
ac0a286f
MK
237 PcdFlashNvStorageFtwWorkingBase,\r
238 PcdGet32 (PcdOvmfFlashNvStorageFtwWorkingBase)\r
239 );\r
cd99d07d
LE
240 ASSERT_RETURN_ERROR (PcdStatus);\r
241 PcdStatus = PcdSet32S (\r
ac0a286f
MK
242 PcdFlashNvStorageFtwSpareBase,\r
243 PcdGet32 (PcdOvmfFlashNvStorageFtwSpareBase)\r
244 );\r
cd99d07d
LE
245 ASSERT_RETURN_ERROR (PcdStatus);\r
246}\r