2 XenBus Bus driver implementation.
4 This file implement the necessary to discover and enumerate Xen PV devices
7 Copyright (C) 2010 Spectra Logic Corporation
8 Copyright (C) 2008 Doug Rabson
9 Copyright (C) 2005 Rusty Russell, IBM Corporation
10 Copyright (C) 2005 Mike Wray, Hewlett-Packard
11 Copyright (C) 2005 XenSource Ltd
12 Copyright (C) 2014, Citrix Ltd.
14 This file may be distributed separately from the Linux kernel, or
15 incorporated into other software packages, subject to the following license:
17 SPDX-License-Identifier: MIT
20 #include <Library/PrintLib.h>
23 #include "GrantTable.h"
25 #include "EventChannel.h"
27 #include <IndustryStandard/Xen/io/xenbus.h>
29 STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData
;
31 STATIC XENBUS_DEVICE_PATH gXenBusDevicePathTemplate
= {
34 HARDWARE_DEVICE_PATH
, // Vendor.Header.Type
35 HW_VENDOR_DP
, // Vendor.Header.SubType
37 (UINT8
)(sizeof (XENBUS_DEVICE_PATH
)), // Vendor.Header.Length[0]
38 (UINT8
)(sizeof (XENBUS_DEVICE_PATH
) >> 8), // Vendor.Header.Length[1]
41 XENBUS_PROTOCOL_GUID
, // Vendor.Guid
48 Search our internal record of configured devices (not the XenStore) to
49 determine if the XenBus device indicated by Node is known to the system.
51 @param Dev The XENBUS_DEVICE instance to search for device children.
52 @param Node The XenStore node path for the device to find.
54 @return The XENBUS_PRIVATE_DATA of the found device if any, or NULL.
58 XenBusDeviceInitialized (
59 IN XENBUS_DEVICE
*Dev
,
64 XENBUS_PRIVATE_DATA
*Child
;
65 XENBUS_PRIVATE_DATA
*Result
;
67 if (IsListEmpty (&Dev
->ChildList
)) {
72 for (Entry
= GetFirstNode (&Dev
->ChildList
);
73 !IsNodeAtEnd (&Dev
->ChildList
, Entry
);
74 Entry
= GetNextNode (&Dev
->ChildList
, Entry
))
76 Child
= XENBUS_PRIVATE_DATA_FROM_LINK (Entry
);
77 if (!AsciiStrCmp (Child
->XenBusIo
.Node
, Node
)) {
88 XenBusReadDriverState (
94 XENSTORE_STATUS Status
;
96 Status
= XenStoreRead (XST_NIL
, Path
, "state", NULL
, (VOID
**)&Ptr
);
97 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
98 State
= XenbusStateClosed
;
100 State
= AsciiStrDecimalToUintn (Ptr
);
111 // Callers should ensure that they are only one calling XenBusAddDevice.
121 CHAR8 DevicePath
[XENSTORE_ABS_PATH_MAX
];
122 XENSTORE_STATUS StatusXenStore
;
123 XENBUS_PRIVATE_DATA
*Private
;
125 XENBUS_DEVICE_PATH
*TempXenBusPath
;
136 if (XenStorePathExists (XST_NIL
, DevicePath
, "")) {
137 XENBUS_PRIVATE_DATA
*Child
;
138 enum xenbus_state State
;
141 Child
= XenBusDeviceInitialized (Dev
, DevicePath
);
144 * We are already tracking this node
146 Status
= EFI_SUCCESS
;
150 State
= XenBusReadDriverState (DevicePath
);
151 if (State
!= XenbusStateInitialising
) {
153 * Device is not new, so ignore it. This can
154 * happen if a device is going away after
155 * switching to Closed.
159 "XenBus: Device %a ignored. "
164 Status
= EFI_SUCCESS
;
168 StatusXenStore
= XenStoreRead (
173 (VOID
**)&BackendPath
175 if (StatusXenStore
!= XENSTORE_STATUS_SUCCESS
) {
176 DEBUG ((DEBUG_ERROR
, "xenbus: %a no backend path.\n", DevicePath
));
177 Status
= EFI_NOT_FOUND
;
181 Private
= AllocateCopyPool (sizeof (*Private
), &gXenBusPrivateData
);
182 Private
->XenBusIo
.Type
= AsciiStrDup (Type
);
183 Private
->XenBusIo
.Node
= AsciiStrDup (DevicePath
);
184 Private
->XenBusIo
.Backend
= BackendPath
;
185 Private
->XenBusIo
.DeviceId
= (UINT16
)AsciiStrDecimalToUintn (Id
);
188 TempXenBusPath
= AllocateCopyPool (
189 sizeof (XENBUS_DEVICE_PATH
),
190 &gXenBusDevicePathTemplate
192 if (!AsciiStrCmp (Private
->XenBusIo
.Type
, "vbd")) {
193 TempXenBusPath
->Type
= XENBUS_DEVICE_PATH_TYPE_VBD
;
196 TempXenBusPath
->DeviceId
= Private
->XenBusIo
.DeviceId
;
197 Private
->DevicePath
= (XENBUS_DEVICE_PATH
*)AppendDevicePathNode (
199 &TempXenBusPath
->Vendor
.Header
201 FreePool (TempXenBusPath
);
203 InsertTailList (&Dev
->ChildList
, &Private
->Link
);
205 Status
= gBS
->InstallMultipleProtocolInterfaces (
207 &gEfiDevicePathProtocolGuid
,
209 &gXenBusProtocolGuid
,
213 if (EFI_ERROR (Status
)) {
214 goto ErrorInstallProtocol
;
217 Status
= gBS
->OpenProtocol (
218 Dev
->ControllerHandle
,
221 Dev
->This
->DriverBindingHandle
,
223 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
225 if (EFI_ERROR (Status
)) {
228 "open by child controller fail (%r)\n",
231 goto ErrorOpenProtocolByChild
;
234 DEBUG ((DEBUG_ERROR
, "XenBus: does not exist: %a\n", DevicePath
));
235 Status
= EFI_NOT_FOUND
;
240 ErrorOpenProtocolByChild
:
241 gBS
->UninstallMultipleProtocolInterfaces (
243 &gEfiDevicePathProtocolGuid
,
245 &gXenBusProtocolGuid
,
249 ErrorInstallProtocol
:
250 RemoveEntryList (&Private
->Link
);
251 FreePool (Private
->DevicePath
);
252 FreePool ((VOID
*)Private
->XenBusIo
.Backend
);
253 FreePool ((VOID
*)Private
->XenBusIo
.Node
);
254 FreePool ((VOID
*)Private
->XenBusIo
.Type
);
261 Enumerate all devices of the given type on this bus.
263 @param Dev A XENBUS_DEVICE instance.
264 @param Type String indicating the device sub-tree (e.g. "vfb", "vif")
267 Devices that are found are been initialize via XenBusAddDevice ().
268 XenBusAddDevice () ignores duplicate detects and ignores duplicate devices,
269 so it can be called unconditionally for any device found in the XenStore.
273 XenBusEnumerateDeviceType (
278 CONST CHAR8
**Directory
;
281 XENSTORE_STATUS Status
;
283 Status
= XenStoreListDirectory (
290 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
294 for (Index
= 0; Index
< Count
; Index
++) {
295 XenBusAddDevice (Dev
, Type
, Directory
[Index
]);
298 FreePool ((VOID
*)Directory
);
302 Enumerate the devices on a XenBus bus and install a XenBus Protocol instance.
304 Caller should ensure that it is the only one to call this function. This
305 function cannot be called concurrently.
307 @param Dev A XENBUS_DEVICE instance.
309 @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
310 indicating the type of failure.
320 XENSTORE_STATUS Status
;
322 Status
= XenStoreListDirectory (
329 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
333 for (Index
= 0; Index
< Count
; Index
++) {
334 XenBusEnumerateDeviceType (Dev
, Types
[Index
]);
337 FreePool ((VOID
*)Types
);
339 return XENSTORE_STATUS_SUCCESS
;
346 IN XENBUS_PROTOCOL
*This
,
347 IN CONST XENSTORE_TRANSACTION
*Transaction
,
348 IN
enum xenbus_state NewState
351 enum xenbus_state CurrentState
;
352 XENSTORE_STATUS Status
;
355 DEBUG ((DEBUG_INFO
, "XenBus: Set state to %d\n", NewState
));
357 Status
= XenStoreRead (Transaction
, This
->Node
, "state", NULL
, (VOID
**)&Temp
);
358 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
362 CurrentState
= AsciiStrDecimalToUintn (Temp
);
364 if (CurrentState
== NewState
) {
369 Status
= XenStoreSPrint (Transaction
, This
->Node
, "state", "%d", NewState
);
370 } while (Status
== XENSTORE_STATUS_EAGAIN
);
372 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
373 DEBUG ((DEBUG_ERROR
, "XenBus: failed to write new state\n"));
377 DEBUG ((DEBUG_INFO
, "XenBus: Set state to %d, done\n", NewState
));
383 STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData
= {
384 XENBUS_PRIVATE_DATA_SIGNATURE
, // Signature
385 { NULL
, NULL
}, // Link
388 XenBusXenStoreRead
, // XenBusIo.XsRead
389 XenBusXenStoreBackendRead
, // XenBusIo.XsBackendRead
390 XenBusXenStoreSPrint
, // XenBusIo.XsPrintf
391 XenBusXenStoreRemove
, // XenBusIo.XsRemove
392 XenBusXenStoreTransactionStart
, // XenBusIo.XsTransactionStart
393 XenBusXenStoreTransactionEnd
, // XenBusIo.XsTransactionEnd
394 XenBusSetState
, // XenBusIo.SetState
395 XenBusGrantAccess
, // XenBusIo.GrantAccess
396 XenBusGrantEndAccess
, // XenBusIo.GrantEndAccess
397 XenBusEventChannelAllocate
, // XenBusIo.EventChannelAllocate
398 XenBusEventChannelNotify
, // XenBusIo.EventChannelNotify
399 XenBusEventChannelClose
, // XenBusIo.EventChannelClose
400 XenBusRegisterWatch
, // XenBusIo.RegisterWatch
401 XenBusRegisterWatchBackend
, // XenBusIo.RegisterWatchBackend
402 XenBusUnregisterWatch
, // XenBusIo.UnregisterWatch
403 XenBusWaitForWatch
, // XenBusIo.WaitForWatch
405 NULL
, // XenBusIo.Type
406 0, // XenBusIo.DeviceId
407 NULL
, // XenBusIo.Node
408 NULL
, // XenBusIo.Backend