From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM02-SN1-obe.outbound.protection.outlook.com (mail-sn1nam02on0056.outbound.protection.outlook.com [104.47.36.56]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 0F2742095DCB3 for ; Wed, 30 Aug 2017 13:45:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector1-amd-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=lNBK0TPklP0Yu+9D0uhfRF4ippyl8DleiSs/emi8KsI=; b=4ujGcP+ZTKQh4tx+BuZ/fcLfqGS9f6zwxaNlkoH2ftGvd1hs4d3dP+AA7vJ/RV81tKX4aKoklRigRz17uF5jpahwRmElq58CZcFKgw0C0e23ke+lNWFMlUaPavDw+/BDv0yOkpenhuqxLnLuRczp1C9W+tTN4FtuZE8K9d3abH4= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=brijesh.singh@amd.com; Received: from brijesh-build-machine.amd.com (165.204.77.1) by DM2PR12MB0154.namprd12.prod.outlook.com (2a01:111:e400:50ce::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.13.10; Wed, 30 Aug 2017 20:45:19 +0000 From: Brijesh Singh To: edk2-devel@lists.01.org Cc: Brijesh Singh , Ard Biesheuvel , Jordan Justen , Tom Lendacky , Laszlo Ersek Date: Wed, 30 Aug 2017 16:45:02 -0400 Message-Id: <1504125903-29816-4-git-send-email-brijesh.singh@amd.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504125903-29816-1-git-send-email-brijesh.singh@amd.com> References: <1504125903-29816-1-git-send-email-brijesh.singh@amd.com> MIME-Version: 1.0 X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: MWHPR2201CA0040.namprd22.prod.outlook.com (2603:10b6:301:16::14) To DM2PR12MB0154.namprd12.prod.outlook.com (2a01:111:e400:50ce::17) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 589014eb-4867-4524-3688-08d4efe8076c X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(2017030254152)(48565401081)(300000503095)(300135400095)(2017052603199)(201703131423075)(201703031133081)(201702281549075)(300000504095)(300135200095)(300000505095)(300135600095)(300000506095)(300135500095); SRVR:DM2PR12MB0154; X-Microsoft-Exchange-Diagnostics: 1; DM2PR12MB0154; 3:bEGiEDdSOmxRbKSaSW/+pEGE10FNaTE/6gAP66vYLbPgOjjvIPuxd2eQJgQ/b19cEgm+ZH4xg8T5gy2SXWGqvKcgGE01P3pfqtXYo6sFHA09Ky+YDr3LjNDc6N3FyOyVEpeODx53E/N0pah1tJjNwXYbrtKeDw46zRS5pyLf0sLtGUir9Tak9jGST4rsrkOfdA4Q9/GEZV2vF6g9nm9/QfeKS56DOFWBaoWdCI60lvZXpdGWFiLP2WqxOKBeuyIK; 25:lFT4CJKyuBFYngA/aIbu5gwSKI+2owGjF5MYBT9m6GkjJLKo3IyP3a/O1sXxiYZbT2z1FHTLAdRnZqlJi2bWU0xNOPHQYEsf43mo4K1brKZDiLajwhsdgxtNSPupVqsQwTsBY0qhiwKyOkRi18Pl9BJqYrR9NNurPWKPdASgmIfzrjDqcCT6iME9qKKWwvWR33EYC7kYaItJDAsOtCkYs6dIO89obz42cJRBbZ8ql/sevjGfJGyoGvW6EuW806rfuDW9zM/mwGc95JoBCMs4ljVhZPMSTwvUsJ4Xznz4bkdA0mFvBmYaaMPxEjKiv4zBpLOcgAS1e/uQx5moUd6MIA==; 31:BwjKs2iP5f4TIHbag+PyjJpNkVPjDyJoliKZdfczktBsHr9VfXBIwoRw1JYr2VzkKaQW1rFlqGcw0I8jvTbKRtN4iqpvBEDiZraH6ToOq6in0/mbmEzAVAapjB7gG4X94VAt6ErTEq2+fi06UeDsgYH4LMlH0FU1cVxcmadPSyKYCGow0kxZtyjqQk9fB1Vy283X3Y0aRR8dxJxbRzwufAv4yJnrmkTz661tMy4o0Ck= X-MS-TrafficTypeDiagnostic: DM2PR12MB0154: X-Microsoft-Exchange-Diagnostics: 1; DM2PR12MB0154; 20:vlaODmVuXBW9AxVO1DNuicVuUBLPPvfrh4uyxZ9UU8vOgTIpeDuOQCFy70mOo8xdCVLxChV6R/Od84wlMlLQe4tKGK23cUDBsA1B/zCHaZsztBZvQhq0/dnggFEcEoxrK1Xe8lImNGb+AF9A+7N5yfCy8rDVmKF2h8R5OvAc71Zxkk0ZcKedoyJAdXrqMihP5ZafeQH2sSahjQvNYb6MUoPEzXQCVc0ly/DGRwRncdQ9H9t0qm5mGzyw/9bNKizzn79yXjzfS0LHNazgHfJCXE3IyFfj3qfPLM+KMeHQXP2I+b97ladZpwFti7oPRe4DjLb08jdZI6w4IKwYqTllDkPR2qlXaXmSZp4b7aSIhKEi9HjMElmdnyLKnZYbanM7xoczG1t4LMMPVTkWI3oJwoZIkzh/TRROwSC9G0YGOg9W+ZidX2yMMHsHGTSw1r5WMlQRyfG5nb2pK2xUFy7vugoGcPAWPZMySAJH/+SOybbeFRF/Yhqu0x6kAiGyu8vP; 4:OznjY5MfpHGBOaBqVCuZ71AfHRON7s5PO71b5L2ZYisYefh3WpvXBKoHq7J5GVWezRuZlwUkFXzZNbSb2/9WnF49GL0MGlCOD2L7Gqfgt1vBcqQEau6+fJwhlFB7oI/37c2xW0M70RQJ5LhXhhvqyVsysdwco6sh96wQrkR14A/6Te8/nXigndOmcW9NdQcs4e/wRxsBaf2q9h/bf7kfUJHoiXSBQyXwkuzxdDx2o6dWZCe/gZK5v140Okrm5lYaBXUQi7SyOcQxBAZyA5YDsN4L0/V9d7ww7J9D3k+f0A2enlMzdX39Vak4JkxXVyEMpoC6/lXW6CggoVUSyNuA2w== X-Exchange-Antispam-Report-Test: UriScan:(767451399110)(228905959029699); X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(601004)(2401047)(5005006)(8121501046)(10201501046)(93006095)(93001095)(3002001)(100000703101)(100105400095)(6055026)(6041248)(20161123564025)(20161123560025)(20161123555025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123558100)(20161123562025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:DM2PR12MB0154; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:DM2PR12MB0154; X-Forefront-PRVS: 041517DFAB X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6009001)(199003)(189002)(50466002)(86362001)(53936002)(3846002)(6916009)(54906002)(2950100002)(6116002)(478600001)(7736002)(33646002)(68736007)(189998001)(2906002)(48376002)(66066001)(47776003)(4326008)(8676002)(81166006)(97736004)(2351001)(50986999)(25786009)(2361001)(8936002)(101416001)(106356001)(5003940100001)(50226002)(105586002)(6666003)(110136004)(81156014)(36756003)(305945005)(53416004)(6486002)(42186005)(5660300001)(76176999)(21314002); DIR:OUT; SFP:1101; SCL:1; SRVR:DM2PR12MB0154; H:brijesh-build-machine.amd.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; DM2PR12MB0154; 23:Nw+yMVwgxUfdrJ+xweZnFbaPmUCUMJvyM47/gLoGe?= =?us-ascii?Q?mTa2VlDY9z2kCsoheR8ImW0gGOfRa0XxZIPwhccPRHIKByvmacT/q0HM7L5N?= =?us-ascii?Q?1cYKl2d4S58HK8cqDNmWY+d/e7MzgNntljfOE0UFRbUNaw6jxAPs66odSSTw?= =?us-ascii?Q?tkR0HhHXUfXDOhr64eyuYv+dTyOClWV0viiJcfMRhxjEDRerMvXECqy0xZL1?= =?us-ascii?Q?azTkTZaLkNm/Cw3+SvMviQ56V9vwm7UGC+7llTDEzM0OgUUn2yZ8VOF5Z84f?= =?us-ascii?Q?GGdAVpV6QuGrrawHIZnPID14boDL2DobwxwewcRuCCGCadQU49QQeKV2i23D?= =?us-ascii?Q?EJprEO5GyjF++OQoGRsHnwCze5rlwE0YRaLMf4UEL+Kh9B7itkTtgHw1Eoe7?= =?us-ascii?Q?j80t25VnHkyPmGtcSXNH2H3sh0RA7HAt0ave6WvH4KTdtz3NRfFlgCK9+n/w?= =?us-ascii?Q?V1+bCYkxygh56a+3tlY7KI/Z28ZfJHSvycfu2lQZ8xDLathllxmCHe+MLpnk?= =?us-ascii?Q?Yuxb1EOC97mWd90FfguKsdyZKWIlAh62UcQ98UOwowLVAW8u75ZNCAPCdZFX?= =?us-ascii?Q?sDuU3Hx7eQteMbnF4YI1++VaMrJFEX/GIS/LsPk3upH4hBkYtlG89fOGdOcj?= =?us-ascii?Q?Yg1BQ+OyD2rW8Z8BVRC8grUDmA+KzIE7tMhESIt7l+h3j5sWeGMlnYCG7biu?= =?us-ascii?Q?m6mX8HIRPMp79pEsu33e9LP4mdo23Qx4eCeaVQ5t2H+S3aauh4ToHai+HJ1t?= =?us-ascii?Q?MzR/5eg7TykefVFDOnxXVGfMe8Ullfpq6tAchVaBVV8DaevaPf/AGjGPFLLy?= =?us-ascii?Q?ppM0dkIrby81owcFt4zfZ8f1BPYio3Y8iLDnNWQdMYietH6COkM+zAw/yh+F?= =?us-ascii?Q?eBhfN5mjLbuXeQg/DmgN4xu6K7M/F/zCeUQnagqSnH6hEu5h+4Ycs6UoLaep?= =?us-ascii?Q?4oT1VsJshNkfikUiDtgigFCkeDl5qt3EhwasfG206kwZtO9fcw6OXEmihqfR?= =?us-ascii?Q?cJikEPXh8iPoc0Z0NA9foGxug4ARmEJKlDspOZlFApDWy8v0UIzoOsv/wP38?= =?us-ascii?Q?gu6/qlXXW4U2aeHpFw3dHnv8yia?= X-Microsoft-Exchange-Diagnostics: 1; DM2PR12MB0154; 6:LxLRdDbZOF2j6o/svIhPu/82n8hhQ9K4x4+KEw3mSrIM6ZzW7dStEb737Oq7n/3AIIkcQE9VCUMVIIDmYPKF4NkLK3KzeE5r08iSzChTo0cYGOYk2htSqmhs+DM70iqhVkxic01DTf8bB/jMM7sgWabwfsaJtB6yPSfK+eFAzjqUliIfM/THxhqoayCoOscbhntuK4LoMW7TPTT85D9IJUsG9QGZDWUkpCjEEwcw4ttAld+ANtw9lnmtEDS0DyWbxSkedoU5L7lU8fEexe/mIfryLjgd2XO0BOLGqQk9pcWxKwdqr8dnP6Z0LB+gQgl+uSc4g7nZtsb9hk+AG3bQsg==; 5:m0ANvZ79ArqFM/QDaq+H3ZnTwqYXsk5kbsiVytyZsAh0D3qr535PH01rD0l0aOgApj4rWkhPm17QjX+uFczfXIWCzri9/m3TlakJBqzLU4g/Oi+EX0iNcFW617YswxK1eyzhzVFyRDEw4tOLBWJCnw==; 24:0Uw9ustf5NztHPexoRYiz8mKBKB5HS9PjZIyGeEbkutXX+dIdmwnngTKH8MoetwPrGxPq91DNCfMVtXWEKABXYjK0xFvM+gYu+thEo+h6uE=; 7:nenFj9afLZCmzCgbiObecvRt7kIp0ZxJwtqpBmU5uYSNjUOmY8mrNBLBb7s1my180ETLARnA0+k0IHEPRtoux4dE8orqaowenSKPvfY2XWOeAVC5YBVrij+bvPP9+iCHpuqYg8qal4ykbc7ujKADQ0xMJdxBfXA4AsWmXWoChL9/2BIQMvIPqLek9mo8JO3zmrQtYwmFu5U4c78DEySl3SwpavV2+NcETR/s9DgZQ7Q= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; DM2PR12MB0154; 20:rLeu2yO5mlIbgGgBy2PZSIgT3wWXUY9FlOa8ih1bc/4svRA/nxUmqUyt8u7pecGymvof50OJeT2CyV4ZamBWFVl/9xKzQETxwz9Hw/QF54ELUM3CSLOVU7nslLr9JJ0G6mbA0r1kUxN2r7ksy2BnjZiMXqzlbl2ZlOygcy9AfKtM/BELLR9kwbRPqbkNrvCOC8tCZuMrnVPMJXteHydKnIFEjLgcO2xKdnzSjD4/9YqQiMQGOYYIk+oP9FPzF36W X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 30 Aug 2017 20:45:19.4878 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM2PR12MB0154 Subject: [PATCH v2 3/4] Ovmfpkg/VirtioScsiDxe: map virtio-scsi request and response buffers X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 30 Aug 2017 20:45:18 -0000 Content-Type: text/plain When device is behind the IOMMU, driver is require to pass the device address of virtio request, response and any memory referenced by those request/response to the bus master. The patch uses IOMMU-like member functions from VIRTIO_DEVICE_PROTOCOL to map request and response buffers system physical address to the device address. - If the buffer need to be accessed by both the processor and a bus master then map with BusMasterCommonBuffer. - If the buffer need to be accessed for a write operation by a bus master then map with BusMasterWrite. - If the buffer need to be accessed for a read operation by a bus master then map with BusMasterRead. Cc: Ard Biesheuvel Cc: Jordan Justen Cc: Tom Lendacky Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Brijesh Singh --- OvmfPkg/VirtioScsiDxe/VirtioScsi.c | 225 ++++++++++++++++++-- 1 file changed, 209 insertions(+), 16 deletions(-) diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c index cac213129409..3e04097ddd11 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c @@ -429,26 +429,161 @@ VirtioScsiPassThru ( UINT16 TargetValue; EFI_STATUS Status; volatile VIRTIO_SCSI_REQ Request; - volatile VIRTIO_SCSI_RESP Response; + volatile VIRTIO_SCSI_RESP *Response; + VOID *ResponseBuffer; DESC_INDICES Indices; + VOID *RequestMapping; + VOID *ResponseMapping; + VOID *InDataMapping; + VOID *OutDataMapping; + EFI_PHYSICAL_ADDRESS RequestDeviceAddress; + EFI_PHYSICAL_ADDRESS ResponseDeviceAddress; + EFI_PHYSICAL_ADDRESS InDataDeviceAddress; + EFI_PHYSICAL_ADDRESS OutDataDeviceAddress; + VOID *InDataBuffer; + UINTN InDataNumPages; + BOOLEAN InDataBufferIsMapped; + BOOLEAN OutDataBufferIsMapped; ZeroMem ((VOID*) &Request, sizeof (Request)); - ZeroMem ((VOID*) &Response, sizeof (Response)); Dev = VIRTIO_SCSI_FROM_PASS_THRU (This); CopyMem (&TargetValue, Target, sizeof TargetValue); + InDataBuffer = NULL; + InDataBufferIsMapped = FALSE; + OutDataBufferIsMapped = FALSE; + InDataNumPages = 0; + Status = PopulateRequest (Dev, TargetValue, Lun, Packet, &Request); if (EFI_ERROR (Status)) { return Status; } - VirtioPrepare (&Dev->Ring, &Indices); + // + // Map the virtio-scsi Request header buffer + // + Status = VirtioMapAllBytesInSharedBuffer ( + Dev->VirtIo, + VirtioOperationBusMasterRead, + (VOID *) &Request, + sizeof Request, + &RequestDeviceAddress, + &RequestMapping); + if (EFI_ERROR (Status)) { + return ReportHostAdapterError (Packet); + } + + // + // Map the input buffer + // + if (Packet->InTransferLength > 0) { + // + // Allocate a intermediate input buffer. This is mainly to handle the + // following case: + // * caller submits a bi-directional request + // * we perform the request fine + // * but we fail to unmap the "InDataMapping" + // + // In that case simply returing the EFI_DEVICE_ERROR is not sufficient. + // In addition to the error code we also need to update Packet-xxx fields + // accordingly so that we report the full loss of the incoming transfer. + // + // We allocate a temporary buffer and map it with BusMasterCommon. If the + // Virtio request is successful then we copy the data from temporary + // buffer into Packet->InDataBuffer. + // + InDataNumPages = EFI_SIZE_TO_PAGES (Packet->InTransferLength); + Status = Dev->VirtIo->AllocateSharedPages ( + Dev->VirtIo, + InDataNumPages, + &InDataBuffer + ); + if (EFI_ERROR (Status)) { + Status = ReportHostAdapterError (Packet); + goto UnmapRequestBuffer; + } + + ZeroMem (InDataBuffer, Packet->InTransferLength); + + Status = VirtioMapAllBytesInSharedBuffer ( + Dev->VirtIo, + VirtioOperationBusMasterCommonBuffer, + InDataBuffer, + Packet->InTransferLength, + &InDataDeviceAddress, + &InDataMapping + ); + if (EFI_ERROR (Status)) { + Status = ReportHostAdapterError (Packet); + goto FreeInDataBuffer; + } + + InDataBufferIsMapped = TRUE; + } + + // + // Map the output buffer + // + if (Packet->OutTransferLength > 0) { + Status = VirtioMapAllBytesInSharedBuffer ( + Dev->VirtIo, + VirtioOperationBusMasterRead, + Packet->OutDataBuffer, + Packet->OutTransferLength, + &OutDataDeviceAddress, + &OutDataMapping + ); + if (EFI_ERROR (Status)) { + Status = ReportHostAdapterError (Packet); + goto UnmapInDataBuffer; + } + + OutDataBufferIsMapped = TRUE; + } + + // + // Response header is bi-direction (we preset with host status and expect + // the device to update it). Allocate a response buffer which can be mapped + // to access equally by both processor and device. + // + Status = Dev->VirtIo->AllocateSharedPages ( + Dev->VirtIo, + EFI_SIZE_TO_PAGES (sizeof *Response), + &ResponseBuffer + ); + if (EFI_ERROR (Status)) { + Status = ReportHostAdapterError (Packet); + goto UnmapOutDataBuffer; + } + + Response = ResponseBuffer; + + ZeroMem ((VOID *)Response, sizeof (*Response)); // // preset a host status for ourselves that we do not accept as success // - Response.Response = VIRTIO_SCSI_S_FAILURE; + Response->Response = VIRTIO_SCSI_S_FAILURE; + + // + // Map the response buffer with BusMasterCommonBuffer so that response + // buffer can be accessed by both host and device. + // + Status = VirtioMapAllBytesInSharedBuffer ( + Dev->VirtIo, + VirtioOperationBusMasterCommonBuffer, + ResponseBuffer, + sizeof (*Response), + &ResponseDeviceAddress, + &ResponseMapping + ); + if (EFI_ERROR (Status)) { + Status = ReportHostAdapterError (Packet); + goto FreeResponseBuffer; + } + + VirtioPrepare (&Dev->Ring, &Indices); // // ensured by VirtioScsiInit() -- this predicate, in combination with the @@ -459,31 +594,49 @@ VirtioScsiPassThru ( // // enqueue Request // - VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request, - VRING_DESC_F_NEXT, &Indices); + VirtioAppendDesc ( + &Dev->Ring, + RequestDeviceAddress, + sizeof Request, + VRING_DESC_F_NEXT, + &Indices + ); // // enqueue "dataout" if any // if (Packet->OutTransferLength > 0) { - VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->OutDataBuffer, - Packet->OutTransferLength, VRING_DESC_F_NEXT, &Indices); + VirtioAppendDesc ( + &Dev->Ring, + OutDataDeviceAddress, + Packet->OutTransferLength, + VRING_DESC_F_NEXT, + &Indices + ); } // // enqueue Response, to be written by the host // - VirtioAppendDesc (&Dev->Ring, (UINTN) &Response, sizeof Response, - VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ? - VRING_DESC_F_NEXT : 0), - &Indices); + VirtioAppendDesc ( + &Dev->Ring, + ResponseDeviceAddress, + sizeof *Response, + VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ? VRING_DESC_F_NEXT : 0), + &Indices + ); // // enqueue "datain" if any, to be written by the host // if (Packet->InTransferLength > 0) { - VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->InDataBuffer, - Packet->InTransferLength, VRING_DESC_F_WRITE, &Indices); + VirtioAppendDesc ( + &Dev->Ring, + InDataDeviceAddress, + Packet->InTransferLength, + VRING_DESC_F_WRITE, + &Indices + ); } // If kicking the host fails, we must fake a host adapter error. @@ -492,10 +645,50 @@ VirtioScsiPassThru ( // if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring, &Indices, NULL) != EFI_SUCCESS) { - return ReportHostAdapterError (Packet); + Status = ReportHostAdapterError (Packet); + goto UnmapResponseBuffer; } - return ParseResponse (Packet, &Response); + Status = ParseResponse (Packet, Response); + + // + // If virtio request was successful and it was a CPU read request then we + // have used an intermediate buffer. Copy the data from intermediate buffer + // to the final buffer. + // + if (!EFI_ERROR (Status) && (Packet->InTransferLength > 0)) { + CopyMem (Packet->InDataBuffer, InDataBuffer, Packet->InTransferLength); + } + +UnmapResponseBuffer: + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, ResponseMapping); + +FreeResponseBuffer: + Dev->VirtIo->FreeSharedPages ( + Dev->VirtIo, + EFI_SIZE_TO_PAGES (sizeof *Response), + ResponseBuffer + ); + +UnmapOutDataBuffer: + if (OutDataBufferIsMapped == TRUE) { + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, OutDataMapping); + } + +UnmapInDataBuffer: + if (InDataBufferIsMapped == TRUE) { + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, InDataMapping); + } + +FreeInDataBuffer: + if (InDataBuffer != NULL) { + Dev->VirtIo->FreeSharedPages (Dev->VirtIo, InDataNumPages, InDataBuffer); + } + +UnmapRequestBuffer: + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping); + + return Status; } -- 2.7.4