summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg')
-rw-r--r--MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c64
1 files changed, 62 insertions, 2 deletions
diff --git a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
index c1c5c6267c..2fb78d8f96 100644
--- a/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
+++ b/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
@@ -960,13 +960,25 @@ NonCoherentPciIoFreeBuffer (
LIST_ENTRY *Entry;
EFI_STATUS Status;
NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;
+ NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *AllocHead;
+ NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *AllocTail;
BOOLEAN Found;
+ UINTN StartPages;
+ UINTN EndPages;
+
+ if (HostAddress != ALIGN_POINTER (HostAddress, EFI_PAGE_SIZE)) {
+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+ return EFI_INVALID_PARAMETER;
+ }
Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This);
Found = FALSE;
Alloc = NULL;
+ AllocHead = NULL;
+ AllocTail = NULL;
+
//
// Find the uncached allocation list entry associated
// with this allocation
@@ -976,9 +988,19 @@ NonCoherentPciIoFreeBuffer (
Entry = Entry->ForwardLink)
{
Alloc = BASE_CR (Entry, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);
- if ((Alloc->HostAddress == HostAddress) && (Alloc->NumPages == Pages)) {
+
+ StartPages = 0;
+ if (Alloc->HostAddress < HostAddress) {
+ StartPages = EFI_SIZE_TO_PAGES (
+ (UINTN)HostAddress - (UINTN)Alloc->HostAddress
+ );
+ }
+
+ if ((Alloc->HostAddress <= HostAddress) &&
+ (Alloc->NumPages >= (Pages + StartPages)))
+ {
//
- // We are freeing the exact allocation we were given
+ // We are freeing at least part of what we were given
// before by AllocateBuffer()
//
Found = TRUE;
@@ -991,7 +1013,45 @@ NonCoherentPciIoFreeBuffer (
return EFI_NOT_FOUND;
}
+ EndPages = Alloc->NumPages - (Pages + StartPages);
+
+ if (StartPages != 0) {
+ AllocHead = AllocatePool (sizeof *AllocHead);
+ if (AllocHead == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AllocHead->HostAddress = Alloc->HostAddress;
+
+ AllocHead->NumPages = StartPages;
+ AllocHead->Attributes = Alloc->Attributes;
+ }
+
+ if (EndPages != 0) {
+ AllocTail = AllocatePool (sizeof *AllocTail);
+ if (AllocTail == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AllocTail->HostAddress = (UINT8 *)Alloc->HostAddress +
+ EFI_PAGES_TO_SIZE (Pages + StartPages);
+
+ AllocTail->NumPages = EndPages;
+ AllocTail->Attributes = Alloc->Attributes;
+ }
+
RemoveEntryList (&Alloc->List);
+ //
+ // Record this new sub allocations in the linked list, so we
+ // can restore the memory space attributes later
+ //
+ if (AllocHead != NULL) {
+ InsertHeadList (&Dev->UncachedAllocationList, &AllocHead->List);
+ }
+
+ if (AllocTail != NULL) {
+ InsertHeadList (&Dev->UncachedAllocationList, &AllocTail->List);
+ }
Status = gDS->SetMemorySpaceAttributes (
(EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,