+ MapInfo->PlainTextAddress = MAX_ADDRESS;\r
+ AllocateType = AllocateAnyPages;\r
+ DecryptionSource = (VOID *)(UINTN)MapInfo->CryptedAddress;\r
+ switch (Operation) {\r
+ //\r
+ // For BusMasterRead[64] and BusMasterWrite[64] operations, a bounce buffer\r
+ // is necessary regardless of whether the original (crypted) buffer crosses\r
+ // the 4GB limit or not -- we have to allocate a separate plaintext buffer.\r
+ // The only variable is whether the plaintext buffer should be under 4GB.\r
+ //\r
+ case EdkiiIoMmuOperationBusMasterRead:\r
+ case EdkiiIoMmuOperationBusMasterWrite:\r
+ MapInfo->PlainTextAddress = BASE_4GB - 1;\r
+ AllocateType = AllocateMaxAddress;\r
+ //\r
+ // fall through\r
+ //\r
+ case EdkiiIoMmuOperationBusMasterRead64:\r
+ case EdkiiIoMmuOperationBusMasterWrite64:\r
+ //\r
+ // Allocate the implicit plaintext bounce buffer.\r
+ //\r
+ Status = gBS->AllocatePages (\r
+ AllocateType,\r
+ EfiBootServicesData,\r
+ MapInfo->NumberOfPages,\r
+ &MapInfo->PlainTextAddress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto FreeMapInfo;\r
+ }\r
+ break;\r
+\r
+ //\r
+ // For BusMasterCommonBuffer[64] operations, a to-be-plaintext buffer and a\r
+ // stash buffer (for in-place decryption) have been allocated already, with\r
+ // AllocateBuffer(). We only check whether the address of the to-be-plaintext\r
+ // buffer is low enough for the requested operation.\r
+ //\r
+ case EdkiiIoMmuOperationBusMasterCommonBuffer:\r
+ if ((MapInfo->CryptedAddress > BASE_4GB) ||\r
+ (EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages) >\r
+ BASE_4GB - MapInfo->CryptedAddress)) {\r
+ //\r
+ // CommonBuffer operations cannot be remapped. If the common buffer is\r
+ // above 4GB, then it is not possible to generate a mapping, so return an\r
+ // error.\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+ goto FreeMapInfo;\r
+ }\r
+ //\r
+ // fall through\r
+ //\r
+ case EdkiiIoMmuOperationBusMasterCommonBuffer64:\r
+ //\r
+ // The buffer at MapInfo->CryptedAddress comes from AllocateBuffer().\r
+ //\r
+ MapInfo->PlainTextAddress = MapInfo->CryptedAddress;\r
+ //\r
+ // Stash the crypted data.\r
+ //\r
+ CommonBufferHeader = (COMMON_BUFFER_HEADER *)(\r
+ (UINTN)MapInfo->CryptedAddress - EFI_PAGE_SIZE\r
+ );\r
+ ASSERT (CommonBufferHeader->Signature == COMMON_BUFFER_SIG);\r
+ CopyMem (\r
+ CommonBufferHeader->StashBuffer,\r
+ (VOID *)(UINTN)MapInfo->CryptedAddress,\r
+ MapInfo->NumberOfBytes\r
+ );\r
+ //\r
+ // Point "DecryptionSource" to the stash buffer so that we decrypt\r
+ // it to the original location, after the switch statement.\r
+ //\r
+ DecryptionSource = CommonBufferHeader->StashBuffer;\r
+ break;\r
+\r
+ default:\r
+ //\r
+ // Operation is invalid\r
+ //\r
+ Status = EFI_INVALID_PARAMETER;\r
+ goto FreeMapInfo;\r