123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689 |
- /** @file
- Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "DmaProtection.h"
- UINT64 mBelow4GMemoryLimit;
- UINT64 mAbove4GMemoryLimit;
- EDKII_PLATFORM_VTD_POLICY_PROTOCOL *mPlatformVTdPolicy;
- VTD_ACCESS_REQUEST *mAccessRequest = NULL;
- UINTN mAccessRequestCount = 0;
- UINTN mAccessRequestMaxCount = 0;
- /**
- Append VTd Access Request to global.
- @param[in] Segment The Segment used to identify a VTd engine.
- @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
- @param[in] BaseAddress The base of device memory address to be used as the DMA memory.
- @param[in] Length The length of device memory address to be used as the DMA memory.
- @param[in] IoMmuAccess The IOMMU access.
- @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
- @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
- @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
- @retval EFI_INVALID_PARAMETER Length is 0.
- @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
- @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
- @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.
- @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
- @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
- **/
- EFI_STATUS
- RequestAccessAttribute (
- IN UINT16 Segment,
- IN VTD_SOURCE_ID SourceId,
- IN UINT64 BaseAddress,
- IN UINT64 Length,
- IN UINT64 IoMmuAccess
- )
- {
- VTD_ACCESS_REQUEST *NewAccessRequest;
- UINTN Index;
- //
- // Optimization for memory.
- //
- // If the last record is to IoMmuAccess=0,
- // Check previous records and remove the matched entry.
- //
- if (IoMmuAccess == 0) {
- for (Index = 0; Index < mAccessRequestCount; Index++) {
- if ((mAccessRequest[Index].Segment == Segment) &&
- (mAccessRequest[Index].SourceId.Uint16 == SourceId.Uint16) &&
- (mAccessRequest[Index].BaseAddress == BaseAddress) &&
- (mAccessRequest[Index].Length == Length) &&
- (mAccessRequest[Index].IoMmuAccess != 0)) {
- //
- // Remove this record [Index].
- // No need to add the new record.
- //
- if (Index != mAccessRequestCount - 1) {
- CopyMem (
- &mAccessRequest[Index],
- &mAccessRequest[Index + 1],
- sizeof (VTD_ACCESS_REQUEST) * (mAccessRequestCount - 1 - Index)
- );
- }
- ZeroMem (&mAccessRequest[mAccessRequestCount - 1], sizeof(VTD_ACCESS_REQUEST));
- mAccessRequestCount--;
- return EFI_SUCCESS;
- }
- }
- }
- if (mAccessRequestCount >= mAccessRequestMaxCount) {
- NewAccessRequest = AllocateZeroPool (sizeof(*NewAccessRequest) * (mAccessRequestMaxCount + MAX_VTD_ACCESS_REQUEST));
- if (NewAccessRequest == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- mAccessRequestMaxCount += MAX_VTD_ACCESS_REQUEST;
- if (mAccessRequest != NULL) {
- CopyMem (NewAccessRequest, mAccessRequest, sizeof(*NewAccessRequest) * mAccessRequestCount);
- FreePool (mAccessRequest);
- }
- mAccessRequest = NewAccessRequest;
- }
- ASSERT (mAccessRequestCount < mAccessRequestMaxCount);
- mAccessRequest[mAccessRequestCount].Segment = Segment;
- mAccessRequest[mAccessRequestCount].SourceId = SourceId;
- mAccessRequest[mAccessRequestCount].BaseAddress = BaseAddress;
- mAccessRequest[mAccessRequestCount].Length = Length;
- mAccessRequest[mAccessRequestCount].IoMmuAccess = IoMmuAccess;
- mAccessRequestCount++;
- return EFI_SUCCESS;
- }
- /**
- Process Access Requests from before DMAR table is installed.
- **/
- VOID
- ProcessRequestedAccessAttribute (
- VOID
- )
- {
- UINTN Index;
- EFI_STATUS Status;
- DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute ...\n"));
- for (Index = 0; Index < mAccessRequestCount; Index++) {
- DEBUG ((
- DEBUG_INFO,
- "PCI(S%x.B%x.D%x.F%x) ",
- mAccessRequest[Index].Segment,
- mAccessRequest[Index].SourceId.Bits.Bus,
- mAccessRequest[Index].SourceId.Bits.Device,
- mAccessRequest[Index].SourceId.Bits.Function
- ));
- DEBUG ((
- DEBUG_INFO,
- "(0x%lx~0x%lx) - %lx\n",
- mAccessRequest[Index].BaseAddress,
- mAccessRequest[Index].Length,
- mAccessRequest[Index].IoMmuAccess
- ));
- Status = SetAccessAttribute (
- mAccessRequest[Index].Segment,
- mAccessRequest[Index].SourceId,
- mAccessRequest[Index].BaseAddress,
- mAccessRequest[Index].Length,
- mAccessRequest[Index].IoMmuAccess
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "SetAccessAttribute %r: ", Status));
- }
- }
- if (mAccessRequest != NULL) {
- FreePool (mAccessRequest);
- }
- mAccessRequest = NULL;
- mAccessRequestCount = 0;
- mAccessRequestMaxCount = 0;
- DEBUG ((DEBUG_INFO, "ProcessRequestedAccessAttribute Done\n"));
- }
- /**
- Return UEFI memory map information.
- @param[out] Below4GMemoryLimit The below 4GiB memory limit address or 0 if insufficient resources exist to
- determine the address.
- @param[out] Above4GMemoryLimit The above 4GiB memory limit address or 0 if insufficient resources exist to
- determine the address.
- **/
- VOID
- ReturnUefiMemoryMap (
- OUT UINT64 *Below4GMemoryLimit,
- OUT UINT64 *Above4GMemoryLimit
- )
- {
- EFI_STATUS Status;
- EFI_MEMORY_DESCRIPTOR *EfiMemoryMap;
- EFI_MEMORY_DESCRIPTOR *EfiMemoryMapEnd;
- EFI_MEMORY_DESCRIPTOR *EfiEntry;
- EFI_MEMORY_DESCRIPTOR *NextEfiEntry;
- EFI_MEMORY_DESCRIPTOR TempEfiEntry;
- UINTN EfiMemoryMapSize;
- UINTN EfiMapKey;
- UINTN EfiDescriptorSize;
- UINT32 EfiDescriptorVersion;
- UINT64 MemoryBlockLength;
- *Below4GMemoryLimit = 0;
- *Above4GMemoryLimit = 0;
- //
- // Get the EFI memory map.
- //
- EfiMemoryMapSize = 0;
- EfiMemoryMap = NULL;
- Status = gBS->GetMemoryMap (
- &EfiMemoryMapSize,
- EfiMemoryMap,
- &EfiMapKey,
- &EfiDescriptorSize,
- &EfiDescriptorVersion
- );
- ASSERT (Status == EFI_BUFFER_TOO_SMALL);
- do {
- //
- // Use size returned back plus 1 descriptor for the AllocatePool.
- // We don't just multiply by 2 since the "for" loop below terminates on
- // EfiMemoryMapEnd which is dependent upon EfiMemoryMapSize. Otherwize
- // we process bogus entries and create bogus E820 entries.
- //
- EfiMemoryMap = (EFI_MEMORY_DESCRIPTOR *) AllocatePool (EfiMemoryMapSize);
- if (EfiMemoryMap == NULL) {
- ASSERT (EfiMemoryMap != NULL);
- return;
- }
- Status = gBS->GetMemoryMap (
- &EfiMemoryMapSize,
- EfiMemoryMap,
- &EfiMapKey,
- &EfiDescriptorSize,
- &EfiDescriptorVersion
- );
- if (EFI_ERROR (Status)) {
- FreePool (EfiMemoryMap);
- }
- } while (Status == EFI_BUFFER_TOO_SMALL);
- ASSERT_EFI_ERROR (Status);
- //
- // Sort memory map from low to high
- //
- EfiEntry = EfiMemoryMap;
- NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
- EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);
- while (EfiEntry < EfiMemoryMapEnd) {
- while (NextEfiEntry < EfiMemoryMapEnd) {
- if (EfiEntry->PhysicalStart > NextEfiEntry->PhysicalStart) {
- CopyMem (&TempEfiEntry, EfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
- CopyMem (EfiEntry, NextEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
- CopyMem (NextEfiEntry, &TempEfiEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
- }
- NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (NextEfiEntry, EfiDescriptorSize);
- }
- EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
- NextEfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
- }
- DEBUG ((DEBUG_INFO, "MemoryMap:\n"));
- EfiEntry = EfiMemoryMap;
- EfiMemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) EfiMemoryMap + EfiMemoryMapSize);
- while (EfiEntry < EfiMemoryMapEnd) {
- MemoryBlockLength = (UINT64) (LShiftU64 (EfiEntry->NumberOfPages, 12));
- DEBUG ((DEBUG_INFO, "Entry(0x%02x) 0x%016lx - 0x%016lx\n", EfiEntry->Type, EfiEntry->PhysicalStart, EfiEntry->PhysicalStart + MemoryBlockLength));
- switch (EfiEntry->Type) {
- case EfiLoaderCode:
- case EfiLoaderData:
- case EfiBootServicesCode:
- case EfiBootServicesData:
- case EfiConventionalMemory:
- case EfiRuntimeServicesCode:
- case EfiRuntimeServicesData:
- case EfiACPIReclaimMemory:
- case EfiACPIMemoryNVS:
- case EfiReservedMemoryType:
- if ((EfiEntry->PhysicalStart + MemoryBlockLength) <= BASE_1MB) {
- //
- // Skip the memory block is under 1MB
- //
- } else if (EfiEntry->PhysicalStart >= BASE_4GB) {
- if (*Above4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLength) {
- *Above4GMemoryLimit = EfiEntry->PhysicalStart + MemoryBlockLength;
- }
- } else {
- if (*Below4GMemoryLimit < EfiEntry->PhysicalStart + MemoryBlockLength) {
- *Below4GMemoryLimit = EfiEntry->PhysicalStart + MemoryBlockLength;
- }
- }
- break;
- }
- EfiEntry = NEXT_MEMORY_DESCRIPTOR (EfiEntry, EfiDescriptorSize);
- }
- FreePool (EfiMemoryMap);
- DEBUG ((DEBUG_INFO, "Result:\n"));
- DEBUG ((DEBUG_INFO, "Below4GMemoryLimit: 0x%016lx\n", *Below4GMemoryLimit));
- DEBUG ((DEBUG_INFO, "Above4GMemoryLimit: 0x%016lx\n", *Above4GMemoryLimit));
- return ;
- }
- /**
- The scan bus callback function to always enable page attribute.
- @param[in] Context The context of the callback.
- @param[in] Segment The segment of the source.
- @param[in] Bus The bus of the source.
- @param[in] Device The device of the source.
- @param[in] Function The function of the source.
- @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
- **/
- EFI_STATUS
- EFIAPI
- ScanBusCallbackAlwaysEnablePageAttribute (
- IN VOID *Context,
- IN UINT16 Segment,
- IN UINT8 Bus,
- IN UINT8 Device,
- IN UINT8 Function
- )
- {
- VTD_SOURCE_ID SourceId;
- EFI_STATUS Status;
- SourceId.Bits.Bus = Bus;
- SourceId.Bits.Device = Device;
- SourceId.Bits.Function = Function;
- Status = AlwaysEnablePageAttribute (Segment, SourceId);
- return Status;
- }
- /**
- Always enable the VTd page attribute for the device in the DeviceScope.
- @param[in] DeviceScope the input device scope data structure
- @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device in the device scope.
- **/
- EFI_STATUS
- AlwaysEnablePageAttributeDeviceScope (
- IN EDKII_PLATFORM_VTD_DEVICE_SCOPE *DeviceScope
- )
- {
- UINT8 Bus;
- UINT8 Device;
- UINT8 Function;
- VTD_SOURCE_ID SourceId;
- UINT8 SecondaryBusNumber;
- EFI_STATUS Status;
- Status = GetPciBusDeviceFunction (DeviceScope->SegmentNumber, &DeviceScope->DeviceScope, &Bus, &Device, &Function);
- if (DeviceScope->DeviceScope.Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE) {
- //
- // Need scan the bridge and add all devices.
- //
- SecondaryBusNumber = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS(DeviceScope->SegmentNumber, Bus, Device, Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
- Status = ScanPciBus (NULL, DeviceScope->SegmentNumber, SecondaryBusNumber, ScanBusCallbackAlwaysEnablePageAttribute);
- return Status;
- } else {
- SourceId.Bits.Bus = Bus;
- SourceId.Bits.Device = Device;
- SourceId.Bits.Function = Function;
- Status = AlwaysEnablePageAttribute (DeviceScope->SegmentNumber, SourceId);
- return Status;
- }
- }
- /**
- Always enable the VTd page attribute for the device matching DeviceId.
- @param[in] PciDeviceId the input PCI device ID
- @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device matching DeviceId.
- **/
- EFI_STATUS
- AlwaysEnablePageAttributePciDeviceId (
- IN EDKII_PLATFORM_VTD_PCI_DEVICE_ID *PciDeviceId
- )
- {
- UINTN VtdIndex;
- UINTN PciIndex;
- PCI_DEVICE_DATA *PciDeviceData;
- EFI_STATUS Status;
- for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {
- for (PciIndex = 0; PciIndex < mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; PciIndex++) {
- PciDeviceData = &mVtdUnitInformation[VtdIndex].PciDeviceInfo.PciDeviceData[PciIndex];
- if (((PciDeviceId->VendorId == 0xFFFF) || (PciDeviceId->VendorId == PciDeviceData->PciDeviceId.VendorId)) &&
- ((PciDeviceId->DeviceId == 0xFFFF) || (PciDeviceId->DeviceId == PciDeviceData->PciDeviceId.DeviceId)) &&
- ((PciDeviceId->RevisionId == 0xFF) || (PciDeviceId->RevisionId == PciDeviceData->PciDeviceId.RevisionId)) &&
- ((PciDeviceId->SubsystemVendorId == 0xFFFF) || (PciDeviceId->SubsystemVendorId == PciDeviceData->PciDeviceId.SubsystemVendorId)) &&
- ((PciDeviceId->SubsystemDeviceId == 0xFFFF) || (PciDeviceId->SubsystemDeviceId == PciDeviceData->PciDeviceId.SubsystemDeviceId)) ) {
- Status = AlwaysEnablePageAttribute (mVtdUnitInformation[VtdIndex].Segment, PciDeviceData->PciSourceId);
- if (EFI_ERROR(Status)) {
- continue;
- }
- }
- }
- }
- return EFI_SUCCESS;
- }
- /**
- Always enable the VTd page attribute for the device.
- @param[in] DeviceInfo the exception device information
- @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device in the device info.
- **/
- EFI_STATUS
- AlwaysEnablePageAttributeExceptionDeviceInfo (
- IN EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *DeviceInfo
- )
- {
- switch (DeviceInfo->Type) {
- case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_DEVICE_SCOPE:
- return AlwaysEnablePageAttributeDeviceScope ((VOID *)(DeviceInfo + 1));
- case EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_PCI_DEVICE_ID:
- return AlwaysEnablePageAttributePciDeviceId ((VOID *)(DeviceInfo + 1));
- default:
- return EFI_UNSUPPORTED;
- }
- }
- /**
- Initialize platform VTd policy.
- **/
- VOID
- InitializePlatformVTdPolicy (
- VOID
- )
- {
- EFI_STATUS Status;
- UINTN DeviceInfoCount;
- VOID *DeviceInfo;
- EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO *ThisDeviceInfo;
- UINTN Index;
- //
- // It is optional.
- //
- Status = gBS->LocateProtocol (
- &gEdkiiPlatformVTdPolicyProtocolGuid,
- NULL,
- (VOID **)&mPlatformVTdPolicy
- );
- if (!EFI_ERROR(Status)) {
- DEBUG ((DEBUG_INFO, "InitializePlatformVTdPolicy\n"));
- Status = mPlatformVTdPolicy->GetExceptionDeviceList (mPlatformVTdPolicy, &DeviceInfoCount, &DeviceInfo);
- if (!EFI_ERROR(Status)) {
- ThisDeviceInfo = DeviceInfo;
- for (Index = 0; Index < DeviceInfoCount; Index++) {
- if (ThisDeviceInfo->Type == EDKII_PLATFORM_VTD_EXCEPTION_DEVICE_INFO_TYPE_END) {
- break;
- }
- AlwaysEnablePageAttributeExceptionDeviceInfo (ThisDeviceInfo);
- ThisDeviceInfo = (VOID *)((UINTN)ThisDeviceInfo + ThisDeviceInfo->Length);
- }
- FreePool (DeviceInfo);
- }
- }
- }
- /**
- Setup VTd engine.
- **/
- VOID
- SetupVtd (
- VOID
- )
- {
- EFI_STATUS Status;
- VOID *PciEnumerationComplete;
- UINTN Index;
- UINT64 Below4GMemoryLimit;
- UINT64 Above4GMemoryLimit;
- //
- // PCI Enumeration must be done
- //
- Status = gBS->LocateProtocol (
- &gEfiPciEnumerationCompleteProtocolGuid,
- NULL,
- &PciEnumerationComplete
- );
- ASSERT_EFI_ERROR (Status);
- ReturnUefiMemoryMap (&Below4GMemoryLimit, &Above4GMemoryLimit);
- Below4GMemoryLimit = ALIGN_VALUE_UP(Below4GMemoryLimit, SIZE_256MB);
- DEBUG ((DEBUG_INFO, " Adjusted Below4GMemoryLimit: 0x%016lx\n", Below4GMemoryLimit));
- mBelow4GMemoryLimit = Below4GMemoryLimit;
- mAbove4GMemoryLimit = Above4GMemoryLimit;
- //
- // 1. setup
- //
- DEBUG ((DEBUG_INFO, "ParseDmarAcpiTable\n"));
- Status = ParseDmarAcpiTableDrhd ();
- if (EFI_ERROR (Status)) {
- return;
- }
- DumpVtdIfError ();
- DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));
- PrepareVtdConfig ();
- //
- // 2. initialization
- //
- DEBUG ((DEBUG_INFO, "SetupTranslationTable\n"));
- Status = SetupTranslationTable ();
- if (EFI_ERROR (Status)) {
- return;
- }
- InitializePlatformVTdPolicy ();
- ParseDmarAcpiTableRmrr ();
- if ((PcdGet8 (PcdVTdPolicyPropertyMask) & BIT2) == 0) {
- //
- // Support IOMMU access attribute request recording before DMAR table is installed.
- // Here is to process the requests.
- //
- ProcessRequestedAccessAttribute ();
- }
- for (Index = 0; Index < mVtdUnitNumber; Index++) {
- DEBUG ((DEBUG_INFO,"VTD Unit %d (Segment: %04x)\n", Index, mVtdUnitInformation[Index].Segment));
- if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
- DumpDmarExtContextEntryTable (mVtdUnitInformation[Index].ExtRootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);
- }
- if (mVtdUnitInformation[Index].RootEntryTable != NULL) {
- DumpDmarContextEntryTable (mVtdUnitInformation[Index].RootEntryTable, mVtdUnitInformation[Index].Is5LevelPaging);
- }
- }
- //
- // 3. enable
- //
- DEBUG ((DEBUG_INFO, "EnableDmar\n"));
- Status = EnableDmar ();
- if (EFI_ERROR (Status)) {
- return;
- }
- DEBUG ((DEBUG_INFO, "DumpVtdRegs\n"));
- DumpVtdRegsAll ();
- }
- /**
- Notification function of ACPI Table change.
- This is a notification function registered on ACPI Table change event.
- @param Event Event whose notification function is being invoked.
- @param Context Pointer to the notification function's context.
- **/
- VOID
- EFIAPI
- AcpiNotificationFunc (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- EFI_STATUS Status;
- Status = GetDmarAcpiTable ();
- if (EFI_ERROR (Status)) {
- if (Status == EFI_ALREADY_STARTED) {
- gBS->CloseEvent (Event);
- }
- return;
- }
- SetupVtd ();
- gBS->CloseEvent (Event);
- }
- /**
- Exit boot service callback function.
- @param[in] Event The event handle.
- @param[in] Context The event content.
- **/
- VOID
- EFIAPI
- OnExitBootServices (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- UINTN VtdIndex;
- DEBUG ((DEBUG_INFO, "Vtd OnExitBootServices\n"));
- DumpVtdRegsAll ();
- DEBUG ((DEBUG_INFO, "Invalidate all\n"));
- for (VtdIndex = 0; VtdIndex < mVtdUnitNumber; VtdIndex++) {
- FlushWriteBuffer (VtdIndex);
- InvalidateContextCache (VtdIndex);
- InvalidateIOTLB (VtdIndex);
- }
- if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {
- DisableDmar ();
- DumpVtdRegsAll ();
- }
- }
- /**
- Legacy boot callback function.
- @param[in] Event The event handle.
- @param[in] Context The event content.
- **/
- VOID
- EFIAPI
- OnLegacyBoot (
- EFI_EVENT Event,
- VOID *Context
- )
- {
- DEBUG ((DEBUG_INFO, "Vtd OnLegacyBoot\n"));
- DumpVtdRegsAll ();
- DisableDmar ();
- DumpVtdRegsAll ();
- }
- /**
- Initialize DMA protection.
- **/
- VOID
- InitializeDmaProtection (
- VOID
- )
- {
- EFI_STATUS Status;
- EFI_EVENT ExitBootServicesEvent;
- EFI_EVENT LegacyBootEvent;
- EFI_EVENT EventAcpi10;
- EFI_EVENT EventAcpi20;
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- VTD_TPL_LEVEL,
- AcpiNotificationFunc,
- NULL,
- &gEfiAcpi10TableGuid,
- &EventAcpi10
- );
- ASSERT_EFI_ERROR (Status);
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- VTD_TPL_LEVEL,
- AcpiNotificationFunc,
- NULL,
- &gEfiAcpi20TableGuid,
- &EventAcpi20
- );
- ASSERT_EFI_ERROR (Status);
- //
- // Signal the events initially for the case
- // that DMAR table has been installed.
- //
- gBS->SignalEvent (EventAcpi20);
- gBS->SignalEvent (EventAcpi10);
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- OnExitBootServices,
- NULL,
- &gEfiEventExitBootServicesGuid,
- &ExitBootServicesEvent
- );
- ASSERT_EFI_ERROR (Status);
- Status = EfiCreateEventLegacyBootEx (
- TPL_CALLBACK,
- OnLegacyBoot,
- NULL,
- &LegacyBootEvent
- );
- ASSERT_EFI_ERROR (Status);
- return ;
- }
|