]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/XenBusDxe/XenBus.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / XenBusDxe / XenBus.c
CommitLineData
86d968e0 1/** @file\r
493dde94 2 XenBus Bus driver implementation.\r
86d968e0
AP
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
34131e1b 17 SPDX-License-Identifier: MIT\r
86d968e0
AP
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
ac0a286f 29STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData;\r
86d968e0 30\r
ac0a286f 31STATIC XENBUS_DEVICE_PATH gXenBusDevicePathTemplate = {\r
489c5c67
AP
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
ac0a286f
MK
37 (UINT8)(sizeof (XENBUS_DEVICE_PATH)), // Vendor.Header.Length[0]\r
38 (UINT8)(sizeof (XENBUS_DEVICE_PATH) >> 8), // Vendor.Header.Length[1]\r
489c5c67
AP
39 }\r
40 },\r
41 XENBUS_PROTOCOL_GUID, // Vendor.Guid\r
42 },\r
43 0, // Type\r
44 0 // DeviceId\r
86d968e0
AP
45};\r
46\r
86d968e0
AP
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
ac0a286f
MK
59 IN XENBUS_DEVICE *Dev,\r
60 IN CONST CHAR8 *Node\r
86d968e0
AP
61 )\r
62{\r
ac0a286f
MK
63 LIST_ENTRY *Entry;\r
64 XENBUS_PRIVATE_DATA *Child;\r
65 XENBUS_PRIVATE_DATA *Result;\r
86d968e0
AP
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
ac0a286f
MK
74 Entry = GetNextNode (&Dev->ChildList, Entry))\r
75 {\r
86d968e0
AP
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
ac0a286f 89 IN CONST CHAR8 *Path\r
86d968e0
AP
90 )\r
91{\r
ac0a286f
MK
92 XenbusState State;\r
93 CHAR8 *Ptr = NULL;\r
94 XENSTORE_STATUS Status;\r
86d968e0
AP
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
ac0a286f
MK
116 XENBUS_DEVICE *Dev,\r
117 CONST CHAR8 *Type,\r
118 CONST CHAR8 *Id\r
119 )\r
86d968e0 120{\r
ac0a286f
MK
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
86d968e0
AP
135\r
136 if (XenStorePathExists (XST_NIL, DevicePath, "")) {\r
ac0a286f
MK
137 XENBUS_PRIVATE_DATA *Child;\r
138 enum xenbus_state State;\r
139 CHAR8 *BackendPath;\r
86d968e0
AP
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
ac0a286f
MK
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
86d968e0
AP
164 Status = EFI_SUCCESS;\r
165 goto out;\r
166 }\r
167\r
ac0a286f
MK
168 StatusXenStore = XenStoreRead (\r
169 XST_NIL,\r
170 DevicePath,\r
171 "backend",\r
172 NULL,\r
173 (VOID **)&BackendPath\r
174 );\r
86d968e0 175 if (StatusXenStore != XENSTORE_STATUS_SUCCESS) {\r
70d5086c 176 DEBUG ((DEBUG_ERROR, "xenbus: %a no backend path.\n", DevicePath));\r
86d968e0
AP
177 Status = EFI_NOT_FOUND;\r
178 goto out;\r
179 }\r
180\r
ac0a286f
MK
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
017a4866 185 Private->XenBusIo.DeviceId = (UINT16)AsciiStrDecimalToUintn (Id);\r
ac0a286f 186 Private->Dev = Dev;\r
86d968e0 187\r
ac0a286f
MK
188 TempXenBusPath = AllocateCopyPool (\r
189 sizeof (XENBUS_DEVICE_PATH),\r
190 &gXenBusDevicePathTemplate\r
191 );\r
86d968e0
AP
192 if (!AsciiStrCmp (Private->XenBusIo.Type, "vbd")) {\r
193 TempXenBusPath->Type = XENBUS_DEVICE_PATH_TYPE_VBD;\r
194 }\r
ac0a286f 195\r
86d968e0 196 TempXenBusPath->DeviceId = Private->XenBusIo.DeviceId;\r
ac0a286f
MK
197 Private->DevicePath = (XENBUS_DEVICE_PATH *)AppendDevicePathNode (\r
198 Dev->DevicePath,\r
199 &TempXenBusPath->Vendor.Header\r
200 );\r
86d968e0
AP
201 FreePool (TempXenBusPath);\r
202\r
203 InsertTailList (&Dev->ChildList, &Private->Link);\r
204\r
205 Status = gBS->InstallMultipleProtocolInterfaces (\r
ac0a286f
MK
206 &Private->Handle,\r
207 &gEfiDevicePathProtocolGuid,\r
208 Private->DevicePath,\r
209 &gXenBusProtocolGuid,\r
210 &Private->XenBusIo,\r
211 NULL\r
212 );\r
86d968e0
AP
213 if (EFI_ERROR (Status)) {\r
214 goto ErrorInstallProtocol;\r
215 }\r
216\r
ac0a286f
MK
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
86d968e0 225 if (EFI_ERROR (Status)) {\r
ac0a286f
MK
226 DEBUG ((\r
227 DEBUG_ERROR,\r
228 "open by child controller fail (%r)\n",\r
229 Status\r
230 ));\r
86d968e0
AP
231 goto ErrorOpenProtocolByChild;\r
232 }\r
233 } else {\r
70d5086c 234 DEBUG ((DEBUG_ERROR, "XenBus: does not exist: %a\n", DevicePath));\r
86d968e0
AP
235 Status = EFI_NOT_FOUND;\r
236 }\r
237\r
238 return Status;\r
239\r
240ErrorOpenProtocolByChild:\r
241 gBS->UninstallMultipleProtocolInterfaces (\r
ac0a286f
MK
242 Private->Handle,\r
243 &gEfiDevicePathProtocolGuid,\r
244 Private->DevicePath,\r
245 &gXenBusProtocolGuid,\r
246 &Private->XenBusIo,\r
247 NULL\r
248 );\r
86d968e0
AP
249ErrorInstallProtocol:\r
250 RemoveEntryList (&Private->Link);\r
251 FreePool (Private->DevicePath);\r
ac0a286f
MK
252 FreePool ((VOID *)Private->XenBusIo.Backend);\r
253 FreePool ((VOID *)Private->XenBusIo.Node);\r
254 FreePool ((VOID *)Private->XenBusIo.Type);\r
86d968e0
AP
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
ac0a286f
MK
274 XENBUS_DEVICE *Dev,\r
275 CONST CHAR8 *Type\r
86d968e0
AP
276 )\r
277{\r
ac0a286f
MK
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
86d968e0
AP
290 if (Status != XENSTORE_STATUS_SUCCESS) {\r
291 return;\r
292 }\r
ac0a286f 293\r
86d968e0
AP
294 for (Index = 0; Index < Count; Index++) {\r
295 XenBusAddDevice (Dev, Type, Directory[Index]);\r
296 }\r
297\r
ac0a286f 298 FreePool ((VOID *)Directory);\r
86d968e0
AP
299}\r
300\r
86d968e0
AP
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
ac0a286f 314 XENBUS_DEVICE *Dev\r
86d968e0
AP
315 )\r
316{\r
ac0a286f
MK
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
86d968e0
AP
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
ac0a286f 337 FreePool ((VOID *)Types);\r
86d968e0
AP
338\r
339 return XENSTORE_STATUS_SUCCESS;\r
340}\r
341\r
342STATIC\r
343XENSTORE_STATUS\r
344EFIAPI\r
345XenBusSetState (\r
ac0a286f
MK
346 IN XENBUS_PROTOCOL *This,\r
347 IN CONST XENSTORE_TRANSACTION *Transaction,\r
348 IN enum xenbus_state NewState\r
86d968e0
AP
349 )\r
350{\r
ac0a286f
MK
351 enum xenbus_state CurrentState;\r
352 XENSTORE_STATUS Status;\r
353 CHAR8 *Temp;\r
86d968e0 354\r
70d5086c 355 DEBUG ((DEBUG_INFO, "XenBus: Set state to %d\n", NewState));\r
86d968e0
AP
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
ac0a286f 361\r
86d968e0
AP
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
ac0a286f 371\r
86d968e0 372 if (Status != XENSTORE_STATUS_SUCCESS) {\r
70d5086c 373 DEBUG ((DEBUG_ERROR, "XenBus: failed to write new state\n"));\r
86d968e0
AP
374 goto Out;\r
375 }\r
ac0a286f 376\r
70d5086c 377 DEBUG ((DEBUG_INFO, "XenBus: Set state to %d, done\n", NewState));\r
86d968e0
AP
378\r
379Out:\r
380 return Status;\r
381}\r
382\r
ac0a286f 383STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData = {\r
43be9f4c
AP
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
86d968e0 413};\r