From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM02-CY1-obe.outbound.protection.outlook.com (mail-cys01nam02on0079.outbound.protection.outlook.com [104.47.37.79]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 015D821EB5269 for ; Thu, 31 Aug 2017 07:58:50 -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=hx/31elm9bY1rZZAKeiMTYLSitOBtCjCftpU0TXkUHY=; b=4gcApEsipwRecJzMHElk35E1KVELAcnE/0NTWSZRG/4KpHqLTk7TjO7S9RM45eix6WNoa0xtoCUE0HPsamiKkWeVYun7Yh+7XDkw8obCJC2DLWzGdDtxOFmvoP39PtvND+rFGJro0iHIV3SdsvdicaQHzddoov2HAyYuLXOLnpg= 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 SN1PR12MB0158.namprd12.prod.outlook.com (10.162.3.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.1.1385.9; Thu, 31 Aug 2017 15:01:30 +0000 From: Brijesh Singh To: edk2-devel@lists.01.org Cc: Brijesh Singh , Ard Biesheuvel , Jordan Justen , Tom Lendacky , Laszlo Ersek Date: Thu, 31 Aug 2017 11:01:13 -0400 Message-Id: <1504191674-3949-4-git-send-email-brijesh.singh@amd.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1504191674-3949-1-git-send-email-brijesh.singh@amd.com> References: <1504191674-3949-1-git-send-email-brijesh.singh@amd.com> MIME-Version: 1.0 X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: MWHPR08CA0056.namprd08.prod.outlook.com (10.173.236.30) To SN1PR12MB0158.namprd12.prod.outlook.com (10.162.3.145) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 0cb09188-65b9-4e1a-c583-08d4f08129ea X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(300000500095)(300135000095)(300000501095)(300135300095)(22001)(300000502095)(300135100095)(2017030254152)(300000503095)(300135400095)(48565401081)(2017052603199)(201703131423075)(201703031133081)(201702281549075)(300000504095)(300135200095)(300000505095)(300135600095)(300000506095)(300135500095); SRVR:SN1PR12MB0158; X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0158; 3:0T9wtlaW5E975wmjX42XG4FtnYH0+THIK/onSjaeJvZK8i7sz5h26V/MG3YuHTcTTMppSPdxC1zt+xNq+uYpXugq9+jGNZZ1WQV6mwM7YO899ljrVcSF4kc4hRuizPUBFLNndQuDJxeuBfejoIFz/WUplO1VyH+xqp7LUZhQ6f2U15mYx8AJXEbWVLU+svMksW+eJQ9ZcujC7lFx4WbEvhzIntW3wFTMDCveLod7sGCRx8UYFYp7FT5b0+tWe05x; 25:2f0L8BsL3/PWqG6DqSOkLLxdlhIa2N3+MB5EYv5o+HOPH8Wde9Y2puA+8bzPhUMTf3DZDPY1h+Cc1jFdXUQmKKbophM5zNoLyKbJwVFxIb8Q7AoMj1UQuqgcZUt7YI2us+siGwOh69ModfKV8Q5iJg8gBJ4OS3u11RWOJrKUEg9TEI4D+FT+JA/xJFUFeyJ1N+JfZ4woKY368eGd3M//jJ9sowpKCekbJOB7dE3d9b3NyVwFt/8sVmn792QFODk1F6yLi1RmGHnUQLAl8nEe48+Zr/T6OvPl/LmPvMPHfTGeiI68Ba6yodq1Bacw2vgIwE/FXFuU+EkuosUsJpnkdA==; 31:HeByiW4HPbM8Xk8+eQEqZ8xQcRPpHjPf5ZEAOPOXwx/dGsxhniytNhY5TyTUyqKNuYFqmXaOr+FouJZhgIp/fStqcsEQTbGyMtTFoAEdLRA+vnIfN3sIYh2VBvdwy3m6z8qqtdxeHM/11FDAvlDmb0qqHhEwg6J/qLLSyZijqpk64jKV56YiGY4hCYtL4qHS7M2GOX5ctwT3c6WP9h1q7WR7Wh/pegSKQFeBY0DtUFc= X-MS-TrafficTypeDiagnostic: SN1PR12MB0158: X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0158; 20:+ciGic4iT81L317ddjJ1jWxAD1i7IjoX0+IKo01xhRmm3XgNndIWuouZz0H4uF2tNju8z0as4mn6iOpeP3AVapNQ1uJvxe0sDY+t4BdnZjcpVXygN4dPNoXTjBns9BI3dD0FBwnx5RLE0Oksrs0E7O22XVkiC9PedZINOEiU4/gZYefv/SShbQmQvan9LrnW5jBJWN/W3kg7kcIcwM9RqU0dGuG2T6rUYGGyHh9ZgyjcQ1+Z5QSQ8bmcc8wghcjIt36Cfeb9l7ikFI/r8j8HK6vPRpTMfrjX09KORu0CWN5T6NbBUKu9jRf2s535bdkFr0HjBMSeUeaPbdVVKKHZ0IFRtnUl9wTuUpQr69UHKHXZlpcbY26BBQP6yqvAO/hZPjqmcqbNYm9mGYQH8LpUaXToRLHnVYM6FsDVEZVPZffMSCOF3ephsphHjSU9PmTGdfzr2g3CeJGv383hlfhmRebFXLhEi4xfzi7763eO/+Zu0z6EFQPHSHdtIwN1gPLN; 4:QifrhSS7fo9a36kgk5bn2Tyc1P/8rQMNxb9mpdxPRJtOsJXDg6/aQ5NitIrKhw2EQIxu4bIEhFJWIiqRGCJw8JgAxHDFydmlpx3ftqqHuebpYlfBTRRNpsteUVLW2x/HvF1fB6WIN/GfhkckPiDrzeMuKr283FSS61pn6nL5mjeqaOiM3NgN9DmUhCECLiiW9WrhaO16NK3JkSDqTtFOseYQnF50TUBwQ2FdL38pa+5TNmCQ2xZF0TQrg9Yx9T45DPgbIRGUEusPyDH/ptAw6rMfNgOjzTQxMvTt5U5qnEQAJBWVvaA7iabPmNaiZnq+7W1m2cQdkO66ClKmPzZtIZNUJt+cn9pqTmDfsZEEs2E= X-Exchange-Antispam-Report-Test: UriScan:(767451399110)(211171220733660)(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)(100000703101)(100105400095)(10201501046)(3002001)(93006095)(93001095)(6055026)(6041248)(20161123560025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123558100)(20161123555025)(20161123564025)(20161123562025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:SN1PR12MB0158; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:SN1PR12MB0158; X-Forefront-PRVS: 04163EF38A X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6009001)(39860400002)(199003)(189002)(81156014)(8676002)(478600001)(81166006)(5003940100001)(50226002)(76176999)(8936002)(4326008)(50986999)(2361001)(110136004)(2906002)(2351001)(189998001)(66066001)(106356001)(105586002)(7736002)(42186005)(53416004)(54906002)(47776003)(25786009)(97736004)(53936002)(33646002)(101416001)(305945005)(6486002)(6916009)(2950100002)(48376002)(3846002)(6116002)(36756003)(6666003)(575784001)(5660300001)(86362001)(50466002)(68736007); DIR:OUT; SFP:1101; SCL:1; SRVR:SN1PR12MB0158; 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; SN1PR12MB0158; 23:xIgEkszQJh2AJHyfkdVmKdyWlj1lzqeYyj+E/eEZF?= =?us-ascii?Q?CjKUcYjimNu39uGam1M4W//oX9gF4NP+/TjKyrIGCuReru3Z/2HcXFN5QJGr?= =?us-ascii?Q?IJqNYX8wJwgAdfBaOHzbrV9owMFRe7oks38do0t6agDPG7fNTlMpm8Gbclvf?= =?us-ascii?Q?St7blN0ZYi1glfY5OqxEFOaMB5SsZpUDyI0OMb/t74rXxIspE/BuFyFNiXZY?= =?us-ascii?Q?lMofHW5BUYjRVzPRp8+epaPi0H/qrHEx+XNW7Xzus1lcnc1XNDB+zcnS6r6R?= =?us-ascii?Q?9xN9iGvAVdISYKaJwn4/JCFp0G4seklsAH5P/y/5HRj4StfJzG5tQB16Qjxx?= =?us-ascii?Q?fL8dMOlX7yY9S9vTku88XykiCJV2Qm+TAF3KHTqOfmbLq5NlWPN2/VmFwwqb?= =?us-ascii?Q?7P1ftDubzHvkILN4DGG82ccf0FyL0NDr9IwpxEVIxvOhA5x9u1GghInA26gP?= =?us-ascii?Q?Jc2aC6UD/G6v1te2spAZLg+u2YvkKr2Ozpws9txzKrrD1Gu9d7L7iqpFN2PH?= =?us-ascii?Q?EOYok0u2iXgGCKB6Pj70aGgkjCR1v8xsVBGcGN/lw+3RngvBJWXZIP0c4FE/?= =?us-ascii?Q?I5G6HC4PlmENxwGtPKNhv4Qi9zc95hFKdCA/mWyecgjDB2BP7D8fyfpiwBaa?= =?us-ascii?Q?8v6UJ/7hZWnr7xLDCznAoosN6y5slQ4+amcM/poauzK8zsH1cDAy3/+xMXOV?= =?us-ascii?Q?qIEdppyQuG07PRgIn2JieriO8X5DRffGVdTVmX3YBpcy9CNueB1H4H6sVdqm?= =?us-ascii?Q?6MQqhs2CeBCZuNDeJNOciajsiudlR2pA6/OVzG9bh2OQyuTZmCEJ+bFoOeQU?= =?us-ascii?Q?eGm9hL0QVUnqN84qxOjjXTXCTdgLAxMux96PmtXAvOWOpbhAqIz/DUIQiseE?= =?us-ascii?Q?AbqqDONHlDwJ/lRRAYiE7qGMN7fb9ycEv3tN84ODvqluTeM3xdR9W42x7uJJ?= =?us-ascii?Q?NZMLzMFT79ipfYfcIU265D9JchZsdi0PozIXRk8O1vpWSK5s5ZIIX/Yu7eSn?= =?us-ascii?Q?GIkuSJGRjG/HRML4AlUX+UYXKZi1AVXCAo+I7esestlILdEsze1/jmh1dktv?= =?us-ascii?Q?38wI5CsOToro8+i1JeIqCRmPYwOvat7llHOVDIgcpain8kFLiwuih+/orCh3?= =?us-ascii?Q?98nRjwPKB8=3D?= X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0158; 6:Xv3bD8E4KWc6HR7uPLCwtUc4Eb9jvDaQb8c/XvhbR31Ky3QliwHDvnm1aoNqrB9Gu57j6chI1BtvIz3uC+phQBNyxJ2T0wd4aLOhfz8RaStcPb8xQ2KGjXFSCNGnWokRCDVrAVyV9DlhHRQ3iWbGpR06GohP7DxVEdHziZvbM5sWxYwilyDLaEfU7u3ZTX46sWza4zAD+XUSLj4kjo+tTpWVhUTVNfdivcY7uXSbuZNBN2mExtF7lxBlL8vTQuQMp3wmvz4E9vvpUB0ZcIczLPSvB7SkK3cM+lYYl7nqhaYnC+3yyoZSB6Rs1GWuJ8JGENn8mTEDj0dE8w4vlbybjA==; 5:WJsibMklwWs+PskhlI58BiB8m9oAb+t1ytD1D3VO41se2U5KnE8bGOlB7fvSA1D+Ht4DLKHxZDfYRO04vohhlyTAJW44R7r3aeUYa1ixyCRP5diqhNnCdCNgIwJ/JOqDQOvHaI8AHVNx6nlLTebWIg==; 24:8msblz4WULyzOJiwHwYGji40FrGCu7lTMnpXcOj7afLX1okv93Jgxjgma9hP+igdOf3ojtliJpmjmPqTkWGzVebDEMiL368i9mUL2GpHkpI=; 7:CNYWxo8zzansKWqI3obwor5GCL1zdBziGiRd8lIpu2TqpZkjw2n+ew0URiw6XhPyYGxt2WLQxG8tqniDbQ+/MtelyxADlcNx02s8bnFa6M4eZWe13eZz60jvXqET/ZoE51ieabGMtGSDBfhrtF6QNuIt8MdJVAR2Q8oZhaNJNKGIc2SYoLvVCydDdeCMz9xv4VpSh9gNkWHROTRjUZziZ307IvxS5ENWV5vxo+USQ6E= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; SN1PR12MB0158; 20:vURlG0RvnmpD/8lziWl4g7PyLt9xZxnd7bpJ6MsV4uaBd4bOPrCflY24fMKUzc9/17QTxRvNzG0pze4HXb9aEgtRt2uTq+hwY8nWuRBkSPviVcCWyNCFTRGItrG3JlfJYYHN9eexYKdRhfU46MMGzQOACw59npZHv20wLcoZKHFi4avX6SiKwxLeEXTBFiwAlqcjf8RjoStPaCpcgsqAShQ1NprlWnNdZVXbD7XxX5EIKiKRHxBp1Zpr7119XIlL X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 Aug 2017 15:01:30.2813 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR12MB0158 Subject: [PATCH v3 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: Thu, 31 Aug 2017 14:58:50 -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. However, after a BusMasterWrite Unmap() failure, error reporting via EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET would be very complex, therefore we map such buffers too with BusMasterCommonBuffer. - 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 | 220 ++++++++++++++++++-- 1 file changed, 204 insertions(+), 16 deletions(-) diff --git a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c index 5e977c636a0a..337fb4b2f1e0 100644 --- a/OvmfPkg/VirtioScsiDxe/VirtioScsi.c +++ b/OvmfPkg/VirtioScsiDxe/VirtioScsi.c @@ -436,26 +436,156 @@ 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 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; + 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 fields + // accordingly so that we report the full loss of the incoming transfer. + // We allocate a temporary buffer and map it with BusMasterCommonBuffer. + // If the Virtio request is successful then we copy the data from + // temporary buffer into Packet->InDataBuffer. + // + InDataNumPages = (UINTN)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; + } + } + + // + // 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 @@ -466,31 +596,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. @@ -499,10 +647,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 (InDataBuffer != NULL) { + 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) { + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, OutDataMapping); + } + +UnmapInDataBuffer: + if (InDataBuffer != NULL) { + 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