3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php.
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #include "DmaProtection.h"
16 EFI_ACPI_SDT_PROTOCOL
*mAcpiSdt
;
17 UINT64 mBelow4GMemoryLimit
;
18 UINT64 mAbove4GMemoryLimit
;
20 EDKII_PLATFORM_VTD_POLICY_PROTOCOL
*mPlatformVTdPolicy
;
23 return the UEFI memory information.
25 @param[out] Below4GMemoryLimit The below 4GiB memory limit
26 @param[out] Above4GMemoryLimit The above 4GiB memory limit
30 OUT UINT64
*Below4GMemoryLimit
,
31 OUT UINT64
*Above4GMemoryLimit
35 EFI_MEMORY_DESCRIPTOR
*EfiMemoryMap
;
36 EFI_MEMORY_DESCRIPTOR
*EfiMemoryMapEnd
;
37 EFI_MEMORY_DESCRIPTOR
*EfiEntry
;
38 EFI_MEMORY_DESCRIPTOR
*NextEfiEntry
;
39 EFI_MEMORY_DESCRIPTOR TempEfiEntry
;
40 UINTN EfiMemoryMapSize
;
42 UINTN EfiDescriptorSize
;
43 UINT32 EfiDescriptorVersion
;
44 UINT64 MemoryBlockLength
;
46 *Below4GMemoryLimit
= 0;
47 *Above4GMemoryLimit
= 0;
50 // Get the EFI memory map.
54 Status
= gBS
->GetMemoryMap (
61 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
65 // Use size returned back plus 1 descriptor for the AllocatePool.
66 // We don't just multiply by 2 since the "for" loop below terminates on
67 // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize
68 // we process bogus entries and create bogus E820 entries.
70 EfiMemoryMap
= (EFI_MEMORY_DESCRIPTOR
*) AllocatePool (EfiMemoryMapSize
);
71 ASSERT (EfiMemoryMap
!= NULL
);
72 Status
= gBS
->GetMemoryMap (
79 if (EFI_ERROR (Status
)) {
80 FreePool (EfiMemoryMap
);
82 } while (Status
== EFI_BUFFER_TOO_SMALL
);
84 ASSERT_EFI_ERROR (Status
);
87 // Sort memory map from low to high
89 EfiEntry
= EfiMemoryMap
;
90 NextEfiEntry
= NEXT_MEMORY_DESCRIPTOR (EfiEntry
, EfiDescriptorSize
);
91 EfiMemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) EfiMemoryMap
+ EfiMemoryMapSize
);
92 while (EfiEntry
< EfiMemoryMapEnd
) {
93 while (NextEfiEntry
< EfiMemoryMapEnd
) {
94 if (EfiEntry
->PhysicalStart
> NextEfiEntry
->PhysicalStart
) {
95 CopyMem (&TempEfiEntry
, EfiEntry
, sizeof (EFI_MEMORY_DESCRIPTOR
));
96 CopyMem (EfiEntry
, NextEfiEntry
, sizeof (EFI_MEMORY_DESCRIPTOR
));
97 CopyMem (NextEfiEntry
, &TempEfiEntry
, sizeof (EFI_MEMORY_DESCRIPTOR
));
100 NextEfiEntry
= NEXT_MEMORY_DESCRIPTOR (NextEfiEntry
, EfiDescriptorSize
);
103 EfiEntry
= NEXT_MEMORY_DESCRIPTOR (EfiEntry
, EfiDescriptorSize
);
104 NextEfiEntry
= NEXT_MEMORY_DESCRIPTOR (EfiEntry
, EfiDescriptorSize
);
110 DEBUG ((DEBUG_INFO
, "MemoryMap:\n"));
111 EfiEntry
= EfiMemoryMap
;
112 EfiMemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) EfiMemoryMap
+ EfiMemoryMapSize
);
113 while (EfiEntry
< EfiMemoryMapEnd
) {
114 MemoryBlockLength
= (UINT64
) (LShiftU64 (EfiEntry
->NumberOfPages
, 12));
115 DEBUG ((DEBUG_INFO
, "Entry(0x%02x) 0x%016lx - 0x%016lx\n", EfiEntry
->Type
, EfiEntry
->PhysicalStart
, EfiEntry
->PhysicalStart
+ MemoryBlockLength
));
116 switch (EfiEntry
->Type
) {
119 case EfiBootServicesCode
:
120 case EfiBootServicesData
:
121 case EfiConventionalMemory
:
122 case EfiRuntimeServicesCode
:
123 case EfiRuntimeServicesData
:
124 case EfiACPIReclaimMemory
:
125 case EfiACPIMemoryNVS
:
126 case EfiReservedMemoryType
:
127 if ((EfiEntry
->PhysicalStart
+ MemoryBlockLength
) <= BASE_1MB
) {
129 // Skip the memory block is under 1MB
131 } else if (EfiEntry
->PhysicalStart
>= BASE_4GB
) {
132 if (*Above4GMemoryLimit
< EfiEntry
->PhysicalStart
+ MemoryBlockLength
) {
133 *Above4GMemoryLimit
= EfiEntry
->PhysicalStart
+ MemoryBlockLength
;
136 if (*Below4GMemoryLimit
< EfiEntry
->PhysicalStart
+ MemoryBlockLength
) {
137 *Below4GMemoryLimit
= EfiEntry
->PhysicalStart
+ MemoryBlockLength
;
142 EfiEntry
= NEXT_MEMORY_DESCRIPTOR (EfiEntry
, EfiDescriptorSize
);
145 FreePool (EfiMemoryMap
);
147 DEBUG ((DEBUG_INFO
, "Result:\n"));
148 DEBUG ((DEBUG_INFO
, "Below4GMemoryLimit: 0x%016lx\n", *Below4GMemoryLimit
));
149 DEBUG ((DEBUG_INFO
, "Above4GMemoryLimit: 0x%016lx\n", *Above4GMemoryLimit
));
155 Initialize platform VTd policy.
158 InitializePlatformVTdPolicy (
163 UINTN DeviceInfoCount
;
164 EDKII_PLATFORM_VTD_DEVICE_INFO
*DeviceInfo
;
170 Status
= gBS
->LocateProtocol (
171 &gEdkiiPlatformVTdPolicyProtocolGuid
,
173 (VOID
**)&mPlatformVTdPolicy
175 if (!EFI_ERROR(Status
)) {
176 Status
= mPlatformVTdPolicy
->GetExceptionDeviceList (mPlatformVTdPolicy
, &DeviceInfoCount
, &DeviceInfo
);
177 if (!EFI_ERROR(Status
)) {
178 for (Index
= 0; Index
< DeviceInfoCount
; Index
++) {
179 AlwaysEnablePageAttribute (DeviceInfo
[Index
].Segment
, DeviceInfo
[Index
].SourceId
);
181 FreePool (DeviceInfo
);
195 VOID
*PciEnumerationComplete
;
197 UINT64 Below4GMemoryLimit
;
198 UINT64 Above4GMemoryLimit
;
201 // PCI Enumeration must be done
203 Status
= gBS
->LocateProtocol (
204 &gEfiPciEnumerationCompleteProtocolGuid
,
206 &PciEnumerationComplete
208 ASSERT_EFI_ERROR (Status
);
210 ReturnUefiMemoryMap (&Below4GMemoryLimit
, &Above4GMemoryLimit
);
211 Below4GMemoryLimit
= ALIGN_VALUE_UP(Below4GMemoryLimit
, SIZE_256MB
);
212 DEBUG ((DEBUG_INFO
, " Adjusted Below4GMemoryLimit: 0x%016lx\n", Below4GMemoryLimit
));
214 mBelow4GMemoryLimit
= Below4GMemoryLimit
;
215 mAbove4GMemoryLimit
= Above4GMemoryLimit
;
220 DEBUG ((DEBUG_INFO
, "GetDmarAcpiTable\n"));
221 Status
= GetDmarAcpiTable ();
222 if (EFI_ERROR (Status
)) {
225 DEBUG ((DEBUG_INFO
, "ParseDmarAcpiTable\n"));
226 Status
= ParseDmarAcpiTableDrhd ();
227 if (EFI_ERROR (Status
)) {
230 DEBUG ((DEBUG_INFO
, "PrepareVtdConfig\n"));
236 DEBUG ((DEBUG_INFO
, "SetupTranslationTable\n"));
237 Status
= SetupTranslationTable ();
238 if (EFI_ERROR (Status
)) {
242 InitializePlatformVTdPolicy ();
244 ParseDmarAcpiTableRmrr ();
246 for (Index
= 0; Index
< mVtdUnitNumber
; Index
++) {
247 DEBUG ((DEBUG_INFO
,"VTD Unit %d (Segment: %04x)\n", Index
, mVtdUnitInformation
[Index
].Segment
));
248 if (mVtdUnitInformation
[Index
].ExtRootEntryTable
!= NULL
) {
249 DumpDmarExtContextEntryTable (mVtdUnitInformation
[Index
].ExtRootEntryTable
);
251 if (mVtdUnitInformation
[Index
].RootEntryTable
!= NULL
) {
252 DumpDmarContextEntryTable (mVtdUnitInformation
[Index
].RootEntryTable
);
259 DEBUG ((DEBUG_INFO
, "EnableDmar\n"));
260 Status
= EnableDmar ();
261 if (EFI_ERROR (Status
)) {
264 DEBUG ((DEBUG_INFO
, "DumpVtdRegs\n"));
269 ACPI notification function.
271 @param[in] Table A pointer to the ACPI table header.
272 @param[in] Version The ACPI table's version.
273 @param[in] TableKey The table key for this ACPI table.
275 @retval EFI_SUCCESS The notification function is executed.
279 AcpiNotificationFunc (
280 IN EFI_ACPI_SDT_HEADER
*Table
,
281 IN EFI_ACPI_TABLE_VERSION Version
,
285 if (Table
->Signature
== EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE
) {
286 DEBUG((DEBUG_INFO
, "Vtd AcpiNotificationFunc\n"));
293 Exit boot service callback function.
295 @param[in] Event The event handle.
296 @param[in] Context The event content.
305 DEBUG ((DEBUG_INFO
, "Vtd OnExitBootServices\n"));
312 Legacy boot callback function.
314 @param[in] Event The event handle.
315 @param[in] Context The event content.
324 DEBUG ((DEBUG_INFO
, "Vtd OnLegacyBoot\n"));
331 Initialize DMA protection.
334 InitializeDmaProtection (
339 EFI_EVENT ExitBootServicesEvent
;
340 EFI_EVENT LegacyBootEvent
;
342 Status
= gBS
->LocateProtocol (&gEfiAcpiSdtProtocolGuid
, NULL
, (VOID
**) &mAcpiSdt
);
343 ASSERT_EFI_ERROR (Status
);
345 Status
= mAcpiSdt
->RegisterNotify (TRUE
, AcpiNotificationFunc
);
346 ASSERT_EFI_ERROR (Status
);
348 Status
= gBS
->CreateEventEx (
353 &gEfiEventExitBootServicesGuid
,
354 &ExitBootServicesEvent
356 ASSERT_EFI_ERROR (Status
);
358 Status
= EfiCreateEventLegacyBootEx (
364 ASSERT_EFI_ERROR (Status
);