LIST_ENTRY *Entry;\r
EFI_STATUS Status;\r
NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *Alloc;\r
+ NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *AllocHead;\r
+ NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION *AllocTail;\r
BOOLEAN Found;\r
+ UINTN StartPages;\r
+ UINTN EndPages;\r
+\r
+ if (HostAddress != ALIGN_POINTER (HostAddress, EFI_PAGE_SIZE)) {\r
+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
Dev = NON_DISCOVERABLE_PCI_DEVICE_FROM_PCI_IO (This);\r
\r
Found = FALSE;\r
Alloc = NULL;\r
\r
+ AllocHead = NULL;\r
+ AllocTail = NULL;\r
+\r
//\r
// Find the uncached allocation list entry associated\r
// with this allocation\r
Entry = Entry->ForwardLink)\r
{\r
Alloc = BASE_CR (Entry, NON_DISCOVERABLE_DEVICE_UNCACHED_ALLOCATION, List);\r
- if ((Alloc->HostAddress == HostAddress) && (Alloc->NumPages == Pages)) {\r
+\r
+ StartPages = 0;\r
+ if (Alloc->HostAddress < HostAddress) {\r
+ StartPages = EFI_SIZE_TO_PAGES (\r
+ (UINTN)HostAddress - (UINTN)Alloc->HostAddress\r
+ );\r
+ }\r
+\r
+ if ((Alloc->HostAddress <= HostAddress) &&\r
+ (Alloc->NumPages >= (Pages + StartPages)))\r
+ {\r
//\r
- // We are freeing the exact allocation we were given\r
+ // We are freeing at least part of what we were given\r
// before by AllocateBuffer()\r
//\r
Found = TRUE;\r
return EFI_NOT_FOUND;\r
}\r
\r
+ EndPages = Alloc->NumPages - (Pages + StartPages);\r
+\r
+ if (StartPages != 0) {\r
+ AllocHead = AllocatePool (sizeof *AllocHead);\r
+ if (AllocHead == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ AllocHead->HostAddress = Alloc->HostAddress;\r
+\r
+ AllocHead->NumPages = StartPages;\r
+ AllocHead->Attributes = Alloc->Attributes;\r
+ }\r
+\r
+ if (EndPages != 0) {\r
+ AllocTail = AllocatePool (sizeof *AllocTail);\r
+ if (AllocTail == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ AllocTail->HostAddress = (UINT8 *)Alloc->HostAddress +\r
+ EFI_PAGES_TO_SIZE (Pages + StartPages);\r
+\r
+ AllocTail->NumPages = EndPages;\r
+ AllocTail->Attributes = Alloc->Attributes;\r
+ }\r
+\r
RemoveEntryList (&Alloc->List);\r
+ //\r
+ // Record this new sub allocations in the linked list, so we\r
+ // can restore the memory space attributes later\r
+ //\r
+ if (AllocHead != NULL) {\r
+ InsertHeadList (&Dev->UncachedAllocationList, &AllocHead->List);\r
+ }\r
+\r
+ if (AllocTail != NULL) {\r
+ InsertHeadList (&Dev->UncachedAllocationList, &AllocTail->List);\r
+ }\r
\r
Status = gDS->SetMemorySpaceAttributes (\r
(EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress,\r