From c23c037fb3b47574950a19d4753fbeccff5e3d42 Mon Sep 17 00:00:00 2001 From: Anthony PERARD Date: Wed, 29 Oct 2014 06:51:04 +0000 Subject: [PATCH 1/1] OvmfPkg/XenBusDxe: Add XenStore function into the XenBus protocol Change in V3: - Have XenStoreWaitWatch/XenBusWaitForWatch return a XENSTORE_STATUS instead of VOID. - Add description of the introducted member of the protocol. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Anthony PERARD Reviewed-by: Konrad Rzeszutek Wilk Acked-by: Jordan Justen git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16269 6f19259b-4bc3-4df7-8a09-765794883524 --- OvmfPkg/Include/Protocol/XenBus.h | 223 ++++++++++++++++++++++++++++++ OvmfPkg/XenBusDxe/XenStore.c | 164 ++++++++++++++++++++++ OvmfPkg/XenBusDxe/XenStore.h | 87 ++++++++++++ 3 files changed, 474 insertions(+) diff --git a/OvmfPkg/Include/Protocol/XenBus.h b/OvmfPkg/Include/Protocol/XenBus.h index 565d491db6..5693b3f284 100644 --- a/OvmfPkg/Include/Protocol/XenBus.h +++ b/OvmfPkg/Include/Protocol/XenBus.h @@ -68,6 +68,136 @@ typedef enum { /// Function prototypes /// +/** + Get the contents of the node Node of the PV device. Returns the contents in + *Result which should be freed after use. + + @param This A pointer to XENBUS_PROTOCOL instance. + @param Transaction The XenStore transaction covering this request. + @param Node The basename of the file to read. + @param Result The returned contents from this file. + + @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value + indicating the type of failure. + + @note The results buffer is malloced and should be free'd by the + caller. +**/ +typedef +XENSTORE_STATUS +(EFIAPI *XENBUS_XS_READ)( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *Node, + OUT VOID **Result + ); + +/** + Get the contents of the node Node of the PV device's backend. Returns the + contents in *Result which should be freed after use. + + @param This A pointer to XENBUS_PROTOCOL instance. + @param Transaction The XenStore transaction covering this request. + @param Node The basename of the file to read. + @param Result The returned contents from this file. + + @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value + indicating the type of failure. + + @note The results buffer is malloced and should be free'd by the + caller. +**/ +typedef +XENSTORE_STATUS +(EFIAPI *XENBUS_XS_BACKEND_READ)( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *Node, + OUT VOID **Result + ); + +/** + Print formatted write to a XenStore node. + + @param This A pointer to XENBUS_PROTOCOL instance. + @param Transaction The XenStore transaction covering this request. + @param Directory The dirname of the path to read. + @param Node The basename of the path to read. + @param Format AsciiSPrint format string followed by a variable number + of arguments. + + @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value + indicating the type of write failure. +**/ +typedef +XENSTORE_STATUS +(EFIAPI *XENBUS_XS_PRINTF) ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *Directory, + IN CONST CHAR8 *Node, + IN CONST CHAR8 *Format, + ... + ); + +/** + Remove a node or directory (directories must be empty) of the PV driver's + subdirectory. + + @param This A pointer to XENBUS_PROTOCOL instance. + @param Transaction The XenStore transaction covering this request. + @param Node The basename of the node to remove. + + @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value + indicating the type of failure. +**/ +typedef +XENSTORE_STATUS +(EFIAPI *XENBUS_XS_REMOVE) ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *Node + ); + +/** + Start a transaction. + + Changes by others will not be seen during the lifetime of this + transaction, and changes will not be visible to others until it + is committed (XsTransactionEnd). + + @param This A pointer to XENBUS_PROTOCOL instance. + @param Transaction The returned transaction. + + @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value + indicating the type of failure. +**/ +typedef +XENSTORE_STATUS +(EFIAPI *XENBUS_XS_TRANSACTION_START)( + IN XENBUS_PROTOCOL *This, + OUT XENSTORE_TRANSACTION *Transaction + ); + +/** + End a transaction. + + @param This A pointer to XENBUS_PROTOCOL instance. + @param Transaction The transaction to end/commit. + @param Abort If TRUE, the transaction is discarded + instead of committed. + + @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value + indicating the type of failure. +**/ +typedef +XENSTORE_STATUS +(EFIAPI *XENBUS_XS_TRANSACTION_END) ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN BOOLEAN Abort + ); + /** Grant access to the page Frame to the domain DomainId. @@ -101,6 +231,83 @@ EFI_STATUS IN grant_ref_t Ref ); +/** + Register a XenStore watch. + + XenStore watches allow a client to wait for changes to an object in the + XenStore. + + @param This A pointer to the XENBUS_PROTOCOL. + @param Node The basename of the path to watch. + @param Token A token. + + @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value + indicating the type of write failure. EEXIST errors from the + XenStore are supressed, allowing multiple, physically different, + xenbus_watch objects, to watch the same path in the XenStore. +**/ +typedef +XENSTORE_STATUS +(EFIAPI *XENBUS_REGISTER_WATCH) ( + IN XENBUS_PROTOCOL *This, + IN CONST CHAR8 *Node, + OUT VOID **Token + ); + +/** + Register a XenStore watch on a backend's node. + + XenStore watches allow a client to wait for changes to an object in the + XenStore. + + @param This A pointer to the XENBUS_PROTOCOL. + @param Node The basename of the path to watch. + @param Token A token. + + @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value + indicating the type of write failure. EEXIST errors from the + XenStore are supressed, allowing multiple, physically different, + xenbus_watch objects, to watch the same path in the XenStore. +**/ +typedef +XENSTORE_STATUS +(EFIAPI *XENBUS_REGISTER_WATCH_BACKEND) ( + IN XENBUS_PROTOCOL *This, + IN CONST CHAR8 *Node, + OUT VOID **Token + ); + +/** + Unregister a XenStore watch. + + @param This A pointer to the XENBUS_PROTOCOL. + @param Token An token previously returned by a successful + call to RegisterWatch (). +**/ +typedef +VOID +(EFIAPI *XENBUS_UNREGISTER_WATCH) ( + IN XENBUS_PROTOCOL *This, + IN VOID *Token + ); + +/** + Block until the node watch by Token change. + + @param This A pointer to the XENBUS_PROTOCOL. + @param Token An token previously returned by a successful + call to RegisterWatch or RegisterWatchBackend. + + @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value + indicating the type of failure. +**/ +typedef +XENSTORE_STATUS +(EFIAPI *XENBUS_WAIT_FOR_WATCH) ( + IN XENBUS_PROTOCOL *This, + IN VOID *Token + ); + /// /// Protocol structure @@ -109,11 +316,27 @@ EFI_STATUS /// should not be used outside of the EDK II tree. /// struct _XENBUS_PROTOCOL { + XENBUS_XS_READ XsRead; + XENBUS_XS_BACKEND_READ XsBackendRead; + XENBUS_XS_PRINTF XsPrintf; + XENBUS_XS_REMOVE XsRemove; + XENBUS_XS_TRANSACTION_START XsTransactionStart; + XENBUS_XS_TRANSACTION_END XsTransactionEnd; + XENBUS_GRANT_ACCESS GrantAccess; XENBUS_GRANT_END_ACCESS GrantEndAccess; + + XENBUS_REGISTER_WATCH RegisterWatch; + XENBUS_REGISTER_WATCH_BACKEND RegisterWatchBackend; + XENBUS_UNREGISTER_WATCH UnregisterWatch; + XENBUS_WAIT_FOR_WATCH WaitForWatch; // // Protocol data fields // + CONST CHAR8 *Type; + UINT16 DeviceId; + CONST CHAR8 *Node; + CONST CHAR8 *Backend; }; extern EFI_GUID gXenBusProtocolGuid; diff --git a/OvmfPkg/XenBusDxe/XenStore.c b/OvmfPkg/XenBusDxe/XenStore.c index 4b99c9ca1f..aed6b141bd 100644 --- a/OvmfPkg/XenBusDxe/XenStore.c +++ b/OvmfPkg/XenBusDxe/XenStore.c @@ -941,6 +941,46 @@ XenStoreUnwatch ( return XenStoreTalkv (XST_NIL, XS_UNWATCH, WriteRequest, 2, NULL, NULL); } +STATIC +XENSTORE_STATUS +XenStoreWaitWatch ( + VOID *Token + ) +{ + XENSTORE_MESSAGE *Message; + LIST_ENTRY *Entry = NULL; + LIST_ENTRY *Last = NULL; + XENSTORE_STATUS Status; + + while (TRUE) { + EfiAcquireLock (&xs.WatchEventsLock); + if (IsListEmpty (&xs.WatchEvents) || + Last == GetFirstNode (&xs.WatchEvents)) { + EfiReleaseLock (&xs.WatchEventsLock); + Status = XenStoreProcessMessage (); + if (Status != XENSTORE_STATUS_SUCCESS && Status != XENSTORE_STATUS_EAGAIN) { + return Status; + } + continue; + } + + for (Entry = GetFirstNode (&xs.WatchEvents); + Entry != Last && !IsNull (&xs.WatchEvents, Entry); + Entry = GetNextNode (&xs.WatchEvents, Entry)) { + Message = XENSTORE_MESSAGE_FROM_LINK (Entry); + if (Message->u.Watch.Handle == Token) { + RemoveEntryList (Entry); + EfiReleaseLock (&xs.WatchEventsLock); + FreePool(Message->u.Watch.Vector); + FreePool(Message); + return XENSTORE_STATUS_SUCCESS; + } + } + Last = GetFirstNode (&xs.WatchEvents); + EfiReleaseLock (&xs.WatchEventsLock); + } +} + VOID EFIAPI NotifyEventChannelCheckForEvent ( @@ -1384,3 +1424,127 @@ XenStoreUnregisterWatch ( FreePool (Watch->Node); FreePool (Watch); } + + +// +// XENBUS protocol +// + +XENSTORE_STATUS +EFIAPI +XenBusWaitForWatch ( + IN XENBUS_PROTOCOL *This, + IN VOID *Token + ) +{ + return XenStoreWaitWatch (Token); +} + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreRead ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *Node, + OUT VOID **Value + ) +{ + return XenStoreRead (Transaction, This->Node, Node, NULL, Value); +} + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreBackendRead ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *Node, + OUT VOID **Value + ) +{ + return XenStoreRead (Transaction, This->Backend, Node, NULL, Value); +} + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreRemove ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN const char *Node + ) +{ + return XenStoreRemove (Transaction, This->Node, Node); +} + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreTransactionStart ( + IN XENBUS_PROTOCOL *This, + OUT XENSTORE_TRANSACTION *Transaction + ) +{ + return XenStoreTransactionStart (Transaction); +} + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreTransactionEnd ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN BOOLEAN Abort + ) +{ + return XenStoreTransactionEnd (Transaction, Abort); +} + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreSPrint ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *DirectoryPath, + IN CONST CHAR8 *Node, + IN CONST CHAR8 *FormatString, + ... + ) +{ + VA_LIST Marker; + XENSTORE_STATUS Status; + + VA_START (Marker, FormatString); + Status = XenStoreVSPrint (Transaction, DirectoryPath, Node, FormatString, Marker); + VA_END (Marker); + + return Status; +} + +XENSTORE_STATUS +EFIAPI +XenBusRegisterWatch ( + IN XENBUS_PROTOCOL *This, + IN CONST CHAR8 *Node, + OUT VOID **Token + ) +{ + return XenStoreRegisterWatch (This->Node, Node, (XENSTORE_WATCH **) Token); +} + +XENSTORE_STATUS +EFIAPI +XenBusRegisterWatchBackend ( + IN XENBUS_PROTOCOL *This, + IN CONST CHAR8 *Node, + OUT VOID **Token + ) +{ + return XenStoreRegisterWatch (This->Backend, Node, (XENSTORE_WATCH **) Token); +} + +VOID +EFIAPI +XenBusUnregisterWatch ( + IN XENBUS_PROTOCOL *This, + IN VOID *Token + ) +{ + XenStoreUnregisterWatch ((XENSTORE_WATCH *) Token); +} diff --git a/OvmfPkg/XenBusDxe/XenStore.h b/OvmfPkg/XenBusDxe/XenStore.h index 1503ed0473..9020411f6a 100644 --- a/OvmfPkg/XenBusDxe/XenStore.h +++ b/OvmfPkg/XenBusDxe/XenStore.h @@ -289,4 +289,91 @@ XenStoreDeinit ( IN XENBUS_DEVICE *Dev ); + +// +// XENBUS protocol +// + +XENSTORE_STATUS +EFIAPI +XenBusWaitForWatch ( + IN XENBUS_PROTOCOL *This, + IN VOID *Token + ); + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreRead ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *Node, + OUT VOID **Value + ); + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreBackendRead ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *Node, + OUT VOID **Value + ); + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreRemove ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *Node + ); + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreTransactionStart ( + IN XENBUS_PROTOCOL *This, + OUT XENSTORE_TRANSACTION *Transaction + ); + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreTransactionEnd ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN BOOLEAN Abort + ); + +XENSTORE_STATUS +EFIAPI +XenBusXenStoreSPrint ( + IN XENBUS_PROTOCOL *This, + IN XENSTORE_TRANSACTION Transaction, + IN CONST CHAR8 *DirectoryPath, + IN CONST CHAR8 *Node, + IN CONST CHAR8 *FormatString, + ... + ); + +XENSTORE_STATUS +EFIAPI +XenBusRegisterWatch ( + IN XENBUS_PROTOCOL *This, + IN CONST CHAR8 *Node, + OUT VOID **Token + ); + +XENSTORE_STATUS +EFIAPI +XenBusRegisterWatchBackend ( + IN XENBUS_PROTOCOL *This, + IN CONST CHAR8 *Node, + OUT VOID **Token + ); + +VOID +EFIAPI +XenBusUnregisterWatch ( + IN XENBUS_PROTOCOL *This, + IN VOID *Token + ); + #endif /* _XEN_XENSTORE_XENSTOREVAR_H */ -- 2.39.2