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