From mboxrd@z Thu Jan 1 00:00:00 1970 From: Anthony PERARD Subject: [PATCH RFC 17/18] OvmfPkg/XenPvBlkDxe: Add BlockFront client. Date: Wed, 16 Jul 2014 16:15:46 +0100 Message-ID: <1405523747-5024-18-git-send-email-anthony.perard__5557.48923584378$1405524256$gmane$org@citrix.com> References: <1405523747-5024-1-git-send-email-anthony.perard@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <1405523747-5024-1-git-send-email-anthony.perard@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: EDK2 devel Cc: Anthony PERARD , Samuel Thibault , Xen Devel List-Id: xen-devel@lists.xenproject.org This is the code that will do the actual communication between OVMF and a PV block backend, where the block device lives. This implementation originally comes from Mini-OS, a part of the Xen Project. Signed-off-by: Samuel Thibault Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Anthony PERARD --- OvmfPkg/XenPvBlkDxe/BlockFront.c | 583 ++++++++++++++++++++++++++++++++++++ OvmfPkg/XenPvBlkDxe/BlockFront.h | 88 ++++++ OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c | 8 + OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf | 2 + 4 files changed, 681 insertions(+) create mode 100644 OvmfPkg/XenPvBlkDxe/BlockFront.c create mode 100644 OvmfPkg/XenPvBlkDxe/BlockFront.h diff --git a/OvmfPkg/XenPvBlkDxe/BlockFront.c b/OvmfPkg/XenPvBlkDxe/BlockFront.c new file mode 100644 index 0000000..ff5641c --- /dev/null +++ b/OvmfPkg/XenPvBlkDxe/BlockFront.c @@ -0,0 +1,583 @@ +/* Minimal block driver for Mini-OS. + * Copyright (c) 2007-2008 Samuel Thibault. + * Based on netfront.c. + */ + +#include +#include + +#include "BlockFront.h" + +#include +#include + +#include "inttypes.h" + +STATIC +XENSTORE_STATUS +XenbusReadInteger ( + IN XENBUS_PROTOCOL *This, + IN CONST CHAR8 *Node, + IN BOOLEAN FromBackend, + OUT UINT64 *ValuePtr + ) +{ + XENSTORE_STATUS Status; + CHAR8 *p; + + if (!FromBackend) { + Status = This->XsRead (This, XST_NIL, Node, (VOID**)&p); + } else { + Status = This->XsBackendRead (This, XST_NIL, Node, (VOID**)&p); + } + if (Status != XENSTORE_STATUS_SUCCESS) { + return Status; + } + // XXX Will assert if p overflow UINT64 ... + *ValuePtr = AsciiStrDecimalToUint64 (p); + FreePool (p); + return Status; +} + +STATIC +VOID +XenPvBlockFree ( + IN XEN_BLOCK_FRONT_DEVICE *Dev + ) +{ + XENBUS_PROTOCOL *XenbusIo = Dev->XenbusIo; + + if (Dev->RingRef != 0) { + XenbusIo->GrantEndAccess (XenbusIo, Dev->RingRef); + } + if (Dev->Ring.sring != NULL) { + FreePages (Dev->Ring.sring, 1); + } + if (Dev->EventChannel != 0) { + XenbusIo->EventChannelClose (XenbusIo, Dev->EventChannel); + } + FreePool (Dev); +} + +XENSTORE_STATUS +XenPvBlkWaitForBackendState ( + IN XEN_BLOCK_FRONT_DEVICE *Dev, + IN XenbusState WaitedState, + OUT XenbusState *LastStatePtr OPTIONAL + ) +{ + XENBUS_PROTOCOL *XenbusIo = Dev->XenbusIo; + XenbusState State; + UINT64 Value; + XENSTORE_STATUS Status; + + while (TRUE) { + Status = XenbusReadInteger (XenbusIo, "state", TRUE, &Value); + if (Status != XENSTORE_STATUS_SUCCESS) { + return Status; + } + if (Value > XenbusStateReconfigured) { + return XENSTORE_STATUS_EIO; + } + State = Value; + if (State >= WaitedState) { + break; + } + DEBUG ((EFI_D_INFO, + "XenPvBlk: waiting backend state %d, current: %d\n", + WaitedState, State)); + XenbusIo->WaitForWatch (XenbusIo, Dev->StateWatchToken); + } + + if (LastStatePtr != NULL) { + *LastStatePtr = State; + } + + return XENSTORE_STATUS_SUCCESS; +} + +EFI_STATUS +XenPvBlockFrontInitialization ( + IN XENBUS_PROTOCOL *XenbusIo, + IN CONST CHAR8 *NodeName, + OUT XEN_BLOCK_FRONT_DEVICE **DevPtr + ) +{ + XENSTORE_TRANSACTION xbt; + CHAR8 *DeviceType; + blkif_sring_t *SharedRing; + XENSTORE_STATUS Status; + XEN_BLOCK_FRONT_DEVICE *Dev; + XenbusState State; + UINT64 Value; + + ASSERT (NodeName != NULL); + + Dev = AllocateZeroPool (sizeof (XEN_BLOCK_FRONT_DEVICE)); + Dev->Signature = XEN_BLOCK_FRONT_SIGNATURE; + Dev->NodeName = NodeName; + Dev->XenbusIo = XenbusIo; + Dev->DeviceId = XenbusIo->DeviceId; + + XenbusIo->XsRead (XenbusIo, XST_NIL, "device-type", (VOID**)&DeviceType); + if (AsciiStrCmp (DeviceType, "cdrom") == 0) { + Dev->MediaInfo.CdRom = TRUE; + } else { + Dev->MediaInfo.CdRom = FALSE; + } + FreePool (DeviceType); + + Status = XenbusReadInteger (XenbusIo, "backend-id", FALSE, &Value); + if (Status != XENSTORE_STATUS_SUCCESS || Value > UINT16_MAX) { + DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to get backend-id (%d)\n", + Status)); + goto Error; + } + Dev->DomainId = Value; + XenbusIo->EventChannelAllocate (XenbusIo, Dev->DomainId, &Dev->EventChannel); + + SharedRing = (blkif_sring_t*) AllocatePages (1); + SHARED_RING_INIT (SharedRing); + FRONT_RING_INIT (&Dev->Ring, SharedRing, EFI_PAGE_SIZE); + XenbusIo->GrantAccess (XenbusIo, + Dev->DomainId, + (INTN) SharedRing >> EFI_PAGE_SHIFT, + FALSE, + &Dev->RingRef); + +Again: + Status = XenbusIo->XsTransactionStart (XenbusIo, &xbt); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_WARN, "XenPvBlk: Failed to start transaction, %d\n", Status)); + } + + Status = XenbusIo->XsPrintf (XenbusIo, xbt, NodeName, "ring-ref", "%d", + Dev->RingRef); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write ring-ref.\n")); + goto AbortTransaction; + } + Status = XenbusIo->XsPrintf (XenbusIo, xbt, NodeName, + "event-channel", "%d", Dev->EventChannel); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write event-channel.\n")); + goto AbortTransaction; + } + Status = XenbusIo->XsPrintf (XenbusIo, xbt, NodeName, + "protocol", "%a", XEN_IO_PROTO_ABI_NATIVE); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed to write protocol.\n")); + goto AbortTransaction; + } + + Status = XenbusIo->SetState (XenbusIo, xbt, XenbusStateConnected); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_ERROR, "XenPvBlk: Failed switch state.\n")); + goto AbortTransaction; + } + + Status = XenbusIo->XsTransactionEnd (XenbusIo, xbt, FALSE); + if (Status == XENSTORE_STATUS_EAGAIN) { + goto Again; + } + + XenbusIo->RegisterWatchBackend (XenbusIo, "state", &Dev->StateWatchToken); + + // Waiting backend + Status = XenPvBlkWaitForBackendState (Dev, XenbusStateConnected, &State); + if (Status != XENSTORE_STATUS_SUCCESS || State != XenbusStateConnected) { + DEBUG ((EFI_D_ERROR, + "XenPvBlk: backend for %a/%d not available, rc=%d state=%d\n", + XenbusIo->Type, XenbusIo->DeviceId, Status, State)); + goto Error2; + } + + Status = XenbusReadInteger (XenbusIo, "info", TRUE, &Value); + if (Status != XENSTORE_STATUS_SUCCESS || Value > UINT32_MAX) { + goto Error2; + } + Dev->MediaInfo.VDiskInfo = Value; + if (Dev->MediaInfo.VDiskInfo & VDISK_READONLY) { + Dev->MediaInfo.ReadWrite = FALSE; + } else { + Dev->MediaInfo.ReadWrite = TRUE; + } + + Status = XenbusReadInteger (XenbusIo, "sectors", TRUE, &Dev->MediaInfo.Sectors); + if (Status != XENSTORE_STATUS_SUCCESS) { + goto Error2; + } + + Status = XenbusReadInteger (XenbusIo, "sector-size", TRUE, &Value); + if (Status != XENSTORE_STATUS_SUCCESS || Value > UINT32_MAX) { + goto Error2; + } + Dev->MediaInfo.SectorSize = Value; + + // Default value + Value = 0; + Status = XenbusReadInteger (XenbusIo, "feature-barrier", TRUE, &Value); + if (Value == 1) { + Dev->MediaInfo.FeatureBarrier = TRUE; + } else { + Dev->MediaInfo.FeatureBarrier = FALSE; + } + + // Default value + Value = 0; + XenbusReadInteger (XenbusIo, "feature-flush-cache", TRUE, &Value); + if (Value == 1) { + Dev->MediaInfo.FeatureFlushCache = TRUE; + } else { + Dev->MediaInfo.FeatureFlushCache = FALSE; + } + + DEBUG ((EFI_D_INFO, "XenPvBlk: New disk with %d sectors of %d bytes\n", + Dev->MediaInfo.Sectors, Dev->MediaInfo.SectorSize)); + + *DevPtr = Dev; + return EFI_SUCCESS; + +Error2: + XenbusIo->UnregisterWatch (XenbusIo, Dev->StateWatchToken); + XenbusIo->XsRemove (XenbusIo, XST_NIL, "ring-ref"); + XenbusIo->XsRemove (XenbusIo, XST_NIL, "event-channel"); + goto Error; +AbortTransaction: + XenbusIo->XsTransactionEnd (XenbusIo, xbt, TRUE); +Error: + XenPvBlockFree (Dev); + return EFI_DEVICE_ERROR; +} + +VOID +XenPvBlockFrontShutdown ( + IN XEN_BLOCK_FRONT_DEVICE *Dev + ) +{ + XENBUS_PROTOCOL *XenbusIo = Dev->XenbusIo; + XENSTORE_STATUS Status; + UINT64 Value; + + XenPvBlockSync (Dev); + + Status = XenbusIo->SetState (XenbusIo, XST_NIL, XenbusStateClosing); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_ERROR, + "XenPvBlk: error while changing state to Closing: %d\n", + Status)); + goto Close; + } + + Status = XenPvBlkWaitForBackendState (Dev, XenbusStateClosing, NULL); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_ERROR, + "XenPvBlk: error while waiting for closing backend state: %d\n", + Status)); + goto Close; + } + + Status = XenbusIo->SetState (XenbusIo, XST_NIL, XenbusStateClosed); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_ERROR, + "XenPvBlk: error while changing state to Closed: %d\n", + Status)); + goto Close; + } + + Status = XenPvBlkWaitForBackendState (Dev, XenbusStateClosed, NULL); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_ERROR, + "XenPvBlk: error while waiting for closed backend state: %d\n", + Status)); + goto Close; + } + + Status = XenbusIo->SetState (XenbusIo, XST_NIL, XenbusStateInitialising); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_ERROR, + "XenPvBlk: error while changing state to initialising: %d\n", + Status)); + goto Close; + } + + while (TRUE) { + Status = XenbusReadInteger (XenbusIo, "state", TRUE, &Value); + if (Status != XENSTORE_STATUS_SUCCESS) { + DEBUG ((EFI_D_ERROR, + "XenPvBlk: error while waiting for new backend state: %d\n", + Status)); + goto Close; + } + if (Value < XenbusStateInitWait || Value >= XenbusStateClosed) { + break; + } + DEBUG ((EFI_D_INFO, + "XenPvBlk: waiting backend state %d, current: %d\n", + XenbusStateInitWait, Value)); + XenbusIo->WaitForWatch (XenbusIo, Dev->StateWatchToken); + } + +Close: + XenbusIo->UnregisterWatch (XenbusIo, Dev->StateWatchToken); + XenbusIo->XsRemove (XenbusIo, XST_NIL, "ring-ref"); + XenbusIo->XsRemove (XenbusIo, XST_NIL, "event-channel"); + + XenPvBlockFree (Dev); +} + +STATIC +VOID +XenPvBlockWaitSlot ( + IN XEN_BLOCK_FRONT_DEVICE *Dev + ) +{ + /* Wait for a slot */ + if (RING_FULL (&Dev->Ring)) { + while (TRUE) { + XenPvBlockAsyncIoPoll (Dev); + if (!RING_FULL(&Dev->Ring)) { + break; + } + /* Really no slot, go to sleep. */ + // XXX wait for an event on Dev->EventChannel + DEBUG ((EFI_D_INFO, "%a %d, waiting\n", __func__, __LINE__)); + } + } +} + +/* Issue an aio */ +VOID +XenPvBlockAsyncIo ( + IN OUT XEN_BLOCK_FRONT_IO *IoData, + IN BOOLEAN IsWrite + ) +{ + XEN_BLOCK_FRONT_DEVICE *Dev = IoData->Dev; + XENBUS_PROTOCOL *XenbusIo = Dev->XenbusIo; + blkif_request_t *Request; + RING_IDX RingIndex; + BOOLEAN Notify; + INT32 NumSegments, Index; + UINTN Start, End; + + // Can't io at non-sector-aligned location + ASSERT(!(IoData->Offset & (Dev->MediaInfo.SectorSize - 1))); + // Can't io non-sector-sized amounts + ASSERT(!(IoData->Size & (Dev->MediaInfo.SectorSize - 1))); + // Can't io non-sector-aligned buffer + ASSERT(!((UINTN) IoData->Buffer & (Dev->MediaInfo.SectorSize - 1))); + + Start = (UINTN) IoData->Buffer & ~EFI_PAGE_MASK; + End = ((UINTN) IoData->Buffer + IoData->Size + EFI_PAGE_SIZE - 1) & ~EFI_PAGE_MASK; + IoData->NumRef = NumSegments = (End - Start) / EFI_PAGE_SIZE; + + // XXX is this comment still true ? + /* qemu's IDE max multsect is 16 (8KB) and SCSI max DMA was set to 32KB, + * so max 44KB can't happen */ + ASSERT (NumSegments <= BLKIF_MAX_SEGMENTS_PER_REQUEST); + + XenPvBlockWaitSlot (Dev); + RingIndex = Dev->Ring.req_prod_pvt; + Request = RING_GET_REQUEST (&Dev->Ring, RingIndex); + + Request->operation = IsWrite ? BLKIF_OP_WRITE : BLKIF_OP_READ; + Request->nr_segments = NumSegments; + Request->handle = Dev->DeviceId; + Request->id = (UINTN) IoData; + Request->sector_number = IoData->Offset / 512; + + for (Index = 0; Index < NumSegments; Index++) { + Request->seg[Index].first_sect = 0; + Request->seg[Index].last_sect = EFI_PAGE_SIZE / 512 - 1; + } + Request->seg[0].first_sect = ((UINTN) IoData->Buffer & EFI_PAGE_MASK) / 512; + Request->seg[NumSegments - 1].last_sect = + (((UINTN) IoData->Buffer + IoData->Size - 1) & EFI_PAGE_MASK) / 512; + for (Index = 0; Index < NumSegments; Index++) { + UINTN Data = Start + Index * EFI_PAGE_SIZE; + if (!IsWrite) { + /* Trigger CoW if needed */ + *(CHAR8 *)(Data + (Request->seg[Index].first_sect << 9)) = 0; + MemoryFence (); + } + XenbusIo->GrantAccess (XenbusIo, Dev->DomainId, + Data >> EFI_PAGE_SHIFT, IsWrite, + &Request->seg[Index].gref); + IoData->GrantRef[Index] = Request->seg[Index].gref; + } + + Dev->Ring.req_prod_pvt = RingIndex + 1; + + MemoryFence (); + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify); + + if (Notify) { + XenbusIo->EventChannelNotify (XenbusIo, Dev->EventChannel); + } +} + +STATIC +VOID +XenPvBlockAsyncIoCallback ( + IN OUT XEN_BLOCK_FRONT_IO *IoData, + IN EFI_STATUS Status + ) +{ + IoData->Data = (VOID *) 1; + IoData->Callback = NULL; +} + +VOID +XenPvBlockIo ( + IN OUT XEN_BLOCK_FRONT_IO *IoData, + IN BOOLEAN IsWrite + ) +{ + ASSERT (IoData->Callback == NULL); + // XXX Signal/Event instead ? + IoData->Callback = XenPvBlockAsyncIoCallback; + XenPvBlockAsyncIo (IoData, IsWrite); + IoData->Data = NULL; + + while (TRUE) { + XenPvBlockAsyncIoPoll (IoData->Dev); + if (IoData->Data) { + break; + } + } +} + +STATIC +VOID +XenPvBlockPushOperation ( + IN XEN_BLOCK_FRONT_DEVICE *Dev, + IN UINT8 Operation, + IN UINT64 Id + ) +{ + INT32 Index; + blkif_request_t *Request; + BOOLEAN Notify; + + XenPvBlockWaitSlot (Dev); + Index = Dev->Ring.req_prod_pvt; + Request = RING_GET_REQUEST(&Dev->Ring, Index); + Request->operation = Operation; + Request->nr_segments = 0; + Request->handle = Dev->DeviceId; + Request->id = Id; + /* Not needed anyway, but the backend will check it */ + Request->sector_number = 0; + Dev->Ring.req_prod_pvt = Index + 1; + MemoryFence (); + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY (&Dev->Ring, Notify); + if (Notify) { + XENBUS_PROTOCOL *XenbusIo = Dev->XenbusIo; + XenbusIo->EventChannelNotify (XenbusIo, Dev->EventChannel); + } +} + +VOID +XenPvBlockSync ( + IN XEN_BLOCK_FRONT_DEVICE *Dev + ) +{ + if (Dev->MediaInfo.ReadWrite) { + if (Dev->MediaInfo.FeatureBarrier) { + XenPvBlockPushOperation (Dev, BLKIF_OP_WRITE_BARRIER, 0); + } + + if (Dev->MediaInfo.FeatureFlushCache) { + XenPvBlockPushOperation (Dev, BLKIF_OP_FLUSH_DISKCACHE, 0); + } + } + + /* Note: This won't finish if another thread enqueues requests. */ + while (TRUE) { + XenPvBlockAsyncIoPoll (Dev); + if (RING_FREE_REQUESTS (&Dev->Ring) == RING_SIZE (&Dev->Ring)) { + break; + } + } +} + +VOID +XenPvBlockAsyncIoPoll ( + IN XEN_BLOCK_FRONT_DEVICE *Dev + ) +{ + RING_IDX ProducerIndex, ConsumerIndex; + blkif_response_t *Response; + INT32 More; + + do { + ProducerIndex = Dev->Ring.sring->rsp_prod; + /* Ensure we see queued responses up to 'ProducerIndex'. */ + MemoryFence (); + ConsumerIndex = Dev->Ring.rsp_cons; + + while (ConsumerIndex != ProducerIndex) { + XEN_BLOCK_FRONT_IO *IoData; + INT16 Status; + + Response = RING_GET_RESPONSE (&Dev->Ring, ConsumerIndex); + + IoData = (VOID *) (UINTN) Response->id; + Status = Response->status; + + switch (Response->operation) { + case BLKIF_OP_READ: + case BLKIF_OP_WRITE: + { + INT32 Index; + + if (Status != BLKIF_RSP_OKAY) { + DEBUG ((EFI_D_ERROR, + "XenPvBlk: " + "%a error %d on %a at offset %Ld, num bytes %Ld\n", + Response->operation == BLKIF_OP_READ ? "read" : "write", + Status, IoData->Dev->NodeName, + IoData->Offset, + IoData->Size)); + } + + for (Index = 0; Index < IoData->NumRef; Index++) { + Dev->XenbusIo->GrantEndAccess (Dev->XenbusIo, IoData->GrantRef[Index]); + } + + break; + } + + case BLKIF_OP_WRITE_BARRIER: + if (Status != BLKIF_RSP_OKAY) { + DEBUG ((EFI_D_ERROR, "XenPvBlk: write barrier error %d\n", Status)); + } + break; + case BLKIF_OP_FLUSH_DISKCACHE: + if (Status != BLKIF_RSP_OKAY) { + DEBUG ((EFI_D_ERROR, "XenPvBlk: flush error %d\n", Status)); + } + break; + + default: + DEBUG ((EFI_D_ERROR, + "XenPvBlk: unrecognized block operation %d response (status %d)\n", + Response->operation, Status)); + break; + } + + Dev->Ring.rsp_cons = ++ConsumerIndex; + /* Nota: callback frees IoData itself */ + if (IoData && IoData->Callback) { + IoData->Callback (IoData, Status ? EFI_DEVICE_ERROR : EFI_SUCCESS); + } + if (Dev->Ring.rsp_cons != ConsumerIndex) { + /* We reentered, we must not continue here */ + break; + } + } + + RING_FINAL_CHECK_FOR_RESPONSES (&Dev->Ring, More); + } while (More != 0); +} diff --git a/OvmfPkg/XenPvBlkDxe/BlockFront.h b/OvmfPkg/XenPvBlkDxe/BlockFront.h new file mode 100644 index 0000000..d319e0d --- /dev/null +++ b/OvmfPkg/XenPvBlkDxe/BlockFront.h @@ -0,0 +1,88 @@ +#include "XenPvBlkDxe.h" + +#include +#include + +typedef struct _XEN_BLOCK_FRONT_DEVICE XEN_BLOCK_FRONT_DEVICE; +typedef struct _XEN_BLOCK_FRONT_IO XEN_BLOCK_FRONT_IO; + +struct _XEN_BLOCK_FRONT_IO +{ + XEN_BLOCK_FRONT_DEVICE *Dev; + UINT8 *Buffer; + UINTN Size; + UINTN Offset; + + grant_ref_t GrantRef[BLKIF_MAX_SEGMENTS_PER_REQUEST]; + INT32 NumRef; + + VOID (*Callback)(XEN_BLOCK_FRONT_IO *aiocb, EFI_STATUS Status); + VOID *Data; +}; + +typedef struct +{ + UINT64 Sectors; + UINT32 SectorSize; + UINT32 VDiskInfo; + BOOLEAN ReadWrite; + BOOLEAN CdRom; + BOOLEAN FeatureBarrier; + BOOLEAN FeatureFlushCache; +} XEN_BLOCK_FRONT_MEDIA_INFO; + +#define XEN_BLOCK_FRONT_SIGNATURE SIGNATURE_32 ('X', 'p', 'v', 'B') +struct _XEN_BLOCK_FRONT_DEVICE { + UINT32 Signature; + EFI_BLOCK_IO_PROTOCOL BlockIo; + domid_t DomainId; + + blkif_front_ring_t Ring; + grant_ref_t RingRef; + evtchn_port_t EventChannel; + blkif_vdev_t DeviceId; + + CONST CHAR8 *NodeName; + XEN_BLOCK_FRONT_MEDIA_INFO MediaInfo; + + VOID *StateWatchToken; + + XENBUS_PROTOCOL *XenbusIo; +}; + +#define XEN_BLOCK_FRONT_FROM_BLOCK_IO(b) \ + CR (b, XEN_BLOCK_FRONT_DEVICE, BlockIo, XEN_BLOCK_FRONT_SIGNATURE) + +EFI_STATUS +XenPvBlockFrontInitialization ( + IN XENBUS_PROTOCOL *XenbusIo, + IN CONST CHAR8 *NodeName, + OUT XEN_BLOCK_FRONT_DEVICE **DevPtr + ); + +VOID +XenPvBlockFrontShutdown ( + IN XEN_BLOCK_FRONT_DEVICE *Dev + ); + +VOID +XenPvBlockAsyncIo ( + IN OUT XEN_BLOCK_FRONT_IO *IoData, + IN BOOLEAN IsWrite + ); + +VOID +XenPvBlockIo ( + IN OUT XEN_BLOCK_FRONT_IO *IoData, + IN BOOLEAN IsWrite + ); + +VOID +XenPvBlockAsyncIoPoll ( + IN XEN_BLOCK_FRONT_DEVICE *Dev + ); + +VOID +XenPvBlockSync ( + IN XEN_BLOCK_FRONT_DEVICE *Dev + ); diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c index 0ce1e86..7ec7d60 100644 --- a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c +++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.c @@ -12,6 +12,8 @@ #include "XenPvBlkDxe.h" +#include "BlockFront.h" + /// /// Driver Binding Protocol instance @@ -263,6 +265,7 @@ XenPvBlkDxeDriverBindingStart ( { EFI_STATUS Status; XENBUS_PROTOCOL *XenbusIo; + XEN_BLOCK_FRONT_DEVICE *Dev; Status = gBS->OpenProtocol ( ControllerHandle, @@ -276,6 +279,11 @@ XenPvBlkDxeDriverBindingStart ( return Status; } + Status = XenPvBlockFrontInitialization (XenbusIo, XenbusIo->Node, &Dev); + if (EFI_ERROR (Status)) { + return Status; + } + return EFI_SUCCESS; } diff --git a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf index 4444cda..a43d006 100644 --- a/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf +++ b/OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf @@ -30,6 +30,8 @@ XenPvBlkDxe.c ComponentName.c ComponentName.h + BlockFront.c + BlockFront.h [LibraryClasses] -- Anthony PERARD