2 XenBus Bus driver implemtation.
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
49 Search our internal record of configured devices (not the XenStore) to
50 determine if the XenBus device indicated by Node is known to the system.
52 @param Dev The XENBUS_DEVICE instance to search for device children.
53 @param Node The XenStore node path for the device to find.
55 @return The XENBUS_PRIVATE_DATA of the found device if any, or NULL.
59 XenBusDeviceInitialized (
60 IN XENBUS_DEVICE
*Dev
,
65 XENBUS_PRIVATE_DATA
*Child
;
66 XENBUS_PRIVATE_DATA
*Result
;
68 if (IsListEmpty (&Dev
->ChildList
)) {
73 for (Entry
= GetFirstNode (&Dev
->ChildList
);
74 !IsNodeAtEnd (&Dev
->ChildList
, Entry
);
75 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.
120 CHAR8 DevicePath
[XENSTORE_ABS_PATH_MAX
];
121 XENSTORE_STATUS StatusXenStore
;
122 XENBUS_PRIVATE_DATA
*Private
;
124 XENBUS_DEVICE_PATH
*TempXenBusPath
;
127 AsciiSPrint (DevicePath
, sizeof (DevicePath
),
128 "device/%a/%a", Type
, Id
);
130 if (XenStorePathExists (XST_NIL
, DevicePath
, "")) {
131 XENBUS_PRIVATE_DATA
*Child
;
132 enum xenbus_state State
;
135 Child
= XenBusDeviceInitialized (Dev
, DevicePath
);
138 * We are already tracking this node
140 Status
= EFI_SUCCESS
;
144 State
= XenBusReadDriverState (DevicePath
);
145 if (State
!= XenbusStateInitialising
) {
147 * Device is not new, so ignore it. This can
148 * happen if a device is going away after
149 * switching to Closed.
151 DEBUG ((EFI_D_INFO
, "XenBus: Device %a ignored. "
152 "State %d\n", DevicePath
, State
));
153 Status
= EFI_SUCCESS
;
157 StatusXenStore
= XenStoreRead (XST_NIL
, DevicePath
, "backend",
158 NULL
, (VOID
**) &BackendPath
);
159 if (StatusXenStore
!= XENSTORE_STATUS_SUCCESS
) {
160 DEBUG ((EFI_D_ERROR
, "xenbus: %a no backend path.\n", DevicePath
));
161 Status
= EFI_NOT_FOUND
;
165 Private
= AllocateCopyPool (sizeof (*Private
), &gXenBusPrivateData
);
166 Private
->XenBusIo
.Type
= AsciiStrDup (Type
);
167 Private
->XenBusIo
.Node
= AsciiStrDup (DevicePath
);
168 Private
->XenBusIo
.Backend
= BackendPath
;
169 Private
->XenBusIo
.DeviceId
= (UINT16
)AsciiStrDecimalToUintn (Id
);
172 TempXenBusPath
= AllocateCopyPool (sizeof (XENBUS_DEVICE_PATH
),
173 &gXenBusDevicePathTemplate
);
174 if (!AsciiStrCmp (Private
->XenBusIo
.Type
, "vbd")) {
175 TempXenBusPath
->Type
= XENBUS_DEVICE_PATH_TYPE_VBD
;
177 TempXenBusPath
->DeviceId
= Private
->XenBusIo
.DeviceId
;
178 Private
->DevicePath
= (XENBUS_DEVICE_PATH
*)AppendDevicePathNode (
180 &TempXenBusPath
->Vendor
.Header
);
181 FreePool (TempXenBusPath
);
183 InsertTailList (&Dev
->ChildList
, &Private
->Link
);
185 Status
= gBS
->InstallMultipleProtocolInterfaces (
187 &gEfiDevicePathProtocolGuid
, Private
->DevicePath
,
188 &gXenBusProtocolGuid
, &Private
->XenBusIo
,
190 if (EFI_ERROR (Status
)) {
191 goto ErrorInstallProtocol
;
194 Status
= gBS
->OpenProtocol (Dev
->ControllerHandle
,
196 &ChildXenIo
, Dev
->This
->DriverBindingHandle
,
198 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
199 if (EFI_ERROR (Status
)) {
200 DEBUG ((EFI_D_ERROR
, "open by child controller fail (%r)\n",
202 goto ErrorOpenProtocolByChild
;
205 DEBUG ((EFI_D_ERROR
, "XenBus: does not exist: %a\n", DevicePath
));
206 Status
= EFI_NOT_FOUND
;
211 ErrorOpenProtocolByChild
:
212 gBS
->UninstallMultipleProtocolInterfaces (
214 &gEfiDevicePathProtocolGuid
, Private
->DevicePath
,
215 &gXenBusProtocolGuid
, &Private
->XenBusIo
,
217 ErrorInstallProtocol
:
218 RemoveEntryList (&Private
->Link
);
219 FreePool (Private
->DevicePath
);
220 FreePool ((VOID
*) Private
->XenBusIo
.Backend
);
221 FreePool ((VOID
*) Private
->XenBusIo
.Node
);
222 FreePool ((VOID
*) Private
->XenBusIo
.Type
);
229 Enumerate all devices of the given type on this bus.
231 @param Dev A XENBUS_DEVICE instance.
232 @param Type String indicating the device sub-tree (e.g. "vfb", "vif")
235 Devices that are found are been initialize via XenBusAddDevice ().
236 XenBusAddDevice () ignores duplicate detects and ignores duplicate devices,
237 so it can be called unconditionally for any device found in the XenStore.
241 XenBusEnumerateDeviceType (
246 CONST CHAR8
**Directory
;
249 XENSTORE_STATUS Status
;
251 Status
= XenStoreListDirectory (XST_NIL
,
254 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
257 for (Index
= 0; Index
< Count
; Index
++) {
258 XenBusAddDevice (Dev
, Type
, Directory
[Index
]);
261 FreePool ((VOID
*)Directory
);
266 Enumerate the devices on a XenBus bus and install a XenBus Protocol instance.
268 Caller should ensure that it is the only one to call this function. This
269 function cannot be called concurrently.
271 @param Dev A XENBUS_DEVICE instance.
273 @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
274 indicating the type of failure.
284 XENSTORE_STATUS Status
;
286 Status
= XenStoreListDirectory (XST_NIL
,
289 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
293 for (Index
= 0; Index
< Count
; Index
++) {
294 XenBusEnumerateDeviceType (Dev
, Types
[Index
]);
297 FreePool ((VOID
*)Types
);
299 return XENSTORE_STATUS_SUCCESS
;
306 IN XENBUS_PROTOCOL
*This
,
307 IN CONST XENSTORE_TRANSACTION
*Transaction
,
308 IN
enum xenbus_state NewState
311 enum xenbus_state CurrentState
;
312 XENSTORE_STATUS Status
;
315 DEBUG ((EFI_D_INFO
, "XenBus: Set state to %d\n", NewState
));
317 Status
= XenStoreRead (Transaction
, This
->Node
, "state", NULL
, (VOID
**)&Temp
);
318 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
321 CurrentState
= AsciiStrDecimalToUintn (Temp
);
323 if (CurrentState
== NewState
) {
328 Status
= XenStoreSPrint (Transaction
, This
->Node
, "state", "%d", NewState
);
329 } while (Status
== XENSTORE_STATUS_EAGAIN
);
330 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
331 DEBUG ((EFI_D_ERROR
, "XenBus: failed to write new state\n"));
334 DEBUG ((EFI_D_INFO
, "XenBus: Set state to %d, done\n", NewState
));
340 STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData
= {
341 XENBUS_PRIVATE_DATA_SIGNATURE
, // Signature
342 { NULL
, NULL
}, // Link
345 XenBusXenStoreRead
, // XenBusIo.XsRead
346 XenBusXenStoreBackendRead
, // XenBusIo.XsBackendRead
347 XenBusXenStoreSPrint
, // XenBusIo.XsPrintf
348 XenBusXenStoreRemove
, // XenBusIo.XsRemove
349 XenBusXenStoreTransactionStart
, // XenBusIo.XsTransactionStart
350 XenBusXenStoreTransactionEnd
, // XenBusIo.XsTransactionEnd
351 XenBusSetState
, // XenBusIo.SetState
352 XenBusGrantAccess
, // XenBusIo.GrantAccess
353 XenBusGrantEndAccess
, // XenBusIo.GrantEndAccess
354 XenBusEventChannelAllocate
, // XenBusIo.EventChannelAllocate
355 XenBusEventChannelNotify
, // XenBusIo.EventChannelNotify
356 XenBusEventChannelClose
, // XenBusIo.EventChannelClose
357 XenBusRegisterWatch
, // XenBusIo.RegisterWatch
358 XenBusRegisterWatchBackend
, // XenBusIo.RegisterWatchBackend
359 XenBusUnregisterWatch
, // XenBusIo.UnregisterWatch
360 XenBusWaitForWatch
, // XenBusIo.WaitForWatch
362 NULL
, // XenBusIo.Type
363 0, // XenBusIo.DeviceId
364 NULL
, // XenBusIo.Node
365 NULL
, // XenBusIo.Backend