]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockServiceDxe.c
OvmfPkg/QemuFlashFvbServicesRuntimeDxe: Do not expose MMIO in SMM build
[mirror_edk2.git] / OvmfPkg / QemuFlashFvbServicesRuntimeDxe / FwBlockServiceDxe.c
1 /**@file
2 Functions related to the Firmware Volume Block service whose
3 implementation is specific to the runtime DXE driver build.
4
5 Copyright (C) 2015, Red Hat, Inc.
6 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
7
8 This program and the accompanying materials are licensed and made available
9 under the terms and conditions of the BSD License which accompanies this
10 distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 **/
16
17 #include <Guid/EventGroup.h>
18 #include <Library/DebugLib.h>
19 #include <Library/DevicePathLib.h>
20 #include <Library/DxeServicesTableLib.h>
21 #include <Library/PcdLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/UefiRuntimeLib.h>
24 #include <Protocol/DevicePath.h>
25 #include <Protocol/FirmwareVolumeBlock.h>
26
27 #include "FwBlockService.h"
28 #include "QemuFlash.h"
29
30 VOID
31 InstallProtocolInterfaces (
32 IN EFI_FW_VOL_BLOCK_DEVICE *FvbDevice
33 )
34 {
35 EFI_STATUS Status;
36 EFI_HANDLE FwbHandle;
37 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface;
38
39 ASSERT (!FeaturePcdGet (PcdSmmSmramRequire));
40
41 //
42 // Find a handle with a matching device path that has supports FW Block
43 // protocol
44 //
45 Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid,
46 &FvbDevice->DevicePath, &FwbHandle);
47 if (EFI_ERROR (Status)) {
48 //
49 // LocateDevicePath fails so install a new interface and device path
50 //
51 FwbHandle = NULL;
52 DEBUG ((EFI_D_INFO, "Installing QEMU flash FVB\n"));
53 Status = gBS->InstallMultipleProtocolInterfaces (
54 &FwbHandle,
55 &gEfiFirmwareVolumeBlockProtocolGuid,
56 &FvbDevice->FwVolBlockInstance,
57 &gEfiDevicePathProtocolGuid,
58 FvbDevice->DevicePath,
59 NULL
60 );
61 ASSERT_EFI_ERROR (Status);
62 } else if (IsDevicePathEnd (FvbDevice->DevicePath)) {
63 //
64 // Device already exists, so reinstall the FVB protocol
65 //
66 Status = gBS->HandleProtocol (
67 FwbHandle,
68 &gEfiFirmwareVolumeBlockProtocolGuid,
69 (VOID**)&OldFwbInterface
70 );
71 ASSERT_EFI_ERROR (Status);
72
73 DEBUG ((EFI_D_INFO, "Reinstalling FVB for QEMU flash region\n"));
74 Status = gBS->ReinstallProtocolInterface (
75 FwbHandle,
76 &gEfiFirmwareVolumeBlockProtocolGuid,
77 OldFwbInterface,
78 &FvbDevice->FwVolBlockInstance
79 );
80 ASSERT_EFI_ERROR (Status);
81 } else {
82 //
83 // There was a FVB protocol on an End Device Path node
84 //
85 ASSERT (FALSE);
86 }
87 }
88
89
90 STATIC
91 VOID
92 EFIAPI
93 FvbVirtualAddressChangeEvent (
94 IN EFI_EVENT Event,
95 IN VOID *Context
96 )
97 /*++
98
99 Routine Description:
100
101 Fixup internal data so that EFI and SAL can be call in virtual mode.
102 Call the passed in Child Notify event and convert the mFvbModuleGlobal
103 date items to there virtual address.
104
105 Arguments:
106
107 (Standard EFI notify event - EFI_EVENT_NOTIFY)
108
109 Returns:
110
111 None
112
113 --*/
114 {
115 EFI_FW_VOL_INSTANCE *FwhInstance;
116 UINTN Index;
117
118 FwhInstance = mFvbModuleGlobal->FvInstance;
119 EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal->FvInstance);
120
121 //
122 // Convert the base address of all the instances
123 //
124 Index = 0;
125 while (Index < mFvbModuleGlobal->NumFv) {
126 EfiConvertPointer (0x0, (VOID **) &FwhInstance->FvBase);
127 FwhInstance = (EFI_FW_VOL_INSTANCE *)
128 (
129 (UINTN) ((UINT8 *) FwhInstance) +
130 FwhInstance->VolumeHeader.HeaderLength +
131 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
132 );
133 Index++;
134 }
135
136 EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal);
137 QemuFlashConvertPointers ();
138 }
139
140
141 VOID
142 InstallVirtualAddressChangeHandler (
143 VOID
144 )
145 {
146 EFI_STATUS Status;
147 EFI_EVENT VirtualAddressChangeEvent;
148
149 Status = gBS->CreateEventEx (
150 EVT_NOTIFY_SIGNAL,
151 TPL_NOTIFY,
152 FvbVirtualAddressChangeEvent,
153 NULL,
154 &gEfiEventVirtualAddressChangeGuid,
155 &VirtualAddressChangeEvent
156 );
157 ASSERT_EFI_ERROR (Status);
158 }
159
160 EFI_STATUS
161 MarkIoMemoryRangeForRuntimeAccess (
162 IN EFI_PHYSICAL_ADDRESS BaseAddress,
163 IN UINTN Length
164 )
165 {
166 EFI_STATUS Status;
167 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor;
168
169 //
170 // Mark flash region as runtime memory
171 //
172 Status = gDS->RemoveMemorySpace (
173 BaseAddress,
174 Length
175 );
176
177 Status = gDS->AddMemorySpace (
178 EfiGcdMemoryTypeMemoryMappedIo,
179 BaseAddress,
180 Length,
181 EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
182 );
183 ASSERT_EFI_ERROR (Status);
184
185 Status = gDS->AllocateMemorySpace (
186 EfiGcdAllocateAddress,
187 EfiGcdMemoryTypeMemoryMappedIo,
188 0,
189 Length,
190 &BaseAddress,
191 gImageHandle,
192 NULL
193 );
194 ASSERT_EFI_ERROR (Status);
195
196 Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor);
197 ASSERT_EFI_ERROR (Status);
198
199 Status = gDS->SetMemorySpaceAttributes (
200 BaseAddress,
201 Length,
202 GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME
203 );
204 ASSERT_EFI_ERROR (Status);
205
206 return Status;
207 }