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 Permission is hereby granted, free of charge, to any person obtaining a copy
18 of this source file (the "Software"), to deal in the Software without
19 restriction, including without limitation the rights to use, copy, modify,
20 merge, publish, distribute, sublicense, and/or sell copies of the Software,
21 and to permit persons to whom the Software is furnished to do so, subject to
22 the following conditions:
24 The above copyright notice and this permission notice shall be included in
25 all copies or substantial portions of the Software.
27 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
36 #include <Library/PrintLib.h>
39 #include "GrantTable.h"
41 #include "EventChannel.h"
43 #include <IndustryStandard/Xen/io/xenbus.h>
45 STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData
;
47 STATIC XENBUS_DEVICE_PATH gXenBusDevicePathTemplate
= {
50 HARDWARE_DEVICE_PATH
, // Vendor.Header.Type
51 HW_VENDOR_DP
, // Vendor.Header.SubType
53 (UINT8
) (sizeof (XENBUS_DEVICE_PATH
)), // Vendor.Header.Length[0]
54 (UINT8
) (sizeof (XENBUS_DEVICE_PATH
) >> 8), // Vendor.Header.Length[1]
57 XENBUS_PROTOCOL_GUID
, // Vendor.Guid
65 Search our internal record of configured devices (not the XenStore) to
66 determine if the XenBus device indicated by Node is known to the system.
68 @param Dev The XENBUS_DEVICE instance to search for device children.
69 @param Node The XenStore node path for the device to find.
71 @return The XENBUS_PRIVATE_DATA of the found device if any, or NULL.
75 XenBusDeviceInitialized (
76 IN XENBUS_DEVICE
*Dev
,
81 XENBUS_PRIVATE_DATA
*Child
;
82 XENBUS_PRIVATE_DATA
*Result
;
84 if (IsListEmpty (&Dev
->ChildList
)) {
89 for (Entry
= GetFirstNode (&Dev
->ChildList
);
90 !IsNodeAtEnd (&Dev
->ChildList
, Entry
);
91 Entry
= GetNextNode (&Dev
->ChildList
, Entry
)) {
92 Child
= XENBUS_PRIVATE_DATA_FROM_LINK (Entry
);
93 if (!AsciiStrCmp (Child
->XenBusIo
.Node
, Node
)) {
104 XenBusReadDriverState (
110 XENSTORE_STATUS Status
;
112 Status
= XenStoreRead (XST_NIL
, Path
, "state", NULL
, (VOID
**)&Ptr
);
113 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
114 State
= XenbusStateClosed
;
116 State
= AsciiStrDecimalToUintn (Ptr
);
127 // Callers should ensure that they are only one calling XenBusAddDevice.
136 CHAR8 DevicePath
[XENSTORE_ABS_PATH_MAX
];
137 XENSTORE_STATUS StatusXenStore
;
138 XENBUS_PRIVATE_DATA
*Private
;
140 XENBUS_DEVICE_PATH
*TempXenBusPath
;
143 AsciiSPrint (DevicePath
, sizeof (DevicePath
),
144 "device/%a/%a", Type
, Id
);
146 if (XenStorePathExists (XST_NIL
, DevicePath
, "")) {
147 XENBUS_PRIVATE_DATA
*Child
;
148 enum xenbus_state State
;
151 Child
= XenBusDeviceInitialized (Dev
, DevicePath
);
154 * We are already tracking this node
156 Status
= EFI_SUCCESS
;
160 State
= XenBusReadDriverState (DevicePath
);
161 if (State
!= XenbusStateInitialising
) {
163 * Device is not new, so ignore it. This can
164 * happen if a device is going away after
165 * switching to Closed.
167 DEBUG ((EFI_D_INFO
, "XenBus: Device %a ignored. "
168 "State %d\n", DevicePath
, State
));
169 Status
= EFI_SUCCESS
;
173 StatusXenStore
= XenStoreRead (XST_NIL
, DevicePath
, "backend",
174 NULL
, (VOID
**) &BackendPath
);
175 if (StatusXenStore
!= XENSTORE_STATUS_SUCCESS
) {
176 DEBUG ((EFI_D_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 (sizeof (XENBUS_DEVICE_PATH
),
189 &gXenBusDevicePathTemplate
);
190 if (!AsciiStrCmp (Private
->XenBusIo
.Type
, "vbd")) {
191 TempXenBusPath
->Type
= XENBUS_DEVICE_PATH_TYPE_VBD
;
193 TempXenBusPath
->DeviceId
= Private
->XenBusIo
.DeviceId
;
194 Private
->DevicePath
= (XENBUS_DEVICE_PATH
*)AppendDevicePathNode (
196 &TempXenBusPath
->Vendor
.Header
);
197 FreePool (TempXenBusPath
);
199 InsertTailList (&Dev
->ChildList
, &Private
->Link
);
201 Status
= gBS
->InstallMultipleProtocolInterfaces (
203 &gEfiDevicePathProtocolGuid
, Private
->DevicePath
,
204 &gXenBusProtocolGuid
, &Private
->XenBusIo
,
206 if (EFI_ERROR (Status
)) {
207 goto ErrorInstallProtocol
;
210 Status
= gBS
->OpenProtocol (Dev
->ControllerHandle
,
212 &ChildXenIo
, Dev
->This
->DriverBindingHandle
,
214 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
215 if (EFI_ERROR (Status
)) {
216 DEBUG ((EFI_D_ERROR
, "open by child controller fail (%r)\n",
218 goto ErrorOpenProtocolByChild
;
221 DEBUG ((EFI_D_ERROR
, "XenBus: does not exist: %a\n", DevicePath
));
222 Status
= EFI_NOT_FOUND
;
227 ErrorOpenProtocolByChild
:
228 gBS
->UninstallMultipleProtocolInterfaces (
230 &gEfiDevicePathProtocolGuid
, Private
->DevicePath
,
231 &gXenBusProtocolGuid
, &Private
->XenBusIo
,
233 ErrorInstallProtocol
:
234 RemoveEntryList (&Private
->Link
);
235 FreePool (Private
->DevicePath
);
236 FreePool ((VOID
*) Private
->XenBusIo
.Backend
);
237 FreePool ((VOID
*) Private
->XenBusIo
.Node
);
238 FreePool ((VOID
*) Private
->XenBusIo
.Type
);
245 Enumerate all devices of the given type on this bus.
247 @param Dev A XENBUS_DEVICE instance.
248 @param Type String indicating the device sub-tree (e.g. "vfb", "vif")
251 Devices that are found are been initialize via XenBusAddDevice ().
252 XenBusAddDevice () ignores duplicate detects and ignores duplicate devices,
253 so it can be called unconditionally for any device found in the XenStore.
257 XenBusEnumerateDeviceType (
262 CONST CHAR8
**Directory
;
265 XENSTORE_STATUS Status
;
267 Status
= XenStoreListDirectory (XST_NIL
,
270 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
273 for (Index
= 0; Index
< Count
; Index
++) {
274 XenBusAddDevice (Dev
, Type
, Directory
[Index
]);
277 FreePool ((VOID
*)Directory
);
282 Enumerate the devices on a XenBus bus and install a XenBus Protocol instance.
284 Caller should ensure that it is the only one to call this function. This
285 function cannot be called concurrently.
287 @param Dev A XENBUS_DEVICE instance.
289 @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
290 indicating the type of failure.
300 XENSTORE_STATUS Status
;
302 Status
= XenStoreListDirectory (XST_NIL
,
305 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
309 for (Index
= 0; Index
< Count
; Index
++) {
310 XenBusEnumerateDeviceType (Dev
, Types
[Index
]);
313 FreePool ((VOID
*)Types
);
315 return XENSTORE_STATUS_SUCCESS
;
322 IN XENBUS_PROTOCOL
*This
,
323 IN CONST XENSTORE_TRANSACTION
*Transaction
,
324 IN
enum xenbus_state NewState
327 enum xenbus_state CurrentState
;
328 XENSTORE_STATUS Status
;
331 DEBUG ((EFI_D_INFO
, "XenBus: Set state to %d\n", NewState
));
333 Status
= XenStoreRead (Transaction
, This
->Node
, "state", NULL
, (VOID
**)&Temp
);
334 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
337 CurrentState
= AsciiStrDecimalToUintn (Temp
);
339 if (CurrentState
== NewState
) {
344 Status
= XenStoreSPrint (Transaction
, This
->Node
, "state", "%d", NewState
);
345 } while (Status
== XENSTORE_STATUS_EAGAIN
);
346 if (Status
!= XENSTORE_STATUS_SUCCESS
) {
347 DEBUG ((EFI_D_ERROR
, "XenBus: failed to write new state\n"));
350 DEBUG ((EFI_D_INFO
, "XenBus: Set state to %d, done\n", NewState
));
356 STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData
= {
357 XENBUS_PRIVATE_DATA_SIGNATURE
, // Signature
358 { NULL
, NULL
}, // Link
361 XenBusXenStoreRead
, // XenBusIo.XsRead
362 XenBusXenStoreBackendRead
, // XenBusIo.XsBackendRead
363 XenBusXenStoreSPrint
, // XenBusIo.XsPrintf
364 XenBusXenStoreRemove
, // XenBusIo.XsRemove
365 XenBusXenStoreTransactionStart
, // XenBusIo.XsTransactionStart
366 XenBusXenStoreTransactionEnd
, // XenBusIo.XsTransactionEnd
367 XenBusSetState
, // XenBusIo.SetState
368 XenBusGrantAccess
, // XenBusIo.GrantAccess
369 XenBusGrantEndAccess
, // XenBusIo.GrantEndAccess
370 XenBusEventChannelAllocate
, // XenBusIo.EventChannelAllocate
371 XenBusEventChannelNotify
, // XenBusIo.EventChannelNotify
372 XenBusEventChannelClose
, // XenBusIo.EventChannelClose
373 XenBusRegisterWatch
, // XenBusIo.RegisterWatch
374 XenBusRegisterWatchBackend
, // XenBusIo.RegisterWatchBackend
375 XenBusUnregisterWatch
, // XenBusIo.UnregisterWatch
376 XenBusWaitForWatch
, // XenBusIo.WaitForWatch
378 NULL
, // XenBusIo.Type
379 0, // XenBusIo.DeviceId
380 NULL
, // XenBusIo.Node
381 NULL
, // XenBusIo.Backend