TianoCore EDK2 master
Loading...
Searching...
No Matches
SmmIoLib.c
Go to the documentation of this file.
1
13#include <PiSmm.h>
14
15#include <Library/BaseLib.h>
17#include <Library/DebugLib.h>
21#include <Library/HobLib.h>
25
26EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mSmmIoLibGcdMemSpace = NULL;
27UINTN mSmmIoLibGcdMemNumberOfDesc = 0;
28
29EFI_PHYSICAL_ADDRESS mSmmIoLibInternalMaximumSupportMemAddress = 0;
30
31VOID *mSmmIoLibRegistrationEndOfDxe;
32VOID *mSmmIoLibRegistrationReadyToLock;
33
34BOOLEAN mSmmIoLibReadyToLock = FALSE;
35
40VOID
42 VOID
43 )
44{
45 VOID *Hob;
46 UINT32 RegEax;
47 UINT8 MemPhysicalAddressBits;
48
49 //
50 // Get physical address bits supported.
51 //
52 Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
53 if (Hob != NULL) {
54 MemPhysicalAddressBits = ((EFI_HOB_CPU *)Hob)->SizeOfMemorySpace;
55 } else {
56 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
57 if (RegEax >= 0x80000008) {
58 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
59 MemPhysicalAddressBits = (UINT8)RegEax;
60 } else {
61 MemPhysicalAddressBits = 36;
62 }
63 }
64
65 //
66 // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
67 //
68 ASSERT (MemPhysicalAddressBits <= 52);
69 if (MemPhysicalAddressBits > 48) {
70 MemPhysicalAddressBits = 48;
71 }
72
73 //
74 // Save the maximum support address in one global variable
75 //
76 mSmmIoLibInternalMaximumSupportMemAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, MemPhysicalAddressBits) - 1);
77 DEBUG ((DEBUG_INFO, "mSmmIoLibInternalMaximumSupportMemAddress = 0x%lx\n", mSmmIoLibInternalMaximumSupportMemAddress));
78}
79
93BOOLEAN
94EFIAPI
96 IN EFI_PHYSICAL_ADDRESS BaseAddress,
97 IN UINT64 Length,
98 IN EFI_GUID *Owner OPTIONAL
99 )
100{
101 UINTN Index;
103 BOOLEAN InValidRegion;
104
105 //
106 // Check override.
107 // NOTE: (B:0->L:4G) is invalid for IA32, but (B:1->L:4G-1)/(B:4G-1->L:1) is valid.
108 //
109 if ((Length > mSmmIoLibInternalMaximumSupportMemAddress) ||
110 (BaseAddress > mSmmIoLibInternalMaximumSupportMemAddress) ||
111 ((Length != 0) && (BaseAddress > (mSmmIoLibInternalMaximumSupportMemAddress - (Length - 1)))))
112 {
113 //
114 // Overflow happen
115 //
116 DEBUG ((
117 DEBUG_ERROR,
118 "SmmIsMmioValid: Overflow: BaseAddress (0x%lx) - Length (0x%lx), MaximumSupportMemAddress (0x%lx)\n",
119 BaseAddress,
120 Length,
121 mSmmIoLibInternalMaximumSupportMemAddress
122 ));
123 return FALSE;
124 }
125
126 //
127 // Check override for valid MMIO region
128 //
129 if (mSmmIoLibReadyToLock) {
130 InValidRegion = FALSE;
131 for (Index = 0; Index < mSmmIoLibGcdMemNumberOfDesc; Index++) {
132 Desc = &mSmmIoLibGcdMemSpace[Index];
133 if ((Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&
134 (BaseAddress >= Desc->BaseAddress) &&
135 ((BaseAddress + Length) <= (Desc->BaseAddress + Desc->Length)))
136 {
137 InValidRegion = TRUE;
138 }
139 }
140
141 if (!InValidRegion) {
142 DEBUG ((
143 DEBUG_ERROR,
144 "SmmIsMmioValid: Not in valid MMIO region: BaseAddress (0x%lx) - Length (0x%lx)\n",
145 BaseAddress,
146 Length
147 ));
148 return FALSE;
149 }
150 }
151
152 return TRUE;
153}
154
165STATIC
166VOID
169 IN OUT UINTN *NumberOfDescriptors
170 )
171{
172 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *GcdMemoryMapEntry;
173 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *GcdMemoryMapEnd;
174 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *NewGcdMemoryMapEntry;
175 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *NextGcdMemoryMapEntry;
176
177 GcdMemoryMapEntry = GcdMemoryMap;
178 NewGcdMemoryMapEntry = GcdMemoryMap;
179 GcdMemoryMapEnd = (EFI_GCD_MEMORY_SPACE_DESCRIPTOR *)((UINT8 *)GcdMemoryMap + (*NumberOfDescriptors) * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));
180 while ((UINTN)GcdMemoryMapEntry < (UINTN)GcdMemoryMapEnd) {
181 CopyMem (NewGcdMemoryMapEntry, GcdMemoryMapEntry, sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));
182 NextGcdMemoryMapEntry = GcdMemoryMapEntry + 1;
183
184 do {
185 if (((UINTN)NextGcdMemoryMapEntry < (UINTN)GcdMemoryMapEnd) &&
186 (GcdMemoryMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && (NextGcdMemoryMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&
187 ((GcdMemoryMapEntry->BaseAddress + GcdMemoryMapEntry->Length) == NextGcdMemoryMapEntry->BaseAddress))
188 {
189 GcdMemoryMapEntry->Length += NextGcdMemoryMapEntry->Length;
190 if (NewGcdMemoryMapEntry != GcdMemoryMapEntry) {
191 NewGcdMemoryMapEntry->Length += NextGcdMemoryMapEntry->Length;
192 }
193
194 NextGcdMemoryMapEntry = NextGcdMemoryMapEntry + 1;
195 continue;
196 } else {
197 GcdMemoryMapEntry = NextGcdMemoryMapEntry - 1;
198 break;
199 }
200 } while (TRUE);
201
202 GcdMemoryMapEntry = GcdMemoryMapEntry + 1;
203 NewGcdMemoryMapEntry = NewGcdMemoryMapEntry + 1;
204 }
205
206 *NumberOfDescriptors = ((UINTN)NewGcdMemoryMapEntry - (UINTN)GcdMemoryMap) / sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR);
207
208 return;
209}
210
222EFIAPI
224 IN CONST EFI_GUID *Protocol,
225 IN VOID *Interface,
226 IN EFI_HANDLE Handle
227 )
228{
229 UINTN NumberOfDescriptors;
231 EFI_STATUS Status;
232
233 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemSpaceMap);
234 if (!EFI_ERROR (Status)) {
235 MergeGcdMmioEntry (MemSpaceMap, &NumberOfDescriptors);
236
237 mSmmIoLibGcdMemSpace = AllocateCopyPool (NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR), MemSpaceMap);
238 ASSERT (mSmmIoLibGcdMemSpace != NULL);
239 if (mSmmIoLibGcdMemSpace == NULL) {
240 gBS->FreePool (MemSpaceMap);
241 return EFI_OUT_OF_RESOURCES;
242 }
243
244 mSmmIoLibGcdMemNumberOfDesc = NumberOfDescriptors;
245 gBS->FreePool (MemSpaceMap);
246 }
247
248 return EFI_SUCCESS;
249}
250
261EFIAPI
263 IN CONST EFI_GUID *Protocol,
264 IN VOID *Interface,
265 IN EFI_HANDLE Handle
266 )
267{
268 mSmmIoLibReadyToLock = TRUE;
269 return EFI_SUCCESS;
270}
271
282EFIAPI
284 IN EFI_HANDLE ImageHandle,
285 IN EFI_SYSTEM_TABLE *SystemTable
286 )
287{
288 EFI_STATUS Status;
289
290 //
291 // Calculate and save maximum support address
292 //
294
295 //
296 // Register EndOfDxe to get GCD resource map
297 //
298 Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, SmmIoLibInternalEndOfDxeNotify, &mSmmIoLibRegistrationEndOfDxe);
299 ASSERT_EFI_ERROR (Status);
300
301 //
302 // Register ready to lock so that we can know when to check valid resource region
303 //
304 Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid, SmmIoLibInternalReadyToLockNotify, &mSmmIoLibRegistrationReadyToLock);
305 ASSERT_EFI_ERROR (Status);
306
307 return EFI_SUCCESS;
308}
309
319EFIAPI
321 IN EFI_HANDLE ImageHandle,
322 IN EFI_SYSTEM_TABLE *SystemTable
323 )
324{
325 gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, NULL, &mSmmIoLibRegistrationEndOfDxe);
326 gSmst->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid, NULL, &mSmmIoLibRegistrationReadyToLock);
327 return EFI_SUCCESS;
328}
UINT64 UINTN
VOID *EFIAPI GetFirstHob(IN UINT16 Type)
Definition: HobLib.c:142
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_DXE_SERVICES * gDS
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
UINT32 EFIAPI AsmCpuid(IN UINT32 Index, OUT UINT32 *RegisterEax OPTIONAL, OUT UINT32 *RegisterEbx OPTIONAL, OUT UINT32 *RegisterEcx OPTIONAL, OUT UINT32 *RegisterEdx OPTIONAL)
Definition: CpuId.c:36
@ EfiGcdMemoryTypeMemoryMappedIo
Definition: PiDxeCis.h:44
EFI_SMM_SYSTEM_TABLE2 * gSmst
EFI_STATUS EFIAPI SmmIoLibInternalEndOfDxeNotify(IN CONST EFI_GUID *Protocol, IN VOID *Interface, IN EFI_HANDLE Handle)
Definition: SmmIoLib.c:223
VOID SmmIoLibInternalCalculateMaximumSupportAddress(VOID)
Definition: SmmIoLib.c:41
EFI_STATUS EFIAPI SmmIoLibDestructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: SmmIoLib.c:320
EFI_STATUS EFIAPI SmmIoLibInternalReadyToLockNotify(IN CONST EFI_GUID *Protocol, IN VOID *Interface, IN EFI_HANDLE Handle)
Definition: SmmIoLib.c:262
EFI_STATUS EFIAPI SmmIoLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: SmmIoLib.c:283
STATIC VOID MergeGcdMmioEntry(IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *GcdMemoryMap, IN OUT UINTN *NumberOfDescriptors)
Definition: SmmIoLib.c:167
BOOLEAN EFIAPI SmmIsMmioValid(IN EFI_PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN EFI_GUID *Owner OPTIONAL)
Definition: SmmIoLib.c:95
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_GCD_MEMORY_TYPE GcdMemoryType
Definition: PiDxeCis.h:152
EFI_PHYSICAL_ADDRESS BaseAddress
Definition: PiDxeCis.h:130
Definition: Base.h:213