]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/XenBusDxe/XenBus.c
OvmfPkg/XenBusDxe: fix VS2010 build failures
[mirror_edk2.git] / OvmfPkg / XenBusDxe / XenBus.c
CommitLineData
86d968e0
AP
1/** @file\r
2 XenBus Bus driver implemtation.\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 Permission is hereby granted, free of charge, to any person obtaining a copy\r
18 of this source file (the "Software"), to deal in the Software without\r
19 restriction, including without limitation the rights to use, copy, modify,\r
20 merge, publish, distribute, sublicense, and/or sell copies of the Software,\r
21 and to permit persons to whom the Software is furnished to do so, subject to\r
22 the following conditions:\r
23\r
24 The above copyright notice and this permission notice shall be included in\r
25 all copies or substantial portions of the Software.\r
26\r
27 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
28 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
29 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
30 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
31 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
32 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\r
33 IN THE SOFTWARE.\r
34**/\r
35\r
36#include <Library/PrintLib.h>\r
37\r
38#include "XenBus.h"\r
39#include "GrantTable.h"\r
40#include "XenStore.h"\r
41#include "EventChannel.h"\r
42\r
43#include <IndustryStandard/Xen/io/xenbus.h>\r
44\r
45STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData;\r
46\r
47STATIC XENBUS_DEVICE_PATH gXenBusDevicePathTemplate = {\r
489c5c67
AP
48 { // Vendor\r
49 { // Vendor.Header\r
50 HARDWARE_DEVICE_PATH, // Vendor.Header.Type\r
51 HW_VENDOR_DP, // Vendor.Header.SubType\r
52 {\r
53 (UINT8) (sizeof (XENBUS_DEVICE_PATH)), // Vendor.Header.Length[0]\r
54 (UINT8) (sizeof (XENBUS_DEVICE_PATH) >> 8), // Vendor.Header.Length[1]\r
55 }\r
56 },\r
57 XENBUS_PROTOCOL_GUID, // Vendor.Guid\r
58 },\r
59 0, // Type\r
60 0 // DeviceId\r
86d968e0
AP
61};\r
62\r
63\r
64/**\r
65 Search our internal record of configured devices (not the XenStore) to\r
66 determine if the XenBus device indicated by Node is known to the system.\r
67\r
68 @param Dev The XENBUS_DEVICE instance to search for device children.\r
69 @param Node The XenStore node path for the device to find.\r
70\r
71 @return The XENBUS_PRIVATE_DATA of the found device if any, or NULL.\r
72 */\r
73STATIC\r
74XENBUS_PRIVATE_DATA *\r
75XenBusDeviceInitialized (\r
76 IN XENBUS_DEVICE *Dev,\r
77 IN CONST CHAR8 *Node\r
78 )\r
79{\r
80 LIST_ENTRY *Entry;\r
81 XENBUS_PRIVATE_DATA *Child;\r
82 XENBUS_PRIVATE_DATA *Result;\r
83\r
84 if (IsListEmpty (&Dev->ChildList)) {\r
85 return NULL;\r
86 }\r
87\r
88 Result = NULL;\r
89 for (Entry = GetFirstNode (&Dev->ChildList);\r
90 !IsNodeAtEnd (&Dev->ChildList, Entry);\r
91 Entry = GetNextNode (&Dev->ChildList, Entry)) {\r
92 Child = XENBUS_PRIVATE_DATA_FROM_LINK (Entry);\r
93 if (!AsciiStrCmp (Child->XenBusIo.Node, Node)) {\r
94 Result = Child;\r
95 break;\r
96 }\r
97 }\r
98\r
99 return (Result);\r
100}\r
101\r
102STATIC\r
103XenbusState\r
104XenBusReadDriverState (\r
105 IN CONST CHAR8 *Path\r
106 )\r
107{\r
108 XenbusState State;\r
109 CHAR8 *Ptr = NULL;\r
110 XENSTORE_STATUS Status;\r
111\r
112 Status = XenStoreRead (XST_NIL, Path, "state", NULL, (VOID **)&Ptr);\r
113 if (Status != XENSTORE_STATUS_SUCCESS) {\r
114 State = XenbusStateClosed;\r
115 } else {\r
116 State = AsciiStrDecimalToUintn (Ptr);\r
117 }\r
118\r
119 if (Ptr != NULL) {\r
120 FreePool (Ptr);\r
121 }\r
122\r
123 return State;\r
124}\r
125\r
126//\r
127// Callers should ensure that they are only one calling XenBusAddDevice.\r
128//\r
129STATIC\r
130EFI_STATUS\r
131XenBusAddDevice (\r
132 XENBUS_DEVICE *Dev,\r
133 CONST CHAR8 *Type,\r
134 CONST CHAR8 *Id)\r
135{\r
136 CHAR8 DevicePath[XENSTORE_ABS_PATH_MAX];\r
137 XENSTORE_STATUS StatusXenStore;\r
138 XENBUS_PRIVATE_DATA *Private;\r
139 EFI_STATUS Status;\r
140 XENBUS_DEVICE_PATH *TempXenBusPath;\r
141 VOID *ChildPciIo;\r
142\r
143 AsciiSPrint (DevicePath, sizeof (DevicePath),\r
144 "device/%a/%a", Type, Id);\r
145\r
146 if (XenStorePathExists (XST_NIL, DevicePath, "")) {\r
147 XENBUS_PRIVATE_DATA *Child;\r
148 enum xenbus_state State;\r
149 CHAR8 *BackendPath;\r
150\r
151 Child = XenBusDeviceInitialized (Dev, DevicePath);\r
152 if (Child != NULL) {\r
153 /*\r
154 * We are already tracking this node\r
155 */\r
156 Status = EFI_SUCCESS;\r
157 goto out;\r
158 }\r
159\r
160 State = XenBusReadDriverState (DevicePath);\r
161 if (State != XenbusStateInitialising) {\r
162 /*\r
163 * Device is not new, so ignore it. This can\r
164 * happen if a device is going away after\r
165 * switching to Closed.\r
166 */\r
167 DEBUG ((EFI_D_INFO, "XenBus: Device %a ignored. "\r
168 "State %d\n", DevicePath, State));\r
169 Status = EFI_SUCCESS;\r
170 goto out;\r
171 }\r
172\r
173 StatusXenStore = XenStoreRead (XST_NIL, DevicePath, "backend",\r
174 NULL, (VOID **) &BackendPath);\r
175 if (StatusXenStore != XENSTORE_STATUS_SUCCESS) {\r
176 DEBUG ((EFI_D_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
017a4866 185 Private->XenBusIo.DeviceId = (UINT16)AsciiStrDecimalToUintn (Id);\r
86d968e0
AP
186 Private->Dev = Dev;\r
187\r
188 TempXenBusPath = AllocateCopyPool (sizeof (XENBUS_DEVICE_PATH),\r
189 &gXenBusDevicePathTemplate);\r
190 if (!AsciiStrCmp (Private->XenBusIo.Type, "vbd")) {\r
191 TempXenBusPath->Type = XENBUS_DEVICE_PATH_TYPE_VBD;\r
192 }\r
193 TempXenBusPath->DeviceId = Private->XenBusIo.DeviceId;\r
194 Private->DevicePath = (XENBUS_DEVICE_PATH *)AppendDevicePathNode (\r
195 Dev->DevicePath,\r
196 &TempXenBusPath->Vendor.Header);\r
197 FreePool (TempXenBusPath);\r
198\r
199 InsertTailList (&Dev->ChildList, &Private->Link);\r
200\r
201 Status = gBS->InstallMultipleProtocolInterfaces (\r
202 &Private->Handle,\r
203 &gEfiDevicePathProtocolGuid, Private->DevicePath,\r
204 &gXenBusProtocolGuid, &Private->XenBusIo,\r
205 NULL);\r
206 if (EFI_ERROR (Status)) {\r
207 goto ErrorInstallProtocol;\r
208 }\r
209\r
210 Status = gBS->OpenProtocol (Dev->ControllerHandle,\r
211 &gEfiPciIoProtocolGuid,\r
212 &ChildPciIo, Dev->This->DriverBindingHandle,\r
213 Private->Handle,\r
214 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);\r
215 if (EFI_ERROR (Status)) {\r
216 DEBUG ((EFI_D_ERROR, "open by child controller fail (%r)\n",\r
217 Status));\r
218 goto ErrorOpenProtocolByChild;\r
219 }\r
220 } else {\r
221 DEBUG ((EFI_D_ERROR, "XenBus: does not exist: %a\n", DevicePath));\r
222 Status = EFI_NOT_FOUND;\r
223 }\r
224\r
225 return Status;\r
226\r
227ErrorOpenProtocolByChild:\r
228 gBS->UninstallMultipleProtocolInterfaces (\r
229 &Private->Handle,\r
230 &gEfiDevicePathProtocolGuid, Private->DevicePath,\r
231 &gXenBusProtocolGuid, &Private->XenBusIo,\r
232 NULL);\r
233ErrorInstallProtocol:\r
234 RemoveEntryList (&Private->Link);\r
235 FreePool (Private->DevicePath);\r
236 FreePool ((VOID *) Private->XenBusIo.Backend);\r
237 FreePool ((VOID *) Private->XenBusIo.Node);\r
238 FreePool ((VOID *) Private->XenBusIo.Type);\r
239 FreePool (Private);\r
240out:\r
241 return Status;\r
242}\r
243\r
244/**\r
245 Enumerate all devices of the given type on this bus.\r
246\r
247 @param Dev A XENBUS_DEVICE instance.\r
248 @param Type String indicating the device sub-tree (e.g. "vfb", "vif")\r
249 to enumerate.\r
250\r
251 Devices that are found are been initialize via XenBusAddDevice ().\r
252 XenBusAddDevice () ignores duplicate detects and ignores duplicate devices,\r
253 so it can be called unconditionally for any device found in the XenStore.\r
254 */\r
255STATIC\r
256VOID\r
257XenBusEnumerateDeviceType (\r
258 XENBUS_DEVICE *Dev,\r
259 CONST CHAR8 *Type\r
260 )\r
261{\r
262 CONST CHAR8 **Directory;\r
263 UINTN Index;\r
264 UINT32 Count;\r
265 XENSTORE_STATUS Status;\r
266\r
267 Status = XenStoreListDirectory (XST_NIL,\r
268 "device", Type,\r
269 &Count, &Directory);\r
270 if (Status != XENSTORE_STATUS_SUCCESS) {\r
271 return;\r
272 }\r
273 for (Index = 0; Index < Count; Index++) {\r
274 XenBusAddDevice (Dev, Type, Directory[Index]);\r
275 }\r
276\r
017a4866 277 FreePool ((VOID*)Directory);\r
86d968e0
AP
278}\r
279\r
280\r
281/**\r
282 Enumerate the devices on a XenBus bus and install a XenBus Protocol instance.\r
283\r
284 Caller should ensure that it is the only one to call this function. This\r
285 function cannot be called concurrently.\r
286\r
287 @param Dev A XENBUS_DEVICE instance.\r
288\r
289 @return On success, XENSTORE_STATUS_SUCCESS. Otherwise an errno value\r
290 indicating the type of failure.\r
291 */\r
292XENSTORE_STATUS\r
293XenBusEnumerateBus (\r
294 XENBUS_DEVICE *Dev\r
295 )\r
296{\r
297 CONST CHAR8 **Types;\r
298 UINTN Index;\r
299 UINT32 Count;\r
300 XENSTORE_STATUS Status;\r
301\r
302 Status = XenStoreListDirectory (XST_NIL,\r
303 "device", "",\r
304 &Count, &Types);\r
305 if (Status != XENSTORE_STATUS_SUCCESS) {\r
306 return Status;\r
307 }\r
308\r
309 for (Index = 0; Index < Count; Index++) {\r
310 XenBusEnumerateDeviceType (Dev, Types[Index]);\r
311 }\r
312\r
017a4866 313 FreePool ((VOID*)Types);\r
86d968e0
AP
314\r
315 return XENSTORE_STATUS_SUCCESS;\r
316}\r
317\r
318STATIC\r
319XENSTORE_STATUS\r
320EFIAPI\r
321XenBusSetState (\r
322 IN XENBUS_PROTOCOL *This,\r
e26a83cd 323 IN CONST XENSTORE_TRANSACTION *Transaction,\r
86d968e0
AP
324 IN enum xenbus_state NewState\r
325 )\r
326{\r
327 enum xenbus_state CurrentState;\r
328 XENSTORE_STATUS Status;\r
329 CHAR8 *Temp;\r
330\r
331 DEBUG ((EFI_D_INFO, "XenBus: Set state to %d\n", NewState));\r
332\r
333 Status = XenStoreRead (Transaction, This->Node, "state", NULL, (VOID **)&Temp);\r
334 if (Status != XENSTORE_STATUS_SUCCESS) {\r
335 goto Out;\r
336 }\r
337 CurrentState = AsciiStrDecimalToUintn (Temp);\r
338 FreePool (Temp);\r
339 if (CurrentState == NewState) {\r
340 goto Out;\r
341 }\r
342\r
343 do {\r
344 Status = XenStoreSPrint (Transaction, This->Node, "state", "%d", NewState);\r
345 } while (Status == XENSTORE_STATUS_EAGAIN);\r
346 if (Status != XENSTORE_STATUS_SUCCESS) {\r
347 DEBUG ((EFI_D_ERROR, "XenBus: failed to write new state\n"));\r
348 goto Out;\r
349 }\r
350 DEBUG ((EFI_D_INFO, "XenBus: Set state to %d, done\n", NewState));\r
351\r
352Out:\r
353 return Status;\r
354}\r
355\r
356STATIC XENBUS_PRIVATE_DATA gXenBusPrivateData = {\r
43be9f4c
AP
357 XENBUS_PRIVATE_DATA_SIGNATURE, // Signature\r
358 { NULL, NULL }, // Link\r
359 NULL, // Handle\r
360 { // XenBusIo\r
361 XenBusXenStoreRead, // XenBusIo.XsRead\r
362 XenBusXenStoreBackendRead, // XenBusIo.XsBackendRead\r
363 XenBusXenStoreSPrint, // XenBusIo.XsPrintf\r
364 XenBusXenStoreRemove, // XenBusIo.XsRemove\r
365 XenBusXenStoreTransactionStart, // XenBusIo.XsTransactionStart\r
366 XenBusXenStoreTransactionEnd, // XenBusIo.XsTransactionEnd\r
367 XenBusSetState, // XenBusIo.SetState\r
368 XenBusGrantAccess, // XenBusIo.GrantAccess\r
369 XenBusGrantEndAccess, // XenBusIo.GrantEndAccess\r
370 XenBusEventChannelAllocate, // XenBusIo.EventChannelAllocate\r
371 XenBusEventChannelNotify, // XenBusIo.EventChannelNotify\r
372 XenBusEventChannelClose, // XenBusIo.EventChannelClose\r
373 XenBusRegisterWatch, // XenBusIo.RegisterWatch\r
374 XenBusRegisterWatchBackend, // XenBusIo.RegisterWatchBackend\r
375 XenBusUnregisterWatch, // XenBusIo.UnregisterWatch\r
376 XenBusWaitForWatch, // XenBusIo.WaitForWatch\r
377\r
378 NULL, // XenBusIo.Type\r
379 0, // XenBusIo.DeviceId\r
380 NULL, // XenBusIo.Node\r
381 NULL, // XenBusIo.Backend\r
382 },\r
383\r
384 NULL, // Dev\r
385 NULL // DevicePath\r
86d968e0 386};\r