XenBus.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /** @file
  2. XenBus Bus driver implementation.
  3. This file implement the necessary to discover and enumerate Xen PV devices
  4. through XenStore.
  5. Copyright (C) 2010 Spectra Logic Corporation
  6. Copyright (C) 2008 Doug Rabson
  7. Copyright (C) 2005 Rusty Russell, IBM Corporation
  8. Copyright (C) 2005 Mike Wray, Hewlett-Packard
  9. Copyright (C) 2005 XenSource Ltd
  10. Copyright (C) 2014, Citrix Ltd.
  11. This file may be distributed separately from the Linux kernel, or
  12. incorporated into other software packages, subject to the following license:
  13. SPDX-License-Identifier: MIT
  14. **/
  15. #include <Library/PrintLib.h>
  16. #include "XenBus.h"
  17. #include "GrantTable.h"
  18. #include "XenStore.h"
  19. #include "EventChannel.h"
  20. #include <IndustryStandard/Xen/io/xenbus.h>
  21. STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData;
  22. STATIC XENBUS_DEVICE_PATH gXenBusDevicePathTemplate = {
  23. { // Vendor
  24. { // Vendor.Header
  25. HARDWARE_DEVICE_PATH, // Vendor.Header.Type
  26. HW_VENDOR_DP, // Vendor.Header.SubType
  27. {
  28. (UINT8)(sizeof (XENBUS_DEVICE_PATH)), // Vendor.Header.Length[0]
  29. (UINT8)(sizeof (XENBUS_DEVICE_PATH) >> 8), // Vendor.Header.Length[1]
  30. }
  31. },
  32. XENBUS_PROTOCOL_GUID, // Vendor.Guid
  33. },
  34. 0, // Type
  35. 0 // DeviceId
  36. };
  37. /**
  38. Search our internal record of configured devices (not the XenStore) to
  39. determine if the XenBus device indicated by Node is known to the system.
  40. @param Dev The XENBUS_DEVICE instance to search for device children.
  41. @param Node The XenStore node path for the device to find.
  42. @return The XENBUS_PRIVATE_DATA of the found device if any, or NULL.
  43. */
  44. STATIC
  45. XENBUS_PRIVATE_DATA *
  46. XenBusDeviceInitialized (
  47. IN XENBUS_DEVICE *Dev,
  48. IN CONST CHAR8 *Node
  49. )
  50. {
  51. LIST_ENTRY *Entry;
  52. XENBUS_PRIVATE_DATA *Child;
  53. XENBUS_PRIVATE_DATA *Result;
  54. if (IsListEmpty (&Dev->ChildList)) {
  55. return NULL;
  56. }
  57. Result = NULL;
  58. for (Entry = GetFirstNode (&Dev->ChildList);
  59. !IsNodeAtEnd (&Dev->ChildList, Entry);
  60. Entry = GetNextNode (&Dev->ChildList, Entry))
  61. {
  62. Child = XENBUS_PRIVATE_DATA_FROM_LINK (Entry);
  63. if (!AsciiStrCmp (Child->XenBusIo.Node, Node)) {
  64. Result = Child;
  65. break;
  66. }
  67. }
  68. return (Result);
  69. }
  70. STATIC
  71. XenbusState
  72. XenBusReadDriverState (
  73. IN CONST CHAR8 *Path
  74. )
  75. {
  76. XenbusState State;
  77. CHAR8 *Ptr = NULL;
  78. XENSTORE_STATUS Status;
  79. Status = XenStoreRead (XST_NIL, Path, "state", NULL, (VOID **)&Ptr);
  80. if (Status != XENSTORE_STATUS_SUCCESS) {
  81. State = XenbusStateClosed;
  82. } else {
  83. State = AsciiStrDecimalToUintn (Ptr);
  84. }
  85. if (Ptr != NULL) {
  86. FreePool (Ptr);
  87. }
  88. return State;
  89. }
  90. //
  91. // Callers should ensure that they are only one calling XenBusAddDevice.
  92. //
  93. STATIC
  94. EFI_STATUS
  95. XenBusAddDevice (
  96. XENBUS_DEVICE *Dev,
  97. CONST CHAR8 *Type,
  98. CONST CHAR8 *Id
  99. )
  100. {
  101. CHAR8 DevicePath[XENSTORE_ABS_PATH_MAX];
  102. XENSTORE_STATUS StatusXenStore;
  103. XENBUS_PRIVATE_DATA *Private;
  104. EFI_STATUS Status;
  105. XENBUS_DEVICE_PATH *TempXenBusPath;
  106. VOID *ChildXenIo;
  107. AsciiSPrint (
  108. DevicePath,
  109. sizeof (DevicePath),
  110. "device/%a/%a",
  111. Type,
  112. Id
  113. );
  114. if (XenStorePathExists (XST_NIL, DevicePath, "")) {
  115. XENBUS_PRIVATE_DATA *Child;
  116. enum xenbus_state State;
  117. CHAR8 *BackendPath;
  118. Child = XenBusDeviceInitialized (Dev, DevicePath);
  119. if (Child != NULL) {
  120. /*
  121. * We are already tracking this node
  122. */
  123. Status = EFI_SUCCESS;
  124. goto out;
  125. }
  126. State = XenBusReadDriverState (DevicePath);
  127. if (State != XenbusStateInitialising) {
  128. /*
  129. * Device is not new, so ignore it. This can
  130. * happen if a device is going away after
  131. * switching to Closed.
  132. */
  133. DEBUG ((
  134. DEBUG_INFO,
  135. "XenBus: Device %a ignored. "
  136. "State %d\n",
  137. DevicePath,
  138. State
  139. ));
  140. Status = EFI_SUCCESS;
  141. goto out;
  142. }
  143. StatusXenStore = XenStoreRead (
  144. XST_NIL,
  145. DevicePath,
  146. "backend",
  147. NULL,
  148. (VOID **)&BackendPath
  149. );
  150. if (StatusXenStore != XENSTORE_STATUS_SUCCESS) {
  151. DEBUG ((DEBUG_ERROR, "xenbus: %a no backend path.\n", DevicePath));
  152. Status = EFI_NOT_FOUND;
  153. goto out;
  154. }
  155. Private = AllocateCopyPool (sizeof (*Private), &gXenBusPrivateData);
  156. Private->XenBusIo.Type = AsciiStrDup (Type);
  157. Private->XenBusIo.Node = AsciiStrDup (DevicePath);
  158. Private->XenBusIo.Backend = BackendPath;
  159. Private->XenBusIo.DeviceId = (UINT16)AsciiStrDecimalToUintn (Id);
  160. Private->Dev = Dev;
  161. TempXenBusPath = AllocateCopyPool (
  162. sizeof (XENBUS_DEVICE_PATH),
  163. &gXenBusDevicePathTemplate
  164. );
  165. if (!AsciiStrCmp (Private->XenBusIo.Type, "vbd")) {
  166. TempXenBusPath->Type = XENBUS_DEVICE_PATH_TYPE_VBD;
  167. }
  168. TempXenBusPath->DeviceId = Private->XenBusIo.DeviceId;
  169. Private->DevicePath = (XENBUS_DEVICE_PATH *)AppendDevicePathNode (
  170. Dev->DevicePath,
  171. &TempXenBusPath->Vendor.Header
  172. );
  173. FreePool (TempXenBusPath);
  174. InsertTailList (&Dev->ChildList, &Private->Link);
  175. Status = gBS->InstallMultipleProtocolInterfaces (
  176. &Private->Handle,
  177. &gEfiDevicePathProtocolGuid,
  178. Private->DevicePath,
  179. &gXenBusProtocolGuid,
  180. &Private->XenBusIo,
  181. NULL
  182. );
  183. if (EFI_ERROR (Status)) {
  184. goto ErrorInstallProtocol;
  185. }
  186. Status = gBS->OpenProtocol (
  187. Dev->ControllerHandle,
  188. &gXenIoProtocolGuid,
  189. &ChildXenIo,
  190. Dev->This->DriverBindingHandle,
  191. Private->Handle,
  192. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  193. );
  194. if (EFI_ERROR (Status)) {
  195. DEBUG ((
  196. DEBUG_ERROR,
  197. "open by child controller fail (%r)\n",
  198. Status
  199. ));
  200. goto ErrorOpenProtocolByChild;
  201. }
  202. } else {
  203. DEBUG ((DEBUG_ERROR, "XenBus: does not exist: %a\n", DevicePath));
  204. Status = EFI_NOT_FOUND;
  205. }
  206. return Status;
  207. ErrorOpenProtocolByChild:
  208. gBS->UninstallMultipleProtocolInterfaces (
  209. Private->Handle,
  210. &gEfiDevicePathProtocolGuid,
  211. Private->DevicePath,
  212. &gXenBusProtocolGuid,
  213. &Private->XenBusIo,
  214. NULL
  215. );
  216. ErrorInstallProtocol:
  217. RemoveEntryList (&Private->Link);
  218. FreePool (Private->DevicePath);
  219. FreePool ((VOID *)Private->XenBusIo.Backend);
  220. FreePool ((VOID *)Private->XenBusIo.Node);
  221. FreePool ((VOID *)Private->XenBusIo.Type);
  222. FreePool (Private);
  223. out:
  224. return Status;
  225. }
  226. /**
  227. Enumerate all devices of the given type on this bus.
  228. @param Dev A XENBUS_DEVICE instance.
  229. @param Type String indicating the device sub-tree (e.g. "vfb", "vif")
  230. to enumerate.
  231. Devices that are found are been initialize via XenBusAddDevice ().
  232. XenBusAddDevice () ignores duplicate detects and ignores duplicate devices,
  233. so it can be called unconditionally for any device found in the XenStore.
  234. */
  235. STATIC
  236. VOID
  237. XenBusEnumerateDeviceType (
  238. XENBUS_DEVICE *Dev,
  239. CONST CHAR8 *Type
  240. )
  241. {
  242. CONST CHAR8 **Directory;
  243. UINTN Index;
  244. UINT32 Count;
  245. XENSTORE_STATUS Status;
  246. Status = XenStoreListDirectory (
  247. XST_NIL,
  248. "device",
  249. Type,
  250. &Count,
  251. &Directory
  252. );
  253. if (Status != XENSTORE_STATUS_SUCCESS) {
  254. return;
  255. }
  256. for (Index = 0; Index < Count; Index++) {
  257. XenBusAddDevice (Dev, Type, Directory[Index]);
  258. }
  259. FreePool ((VOID *)Directory);
  260. }
  261. /**
  262. Enumerate the devices on a XenBus bus and install a XenBus Protocol instance.
  263. Caller should ensure that it is the only one to call this function. This
  264. function cannot be called concurrently.
  265. @param Dev A XENBUS_DEVICE instance.
  266. @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value
  267. indicating the type of failure.
  268. */
  269. XENSTORE_STATUS
  270. XenBusEnumerateBus (
  271. XENBUS_DEVICE *Dev
  272. )
  273. {
  274. CONST CHAR8 **Types;
  275. UINTN Index;
  276. UINT32 Count;
  277. XENSTORE_STATUS Status;
  278. Status = XenStoreListDirectory (
  279. XST_NIL,
  280. "device",
  281. "",
  282. &Count,
  283. &Types
  284. );
  285. if (Status != XENSTORE_STATUS_SUCCESS) {
  286. return Status;
  287. }
  288. for (Index = 0; Index < Count; Index++) {
  289. XenBusEnumerateDeviceType (Dev, Types[Index]);
  290. }
  291. FreePool ((VOID *)Types);
  292. return XENSTORE_STATUS_SUCCESS;
  293. }
  294. STATIC
  295. XENSTORE_STATUS
  296. EFIAPI
  297. XenBusSetState (
  298. IN XENBUS_PROTOCOL *This,
  299. IN CONST XENSTORE_TRANSACTION *Transaction,
  300. IN enum xenbus_state NewState
  301. )
  302. {
  303. enum xenbus_state CurrentState;
  304. XENSTORE_STATUS Status;
  305. CHAR8 *Temp;
  306. DEBUG ((DEBUG_INFO, "XenBus: Set state to %d\n", NewState));
  307. Status = XenStoreRead (Transaction, This->Node, "state", NULL, (VOID **)&Temp);
  308. if (Status != XENSTORE_STATUS_SUCCESS) {
  309. goto Out;
  310. }
  311. CurrentState = AsciiStrDecimalToUintn (Temp);
  312. FreePool (Temp);
  313. if (CurrentState == NewState) {
  314. goto Out;
  315. }
  316. do {
  317. Status = XenStoreSPrint (Transaction, This->Node, "state", "%d", NewState);
  318. } while (Status == XENSTORE_STATUS_EAGAIN);
  319. if (Status != XENSTORE_STATUS_SUCCESS) {
  320. DEBUG ((DEBUG_ERROR, "XenBus: failed to write new state\n"));
  321. goto Out;
  322. }
  323. DEBUG ((DEBUG_INFO, "XenBus: Set state to %d, done\n", NewState));
  324. Out:
  325. return Status;
  326. }
  327. STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData = {
  328. XENBUS_PRIVATE_DATA_SIGNATURE, // Signature
  329. { NULL, NULL }, // Link
  330. NULL, // Handle
  331. { // XenBusIo
  332. XenBusXenStoreRead, // XenBusIo.XsRead
  333. XenBusXenStoreBackendRead, // XenBusIo.XsBackendRead
  334. XenBusXenStoreSPrint, // XenBusIo.XsPrintf
  335. XenBusXenStoreRemove, // XenBusIo.XsRemove
  336. XenBusXenStoreTransactionStart, // XenBusIo.XsTransactionStart
  337. XenBusXenStoreTransactionEnd, // XenBusIo.XsTransactionEnd
  338. XenBusSetState, // XenBusIo.SetState
  339. XenBusGrantAccess, // XenBusIo.GrantAccess
  340. XenBusGrantEndAccess, // XenBusIo.GrantEndAccess
  341. XenBusEventChannelAllocate, // XenBusIo.EventChannelAllocate
  342. XenBusEventChannelNotify, // XenBusIo.EventChannelNotify
  343. XenBusEventChannelClose, // XenBusIo.EventChannelClose
  344. XenBusRegisterWatch, // XenBusIo.RegisterWatch
  345. XenBusRegisterWatchBackend, // XenBusIo.RegisterWatchBackend
  346. XenBusUnregisterWatch, // XenBusIo.UnregisterWatch
  347. XenBusWaitForWatch, // XenBusIo.WaitForWatch
  348. NULL, // XenBusIo.Type
  349. 0, // XenBusIo.DeviceId
  350. NULL, // XenBusIo.Node
  351. NULL, // XenBusIo.Backend
  352. },
  353. NULL, // Dev
  354. NULL // DevicePath
  355. };