} MAP_INFO;\r
\r
//\r
-// List of MAP_INFO structures recycled by Unmap().\r
+// List of the MAP_INFO structures that have been set up by IoMmuMap() and not\r
+// yet torn down by IoMmuUnmap(). The list represents the full set of mappings\r
+// currently in effect.\r
//\r
-// Recycled MAP_INFO structures are equally good for future recycling and\r
-// freeing.\r
-//\r
-STATIC LIST_ENTRY mRecycledMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (\r
- mRecycledMapInfos\r
- );\r
+STATIC LIST_ENTRY mMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (mMapInfos);\r
\r
#define COMMON_BUFFER_SIG SIGNATURE_64 ('C', 'M', 'N', 'B', 'U', 'F', 'F', 'R')\r
\r
)\r
{\r
EFI_STATUS Status;\r
- LIST_ENTRY *RecycledMapInfo;\r
MAP_INFO *MapInfo;\r
EFI_ALLOCATE_TYPE AllocateType;\r
COMMON_BUFFER_HEADER *CommonBufferHeader;\r
// Allocate a MAP_INFO structure to remember the mapping when Unmap() is\r
// called later.\r
//\r
- RecycledMapInfo = GetFirstNode (&mRecycledMapInfos);\r
- if (RecycledMapInfo == &mRecycledMapInfos) {\r
- //\r
- // No recycled MAP_INFO structure, allocate a new one.\r
- //\r
- MapInfo = AllocatePool (sizeof (MAP_INFO));\r
- if (MapInfo == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Failed;\r
- }\r
- } else {\r
- MapInfo = CR (RecycledMapInfo, MAP_INFO, Link, MAP_INFO_SIG);\r
- RemoveEntryList (RecycledMapInfo);\r
+ MapInfo = AllocatePool (sizeof (MAP_INFO));\r
+ if (MapInfo == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Failed;\r
}\r
\r
//\r
);\r
}\r
\r
+ //\r
+ // Track all MAP_INFO structures.\r
+ //\r
+ InsertHeadList (&mMapInfos, &MapInfo->Link);\r
//\r
// Populate output parameters.\r
//\r
/**\r
Completes the Map() operation and releases any corresponding resources.\r
\r
+ This is an internal worker function that only extends the Map() API with\r
+ the MemoryMapLocked parameter.\r
+\r
@param This The protocol instance pointer.\r
@param Mapping The mapping value returned from Map().\r
+ @param MemoryMapLocked The function is executing on the stack of\r
+ gBS->ExitBootServices(); changes to the UEFI\r
+ memory map are forbidden.\r
\r
@retval EFI_SUCCESS The range was unmapped.\r
@retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by\r
@retval EFI_DEVICE_ERROR The data was not committed to the target system\r
memory.\r
**/\r
+STATIC\r
EFI_STATUS\r
EFIAPI\r
-IoMmuUnmap (\r
+IoMmuUnmapWorker (\r
IN EDKII_IOMMU_PROTOCOL *This,\r
- IN VOID *Mapping\r
+ IN VOID *Mapping,\r
+ IN BOOLEAN MemoryMapLocked\r
)\r
{\r
MAP_INFO *MapInfo;\r
COMMON_BUFFER_HEADER *CommonBufferHeader;\r
VOID *EncryptionTarget;\r
\r
- DEBUG ((DEBUG_VERBOSE, "%a: Mapping=0x%p\n", __FUNCTION__, Mapping));\r
+ DEBUG ((\r
+ DEBUG_VERBOSE,\r
+ "%a: Mapping=0x%p MemoryMapLocked=%d\n",\r
+ __FUNCTION__,\r
+ Mapping,\r
+ MemoryMapLocked\r
+ ));\r
\r
if (Mapping == NULL) {\r
return EFI_INVALID_PARAMETER;\r
// original (now encrypted) location.\r
//\r
// For all other operations, fill the late bounce buffer (which existed as\r
- // plaintext at some point) with zeros, and then release it.\r
+ // plaintext at some point) with zeros, and then release it (unless the UEFI\r
+ // memory map is locked).\r
//\r
if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||\r
MapInfo->Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {\r
CommonBufferHeader->StashBuffer,\r
MapInfo->NumberOfBytes\r
);\r
-\r
- //\r
- // Recycle the MAP_INFO structure.\r
- //\r
- InsertTailList (&mRecycledMapInfos, &MapInfo->Link);\r
} else {\r
ZeroMem (\r
(VOID *)(UINTN)MapInfo->PlainTextAddress,\r
EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages)\r
);\r
- gBS->FreePages (MapInfo->PlainTextAddress, MapInfo->NumberOfPages);\r
+ if (!MemoryMapLocked) {\r
+ gBS->FreePages (MapInfo->PlainTextAddress, MapInfo->NumberOfPages);\r
+ }\r
+ }\r
\r
- //\r
- // Free the MAP_INFO structure.\r
- //\r
+ //\r
+ // Forget the MAP_INFO structure, then free it (unless the UEFI memory map is\r
+ // locked).\r
+ //\r
+ RemoveEntryList (&MapInfo->Link);\r
+ if (!MemoryMapLocked) {\r
FreePool (MapInfo);\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Completes the Map() operation and releases any corresponding resources.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param Mapping The mapping value returned from Map().\r
+\r
+ @retval EFI_SUCCESS The range was unmapped.\r
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by\r
+ Map().\r
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system\r
+ memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IoMmuUnmap (\r
+ IN EDKII_IOMMU_PROTOCOL *This,\r
+ IN VOID *Mapping\r
+ )\r
+{\r
+ return IoMmuUnmapWorker (\r
+ This,\r
+ Mapping,\r
+ FALSE // MemoryMapLocked\r
+ );\r
+}\r
+\r
/**\r
Allocates pages that are suitable for an OperationBusMasterCommonBuffer or\r
OperationBusMasterCommonBuffer64 mapping.\r