diff options
author | Olivier Martin <olivier.martin@arm.com> | 2013-12-11 16:58:22 +0000 |
---|---|---|
committer | jljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524> | 2013-12-11 16:58:22 +0000 |
commit | 56f65ed838e8d73e91d54a8ed984d777c936843c (patch) | |
tree | 63324a40af24074a70f69c26865c6a226c070852 /OvmfPkg/VirtioBlkDxe | |
parent | 6fb4e772a0ad14399532201d1b9ecb811c9c7262 (diff) | |
download | edk2-platforms-56f65ed838e8d73e91d54a8ed984d777c936843c.tar.xz |
OvmfPkg: Make the VirtIo devices use the new VIRTIO_DEVICE_PROTOCOL
This change replaces the accesses to the PCI bus from the Block, Scsi and Net drivers by
the use of the new VIRTIO_DEVICE_PROTOCOL protocol that abstracts the transport layer.
It means these drivers can be used on PCI and MMIO transport layer.
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
v5:
- VirtioFlush(): update comment block in VirtioLib.[hc]; error code is
propagated from VirtIo->SetQueueNotify().
- VirtioBlkInit(): jump to Failed label if SetPageSize() fails
- VirtioBlkInit(): fixup comment, and add error handling, near
SetQueueNum() call
- VirtioBlkDriverBindingStart(): remove redundant (always false) check for
a subsystem device ID different from VIRTIO_SUBSYSTEM_BLOCK_DEVICE;
VirtioBlkDriverBindingSupported() handles it already
- VirtioNetGetFeatures(): update stale comment block
- VirtioNetGetFeatures(): retrieve MAC address byte for byte (open-coded
loop)
- VirtioNetDriverBindingStart(): remove redundant (always false) check for
a subsystem device ID different from VIRTIO_SUBSYSTEM_NETWORK_CARD;
VirtioNetDriverBindingSupported() handles it already
- VirtioNetInitRing(): call SetQueueNum() and SetQueueAlign() for proper
MMIO operation
- VirtioNetInitialize(): fix destination error label for when
SetPageSize() fails
- VirtioScsi.c: fix comment block of VIRTIO_CFG_WRITE()/VIRTIO_CFG_READ()
- VirtioScsiInit(): fix destination error label for when SetPageSize()
fails
- VirtioScsiInit(): call SetQueueNum() and SetQueueAlign() for proper MMIO
operation
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14966 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'OvmfPkg/VirtioBlkDxe')
-rw-r--r-- | OvmfPkg/VirtioBlkDxe/VirtioBlk.c | 180 | ||||
-rw-r--r-- | OvmfPkg/VirtioBlkDxe/VirtioBlk.h | 32 | ||||
-rw-r--r-- | OvmfPkg/VirtioBlkDxe/VirtioBlk.inf | 4 |
3 files changed, 87 insertions, 129 deletions
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c index 17b9f71d63..f09b0d1118 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.c +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.c @@ -23,7 +23,6 @@ **/
-#include <IndustryStandard/Pci.h>
#include <IndustryStandard/VirtioBlk.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
@@ -37,14 +36,14 @@ /**
Convenience macros to read and write region 0 IO space elements of the
- virtio-blk PCI device, for configuration purposes.
+ virtio-blk device, for configuration purposes.
The following macros make it possible to specify only the "core parameters"
for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()
returns, the transaction will have been completed.
- @param[in] Dev Pointer to the VBLK_DEV structure whose PCI IO space
- we're accessing. Dev->PciIo must be valid.
+ @param[in] Dev Pointer to the VBLK_DEV structure whose VirtIo space
+ we're accessing. Dev->VirtIo must be valid.
@param[in] Field A field name from VBLK_HDR, identifying the virtio-blk
configuration item to access.
@@ -57,19 +56,19 @@ one of UINT8, UINT16, UINT32, UINT64.
- @return Status code returned by VirtioWrite() / VirtioRead().
+ @return Status code returned by VirtioWriteDevice() / VirtioReadDevice().
**/
-#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWrite ( \
- (Dev)->PciIo, \
+#define VIRTIO_CFG_WRITE(Dev, Field, Value) (VirtioWriteDevice ( \
+ (Dev)->VirtIo, \
OFFSET_OF_VBLK (Field), \
SIZE_OF_VBLK (Field), \
(Value) \
))
-#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioRead ( \
- (Dev)->PciIo, \
+#define VIRTIO_CFG_READ(Dev, Field, Pointer) (VirtioReadDevice ( \
+ (Dev)->VirtIo, \
OFFSET_OF_VBLK (Field), \
SIZE_OF_VBLK (Field), \
sizeof *(Pointer), \
@@ -229,7 +228,7 @@ VerifyReadWriteRequest ( @retval EFI_SUCCESS Transfer complete.
- @retval EFI_DEVICE_ERROR Failed to notify host side via PCI write, or
+ @retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or
unable to parse host response, or host response
is not VIRTIO_BLK_S_OK.
@@ -324,7 +323,7 @@ SynchronousRequest ( //
// virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
//
- if (VirtioFlush (Dev->PciIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&
+ if (VirtioFlush (Dev->VirtIo, 0, &Dev->Ring, &Indices) == EFI_SUCCESS &&
HostStatus == VIRTIO_BLK_S_OK) {
return EFI_SUCCESS;
}
@@ -500,11 +499,6 @@ VirtioBlkFlushBlocks ( underlying device
- 9 Driver Binding Protocol -- for exporting ourselves
- Specs relevant in the specific sense:
- - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol
- - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design
- Guidelines, 18.3 PCI drivers.
-
@param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
incorporating this driver (independently of
any device).
@@ -516,11 +510,11 @@ VirtioBlkFlushBlocks ( @retval EFI_SUCCESS The driver supports the device being probed.
- @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support
+ @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support
the device.
@return Error codes from the OpenProtocol() boot service or
- the PciIo protocol.
+ the VirtIo protocol.
**/
@@ -533,56 +527,36 @@ VirtioBlkDriverBindingSupported ( )
{
EFI_STATUS Status;
- EFI_PCI_IO_PROTOCOL *PciIo;
- PCI_TYPE00 Pci;
+ VIRTIO_DEVICE_PROTOCOL *VirtIo;
//
- // Attempt to open the device with the PciIo set of interfaces. On success,
- // the protocol is "instantiated" for the PCI device. Covers duplicate open
+ // Attempt to open the device with the VirtIo set of interfaces. On success,
+ // the protocol is "instantiated" for the VirtIo device. Covers duplicate open
// attempts (EFI_ALREADY_STARTED).
//
Status = gBS->OpenProtocol (
DeviceHandle, // candidate device
- &gEfiPciIoProtocolGuid, // for generic PCI access
- (VOID **)&PciIo, // handle to instantiate
+ &gVirtioDeviceProtocolGuid, // for generic VirtIo access
+ (VOID **)&VirtIo, // handle to instantiate
This->DriverBindingHandle, // requestor driver identity
DeviceHandle, // ControllerHandle, according to
// the UEFI Driver Model
- EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive PciIo access to
+ EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
// the device; to be released
);
if (EFI_ERROR (Status)) {
return Status;
}
- //
- // Read entire PCI configuration header for more extensive check ahead.
- //
- Status = PciIo->Pci.Read (
- PciIo, // (protocol, device)
- // handle
- EfiPciIoWidthUint32, // access width & copy
- // mode
- 0, // Offset
- sizeof Pci / sizeof (UINT32), // Count
- &Pci // target buffer
- );
-
- if (Status == EFI_SUCCESS) {
- //
- // virtio-0.9.5, 2.1 PCI Discovery
- //
- Status = (Pci.Hdr.VendorId == 0x1AF4 &&
- Pci.Hdr.DeviceId >= 0x1000 && Pci.Hdr.DeviceId <= 0x103F &&
- Pci.Hdr.RevisionID == 0x00 &&
- Pci.Device.SubsystemID == VIRTIO_SUBSYSTEM_BLOCK_DEVICE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
+ if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_BLOCK_DEVICE) {
+ Status = EFI_UNSUPPORTED;
}
//
- // We needed PCI IO access only transitorily, to see whether we support the
+ // We needed VirtIo access only transitorily, to see whether we support the
// device or not.
//
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
return Status;
}
@@ -594,8 +568,8 @@ VirtioBlkDriverBindingSupported ( device.
@param[in out] Dev The driver instance to configure. The caller is
- responsible for Dev->PciIo's validity (ie. working IO
- access to the underlying virtio-blk PCI device).
+ responsible for Dev->VirtIo's validity (ie. working IO
+ access to the underlying virtio-blk device).
@retval EFI_SUCCESS Setup complete.
@@ -626,19 +600,27 @@ VirtioBlkInit ( // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
//
NextDevStat = 0; // step 1 -- reset device
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto Failed;
}
NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto Failed;
}
NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // Set Page Size - MMIO VirtIo Specific
+ //
+ Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -646,11 +628,12 @@ VirtioBlkInit ( //
// step 4a -- retrieve and validate features
//
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrDeviceFeatureBits, &Features);
+ Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
if (EFI_ERROR (Status)) {
goto Failed;
}
- Status = VIRTIO_CFG_READ (Dev, VhdrCapacity, &NumSectors);
+
+ Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -660,7 +643,7 @@ VirtioBlkInit ( }
if (Features & VIRTIO_BLK_F_BLK_SIZE) {
- Status = VIRTIO_CFG_READ (Dev, VhdrBlkSize, &BlockSize);
+ Status = VIRTIO_CFG_READ (Dev, BlkSize, &BlockSize);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -681,11 +664,11 @@ VirtioBlkInit ( //
// step 4b -- allocate virtqueue
//
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueSelect, 0);
+ Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0);
if (EFI_ERROR (Status)) {
goto Failed;
}
- Status = VIRTIO_CFG_READ (Dev, Generic.VhdrQueueSize, &QueueSize);
+ Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
if (EFI_ERROR (Status)) {
goto Failed;
}
@@ -700,22 +683,36 @@ VirtioBlkInit ( }
//
- // step 4c -- Report GPFN (guest-physical frame number) of queue. If anything
- // fails from here on, we must release the ring resources.
+ // Additional steps for MMIO: align the queue appropriately, and set the
+ // size. If anything fails from here on, we must release the ring resources.
+ //
+ Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
+ if (EFI_ERROR (Status)) {
+ goto ReleaseQueue;
+ }
+
+ Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
+ if (EFI_ERROR (Status)) {
+ goto ReleaseQueue;
+ }
+
+ //
+ // step 4c -- Report GPFN (guest-physical frame number) of queue.
//
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrQueueAddress,
- (UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
+ Status = Dev->VirtIo->SetQueueAddress (Dev->VirtIo,
+ (UINT32)(UINTN) Dev->Ring.Base >> EFI_PAGE_SHIFT);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
+
//
// step 5 -- Report understood features. There are no virtio-blk specific
// features to negotiate in virtio-0.9.5, plus we do not want any of the
// device-independent (known or unknown) VIRTIO_F_* capabilities (see
// Appendix B).
//
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrGuestFeatureBits, 0);
+ Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, 0);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -724,7 +721,7 @@ VirtioBlkInit ( // step 6 -- initialization complete
//
NextDevStat |= VSTAT_DRIVER_OK;
- Status = VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
if (EFI_ERROR (Status)) {
goto ReleaseQueue;
}
@@ -758,10 +755,10 @@ ReleaseQueue: Failed:
//
// Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
- // Status. PCI IO access failure here should not mask the original error.
+ // Status. VirtIo access failure here should not mask the original error.
//
NextDevStat |= VSTAT_FAILED;
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, NextDevStat);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
return Status; // reached only via Failed above
}
@@ -788,7 +785,7 @@ VirtioBlkUninit ( // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
// the old comms area.
//
- VIRTIO_CFG_WRITE (Dev, Generic.VhdrDeviceStatus, 0);
+ Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
VirtioRingUninit (&Dev->Ring);
@@ -815,13 +812,13 @@ VirtioBlkUninit ( @retval EFI_SUCCESS Driver instance has been created and
- initialized for the virtio-blk PCI device, it
+ initialized for the virtio-blk device, it
is now accessibla via EFI_BLOCK_IO_PROTOCOL.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@return Error codes from the OpenProtocol() boot
- service, the PciIo protocol, VirtioBlkInit(),
+ service, the VirtIo protocol, VirtioBlkInit(),
or the InstallProtocolInterface() boot service.
**/
@@ -842,43 +839,19 @@ VirtioBlkDriverBindingStart ( return EFI_OUT_OF_RESOURCES;
}
- Status = gBS->OpenProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
- (VOID **)&Dev->PciIo, This->DriverBindingHandle,
+ Status = gBS->OpenProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
+ (VOID **)&Dev->VirtIo, This->DriverBindingHandle,
DeviceHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
if (EFI_ERROR (Status)) {
goto FreeVirtioBlk;
}
//
- // We must retain and ultimately restore the original PCI attributes of the
- // device. See Driver Writer's Guide for UEFI 2.3.1 v1.01, 18.3 PCI drivers /
- // 18.3.2 Start() and Stop().
- //
- // The third parameter ("Attributes", input) is ignored by the Get operation.
- // The fourth parameter ("Result", output) is ignored by the Enable and Set
- // operations.
- //
- // For virtio-blk we only need IO space access.
- //
- Status = Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationGet,
- 0, &Dev->OriginalPciAttributes);
- if (EFI_ERROR (Status)) {
- goto ClosePciIo;
- }
-
- Status = Dev->PciIo->Attributes (Dev->PciIo,
- EfiPciIoAttributeOperationEnable,
- EFI_PCI_IO_ATTRIBUTE_IO, NULL);
- if (EFI_ERROR (Status)) {
- goto ClosePciIo;
- }
-
- //
- // PCI IO access granted, configure virtio-blk device.
+ // VirtIo access granted, configure virtio-blk device.
//
Status = VirtioBlkInit (Dev);
if (EFI_ERROR (Status)) {
- goto RestorePciAttributes;
+ goto CloseVirtIo;
}
//
@@ -897,12 +870,8 @@ VirtioBlkDriverBindingStart ( UninitDev:
VirtioBlkUninit (Dev);
-RestorePciAttributes:
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,
- Dev->OriginalPciAttributes, NULL);
-
-ClosePciIo:
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+CloseVirtIo:
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
FreeVirtioBlk:
@@ -973,10 +942,7 @@ VirtioBlkDriverBindingStop ( VirtioBlkUninit (Dev);
- Dev->PciIo->Attributes (Dev->PciIo, EfiPciIoAttributeOperationSet,
- Dev->OriginalPciAttributes, NULL);
-
- gBS->CloseProtocol (DeviceHandle, &gEfiPciIoProtocolGuid,
+ gBS->CloseProtocol (DeviceHandle, &gVirtioDeviceProtocolGuid,
This->DriverBindingHandle, DeviceHandle);
FreePool (Dev);
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h index d22570def9..789caf9a37 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.h +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.h @@ -21,7 +21,6 @@ #include <Protocol/BlockIo.h>
#include <Protocol/ComponentName.h>
#include <Protocol/DriverBinding.h>
-#include <Protocol/PciIo.h>
#include <IndustryStandard/Virtio.h>
@@ -34,14 +33,13 @@ typedef struct { // at various call depths. The table to the right should make it easier to
// track them.
//
- // field init function init dpth
- // ---------------------- ------------------ ---------
- UINT32 Signature; // DriverBindingStart 0
- EFI_PCI_IO_PROTOCOL *PciIo; // DriverBindingStart 0
- UINT64 OriginalPciAttributes; // DriverBindingStart 0
- VRING Ring; // VirtioRingInit 2
- EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1
- EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1
+ // field init function init dpth
+ // --------------------- ------------------ ---------
+ UINT32 Signature; // DriverBindingStart 0
+ VIRTIO_DEVICE_PROTOCOL *VirtIo; // DriverBindingStart 0
+ VRING Ring; // VirtioRingInit 2
+ EFI_BLOCK_IO_PROTOCOL BlockIo; // VirtioBlkInit 1
+ EFI_BLOCK_IO_MEDIA BlockIoMedia; // VirtioBlkInit 1
} VBLK_DEV;
#define VIRTIO_BLK_FROM_BLOCK_IO(BlockIoPointer) \
@@ -66,11 +64,6 @@ typedef struct { underlying device
- 9 Driver Binding Protocol -- for exporting ourselves
- Specs relevant in the specific sense:
- - UEFI Spec 2.3.1 + Errata C, 13.4 EFI PCI I/O Protocol
- - Driver Writer's Guide for UEFI 2.3.1 v1.01, 18 PCI Driver Design
- Guidelines, 18.3 PCI drivers.
-
@param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
incorporating this driver (independently of
any device).
@@ -82,11 +75,10 @@ typedef struct { @retval EFI_SUCCESS The driver supports the device being probed.
- @retval EFI_UNSUPPORTED Based on virtio-blk PCI discovery, we do not support
+ @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support
the device.
- @return Error codes from the OpenProtocol() boot service or
- the PciIo protocol.
+ @return Error codes from the OpenProtocol() boot service.
**/
@@ -117,14 +109,14 @@ VirtioBlkDriverBindingSupported ( @retval EFI_SUCCESS Driver instance has been created and
- initialized for the virtio-blk PCI device, it
+ initialized for the virtio-blk device, it
is now accessibla via EFI_BLOCK_IO_PROTOCOL.
@retval EFI_OUT_OF_RESOURCES Memory allocation failed.
@return Error codes from the OpenProtocol() boot
- service, the PciIo protocol, VirtioBlkInit(),
- or the InstallProtocolInterface() boot service.
+ service, VirtioBlkInit(), or the
+ InstallProtocolInterface() boot service.
**/
diff --git a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf index 6dffc3a22a..d5975b74eb 100644 --- a/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf +++ b/OvmfPkg/VirtioBlkDxe/VirtioBlk.inf @@ -38,5 +38,5 @@ VirtioLib
[Protocols]
- gEfiBlockIoProtocolGuid ## BY_START
- gEfiPciIoProtocolGuid ## TO_START
+ gEfiBlockIoProtocolGuid ## BY_START
+ gVirtioDeviceProtocolGuid ## TO_START
|