1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612 |
- /** @file
- Low-level kernel interface to the XenStore.
- The XenStore interface is a simple storage system that is a means of
- communicating state and configuration data between the Xen Domain 0
- and the various guest domains. All configuration data other than
- a small amount of essential information required during the early
- boot process of launching a Xen aware guest, is managed using the
- XenStore.
- The XenStore is ASCII string based, and has a structure and semantics
- similar to a filesystem. There are files and directories, the directories
- able to contain files or other directories. The depth of the hierarchy
- is only limited by the XenStore's maximum path length.
- The communication channel between the XenStore service and other
- domains is via two, guest specific, ring buffers in a shared memory
- area. One ring buffer is used for communicating in each direction.
- The grant table references for this shared memory are given to the
- guest either via the xen_start_info structure for a fully para-
- virtualized guest, or via HVM hypercalls for a hardware virtualized
- guest.
- The XenStore communication relies on an event channel and thus
- interrupts. But under OVMF this XenStore client will pull the
- state of the event channel.
- Several Xen services depend on the XenStore, most notably the
- XenBus used to discover and manage Xen devices.
- Copyright (C) 2005 Rusty Russell, IBM Corporation
- Copyright (C) 2009,2010 Spectra Logic Corporation
- Copyright (C) 2014, Citrix Ltd.
- This file may be distributed separately from the Linux kernel, or
- incorporated into other software packages, subject to the following license:
- SPDX-License-Identifier: MIT
- **/
- #include "XenStore.h"
- #include <Library/PrintLib.h>
- #include <IndustryStandard/Xen/hvm/params.h>
- #include "EventChannel.h"
- #include <Library/XenHypercallLib.h>
- //
- // Private Data Structures
- //
- typedef struct {
- CONST VOID *Data;
- UINT32 Len;
- } WRITE_REQUEST;
- /* Register callback to watch subtree (node) in the XenStore. */
- #define XENSTORE_WATCH_SIGNATURE SIGNATURE_32 ('X','S','w','a')
- struct _XENSTORE_WATCH {
- UINT32 Signature;
- LIST_ENTRY Link;
- /* Path being watched. */
- CHAR8 *Node;
- };
- #define XENSTORE_WATCH_FROM_LINK(l) \
- CR (l, XENSTORE_WATCH, Link, XENSTORE_WATCH_SIGNATURE)
- /**
- * Structure capturing messages received from the XenStore service.
- */
- #define XENSTORE_MESSAGE_SIGNATURE SIGNATURE_32 ('X', 'S', 's', 'm')
- typedef struct {
- UINT32 Signature;
- LIST_ENTRY Link;
- struct xsd_sockmsg Header;
- union {
- /* Queued replies. */
- struct {
- CHAR8 *Body;
- } Reply;
- /* Queued watch events. */
- struct {
- XENSTORE_WATCH *Handle;
- CONST CHAR8 **Vector;
- UINT32 VectorSize;
- } Watch;
- } u;
- } XENSTORE_MESSAGE;
- #define XENSTORE_MESSAGE_FROM_LINK(r) \
- CR (r, XENSTORE_MESSAGE, Link, XENSTORE_MESSAGE_SIGNATURE)
- /**
- * Container for all XenStore related state.
- */
- typedef struct {
- /**
- * Pointer to shared memory communication structures allowing us
- * to communicate with the XenStore service.
- */
- struct xenstore_domain_interface *XenStore;
- XENBUS_DEVICE *Dev;
- /**
- * A list of replies to our requests.
- *
- * The reply list is filled by xs_rcv_thread(). It
- * is consumed by the context that issued the request
- * to which a reply is made. The requester blocks in
- * XenStoreReadReply ().
- *
- * /note Only one requesting context can be active at a time.
- */
- LIST_ENTRY ReplyList;
- /** Lock protecting the reply list. */
- EFI_LOCK ReplyLock;
- /**
- * List of registered watches.
- */
- LIST_ENTRY RegisteredWatches;
- /** Lock protecting the registered watches list. */
- EFI_LOCK RegisteredWatchesLock;
- /**
- * List of pending watch callback events.
- */
- LIST_ENTRY WatchEvents;
- /** Lock protecting the watch callback list. */
- EFI_LOCK WatchEventsLock;
- /**
- * The event channel for communicating with the
- * XenStore service.
- */
- evtchn_port_t EventChannel;
- /** Handle for XenStore events. */
- EFI_EVENT EventChannelEvent;
- } XENSTORE_PRIVATE;
- //
- // Global Data
- //
- static XENSTORE_PRIVATE xs;
- //
- // Private Utility Functions
- //
- /**
- Count and optionally record pointers to a number of NUL terminated
- strings in a buffer.
- @param Strings A pointer to a contiguous buffer of NUL terminated strings.
- @param Len The length of the buffer pointed to by strings.
- @param Dst An array to store pointers to each string found in strings.
- @return A count of the number of strings found.
- **/
- STATIC
- UINT32
- ExtractStrings (
- IN CONST CHAR8 *Strings,
- IN UINTN Len,
- OUT CONST CHAR8 **Dst OPTIONAL
- )
- {
- UINT32 Num = 0;
- CONST CHAR8 *Ptr;
- for (Ptr = Strings; Ptr < Strings + Len; Ptr += AsciiStrSize (Ptr)) {
- if (Dst != NULL) {
- *Dst++ = Ptr;
- }
- Num++;
- }
- return Num;
- }
- /**
- Convert a contiguous buffer containing a series of NUL terminated
- strings into an array of pointers to strings.
- The returned pointer references the array of string pointers which
- is followed by the storage for the string data. It is the client's
- responsibility to free this storage.
- The storage addressed by Strings is free'd prior to Split returning.
- @param Strings A pointer to a contiguous buffer of NUL terminated strings.
- @param Len The length of the buffer pointed to by strings.
- @param NumPtr The number of strings found and returned in the strings
- array.
- @return An array of pointers to the strings found in the input buffer.
- **/
- STATIC
- CONST CHAR8 **
- Split (
- IN CHAR8 *Strings,
- IN UINTN Len,
- OUT UINT32 *NumPtr
- )
- {
- CONST CHAR8 **Dst;
- ASSERT (NumPtr != NULL);
- ASSERT (Strings != NULL);
- /* Protect against unterminated buffers. */
- if (Len > 0) {
- Strings[Len - 1] = '\0';
- }
- /* Count the Strings. */
- *NumPtr = ExtractStrings (Strings, Len, NULL);
- /* Transfer to one big alloc for easy freeing by the caller. */
- Dst = AllocatePool (*NumPtr * sizeof (CHAR8 *) + Len);
- CopyMem ((VOID *)&Dst[*NumPtr], Strings, Len);
- FreePool (Strings);
- /* Extract pointers to newly allocated array. */
- Strings = (CHAR8 *)&Dst[*NumPtr];
- ExtractStrings (Strings, Len, Dst);
- return (Dst);
- }
- /**
- Convert from watch token (unique identifier) to the associated
- internal tracking structure for this watch.
- @param Tocken The unique identifier for the watch to find.
- @return A pointer to the found watch structure or NULL.
- **/
- STATIC
- XENSTORE_WATCH *
- XenStoreFindWatch (
- IN CONST CHAR8 *Token
- )
- {
- XENSTORE_WATCH *Watch, *WantedWatch;
- LIST_ENTRY *Entry;
- WantedWatch = (VOID *)AsciiStrHexToUintn (Token);
- if (IsListEmpty (&xs.RegisteredWatches)) {
- return NULL;
- }
- for (Entry = GetFirstNode (&xs.RegisteredWatches);
- !IsNull (&xs.RegisteredWatches, Entry);
- Entry = GetNextNode (&xs.RegisteredWatches, Entry))
- {
- Watch = XENSTORE_WATCH_FROM_LINK (Entry);
- if (Watch == WantedWatch) {
- return Watch;
- }
- }
- return NULL;
- }
- //
- // Public Utility Functions
- // API comments for these methods can be found in XenStore.h
- //
- CHAR8 *
- XenStoreJoin (
- IN CONST CHAR8 *DirectoryPath,
- IN CONST CHAR8 *Node
- )
- {
- CHAR8 *Buf;
- UINTN BufSize;
- /* +1 for '/' and +1 for '\0' */
- BufSize = AsciiStrLen (DirectoryPath) + AsciiStrLen (Node) + 2;
- Buf = AllocatePool (BufSize);
- ASSERT (Buf != NULL);
- if (Node[0] == '\0') {
- AsciiSPrint (Buf, BufSize, "%a", DirectoryPath);
- } else {
- AsciiSPrint (Buf, BufSize, "%a/%a", DirectoryPath, Node);
- }
- return Buf;
- }
- //
- // Low Level Communication Management
- //
- /**
- Verify that the indexes for a ring are valid.
- The difference between the producer and consumer cannot
- exceed the size of the ring.
- @param Cons The consumer index for the ring to test.
- @param Prod The producer index for the ring to test.
- @retval TRUE If indexes are in range.
- @retval FALSE If the indexes are out of range.
- **/
- STATIC
- BOOLEAN
- XenStoreCheckIndexes (
- XENSTORE_RING_IDX Cons,
- XENSTORE_RING_IDX Prod
- )
- {
- return ((Prod - Cons) <= XENSTORE_RING_SIZE);
- }
- /**
- Return a pointer to, and the length of, the contiguous
- free region available for output in a ring buffer.
- @param Cons The consumer index for the ring.
- @param Prod The producer index for the ring.
- @param Buffer The base address of the ring's storage.
- @param LenPtr The amount of contiguous storage available.
- @return A pointer to the start location of the free region.
- **/
- STATIC
- VOID *
- XenStoreGetOutputChunk (
- IN XENSTORE_RING_IDX Cons,
- IN XENSTORE_RING_IDX Prod,
- IN CHAR8 *Buffer,
- OUT UINT32 *LenPtr
- )
- {
- UINT32 Len;
- Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Prod);
- if ((XENSTORE_RING_SIZE - (Prod - Cons)) < Len) {
- Len = XENSTORE_RING_SIZE - (Prod - Cons);
- }
- *LenPtr = Len;
- return (Buffer + MASK_XENSTORE_IDX (Prod));
- }
- /**
- Return a pointer to, and the length of, the contiguous
- data available to read from a ring buffer.
- @param Cons The consumer index for the ring.
- @param Prod The producer index for the ring.
- @param Buffer The base address of the ring's storage.
- @param LenPtr The amount of contiguous data available to read.
- @return A pointer to the start location of the available data.
- **/
- STATIC
- CONST VOID *
- XenStoreGetInputChunk (
- IN XENSTORE_RING_IDX Cons,
- IN XENSTORE_RING_IDX Prod,
- IN CONST CHAR8 *Buffer,
- OUT UINT32 *LenPtr
- )
- {
- UINT32 Len;
- Len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX (Cons);
- if ((Prod - Cons) < Len) {
- Len = Prod - Cons;
- }
- *LenPtr = Len;
- return (Buffer + MASK_XENSTORE_IDX (Cons));
- }
- /**
- Wait for an event or timeout.
- @param Event Event to wait for.
- @param Timeout A timeout value in 100ns units.
- @retval EFI_SUCCESS Event have been triggered or the current TPL is not
- TPL_APPLICATION.
- @retval EFI_TIMEOUT Timeout have expired.
- **/
- STATIC
- EFI_STATUS
- XenStoreWaitForEvent (
- IN EFI_EVENT Event,
- IN UINT64 Timeout
- )
- {
- UINTN Index;
- EFI_STATUS Status;
- EFI_EVENT TimerEvent;
- EFI_EVENT WaitList[2];
- gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
- gBS->SetTimer (TimerEvent, TimerRelative, Timeout);
- WaitList[0] = xs.EventChannelEvent;
- WaitList[1] = TimerEvent;
- Status = gBS->WaitForEvent (2, WaitList, &Index);
- ASSERT (Status != EFI_INVALID_PARAMETER);
- gBS->CloseEvent (TimerEvent);
- if (Status == EFI_UNSUPPORTED) {
- return EFI_SUCCESS;
- }
- if (Index == 1) {
- return EFI_TIMEOUT;
- } else {
- return EFI_SUCCESS;
- }
- }
- /**
- Transmit data to the XenStore service.
- The buffer pointed to by DataPtr is at least Len bytes in length.
- @param DataPtr A pointer to the contiguous data to send.
- @param Len The amount of data to send.
- @return On success 0, otherwise an errno value indicating the
- cause of failure.
- **/
- STATIC
- XENSTORE_STATUS
- XenStoreWriteStore (
- IN CONST VOID *DataPtr,
- IN UINT32 Len
- )
- {
- XENSTORE_RING_IDX Cons, Prod;
- CONST CHAR8 *Data = (CONST CHAR8 *)DataPtr;
- while (Len != 0) {
- void *Dest;
- UINT32 Available;
- Cons = xs.XenStore->req_cons;
- Prod = xs.XenStore->req_prod;
- if ((Prod - Cons) == XENSTORE_RING_SIZE) {
- /*
- * Output ring is full. Wait for a ring event.
- *
- * Note that the events from both queues are combined, so being woken
- * does not guarantee that data exist in the read ring.
- */
- EFI_STATUS Status;
- Status = XenStoreWaitForEvent (
- xs.EventChannelEvent,
- EFI_TIMER_PERIOD_SECONDS (1)
- );
- if (Status == EFI_TIMEOUT) {
- DEBUG ((DEBUG_WARN, "XenStore Write, waiting for a ring event.\n"));
- }
- continue;
- }
- /* Verify queue sanity. */
- if (!XenStoreCheckIndexes (Cons, Prod)) {
- xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
- return XENSTORE_STATUS_EIO;
- }
- Dest = XenStoreGetOutputChunk (Cons, Prod, xs.XenStore->req, &Available);
- if (Available > Len) {
- Available = Len;
- }
- CopyMem (Dest, Data, Available);
- Data += Available;
- Len -= Available;
- /*
- * The store to the producer index, which indicates
- * to the other side that new data has arrived, must
- * be visible only after our copy of the data into the
- * ring has completed.
- */
- MemoryFence ();
- xs.XenStore->req_prod += Available;
- /*
- * The other side will see the change to req_prod at the time of the
- * interrupt.
- */
- MemoryFence ();
- XenEventChannelNotify (xs.Dev, xs.EventChannel);
- }
- return XENSTORE_STATUS_SUCCESS;
- }
- /**
- Receive data from the XenStore service.
- The buffer pointed to by DataPtr is at least Len bytes in length.
- @param DataPtr A pointer to the contiguous buffer to receive the data.
- @param Len The amount of data to receive.
- @return On success 0, otherwise an errno value indicating the
- cause of failure.
- **/
- STATIC
- XENSTORE_STATUS
- XenStoreReadStore (
- OUT VOID *DataPtr,
- IN UINT32 Len
- )
- {
- XENSTORE_RING_IDX Cons, Prod;
- CHAR8 *Data = (CHAR8 *)DataPtr;
- while (Len != 0) {
- UINT32 Available;
- CONST CHAR8 *Src;
- Cons = xs.XenStore->rsp_cons;
- Prod = xs.XenStore->rsp_prod;
- if (Cons == Prod) {
- /*
- * Nothing to read. Wait for a ring event.
- *
- * Note that the events from both queues are combined, so being woken
- * does not guarantee that data exist in the read ring.
- */
- EFI_STATUS Status;
- Status = XenStoreWaitForEvent (
- xs.EventChannelEvent,
- EFI_TIMER_PERIOD_SECONDS (1)
- );
- if (Status == EFI_TIMEOUT) {
- DEBUG ((DEBUG_WARN, "XenStore Read, waiting for a ring event.\n"));
- }
- continue;
- }
- /* Verify queue sanity. */
- if (!XenStoreCheckIndexes (Cons, Prod)) {
- xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
- return XENSTORE_STATUS_EIO;
- }
- Src = XenStoreGetInputChunk (Cons, Prod, xs.XenStore->rsp, &Available);
- if (Available > Len) {
- Available = Len;
- }
- /*
- * Insure the data we read is related to the indexes
- * we read above.
- */
- MemoryFence ();
- CopyMem (Data, Src, Available);
- Data += Available;
- Len -= Available;
- /*
- * Insure that the producer of this ring does not see
- * the ring space as free until after we have copied it
- * out.
- */
- MemoryFence ();
- xs.XenStore->rsp_cons += Available;
- /*
- * The producer will see the updated consumer index when the event is
- * delivered.
- */
- MemoryFence ();
- XenEventChannelNotify (xs.Dev, xs.EventChannel);
- }
- return XENSTORE_STATUS_SUCCESS;
- }
- //
- // Received Message Processing
- //
- /**
- Block reading the next message from the XenStore service and
- process the result.
- @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno value
- indicating the type of failure encountered.
- **/
- STATIC
- XENSTORE_STATUS
- XenStoreProcessMessage (
- VOID
- )
- {
- XENSTORE_MESSAGE *Message;
- CHAR8 *Body;
- XENSTORE_STATUS Status;
- Message = AllocateZeroPool (sizeof (XENSTORE_MESSAGE));
- Message->Signature = XENSTORE_MESSAGE_SIGNATURE;
- Status = XenStoreReadStore (&Message->Header, sizeof (Message->Header));
- if (Status != XENSTORE_STATUS_SUCCESS) {
- FreePool (Message);
- DEBUG ((DEBUG_ERROR, "XenStore: Error read store (%d)\n", Status));
- return Status;
- }
- Body = AllocatePool (Message->Header.len + 1);
- Status = XenStoreReadStore (Body, Message->Header.len);
- if (Status != XENSTORE_STATUS_SUCCESS) {
- FreePool (Body);
- FreePool (Message);
- DEBUG ((DEBUG_ERROR, "XenStore: Error read store (%d)\n", Status));
- return Status;
- }
- Body[Message->Header.len] = '\0';
- if (Message->Header.type == XS_WATCH_EVENT) {
- Message->u.Watch.Vector = Split (
- Body,
- Message->Header.len,
- &Message->u.Watch.VectorSize
- );
- EfiAcquireLock (&xs.RegisteredWatchesLock);
- Message->u.Watch.Handle =
- XenStoreFindWatch (Message->u.Watch.Vector[XS_WATCH_TOKEN]);
- DEBUG ((
- DEBUG_INFO,
- "XenStore: Watch event %a\n",
- Message->u.Watch.Vector[XS_WATCH_TOKEN]
- ));
- if (Message->u.Watch.Handle != NULL) {
- EfiAcquireLock (&xs.WatchEventsLock);
- InsertHeadList (&xs.WatchEvents, &Message->Link);
- EfiReleaseLock (&xs.WatchEventsLock);
- } else {
- DEBUG ((
- DEBUG_WARN,
- "XenStore: Watch handle %a not found\n",
- Message->u.Watch.Vector[XS_WATCH_TOKEN]
- ));
- FreePool ((VOID *)Message->u.Watch.Vector);
- FreePool (Message);
- }
- EfiReleaseLock (&xs.RegisteredWatchesLock);
- } else {
- Message->u.Reply.Body = Body;
- EfiAcquireLock (&xs.ReplyLock);
- InsertTailList (&xs.ReplyList, &Message->Link);
- EfiReleaseLock (&xs.ReplyLock);
- }
- return XENSTORE_STATUS_SUCCESS;
- }
- //
- // XenStore Message Request/Reply Processing
- //
- /**
- Convert a XenStore error string into an errno number.
- Unknown error strings are converted to EINVAL.
- @param errorstring The error string to convert.
- @return The errno best matching the input string.
- **/
- typedef struct {
- XENSTORE_STATUS Status;
- CONST CHAR8 *ErrorStr;
- } XenStoreErrors;
- static XenStoreErrors gXenStoreErrors[] = {
- { XENSTORE_STATUS_EINVAL, "EINVAL" },
- { XENSTORE_STATUS_EACCES, "EACCES" },
- { XENSTORE_STATUS_EEXIST, "EEXIST" },
- { XENSTORE_STATUS_EISDIR, "EISDIR" },
- { XENSTORE_STATUS_ENOENT, "ENOENT" },
- { XENSTORE_STATUS_ENOMEM, "ENOMEM" },
- { XENSTORE_STATUS_ENOSPC, "ENOSPC" },
- { XENSTORE_STATUS_EIO, "EIO" },
- { XENSTORE_STATUS_ENOTEMPTY, "ENOTEMPTY" },
- { XENSTORE_STATUS_ENOSYS, "ENOSYS" },
- { XENSTORE_STATUS_EROFS, "EROFS" },
- { XENSTORE_STATUS_EBUSY, "EBUSY" },
- { XENSTORE_STATUS_EAGAIN, "EAGAIN" },
- { XENSTORE_STATUS_EISCONN, "EISCONN" },
- { XENSTORE_STATUS_E2BIG, "E2BIG" }
- };
- STATIC
- XENSTORE_STATUS
- XenStoreGetError (
- CONST CHAR8 *ErrorStr
- )
- {
- UINT32 Index;
- for (Index = 0; Index < ARRAY_SIZE (gXenStoreErrors); Index++) {
- if (!AsciiStrCmp (ErrorStr, gXenStoreErrors[Index].ErrorStr)) {
- return gXenStoreErrors[Index].Status;
- }
- }
- DEBUG ((DEBUG_WARN, "XenStore gave unknown error %a\n", ErrorStr));
- return XENSTORE_STATUS_EINVAL;
- }
- /**
- Block waiting for a reply to a message request.
- @param TypePtr The returned type of the reply.
- @param LenPtr The returned body length of the reply.
- @param Result The returned body of the reply.
- **/
- STATIC
- XENSTORE_STATUS
- XenStoreReadReply (
- OUT enum xsd_sockmsg_type *TypePtr,
- OUT UINT32 *LenPtr OPTIONAL,
- OUT VOID **Result
- )
- {
- XENSTORE_MESSAGE *Message;
- LIST_ENTRY *Entry;
- CHAR8 *Body;
- while (IsListEmpty (&xs.ReplyList)) {
- XENSTORE_STATUS Status;
- Status = XenStoreProcessMessage ();
- if ((Status != XENSTORE_STATUS_SUCCESS) && (Status != XENSTORE_STATUS_EAGAIN)) {
- DEBUG ((
- DEBUG_ERROR,
- "XenStore, error while reading the ring (%d).",
- Status
- ));
- return Status;
- }
- }
- EfiAcquireLock (&xs.ReplyLock);
- Entry = GetFirstNode (&xs.ReplyList);
- Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
- RemoveEntryList (Entry);
- EfiReleaseLock (&xs.ReplyLock);
- *TypePtr = Message->Header.type;
- if (LenPtr != NULL) {
- *LenPtr = Message->Header.len;
- }
- Body = Message->u.Reply.Body;
- FreePool (Message);
- *Result = Body;
- return XENSTORE_STATUS_SUCCESS;
- }
- /**
- Send a message with an optionally multi-part body to the XenStore service.
- @param Transaction The transaction to use for this request.
- @param RequestType The type of message to send.
- @param WriteRequest Pointers to the body sections of the request.
- @param NumRequests The number of body sections in the request.
- @param LenPtr The returned length of the reply.
- @param ResultPtr The returned body of the reply.
- @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating
- the cause of failure.
- **/
- STATIC
- XENSTORE_STATUS
- XenStoreTalkv (
- IN CONST XENSTORE_TRANSACTION *Transaction,
- IN enum xsd_sockmsg_type RequestType,
- IN CONST WRITE_REQUEST *WriteRequest,
- IN UINT32 NumRequests,
- OUT UINT32 *LenPtr OPTIONAL,
- OUT VOID **ResultPtr OPTIONAL
- )
- {
- struct xsd_sockmsg Message;
- void *Return = NULL;
- UINT32 Index;
- XENSTORE_STATUS Status;
- if (Transaction == XST_NIL) {
- Message.tx_id = 0;
- } else {
- Message.tx_id = Transaction->Id;
- }
- Message.req_id = 0;
- Message.type = RequestType;
- Message.len = 0;
- for (Index = 0; Index < NumRequests; Index++) {
- Message.len += WriteRequest[Index].Len;
- }
- Status = XenStoreWriteStore (&Message, sizeof (Message));
- if (Status != XENSTORE_STATUS_SUCCESS) {
- DEBUG ((DEBUG_ERROR, "XenStoreTalkv failed %d\n", Status));
- goto Error;
- }
- for (Index = 0; Index < NumRequests; Index++) {
- Status = XenStoreWriteStore (WriteRequest[Index].Data, WriteRequest[Index].Len);
- if (Status != XENSTORE_STATUS_SUCCESS) {
- DEBUG ((DEBUG_ERROR, "XenStoreTalkv failed %d\n", Status));
- goto Error;
- }
- }
- Status = XenStoreReadReply ((enum xsd_sockmsg_type *)&Message.type, LenPtr, &Return);
- Error:
- if (Status != XENSTORE_STATUS_SUCCESS) {
- return Status;
- }
- if (Message.type == XS_ERROR) {
- Status = XenStoreGetError (Return);
- FreePool (Return);
- return Status;
- }
- /* Reply is either error or an echo of our request message type. */
- ASSERT ((enum xsd_sockmsg_type)Message.type == RequestType);
- if (ResultPtr) {
- *ResultPtr = Return;
- } else {
- FreePool (Return);
- }
- return XENSTORE_STATUS_SUCCESS;
- }
- /**
- Wrapper for XenStoreTalkv allowing easy transmission of a message with
- a single, contiguous, message body.
- The returned result is provided in malloced storage and thus must be free'd
- by the caller.
- @param Transaction The transaction to use for this request.
- @param RequestType The type of message to send.
- @param Body The body of the request.
- @param LenPtr The returned length of the reply.
- @param Result The returned body of the reply.
- @return 0 on success. Otherwise an errno indicating
- the cause of failure.
- **/
- STATIC
- XENSTORE_STATUS
- XenStoreSingle (
- IN CONST XENSTORE_TRANSACTION *Transaction,
- IN enum xsd_sockmsg_type RequestType,
- IN CONST CHAR8 *Body,
- OUT UINT32 *LenPtr OPTIONAL,
- OUT VOID **Result OPTIONAL
- )
- {
- WRITE_REQUEST WriteRequest;
- WriteRequest.Data = (VOID *)Body;
- WriteRequest.Len = (UINT32)AsciiStrSize (Body);
- return XenStoreTalkv (
- Transaction,
- RequestType,
- &WriteRequest,
- 1,
- LenPtr,
- Result
- );
- }
- //
- // XenStore Watch Support
- //
- /**
- Transmit a watch request to the XenStore service.
- @param Path The path in the XenStore to watch.
- @param Tocken A unique identifier for this watch.
- @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating the
- cause of failure.
- **/
- STATIC
- XENSTORE_STATUS
- XenStoreWatch (
- CONST CHAR8 *Path,
- CONST CHAR8 *Token
- )
- {
- WRITE_REQUEST WriteRequest[2];
- WriteRequest[0].Data = (VOID *)Path;
- WriteRequest[0].Len = (UINT32)AsciiStrSize (Path);
- WriteRequest[1].Data = (VOID *)Token;
- WriteRequest[1].Len = (UINT32)AsciiStrSize (Token);
- return XenStoreTalkv (XST_NIL, XS_WATCH, WriteRequest, 2, NULL, NULL);
- }
- /**
- Transmit an uwatch request to the XenStore service.
- @param Path The path in the XenStore to watch.
- @param Tocken A unique identifier for this watch.
- @return XENSTORE_STATUS_SUCCESS on success. Otherwise an errno indicating
- the cause of failure.
- **/
- STATIC
- XENSTORE_STATUS
- XenStoreUnwatch (
- CONST CHAR8 *Path,
- CONST CHAR8 *Token
- )
- {
- WRITE_REQUEST WriteRequest[2];
- WriteRequest[0].Data = (VOID *)Path;
- WriteRequest[0].Len = (UINT32)AsciiStrSize (Path);
- WriteRequest[1].Data = (VOID *)Token;
- WriteRequest[1].Len = (UINT32)AsciiStrSize (Token);
- 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 ((VOID *)Message->u.Watch.Vector);
- FreePool (Message);
- return XENSTORE_STATUS_SUCCESS;
- }
- }
- Last = GetFirstNode (&xs.WatchEvents);
- EfiReleaseLock (&xs.WatchEventsLock);
- }
- }
- VOID
- EFIAPI
- NotifyEventChannelCheckForEvent (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- XENSTORE_PRIVATE *xsp;
- xsp = (XENSTORE_PRIVATE *)Context;
- if (TestAndClearBit (xsp->EventChannel, xsp->Dev->SharedInfo->evtchn_pending)) {
- gBS->SignalEvent (Event);
- }
- }
- /**
- Setup communication channels with the XenStore service.
- @retval EFI_SUCCESS if everything went well.
- **/
- STATIC
- EFI_STATUS
- XenStoreInitComms (
- XENSTORE_PRIVATE *xsp
- )
- {
- EFI_STATUS Status;
- EFI_EVENT TimerEvent;
- struct xenstore_domain_interface *XenStore = xsp->XenStore;
- Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
- Status = gBS->SetTimer (
- TimerEvent,
- TimerRelative,
- EFI_TIMER_PERIOD_SECONDS (5)
- );
- while (XenStore->rsp_prod != XenStore->rsp_cons) {
- Status = gBS->CheckEvent (TimerEvent);
- if (!EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_WARN,
- "XENSTORE response ring is not quiescent "
- "(%08x:%08x): fixing up\n",
- XenStore->rsp_cons,
- XenStore->rsp_prod
- ));
- XenStore->rsp_cons = XenStore->rsp_prod;
- }
- }
- gBS->CloseEvent (TimerEvent);
- Status = gBS->CreateEvent (
- EVT_NOTIFY_WAIT,
- TPL_NOTIFY,
- NotifyEventChannelCheckForEvent,
- xsp,
- &xsp->EventChannelEvent
- );
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
- /**
- Initialize XenStore.
- @param Dev A XENBUS_DEVICE instance.
- @retval EFI_SUCCESS if everything went well.
- **/
- EFI_STATUS
- XenStoreInit (
- XENBUS_DEVICE *Dev
- )
- {
- EFI_STATUS Status;
- /**
- * The HVM guest pseudo-physical frame number. This is Xen's mapping
- * of the true machine frame number into our "physical address space".
- */
- UINTN XenStoreGpfn;
- xs.Dev = Dev;
- xs.EventChannel = (evtchn_port_t)XenHypercallHvmGetParam (HVM_PARAM_STORE_EVTCHN);
- XenStoreGpfn = (UINTN)XenHypercallHvmGetParam (HVM_PARAM_STORE_PFN);
- xs.XenStore = (VOID *)(XenStoreGpfn << EFI_PAGE_SHIFT);
- DEBUG ((
- DEBUG_INFO,
- "XenBusInit: XenBus rings @%p, event channel %x\n",
- xs.XenStore,
- xs.EventChannel
- ));
- InitializeListHead (&xs.ReplyList);
- InitializeListHead (&xs.WatchEvents);
- InitializeListHead (&xs.RegisteredWatches);
- EfiInitializeLock (&xs.ReplyLock, TPL_NOTIFY);
- EfiInitializeLock (&xs.RegisteredWatchesLock, TPL_NOTIFY);
- EfiInitializeLock (&xs.WatchEventsLock, TPL_NOTIFY);
- /* Initialize the shared memory rings to talk to xenstored */
- Status = XenStoreInitComms (&xs);
- return Status;
- }
- VOID
- XenStoreDeinit (
- IN XENBUS_DEVICE *Dev
- )
- {
- //
- // Emptying the list RegisteredWatches, but this list should already be
- // empty. Every driver that is using Watches should unregister them when
- // it is stopped.
- //
- if (!IsListEmpty (&xs.RegisteredWatches)) {
- XENSTORE_WATCH *Watch;
- LIST_ENTRY *Entry;
- DEBUG ((DEBUG_WARN, "XenStore: RegisteredWatches is not empty, cleaning up..."));
- Entry = GetFirstNode (&xs.RegisteredWatches);
- while (!IsNull (&xs.RegisteredWatches, Entry)) {
- Watch = XENSTORE_WATCH_FROM_LINK (Entry);
- Entry = GetNextNode (&xs.RegisteredWatches, Entry);
- XenStoreUnregisterWatch (Watch);
- }
- }
- //
- // Emptying the list WatchEvents, but this list should already be empty after
- // having cleanup the list RegisteredWatches.
- //
- if (!IsListEmpty (&xs.WatchEvents)) {
- LIST_ENTRY *Entry;
- DEBUG ((DEBUG_WARN, "XenStore: WatchEvents is not empty, cleaning up..."));
- Entry = GetFirstNode (&xs.WatchEvents);
- while (!IsNull (&xs.WatchEvents, Entry)) {
- XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
- Entry = GetNextNode (&xs.WatchEvents, Entry);
- RemoveEntryList (&Message->Link);
- FreePool ((VOID *)Message->u.Watch.Vector);
- FreePool (Message);
- }
- }
- if (!IsListEmpty (&xs.ReplyList)) {
- XENSTORE_MESSAGE *Message;
- LIST_ENTRY *Entry;
- Entry = GetFirstNode (&xs.ReplyList);
- while (!IsNull (&xs.ReplyList, Entry)) {
- Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
- Entry = GetNextNode (&xs.ReplyList, Entry);
- RemoveEntryList (&Message->Link);
- FreePool (Message->u.Reply.Body);
- FreePool (Message);
- }
- }
- gBS->CloseEvent (xs.EventChannelEvent);
- if (xs.XenStore->server_features & XENSTORE_SERVER_FEATURE_RECONNECTION) {
- xs.XenStore->connection = XENSTORE_RECONNECT;
- XenEventChannelNotify (xs.Dev, xs.EventChannel);
- while (*(volatile UINT32 *)&xs.XenStore->connection == XENSTORE_RECONNECT) {
- XenStoreWaitForEvent (xs.EventChannelEvent, EFI_TIMER_PERIOD_MILLISECONDS (100));
- }
- } else {
- /* If the backend reads the state while we're erasing it then the
- * ring state will become corrupted, preventing guest frontends from
- * connecting. This is rare. To help diagnose the failure, we fill
- * the ring with XS_INVALID packets. */
- SetMem (xs.XenStore->req, XENSTORE_RING_SIZE, 0xff);
- SetMem (xs.XenStore->rsp, XENSTORE_RING_SIZE, 0xff);
- xs.XenStore->req_cons = xs.XenStore->req_prod = 0;
- xs.XenStore->rsp_cons = xs.XenStore->rsp_prod = 0;
- }
- xs.XenStore = NULL;
- }
- //
- // Public API
- // API comments for these methods can be found in XenStore.h
- //
- XENSTORE_STATUS
- XenStoreListDirectory (
- IN CONST XENSTORE_TRANSACTION *Transaction,
- IN CONST CHAR8 *DirectoryPath,
- IN CONST CHAR8 *Node,
- OUT UINT32 *DirectoryCountPtr,
- OUT CONST CHAR8 ***DirectoryListPtr
- )
- {
- CHAR8 *Path;
- CHAR8 *TempStr;
- UINT32 Len = 0;
- XENSTORE_STATUS Status;
- Path = XenStoreJoin (DirectoryPath, Node);
- Status = XenStoreSingle (
- Transaction,
- XS_DIRECTORY,
- Path,
- &Len,
- (VOID **)&TempStr
- );
- FreePool (Path);
- if (Status != XENSTORE_STATUS_SUCCESS) {
- return Status;
- }
- *DirectoryListPtr = Split (TempStr, Len, DirectoryCountPtr);
- return XENSTORE_STATUS_SUCCESS;
- }
- BOOLEAN
- XenStorePathExists (
- IN CONST XENSTORE_TRANSACTION *Transaction,
- IN CONST CHAR8 *Directory,
- IN CONST CHAR8 *Node
- )
- {
- CONST CHAR8 **TempStr;
- XENSTORE_STATUS Status;
- UINT32 TempNum;
- Status = XenStoreListDirectory (
- Transaction,
- Directory,
- Node,
- &TempNum,
- &TempStr
- );
- if (Status != XENSTORE_STATUS_SUCCESS) {
- return FALSE;
- }
- FreePool ((VOID *)TempStr);
- return TRUE;
- }
- XENSTORE_STATUS
- XenStoreRead (
- IN CONST XENSTORE_TRANSACTION *Transaction,
- IN CONST CHAR8 *DirectoryPath,
- IN CONST CHAR8 *Node,
- OUT UINT32 *LenPtr OPTIONAL,
- OUT VOID **Result
- )
- {
- CHAR8 *Path;
- VOID *Value;
- XENSTORE_STATUS Status;
- Path = XenStoreJoin (DirectoryPath, Node);
- Status = XenStoreSingle (Transaction, XS_READ, Path, LenPtr, &Value);
- FreePool (Path);
- if (Status != XENSTORE_STATUS_SUCCESS) {
- return Status;
- }
- *Result = Value;
- return XENSTORE_STATUS_SUCCESS;
- }
- XENSTORE_STATUS
- XenStoreWrite (
- IN CONST XENSTORE_TRANSACTION *Transaction,
- IN CONST CHAR8 *DirectoryPath,
- IN CONST CHAR8 *Node,
- IN CONST CHAR8 *Str
- )
- {
- CHAR8 *Path;
- WRITE_REQUEST WriteRequest[2];
- XENSTORE_STATUS Status;
- Path = XenStoreJoin (DirectoryPath, Node);
- WriteRequest[0].Data = (VOID *)Path;
- WriteRequest[0].Len = (UINT32)AsciiStrSize (Path);
- WriteRequest[1].Data = (VOID *)Str;
- WriteRequest[1].Len = (UINT32)AsciiStrLen (Str);
- Status = XenStoreTalkv (Transaction, XS_WRITE, WriteRequest, 2, NULL, NULL);
- FreePool (Path);
- return Status;
- }
- XENSTORE_STATUS
- XenStoreRemove (
- IN CONST XENSTORE_TRANSACTION *Transaction,
- IN CONST CHAR8 *DirectoryPath,
- IN CONST CHAR8 *Node
- )
- {
- CHAR8 *Path;
- XENSTORE_STATUS Status;
- Path = XenStoreJoin (DirectoryPath, Node);
- Status = XenStoreSingle (Transaction, XS_RM, Path, NULL, NULL);
- FreePool (Path);
- return Status;
- }
- XENSTORE_STATUS
- XenStoreTransactionStart (
- OUT XENSTORE_TRANSACTION *Transaction
- )
- {
- CHAR8 *IdStr;
- XENSTORE_STATUS Status;
- Status = XenStoreSingle (
- XST_NIL,
- XS_TRANSACTION_START,
- "",
- NULL,
- (VOID **)&IdStr
- );
- if (Status == XENSTORE_STATUS_SUCCESS) {
- Transaction->Id = (UINT32)AsciiStrDecimalToUintn (IdStr);
- FreePool (IdStr);
- }
- return Status;
- }
- XENSTORE_STATUS
- XenStoreTransactionEnd (
- IN CONST XENSTORE_TRANSACTION *Transaction,
- IN BOOLEAN Abort
- )
- {
- CHAR8 AbortStr[2];
- AbortStr[0] = Abort ? 'F' : 'T';
- AbortStr[1] = '\0';
- return XenStoreSingle (Transaction, XS_TRANSACTION_END, AbortStr, NULL, NULL);
- }
- XENSTORE_STATUS
- EFIAPI
- XenStoreVSPrint (
- IN CONST XENSTORE_TRANSACTION *Transaction,
- IN CONST CHAR8 *DirectoryPath,
- IN CONST CHAR8 *Node,
- IN CONST CHAR8 *FormatString,
- IN VA_LIST Marker
- )
- {
- CHAR8 *Buf;
- XENSTORE_STATUS Status;
- UINTN BufSize;
- VA_LIST Marker2;
- VA_COPY (Marker2, Marker);
- BufSize = SPrintLengthAsciiFormat (FormatString, Marker2) + 1;
- VA_END (Marker2);
- Buf = AllocateZeroPool (BufSize);
- AsciiVSPrint (Buf, BufSize, FormatString, Marker);
- Status = XenStoreWrite (Transaction, DirectoryPath, Node, Buf);
- FreePool (Buf);
- return Status;
- }
- XENSTORE_STATUS
- EFIAPI
- XenStoreSPrint (
- IN CONST 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
- XenStoreRegisterWatch (
- IN CONST CHAR8 *DirectoryPath,
- IN CONST CHAR8 *Node,
- OUT XENSTORE_WATCH **WatchPtr
- )
- {
- /* Pointer in ascii is the token. */
- CHAR8 Token[sizeof (XENSTORE_WATCH) * 2 + 1];
- XENSTORE_STATUS Status;
- XENSTORE_WATCH *Watch;
- Watch = AllocateZeroPool (sizeof (XENSTORE_WATCH));
- Watch->Signature = XENSTORE_WATCH_SIGNATURE;
- Watch->Node = XenStoreJoin (DirectoryPath, Node);
- EfiAcquireLock (&xs.RegisteredWatchesLock);
- InsertTailList (&xs.RegisteredWatches, &Watch->Link);
- EfiReleaseLock (&xs.RegisteredWatchesLock);
- AsciiSPrint (Token, sizeof (Token), "%p", (VOID *)Watch);
- Status = XenStoreWatch (Watch->Node, Token);
- /* Ignore errors due to multiple registration. */
- if (Status == XENSTORE_STATUS_EEXIST) {
- Status = XENSTORE_STATUS_SUCCESS;
- }
- if (Status == XENSTORE_STATUS_SUCCESS) {
- *WatchPtr = Watch;
- } else {
- EfiAcquireLock (&xs.RegisteredWatchesLock);
- RemoveEntryList (&Watch->Link);
- EfiReleaseLock (&xs.RegisteredWatchesLock);
- FreePool (Watch->Node);
- FreePool (Watch);
- }
- return Status;
- }
- VOID
- XenStoreUnregisterWatch (
- IN XENSTORE_WATCH *Watch
- )
- {
- CHAR8 Token[sizeof (Watch) * 2 + 1];
- LIST_ENTRY *Entry;
- ASSERT (Watch->Signature == XENSTORE_WATCH_SIGNATURE);
- AsciiSPrint (Token, sizeof (Token), "%p", (VOID *)Watch);
- if (XenStoreFindWatch (Token) == NULL) {
- return;
- }
- EfiAcquireLock (&xs.RegisteredWatchesLock);
- RemoveEntryList (&Watch->Link);
- EfiReleaseLock (&xs.RegisteredWatchesLock);
- XenStoreUnwatch (Watch->Node, Token);
- /* Cancel pending watch events. */
- EfiAcquireLock (&xs.WatchEventsLock);
- Entry = GetFirstNode (&xs.WatchEvents);
- while (!IsNull (&xs.WatchEvents, Entry)) {
- XENSTORE_MESSAGE *Message = XENSTORE_MESSAGE_FROM_LINK (Entry);
- Entry = GetNextNode (&xs.WatchEvents, Entry);
- if (Message->u.Watch.Handle == Watch) {
- RemoveEntryList (&Message->Link);
- FreePool ((VOID *)Message->u.Watch.Vector);
- FreePool (Message);
- }
- }
- EfiReleaseLock (&xs.WatchEventsLock);
- 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 CONST 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 CONST 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 CONST 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 CONST XENSTORE_TRANSACTION *Transaction,
- IN BOOLEAN Abort
- )
- {
- return XenStoreTransactionEnd (Transaction, Abort);
- }
- XENSTORE_STATUS
- EFIAPI
- XenBusXenStoreSPrint (
- IN XENBUS_PROTOCOL *This,
- IN CONST 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);
- }
|