unreasonable for now.\r
\r
Copyright (C) 2012, Red Hat, Inc.\r
- Copyright (c) 2012 - 2014, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>\r
Copyright (c) 2017, AMD Inc, All rights reserved.<BR>\r
\r
- This program and the accompanying materials are licensed and made available\r
- under the terms and conditions of the BSD License which accompanies this\r
- distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
- WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
(Value) \\r
))\r
\r
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \\r
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \\r
(Dev)->VirtIo, \\r
OFFSET_OF_VSCSI (Field), \\r
SIZE_OF_VSCSI (Field), \\r
(Pointer) \\r
))\r
\r
-\r
//\r
// UEFI Spec 2.3.1 + Errata C, 14.7 Extended SCSI Pass Thru Protocol specifies\r
// the PassThru() interface. Beside returning a status code, the function must\r
// set some fields in the EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET in/out\r
// parameter on return. The following is a full list of those fields, for\r
// easier validation of PopulateRequest(), ParseResponse(), and\r
-// VirtioScsiPassThru() below.\r
+// ReportHostAdapterError() below.\r
//\r
// - InTransferLength\r
// - OutTransferLength\r
OUT volatile VIRTIO_SCSI_REQ *Request\r
)\r
{\r
- UINTN Idx;\r
+ UINTN Idx;\r
\r
if (\r
//\r
// bidirectional transfer was requested, but the host doesn't support it\r
//\r
- (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0 &&\r
+ ((Packet->InTransferLength > 0) && (Packet->OutTransferLength > 0) &&\r
!Dev->InOutSupported) ||\r
\r
//\r
// a target / LUN was addressed that's impossible to encode for the host\r
//\r
- Target > 0xFF || Lun >= 0x4000 ||\r
+ (Target > 0xFF) || (Lun >= 0x4000) ||\r
\r
//\r
// Command Descriptor Block bigger than VIRTIO_SCSI_CDB_SIZE\r
//\r
- Packet->CdbLength > VIRTIO_SCSI_CDB_SIZE ||\r
+ (Packet->CdbLength > VIRTIO_SCSI_CDB_SIZE) ||\r
\r
//\r
// From virtio-0.9.5, 2.3.2 Descriptor Table:\r
// "no descriptor chain may be more than 2^32 bytes long in total".\r
//\r
- (UINT64) Packet->InTransferLength + Packet->OutTransferLength > SIZE_1GB\r
- ) {\r
-\r
+ ((UINT64)Packet->InTransferLength + Packet->OutTransferLength > SIZE_1GB)\r
+ )\r
+ {\r
//\r
// this error code doesn't require updates to the Packet output fields\r
//\r
//\r
// addressed invalid device\r
//\r
- Target > Dev->MaxTarget || Lun > Dev->MaxLun ||\r
+ (Target > Dev->MaxTarget) || (Lun > Dev->MaxLun) ||\r
\r
//\r
// invalid direction (there doesn't seem to be a macro for the "no data\r
// transferred" "direction", eg. for TEST UNIT READY)\r
//\r
- Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||\r
+ (Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL) ||\r
\r
//\r
// trying to receive, but destination pointer is NULL, or contradicting\r
// transfer direction\r
//\r
- (Packet->InTransferLength > 0 &&\r
- (Packet->InDataBuffer == NULL ||\r
- Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE\r
- )\r
- ) ||\r
+ ((Packet->InTransferLength > 0) &&\r
+ ((Packet->InDataBuffer == NULL) ||\r
+ (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE)\r
+ )\r
+ ) ||\r
\r
//\r
// trying to send, but source pointer is NULL, or contradicting transfer\r
// direction\r
//\r
- (Packet->OutTransferLength > 0 &&\r
- (Packet->OutDataBuffer == NULL ||\r
- Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ\r
- )\r
+ ((Packet->OutTransferLength > 0) &&\r
+ ((Packet->OutDataBuffer == NULL) ||\r
+ (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ)\r
)\r
- ) {\r
-\r
+ )\r
+ )\r
+ {\r
//\r
// this error code doesn't require updates to the Packet output fields\r
//\r
// then the combined size of a bidirectional request will not exceed the\r
// virtio-scsi device's transfer limit either.\r
//\r
- if (ALIGN_VALUE (Packet->OutTransferLength, 512) / 512\r
- > Dev->MaxSectors / 2 ||\r
- ALIGN_VALUE (Packet->InTransferLength, 512) / 512\r
- > Dev->MaxSectors / 2) {\r
+ if ((ALIGN_VALUE (Packet->OutTransferLength, 512) / 512\r
+ > Dev->MaxSectors / 2) ||\r
+ (ALIGN_VALUE (Packet->InTransferLength, 512) / 512\r
+ > Dev->MaxSectors / 2))\r
+ {\r
Packet->InTransferLength = (Dev->MaxSectors / 2) * 512;\r
Packet->OutTransferLength = (Dev->MaxSectors / 2) * 512;\r
Packet->HostAdapterStatus =\r
- EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
- Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
- Packet->SenseDataLength = 0;\r
+ EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
+ Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
+ Packet->SenseDataLength = 0;\r
return EFI_BAD_BUFFER_SIZE;\r
}\r
\r
// Device Operation: request queues\r
//\r
Request->Lun[0] = 1;\r
- Request->Lun[1] = (UINT8) Target;\r
- Request->Lun[2] = (UINT8) (((UINT32)Lun >> 8) | 0x40);\r
- Request->Lun[3] = (UINT8) Lun;\r
+ Request->Lun[1] = (UINT8)Target;\r
+ Request->Lun[2] = (UINT8)(((UINT32)Lun >> 8) | 0x40);\r
+ Request->Lun[3] = (UINT8)Lun;\r
\r
//\r
// CopyMem() would cast away the "volatile" qualifier before access, which is\r
// undefined behavior (ISO C99 6.7.3p5)\r
//\r
for (Idx = 0; Idx < Packet->CdbLength; ++Idx) {\r
- Request->Cdb[Idx] = ((UINT8 *) Packet->Cdb)[Idx];\r
+ Request->Cdb[Idx] = ((UINT8 *)Packet->Cdb)[Idx];\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
\r
Parse the virtio-scsi device's response, translate it to an EFI status code,\r
EFI_STATUS\r
EFIAPI\r
ParseResponse (\r
- IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
- IN CONST volatile VIRTIO_SCSI_RESP *Response\r
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
+ IN CONST volatile VIRTIO_SCSI_RESP *Response\r
)\r
{\r
- UINTN ResponseSenseLen;\r
- UINTN Idx;\r
+ UINTN ResponseSenseLen;\r
+ UINTN Idx;\r
\r
//\r
// return sense data (length and contents) in all cases, truncated if needed\r
//\r
ResponseSenseLen = MIN (Response->SenseLen, VIRTIO_SCSI_SENSE_SIZE);\r
if (Packet->SenseDataLength > ResponseSenseLen) {\r
- Packet->SenseDataLength = (UINT8) ResponseSenseLen;\r
+ Packet->SenseDataLength = (UINT8)ResponseSenseLen;\r
}\r
+\r
for (Idx = 0; Idx < Packet->SenseDataLength; ++Idx) {\r
- ((UINT8 *) Packet->SenseData)[Idx] = Response->Sense[Idx];\r
+ ((UINT8 *)Packet->SenseData)[Idx] = Response->Sense[Idx];\r
}\r
\r
//\r
// V @ OutTransferLength + InTransferLength -+- @ 0\r
//\r
if (Response->Residual <= Packet->InTransferLength) {\r
- Packet->InTransferLength -= Response->Residual;\r
- }\r
- else {\r
+ Packet->InTransferLength -= Response->Residual;\r
+ } else {\r
Packet->OutTransferLength -= Response->Residual - Packet->InTransferLength;\r
Packet->InTransferLength = 0;\r
}\r
// response code\r
//\r
switch (Response->Response) {\r
- case VIRTIO_SCSI_S_OK:\r
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
- return EFI_SUCCESS;\r
+ case VIRTIO_SCSI_S_OK:\r
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
+ return EFI_SUCCESS;\r
\r
- case VIRTIO_SCSI_S_OVERRUN:\r
- Packet->HostAdapterStatus =\r
- EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
- break;\r
+ case VIRTIO_SCSI_S_OVERRUN:\r
+ Packet->HostAdapterStatus =\r
+ EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;\r
+ break;\r
\r
- case VIRTIO_SCSI_S_BAD_TARGET:\r
- //\r
- // This is non-intuitive but explicitly required by the\r
- // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() specification for\r
- // disconnected (but otherwise valid) target / LUN addresses.\r
- //\r
- Packet->HostAdapterStatus =\r
- EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;\r
- return EFI_TIMEOUT;\r
+ case VIRTIO_SCSI_S_BAD_TARGET:\r
+ //\r
+ // This is non-intuitive but explicitly required by the\r
+ // EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru() specification for\r
+ // disconnected (but otherwise valid) target / LUN addresses.\r
+ //\r
+ Packet->HostAdapterStatus =\r
+ EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;\r
+ return EFI_TIMEOUT;\r
\r
- case VIRTIO_SCSI_S_RESET:\r
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET;\r
- break;\r
+ case VIRTIO_SCSI_S_RESET:\r
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET;\r
+ break;\r
\r
- case VIRTIO_SCSI_S_BUSY:\r
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
- return EFI_NOT_READY;\r
+ case VIRTIO_SCSI_S_BUSY:\r
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;\r
+ return EFI_NOT_READY;\r
\r
- //\r
- // Lump together the rest. The mapping for VIRTIO_SCSI_S_ABORTED is\r
- // intentional as well, not an oversight.\r
- //\r
- case VIRTIO_SCSI_S_ABORTED:\r
- case VIRTIO_SCSI_S_TRANSPORT_FAILURE:\r
- case VIRTIO_SCSI_S_TARGET_FAILURE:\r
- case VIRTIO_SCSI_S_NEXUS_FAILURE:\r
- case VIRTIO_SCSI_S_FAILURE:\r
- default:\r
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
+ //\r
+ // Lump together the rest. The mapping for VIRTIO_SCSI_S_ABORTED is\r
+ // intentional as well, not an oversight.\r
+ //\r
+ case VIRTIO_SCSI_S_ABORTED:\r
+ case VIRTIO_SCSI_S_TRANSPORT_FAILURE:\r
+ case VIRTIO_SCSI_S_TARGET_FAILURE:\r
+ case VIRTIO_SCSI_S_NEXUS_FAILURE:\r
+ case VIRTIO_SCSI_S_FAILURE:\r
+ default:\r
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
}\r
\r
return EFI_DEVICE_ERROR;\r
}\r
\r
+/**\r
+\r
+ The function can be used to create a fake host adapter error.\r
+\r
+ When VirtioScsiPassThru() is failed due to some reasons then this function\r
+ can be called to construct a host adapter error.\r
+\r
+ @param[out] Packet The Extended SCSI Pass Thru Protocol packet that the host\r
+ adapter error shall be placed in.\r
+\r
+\r
+ @retval EFI_DEVICE_ERROR The function returns this status code\r
+ unconditionally, to be propagated by\r
+ VirtioScsiPassThru().\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ReportHostAdapterError (\r
+ OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet\r
+ )\r
+{\r
+ Packet->InTransferLength = 0;\r
+ Packet->OutTransferLength = 0;\r
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
+ Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
+ Packet->SenseDataLength = 0;\r
+ return EFI_DEVICE_ERROR;\r
+}\r
\r
//\r
// The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiPassThru (\r
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
- IN UINT8 *Target,\r
- IN UINT64 Lun,\r
- IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
- IN EFI_EVENT Event OPTIONAL\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN UINT8 *Target,\r
+ IN UINT64 Lun,\r
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,\r
+ IN EFI_EVENT Event OPTIONAL\r
)\r
{\r
- VSCSI_DEV *Dev;\r
- UINT16 TargetValue;\r
- EFI_STATUS Status;\r
- volatile VIRTIO_SCSI_REQ Request;\r
- volatile VIRTIO_SCSI_RESP Response;\r
- DESC_INDICES Indices;\r
-\r
- ZeroMem ((VOID*) &Request, sizeof (Request));\r
- ZeroMem ((VOID*) &Response, sizeof (Response));\r
+ VSCSI_DEV *Dev;\r
+ UINT16 TargetValue;\r
+ EFI_STATUS Status;\r
+ volatile VIRTIO_SCSI_REQ Request;\r
+ volatile VIRTIO_SCSI_RESP *Response;\r
+ VOID *ResponseBuffer;\r
+ DESC_INDICES Indices;\r
+ VOID *RequestMapping;\r
+ VOID *ResponseMapping;\r
+ VOID *InDataMapping;\r
+ VOID *OutDataMapping;\r
+ EFI_PHYSICAL_ADDRESS RequestDeviceAddress;\r
+ EFI_PHYSICAL_ADDRESS ResponseDeviceAddress;\r
+ EFI_PHYSICAL_ADDRESS InDataDeviceAddress;\r
+ EFI_PHYSICAL_ADDRESS OutDataDeviceAddress;\r
+ VOID *InDataBuffer;\r
+ UINTN InDataNumPages;\r
+ BOOLEAN OutDataBufferIsMapped;\r
+\r
+ //\r
+ // Set InDataMapping,OutDataMapping,InDataDeviceAddress and OutDataDeviceAddress to\r
+ // suppress incorrect compiler/analyzer warnings.\r
+ //\r
+ InDataMapping = NULL;\r
+ OutDataMapping = NULL;\r
+ InDataDeviceAddress = 0;\r
+ OutDataDeviceAddress = 0;\r
+\r
+ ZeroMem ((VOID *)&Request, sizeof (Request));\r
\r
Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);\r
CopyMem (&TargetValue, Target, sizeof TargetValue);\r
\r
+ InDataBuffer = NULL;\r
+ OutDataBufferIsMapped = FALSE;\r
+ InDataNumPages = 0;\r
+\r
Status = PopulateRequest (Dev, TargetValue, Lun, Packet, &Request);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- VirtioPrepare (&Dev->Ring, &Indices);\r
+ //\r
+ // Map the virtio-scsi Request header buffer\r
+ //\r
+ Status = VirtioMapAllBytesInSharedBuffer (\r
+ Dev->VirtIo,\r
+ VirtioOperationBusMasterRead,\r
+ (VOID *)&Request,\r
+ sizeof Request,\r
+ &RequestDeviceAddress,\r
+ &RequestMapping\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return ReportHostAdapterError (Packet);\r
+ }\r
+\r
+ //\r
+ // Map the input buffer\r
+ //\r
+ if (Packet->InTransferLength > 0) {\r
+ //\r
+ // Allocate a intermediate input buffer. This is mainly to handle the\r
+ // following case:\r
+ // * caller submits a bi-directional request\r
+ // * we perform the request fine\r
+ // * but we fail to unmap the "InDataMapping"\r
+ //\r
+ // In that case simply returning the EFI_DEVICE_ERROR is not sufficient. In\r
+ // addition to the error code we also need to update Packet fields\r
+ // accordingly so that we report the full loss of the incoming transfer.\r
+ //\r
+ // We allocate a temporary buffer and map it with BusMasterCommonBuffer. If\r
+ // the Virtio request is successful then we copy the data from temporary\r
+ // buffer into Packet->InDataBuffer.\r
+ //\r
+ InDataNumPages = EFI_SIZE_TO_PAGES ((UINTN)Packet->InTransferLength);\r
+ Status = Dev->VirtIo->AllocateSharedPages (\r
+ Dev->VirtIo,\r
+ InDataNumPages,\r
+ &InDataBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = ReportHostAdapterError (Packet);\r
+ goto UnmapRequestBuffer;\r
+ }\r
+\r
+ ZeroMem (InDataBuffer, Packet->InTransferLength);\r
+\r
+ Status = VirtioMapAllBytesInSharedBuffer (\r
+ Dev->VirtIo,\r
+ VirtioOperationBusMasterCommonBuffer,\r
+ InDataBuffer,\r
+ Packet->InTransferLength,\r
+ &InDataDeviceAddress,\r
+ &InDataMapping\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = ReportHostAdapterError (Packet);\r
+ goto FreeInDataBuffer;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Map the output buffer\r
+ //\r
+ if (Packet->OutTransferLength > 0) {\r
+ Status = VirtioMapAllBytesInSharedBuffer (\r
+ Dev->VirtIo,\r
+ VirtioOperationBusMasterRead,\r
+ Packet->OutDataBuffer,\r
+ Packet->OutTransferLength,\r
+ &OutDataDeviceAddress,\r
+ &OutDataMapping\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = ReportHostAdapterError (Packet);\r
+ goto UnmapInDataBuffer;\r
+ }\r
+\r
+ OutDataBufferIsMapped = TRUE;\r
+ }\r
+\r
+ //\r
+ // Response header is bi-direction (we preset with host status and expect\r
+ // the device to update it). Allocate a response buffer which can be mapped\r
+ // to access equally by both processor and device.\r
+ //\r
+ Status = Dev->VirtIo->AllocateSharedPages (\r
+ Dev->VirtIo,\r
+ EFI_SIZE_TO_PAGES (sizeof *Response),\r
+ &ResponseBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = ReportHostAdapterError (Packet);\r
+ goto UnmapOutDataBuffer;\r
+ }\r
+\r
+ Response = ResponseBuffer;\r
+\r
+ ZeroMem ((VOID *)Response, sizeof (*Response));\r
\r
//\r
// preset a host status for ourselves that we do not accept as success\r
//\r
- Response.Response = VIRTIO_SCSI_S_FAILURE;\r
+ Response->Response = VIRTIO_SCSI_S_FAILURE;\r
+\r
+ //\r
+ // Map the response buffer with BusMasterCommonBuffer so that response\r
+ // buffer can be accessed by both host and device.\r
+ //\r
+ Status = VirtioMapAllBytesInSharedBuffer (\r
+ Dev->VirtIo,\r
+ VirtioOperationBusMasterCommonBuffer,\r
+ ResponseBuffer,\r
+ sizeof (*Response),\r
+ &ResponseDeviceAddress,\r
+ &ResponseMapping\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = ReportHostAdapterError (Packet);\r
+ goto FreeResponseBuffer;\r
+ }\r
+\r
+ VirtioPrepare (&Dev->Ring, &Indices);\r
\r
//\r
// ensured by VirtioScsiInit() -- this predicate, in combination with the\r
//\r
// enqueue Request\r
//\r
- VirtioAppendDesc (&Dev->Ring, (UINTN) &Request, sizeof Request,\r
- VRING_DESC_F_NEXT, &Indices);\r
+ VirtioAppendDesc (\r
+ &Dev->Ring,\r
+ RequestDeviceAddress,\r
+ sizeof Request,\r
+ VRING_DESC_F_NEXT,\r
+ &Indices\r
+ );\r
\r
//\r
// enqueue "dataout" if any\r
//\r
if (Packet->OutTransferLength > 0) {\r
- VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->OutDataBuffer,\r
- Packet->OutTransferLength, VRING_DESC_F_NEXT, &Indices);\r
+ VirtioAppendDesc (\r
+ &Dev->Ring,\r
+ OutDataDeviceAddress,\r
+ Packet->OutTransferLength,\r
+ VRING_DESC_F_NEXT,\r
+ &Indices\r
+ );\r
}\r
\r
//\r
// enqueue Response, to be written by the host\r
//\r
- VirtioAppendDesc (&Dev->Ring, (UINTN) &Response, sizeof Response,\r
- VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ?\r
- VRING_DESC_F_NEXT : 0),\r
- &Indices);\r
+ VirtioAppendDesc (\r
+ &Dev->Ring,\r
+ ResponseDeviceAddress,\r
+ sizeof *Response,\r
+ VRING_DESC_F_WRITE | (Packet->InTransferLength > 0 ? VRING_DESC_F_NEXT : 0),\r
+ &Indices\r
+ );\r
\r
//\r
// enqueue "datain" if any, to be written by the host\r
//\r
if (Packet->InTransferLength > 0) {\r
- VirtioAppendDesc (&Dev->Ring, (UINTN) Packet->InDataBuffer,\r
- Packet->InTransferLength, VRING_DESC_F_WRITE, &Indices);\r
+ VirtioAppendDesc (\r
+ &Dev->Ring,\r
+ InDataDeviceAddress,\r
+ Packet->InTransferLength,\r
+ VRING_DESC_F_WRITE,\r
+ &Indices\r
+ );\r
}\r
\r
// If kicking the host fails, we must fake a host adapter error.\r
// EFI_NOT_READY would save us the effort, but it would also suggest that the\r
// caller retry.\r
//\r
- if (VirtioFlush (Dev->VirtIo, VIRTIO_SCSI_REQUEST_QUEUE, &Dev->Ring,\r
- &Indices, NULL) != EFI_SUCCESS) {\r
- Packet->InTransferLength = 0;\r
- Packet->OutTransferLength = 0;\r
- Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;\r
- Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;\r
- Packet->SenseDataLength = 0;\r
- return EFI_DEVICE_ERROR;\r
+ if (VirtioFlush (\r
+ Dev->VirtIo,\r
+ VIRTIO_SCSI_REQUEST_QUEUE,\r
+ &Dev->Ring,\r
+ &Indices,\r
+ NULL\r
+ ) != EFI_SUCCESS)\r
+ {\r
+ Status = ReportHostAdapterError (Packet);\r
+ goto UnmapResponseBuffer;\r
}\r
\r
- return ParseResponse (Packet, &Response);\r
-}\r
+ Status = ParseResponse (Packet, Response);\r
+\r
+ //\r
+ // If virtio request was successful and it was a CPU read request then we\r
+ // have used an intermediate buffer. Copy the data from intermediate buffer\r
+ // to the final buffer.\r
+ //\r
+ if (InDataBuffer != NULL) {\r
+ CopyMem (Packet->InDataBuffer, InDataBuffer, Packet->InTransferLength);\r
+ }\r
+\r
+UnmapResponseBuffer:\r
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, ResponseMapping);\r
+\r
+FreeResponseBuffer:\r
+ Dev->VirtIo->FreeSharedPages (\r
+ Dev->VirtIo,\r
+ EFI_SIZE_TO_PAGES (sizeof *Response),\r
+ ResponseBuffer\r
+ );\r
+\r
+UnmapOutDataBuffer:\r
+ if (OutDataBufferIsMapped) {\r
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, OutDataMapping);\r
+ }\r
+\r
+UnmapInDataBuffer:\r
+ if (InDataBuffer != NULL) {\r
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, InDataMapping);\r
+ }\r
+\r
+FreeInDataBuffer:\r
+ if (InDataBuffer != NULL) {\r
+ Dev->VirtIo->FreeSharedPages (Dev->VirtIo, InDataNumPages, InDataBuffer);\r
+ }\r
\r
+UnmapRequestBuffer:\r
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);\r
+\r
+ return Status;\r
+}\r
\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiGetNextTargetLun (\r
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
- IN OUT UINT8 **TargetPointer,\r
- IN OUT UINT64 *Lun\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN OUT UINT8 **TargetPointer,\r
+ IN OUT UINT64 *Lun\r
)\r
{\r
- UINT8 *Target;\r
- UINTN Idx;\r
- UINT16 LastTarget;\r
- VSCSI_DEV *Dev;\r
+ UINT8 *Target;\r
+ UINTN Idx;\r
+ UINT16 LastTarget;\r
+ VSCSI_DEV *Dev;\r
\r
//\r
// the TargetPointer input parameter is unnecessarily a pointer-to-pointer\r
//\r
// Search for first non-0xFF byte. If not found, return first target & LUN.\r
//\r
- for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)\r
- ;\r
+ for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx) {\r
+ }\r
+\r
if (Idx == TARGET_MAX_BYTES) {\r
SetMem (Target, TARGET_MAX_BYTES, 0x00);\r
*Lun = 0;\r
// increment (target, LUN) pair if valid on input\r
//\r
Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);\r
- if (LastTarget > Dev->MaxTarget || *Lun > Dev->MaxLun) {\r
+ if ((LastTarget > Dev->MaxTarget) || (*Lun > Dev->MaxLun)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
return EFI_NOT_FOUND;\r
}\r
\r
-\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiBuildDevicePath (\r
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
- IN UINT8 *Target,\r
- IN UINT64 Lun,\r
- IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN UINT8 *Target,\r
+ IN UINT64 Lun,\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
)\r
{\r
- UINT16 TargetValue;\r
- VSCSI_DEV *Dev;\r
- SCSI_DEVICE_PATH *ScsiDevicePath;\r
+ UINT16 TargetValue;\r
+ VSCSI_DEV *Dev;\r
+ SCSI_DEVICE_PATH *ScsiDevicePath;\r
\r
if (DevicePath == NULL) {\r
return EFI_INVALID_PARAMETER;\r
\r
CopyMem (&TargetValue, Target, sizeof TargetValue);\r
Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);\r
- if (TargetValue > Dev->MaxTarget || Lun > Dev->MaxLun || Lun > 0xFFFF) {\r
+ if ((TargetValue > Dev->MaxTarget) || (Lun > Dev->MaxLun) || (Lun > 0xFFFF)) {\r
return EFI_NOT_FOUND;\r
}\r
\r
\r
ScsiDevicePath->Header.Type = MESSAGING_DEVICE_PATH;\r
ScsiDevicePath->Header.SubType = MSG_SCSI_DP;\r
- ScsiDevicePath->Header.Length[0] = (UINT8) sizeof *ScsiDevicePath;\r
- ScsiDevicePath->Header.Length[1] = (UINT8) (sizeof *ScsiDevicePath >> 8);\r
+ ScsiDevicePath->Header.Length[0] = (UINT8)sizeof *ScsiDevicePath;\r
+ ScsiDevicePath->Header.Length[1] = (UINT8)(sizeof *ScsiDevicePath >> 8);\r
ScsiDevicePath->Pun = TargetValue;\r
- ScsiDevicePath->Lun = (UINT16) Lun;\r
+ ScsiDevicePath->Lun = (UINT16)Lun;\r
\r
*DevicePath = &ScsiDevicePath->Header;\r
return EFI_SUCCESS;\r
}\r
\r
-\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiGetTargetLun (\r
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- OUT UINT8 **TargetPointer,\r
- OUT UINT64 *Lun\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT UINT8 **TargetPointer,\r
+ OUT UINT64 *Lun\r
)\r
{\r
- SCSI_DEVICE_PATH *ScsiDevicePath;\r
- VSCSI_DEV *Dev;\r
- UINT8 *Target;\r
+ SCSI_DEVICE_PATH *ScsiDevicePath;\r
+ VSCSI_DEV *Dev;\r
+ UINT8 *Target;\r
\r
- if (DevicePath == NULL || TargetPointer == NULL || *TargetPointer == NULL ||\r
- Lun == NULL) {\r
+ if ((DevicePath == NULL) || (TargetPointer == NULL) || (*TargetPointer == NULL) ||\r
+ (Lun == NULL))\r
+ {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (DevicePath->Type != MESSAGING_DEVICE_PATH ||\r
- DevicePath->SubType != MSG_SCSI_DP) {\r
+ if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||\r
+ (DevicePath->SubType != MSG_SCSI_DP))\r
+ {\r
return EFI_UNSUPPORTED;\r
}\r
\r
- ScsiDevicePath = (SCSI_DEVICE_PATH *) DevicePath;\r
- Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);\r
- if (ScsiDevicePath->Pun > Dev->MaxTarget ||\r
- ScsiDevicePath->Lun > Dev->MaxLun) {\r
+ ScsiDevicePath = (SCSI_DEVICE_PATH *)DevicePath;\r
+ Dev = VIRTIO_SCSI_FROM_PASS_THRU (This);\r
+ if ((ScsiDevicePath->Pun > Dev->MaxTarget) ||\r
+ (ScsiDevicePath->Lun > Dev->MaxLun))\r
+ {\r
return EFI_NOT_FOUND;\r
}\r
\r
return EFI_SUCCESS;\r
}\r
\r
-\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiResetChannel (\r
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This\r
)\r
{\r
return EFI_UNSUPPORTED;\r
}\r
\r
-\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiResetTargetLun (\r
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
- IN UINT8 *Target,\r
- IN UINT64 Lun\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN UINT8 *Target,\r
+ IN UINT64 Lun\r
)\r
{\r
return EFI_UNSUPPORTED;\r
}\r
\r
-\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiGetNextTarget (\r
- IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
- IN OUT UINT8 **TargetPointer\r
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,\r
+ IN OUT UINT8 **TargetPointer\r
)\r
{\r
- UINT8 *Target;\r
- UINTN Idx;\r
- UINT16 LastTarget;\r
- VSCSI_DEV *Dev;\r
+ UINT8 *Target;\r
+ UINTN Idx;\r
+ UINT16 LastTarget;\r
+ VSCSI_DEV *Dev;\r
\r
//\r
// the TargetPointer input parameter is unnecessarily a pointer-to-pointer\r
//\r
// Search for first non-0xFF byte. If not found, return first target.\r
//\r
- for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)\r
- ;\r
+ for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx) {\r
+ }\r
+\r
if (Idx == TARGET_MAX_BYTES) {\r
SetMem (Target, TARGET_MAX_BYTES, 0x00);\r
return EFI_SUCCESS;\r
return EFI_NOT_FOUND;\r
}\r
\r
-\r
STATIC\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiInit (\r
- IN OUT VSCSI_DEV *Dev\r
+ IN OUT VSCSI_DEV *Dev\r
)\r
{\r
- UINT8 NextDevStat;\r
- EFI_STATUS Status;\r
-\r
- UINT64 Features;\r
- UINT16 MaxChannel; // for validation only\r
- UINT32 NumQueues; // for validation only\r
- UINT16 QueueSize;\r
+ UINT8 NextDevStat;\r
+ EFI_STATUS Status;\r
+ UINT64 RingBaseShift;\r
+ UINT64 Features;\r
+ UINT16 MaxChannel; // for validation only\r
+ UINT32 NumQueues; // for validation only\r
+ UINT16 QueueSize;\r
\r
//\r
// Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.\r
//\r
NextDevStat = 0; // step 1 -- reset device\r
- Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
\r
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence\r
- Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
\r
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it\r
- Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
- Dev->InOutSupported = (BOOLEAN) ((Features & VIRTIO_SCSI_F_INOUT) != 0);\r
+\r
+ Dev->InOutSupported = (BOOLEAN)((Features & VIRTIO_SCSI_F_INOUT) != 0);\r
\r
Status = VIRTIO_CFG_READ (Dev, MaxChannel, &MaxChannel);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
+\r
if (MaxChannel != 0) {\r
//\r
// this driver is for a single-channel virtio-scsi HBA\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
+\r
if (NumQueues < 1) {\r
Status = EFI_UNSUPPORTED;\r
goto Failed;\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
+\r
if (Dev->MaxTarget > PcdGet16 (PcdVirtioScsiMaxTargetLimit)) {\r
Dev->MaxTarget = PcdGet16 (PcdVirtioScsiMaxTargetLimit);\r
}\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
+\r
if (Dev->MaxLun > PcdGet32 (PcdVirtioScsiMaxLunLimit)) {\r
Dev->MaxLun = PcdGet32 (PcdVirtioScsiMaxLunLimit);\r
}\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
+\r
if (Dev->MaxSectors < 2) {\r
//\r
// We must be able to halve it for bidirectional transfers\r
goto Failed;\r
}\r
\r
- Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1;\r
+ Features &= VIRTIO_SCSI_F_INOUT | VIRTIO_F_VERSION_1 |\r
+ VIRTIO_F_IOMMU_PLATFORM;\r
\r
//\r
// In virtio-1.0, feature negotiation is expected to complete before queue\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
+\r
Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);\r
if (EFI_ERROR (Status)) {\r
goto Failed;\r
}\r
+\r
//\r
// VirtioScsiPassThru() uses at most four descriptors\r
//\r
goto Failed;\r
}\r
\r
+ //\r
+ // If anything fails from here on, we must release the ring resources\r
+ //\r
+ Status = VirtioRingMap (\r
+ Dev->VirtIo,\r
+ &Dev->Ring,\r
+ &RingBaseShift,\r
+ &Dev->RingMap\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ReleaseQueue;\r
+ }\r
+\r
//\r
// Additional steps for MMIO: align the queue appropriately, and set the\r
- // size. If anything fails from here on, we must release the ring resources.\r
+ // size. If anything fails from here on, we must unmap the ring resources.\r
//\r
Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);\r
if (EFI_ERROR (Status)) {\r
- goto ReleaseQueue;\r
+ goto UnmapQueue;\r
}\r
\r
Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);\r
if (EFI_ERROR (Status)) {\r
- goto ReleaseQueue;\r
+ goto UnmapQueue;\r
}\r
\r
//\r
// step 4c -- Report GPFN (guest-physical frame number) of queue.\r
//\r
- Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo, &Dev->Ring, 0);\r
+ Status = Dev->VirtIo->SetQueueAddress (\r
+ Dev->VirtIo,\r
+ &Dev->Ring,\r
+ RingBaseShift\r
+ );\r
if (EFI_ERROR (Status)) {\r
- goto ReleaseQueue;\r
+ goto UnmapQueue;\r
}\r
\r
//\r
// step 5 -- Report understood features and guest-tuneables.\r
//\r
if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {\r
- Features &= ~(UINT64)VIRTIO_F_VERSION_1;\r
- Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
+ Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);\r
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);\r
if (EFI_ERROR (Status)) {\r
- goto ReleaseQueue;\r
+ goto UnmapQueue;\r
}\r
}\r
\r
//\r
Status = VIRTIO_CFG_WRITE (Dev, CdbSize, VIRTIO_SCSI_CDB_SIZE);\r
if (EFI_ERROR (Status)) {\r
- goto ReleaseQueue;\r
+ goto UnmapQueue;\r
}\r
+\r
Status = VIRTIO_CFG_WRITE (Dev, SenseSize, VIRTIO_SCSI_SENSE_SIZE);\r
if (EFI_ERROR (Status)) {\r
- goto ReleaseQueue;\r
+ goto UnmapQueue;\r
}\r
\r
//\r
// step 6 -- initialization complete\r
//\r
NextDevStat |= VSTAT_DRIVER_OK;\r
- Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);\r
if (EFI_ERROR (Status)) {\r
- goto ReleaseQueue;\r
+ goto UnmapQueue;\r
}\r
\r
//\r
\r
return EFI_SUCCESS;\r
\r
+UnmapQueue:\r
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);\r
+\r
ReleaseQueue:\r
VirtioRingUninit (Dev->VirtIo, &Dev->Ring);\r
\r
return Status; // reached only via Failed above\r
}\r
\r
-\r
STATIC\r
VOID\r
EFIAPI\r
VirtioScsiUninit (\r
- IN OUT VSCSI_DEV *Dev\r
+ IN OUT VSCSI_DEV *Dev\r
)\r
{\r
//\r
Dev->MaxLun = 0;\r
Dev->MaxSectors = 0;\r
\r
+ Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);\r
VirtioRingUninit (Dev->VirtIo, &Dev->Ring);\r
\r
- SetMem (&Dev->PassThru, sizeof Dev->PassThru, 0x00);\r
+ SetMem (&Dev->PassThru, sizeof Dev->PassThru, 0x00);\r
SetMem (&Dev->PassThruMode, sizeof Dev->PassThruMode, 0x00);\r
}\r
\r
-\r
//\r
// Event notification function enqueued by ExitBootServices().\r
//\r
VOID\r
EFIAPI\r
VirtioScsiExitBoot (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
)\r
{\r
- VSCSI_DEV *Dev;\r
+ VSCSI_DEV *Dev;\r
\r
+ DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));\r
//\r
// Reset the device. This causes the hypervisor to forget about the virtio\r
// ring.\r
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);\r
}\r
\r
-\r
//\r
// Probe, start and stop functions of this driver, called by the DXE core for\r
// specific devices.\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiDriverBindingSupported (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE DeviceHandle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE DeviceHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
- EFI_STATUS Status;\r
- VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
+ EFI_STATUS Status;\r
+ VIRTIO_DEVICE_PROTOCOL *VirtIo;\r
\r
//\r
// Attempt to open the device with the VirtIo set of interfaces. On success,\r
// We needed VirtIo access only transitorily, to see whether we support the\r
// device or not.\r
//\r
- gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
- This->DriverBindingHandle, DeviceHandle);\r
+ gBS->CloseProtocol (\r
+ DeviceHandle,\r
+ &gVirtioDeviceProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ DeviceHandle\r
+ );\r
return Status;\r
}\r
\r
-\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiDriverBindingStart (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE DeviceHandle,\r
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE DeviceHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
)\r
{\r
- VSCSI_DEV *Dev;\r
- EFI_STATUS Status;\r
+ VSCSI_DEV *Dev;\r
+ EFI_STATUS Status;\r
\r
- Dev = (VSCSI_DEV *) AllocateZeroPool (sizeof *Dev);\r
+ Dev = (VSCSI_DEV *)AllocateZeroPool (sizeof *Dev);\r
if (Dev == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
- (VOID **)&Dev->VirtIo, This->DriverBindingHandle,\r
- DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);\r
+ Status = gBS->OpenProtocol (\r
+ DeviceHandle,\r
+ &gVirtioDeviceProtocolGuid,\r
+ (VOID **)&Dev->VirtIo,\r
+ This->DriverBindingHandle,\r
+ DeviceHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
if (EFI_ERROR (Status)) {\r
goto FreeVirtioScsi;\r
}\r
goto CloseVirtIo;\r
}\r
\r
- Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,\r
- &VirtioScsiExitBoot, Dev, &Dev->ExitBoot);\r
+ Status = gBS->CreateEvent (\r
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
+ TPL_CALLBACK,\r
+ &VirtioScsiExitBoot,\r
+ Dev,\r
+ &Dev->ExitBoot\r
+ );\r
if (EFI_ERROR (Status)) {\r
goto UninitDev;\r
}\r
// interface.\r
//\r
Dev->Signature = VSCSI_SIG;\r
- Status = gBS->InstallProtocolInterface (&DeviceHandle,\r
- &gEfiExtScsiPassThruProtocolGuid, EFI_NATIVE_INTERFACE,\r
- &Dev->PassThru);\r
+ Status = gBS->InstallProtocolInterface (\r
+ &DeviceHandle,\r
+ &gEfiExtScsiPassThruProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &Dev->PassThru\r
+ );\r
if (EFI_ERROR (Status)) {\r
goto CloseExitBoot;\r
}\r
VirtioScsiUninit (Dev);\r
\r
CloseVirtIo:\r
- gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
- This->DriverBindingHandle, DeviceHandle);\r
+ gBS->CloseProtocol (\r
+ DeviceHandle,\r
+ &gVirtioDeviceProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ DeviceHandle\r
+ );\r
\r
FreeVirtioScsi:\r
FreePool (Dev);\r
return Status;\r
}\r
\r
-\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiDriverBindingStop (\r
- IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
- IN EFI_HANDLE DeviceHandle,\r
- IN UINTN NumberOfChildren,\r
- IN EFI_HANDLE *ChildHandleBuffer\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE DeviceHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
)\r
{\r
- EFI_STATUS Status;\r
- EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
- VSCSI_DEV *Dev;\r
+ EFI_STATUS Status;\r
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;\r
+ VSCSI_DEV *Dev;\r
\r
Status = gBS->OpenProtocol (\r
DeviceHandle, // candidate device\r
//\r
// Handle Stop() requests for in-use driver instances gracefully.\r
//\r
- Status = gBS->UninstallProtocolInterface (DeviceHandle,\r
- &gEfiExtScsiPassThruProtocolGuid, &Dev->PassThru);\r
+ Status = gBS->UninstallProtocolInterface (\r
+ DeviceHandle,\r
+ &gEfiExtScsiPassThruProtocolGuid,\r
+ &Dev->PassThru\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
VirtioScsiUninit (Dev);\r
\r
- gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,\r
- This->DriverBindingHandle, DeviceHandle);\r
+ gBS->CloseProtocol (\r
+ DeviceHandle,\r
+ &gVirtioDeviceProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ DeviceHandle\r
+ );\r
\r
FreePool (Dev);\r
\r
return EFI_SUCCESS;\r
}\r
\r
-\r
//\r
// The static object that groups the Supported() (ie. probe), Start() and\r
// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata\r
// C, 10.1 EFI Driver Binding Protocol.\r
//\r
-STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {\r
+STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {\r
&VirtioScsiDriverBindingSupported,\r
&VirtioScsiDriverBindingStart,\r
&VirtioScsiDriverBindingStop,\r
NULL // DriverBindingHandle, ditto\r
};\r
\r
-\r
//\r
// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and\r
// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name\r
//\r
\r
STATIC\r
-EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
+EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {\r
{ "eng;en", L"Virtio SCSI Host Driver" },\r
- { NULL, NULL }\r
+ { NULL, NULL }\r
};\r
\r
STATIC\r
-EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
+EFI_COMPONENT_NAME_PROTOCOL gComponentName;\r
\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiGetDriverName (\r
- IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
- IN CHAR8 *Language,\r
- OUT CHAR16 **DriverName\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
)\r
{\r
return LookupUnicodeString2 (\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiGetDeviceName (\r
- IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
- IN EFI_HANDLE DeviceHandle,\r
- IN EFI_HANDLE ChildHandle,\r
- IN CHAR8 *Language,\r
- OUT CHAR16 **ControllerName\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE DeviceHandle,\r
+ IN EFI_HANDLE ChildHandle,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
)\r
{\r
return EFI_UNSUPPORTED;\r
}\r
\r
STATIC\r
-EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
+EFI_COMPONENT_NAME_PROTOCOL gComponentName = {\r
&VirtioScsiGetDriverName,\r
&VirtioScsiGetDeviceName,\r
"eng" // SupportedLanguages, ISO 639-2 language codes\r
};\r
\r
STATIC\r
-EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
- (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &VirtioScsiGetDriverName,\r
- (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &VirtioScsiGetDeviceName,\r
+EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {\r
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&VirtioScsiGetDriverName,\r
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&VirtioScsiGetDeviceName,\r
"en" // SupportedLanguages, RFC 4646 language codes\r
};\r
\r
-\r
//\r
// Entry point of this driver.\r
//\r
EFI_STATUS\r
EFIAPI\r
VirtioScsiEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
return EfiLibInstallDriverBindingComponentName2 (\r