TianoCore EDK2 master
Loading...
Searching...
No Matches
DxeRuntimePciSegmentLib.c
Go to the documentation of this file.
1
12#include "PciSegmentLibCommon.h"
13#include <PiDxe.h>
14#include <Guid/EventGroup.h>
20
24typedef struct {
25 UINTN PhysicalAddress;
26 UINTN VirtualAddress;
28
33
38
43
48
56VOID
57EFIAPI
59 IN EFI_EVENT Event,
60 IN VOID *Context
61 )
62{
63 UINTN Index;
64 EFI_STATUS Status;
65
66 //
67 // If there have been no runtime registrations, then just return
68 //
70 return;
71 }
72
73 //
74 // Convert physical addresses associated with the set of registered PCI devices to
75 // virtual addresses.
76 //
77 for (Index = 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) {
78 Status = EfiConvertPointer (0, (VOID **)&(mDxeRuntimePciSegmentLibRegistrationTable[Index].VirtualAddress));
79 ASSERT_EFI_ERROR (Status);
80 }
81
82 //
83 // Convert table pointer that is allocated from EfiRuntimeServicesData to a virtual address.
84 //
86 ASSERT_EFI_ERROR (Status);
87}
88
101EFIAPI
103 IN EFI_HANDLE ImageHandle,
104 IN EFI_SYSTEM_TABLE *SystemTable
105 )
106{
107 EFI_STATUS Status;
108
109 //
110 // Register SetVirtualAddressMap () notify function
111 //
112 Status = gBS->CreateEvent (
113 EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
114 TPL_NOTIFY,
116 NULL,
118 );
119 ASSERT_EFI_ERROR (Status);
120
121 return Status;
122}
123
136EFIAPI
138 IN EFI_HANDLE ImageHandle,
139 IN EFI_SYSTEM_TABLE *SystemTable
140 )
141{
142 EFI_STATUS Status;
143
144 //
145 // If one or more PCI devices have been registered for runtime access, then
146 // free the registration table.
147 //
150 }
151
152 //
153 // Close the Set Virtual Address Map event
154 //
155 Status = gBS->CloseEvent (mDxeRuntimePciSegmentLibVirtualNotifyEvent);
156 ASSERT_EFI_ERROR (Status);
157
158 return Status;
159}
160
179RETURN_STATUS
180EFIAPI
182 IN UINTN Address
183 )
184{
185 RETURN_STATUS Status;
187 UINTN Index;
188 VOID *NewTable;
189 UINTN Count;
190 PCI_SEGMENT_INFO *SegmentInfo;
191 UINT64 EcamAddress;
192
193 //
194 // Convert Address to a ECAM address at the beginning of the PCI Configuration
195 // header for the specified PCI Bus/Dev/Func
196 //
197 Address &= ~(UINTN)EFI_PAGE_MASK;
198 SegmentInfo = GetPciSegmentInfo (&Count);
199 EcamAddress = PciSegmentLibGetEcamAddress (Address, SegmentInfo, Count);
200
201 //
202 // Return an error if this function is called after ExitBootServices().
203 //
204 if (EfiAtRuntime ()) {
205 return RETURN_UNSUPPORTED;
206 }
207
208 if (sizeof (UINTN) == sizeof (UINT32)) {
209 ASSERT (EcamAddress < BASE_4GB);
210 }
211
212 Address = (UINTN)EcamAddress;
213
214 //
215 // See if Address has already been registered for runtime access
216 //
217 for (Index = 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) {
218 if (mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress == Address) {
219 return RETURN_SUCCESS;
220 }
221 }
222
223 //
224 // Get the GCD Memory Descriptor for the ECAM Address
225 //
226 Status = gDS->GetMemorySpaceDescriptor (Address, &Descriptor);
227 if (EFI_ERROR (Status)) {
228 return RETURN_UNSUPPORTED;
229 }
230
231 //
232 // Mark the 4KB region for the PCI Express Bus/Dev/Func as EFI_RUNTIME_MEMORY so the OS
233 // will allocate a virtual address range for the 4KB PCI Configuration Header.
234 //
235 Status = gDS->SetMemorySpaceAttributes (Address, EFI_PAGE_SIZE, Descriptor.Attributes | EFI_MEMORY_RUNTIME);
236 if (EFI_ERROR (Status)) {
237 return RETURN_UNSUPPORTED;
238 }
239
240 //
241 // Grow the size of the registration table
242 //
243 NewTable = ReallocateRuntimePool (
247 );
248 if (NewTable == NULL) {
250 }
251
256
257 return RETURN_SUCCESS;
258}
259
267UINTN
269 IN UINTN Address
270 )
271{
272 UINTN Index;
273
274 //
275 // If SetVirtualAddressMap() has not been called, then just return the physical address
276 //
277 if (!EfiGoneVirtual ()) {
278 return Address;
279 }
280
281 //
282 // See if there is a physical address match at the exact same index as the last address match
283 //
284 if (mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibLastRuntimeRange].PhysicalAddress == (Address & (~(UINTN)EFI_PAGE_MASK))) {
285 //
286 // Convert the physical address to a virtual address and return the virtual address
287 //
288 return (Address & EFI_PAGE_MASK) + mDxeRuntimePciSegmentLibRegistrationTable[mDxeRuntimePciSegmentLibLastRuntimeRange].VirtualAddress;
289 }
290
291 //
292 // Search the entire table for a physical address match
293 //
294 for (Index = 0; Index < mDxeRuntimePciSegmentLibNumberOfRuntimeRanges; Index++) {
295 if (mDxeRuntimePciSegmentLibRegistrationTable[Index].PhysicalAddress == (Address & (~(UINTN)EFI_PAGE_MASK))) {
296 //
297 // Cache the matching index value
298 //
300 //
301 // Convert the physical address to a virtual address and return the virtual address
302 //
303 return (Address & EFI_PAGE_MASK) + mDxeRuntimePciSegmentLibRegistrationTable[Index].VirtualAddress;
304 }
305 }
306
307 //
308 // No match was found. This is a critical error at OS runtime, so ASSERT() and force a breakpoint.
309 //
310 ASSERT (FALSE);
311 CpuBreakpoint ();
312
313 //
314 // Return the physical address
315 //
316 return Address;
317}
UINT64 UINTN
VOID EFIAPI CpuBreakpoint(VOID)
Definition: CpuBreakpoint.c:26
UINTN mDxeRuntimePciSegmentLibLastRuntimeRange
UINTN PciSegmentLibVirtualAddress(IN UINTN Address)
EFI_STATUS EFIAPI DxeRuntimePciSegmentLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
RETURN_STATUS EFIAPI PciSegmentRegisterForRuntimeAccess(IN UINTN Address)
PCI_SEGMENT_RUNTIME_REGISTRATION_TABLE * mDxeRuntimePciSegmentLibRegistrationTable
EFI_STATUS EFIAPI DxeRuntimePciSegmentLibDestructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_EVENT mDxeRuntimePciSegmentLibVirtualNotifyEvent
VOID EFIAPI DxeRuntimePciSegmentLibVirtualNotify(IN EFI_EVENT Event, IN VOID *Context)
UINTN mDxeRuntimePciSegmentLibNumberOfRuntimeRanges
EFI_DXE_SERVICES * gDS
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI ReallocateRuntimePool(IN UINTN OldSize, IN UINTN NewSize, IN VOID *OldBuffer OPTIONAL)
#define NULL
Definition: Base.h:319
#define RETURN_UNSUPPORTED
Definition: Base.h:1081
#define RETURN_OUT_OF_RESOURCES
Definition: Base.h:1114
#define RETURN_SUCCESS
Definition: Base.h:1066
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
PCI_SEGMENT_INFO *EFIAPI GetPciSegmentInfo(UINTN *Count)
UINTN PciSegmentLibGetEcamAddress(IN UINT64 Address, IN CONST PCI_SEGMENT_INFO *SegmentInfo, IN UINTN Count)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
EFI_BOOT_SERVICES * gBS
BOOLEAN EFIAPI EfiAtRuntime(VOID)
Definition: RuntimeLib.c:167
EFI_STATUS EFIAPI EfiConvertPointer(IN UINTN DebugDisposition, IN OUT VOID **Address)
Definition: RuntimeLib.c:561
BOOLEAN EFIAPI EfiGoneVirtual(VOID)
Definition: RuntimeLib.c:188