]> git.proxmox.com Git - mirror_edk2.git/blame - EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c
EmulatorPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / EmulatorPkg / EmuBusDriverDxe / EmuBusDriverDxe.c
CommitLineData
949f388f 1/** @file\r
2 Emu Bus driver\r
224e1333 3\r
4Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
949f388f 5Portions copyright (c) 2011, Apple Inc. All rights reserved.\r
e3ba31da 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
949f388f 7\r
8\r
9**/\r
10\r
11#include "EmuBusDriverDxe.h"\r
12\r
13\r
14\r
15//\r
16// DriverBinding protocol global\r
17//\r
18EFI_DRIVER_BINDING_PROTOCOL gEmuBusDriverBinding = {\r
19 EmuBusDriverBindingSupported,\r
20 EmuBusDriverBindingStart,\r
21 EmuBusDriverBindingStop,\r
22 0xa,\r
23 NULL,\r
24 NULL\r
25};\r
26\r
27\r
28\r
29EFI_STATUS\r
30EFIAPI\r
31EmuBusDriverBindingSupported (\r
32 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
33 IN EFI_HANDLE ControllerHandle,\r
34 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
35 )\r
36{\r
37 EFI_STATUS Status;\r
38 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
39 EMU_THUNK_PROTOCOL *EmuThunk;\r
949f388f 40\r
41 //\r
42 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure\r
43 // it is a legal Device Path Node for this bus driver's children.\r
44 //\r
45 if (RemainingDevicePath != NULL) {\r
46 //\r
d18d8a1d 47 // Check if RemainingDevicePath is the End of Device Path Node,\r
949f388f 48 // if yes, go on checking other conditions\r
49 //\r
50 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
51 //\r
52 // If RemainingDevicePath isn't the End of Device Path Node,\r
53 // check its validation\r
54 //\r
55 if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||\r
56 RemainingDevicePath->SubType != HW_VENDOR_DP ||\r
57 DevicePathNodeLength(RemainingDevicePath) != sizeof(EMU_VENDOR_DEVICE_PATH_NODE)) {\r
58 return EFI_UNSUPPORTED;\r
59 }\r
60 }\r
61 }\r
d18d8a1d 62\r
949f388f 63 //\r
64 // Open the IO Abstraction(s) needed to perform the supported test\r
65 //\r
66 Status = gBS->OpenProtocol (\r
67 ControllerHandle,\r
68 &gEmuThunkProtocolGuid,\r
69 (VOID **)&EmuThunk ,\r
70 This->DriverBindingHandle,\r
71 ControllerHandle,\r
72 EFI_OPEN_PROTOCOL_BY_DRIVER\r
73 );\r
74 if (Status == EFI_ALREADY_STARTED) {\r
75 return EFI_SUCCESS;\r
76 }\r
77\r
78 if (EFI_ERROR (Status)) {\r
79 return Status;\r
80 }\r
81\r
82 //\r
83 // Close the I/O Abstraction(s) used to perform the supported test\r
84 //\r
85 gBS->CloseProtocol (\r
86 ControllerHandle,\r
87 &gEmuThunkProtocolGuid,\r
88 This->DriverBindingHandle,\r
89 ControllerHandle\r
90 );\r
91\r
92 //\r
93 // Open the EFI Device Path protocol needed to perform the supported test\r
94 //\r
95 Status = gBS->OpenProtocol (\r
96 ControllerHandle,\r
97 &gEfiDevicePathProtocolGuid,\r
98 (VOID **)&ParentDevicePath,\r
99 This->DriverBindingHandle,\r
100 ControllerHandle,\r
101 EFI_OPEN_PROTOCOL_BY_DRIVER\r
102 );\r
103 if (Status == EFI_ALREADY_STARTED) {\r
104 return EFI_SUCCESS;\r
105 }\r
106\r
107 if (EFI_ERROR (Status)) {\r
108 return Status;\r
109 }\r
110\r
111\r
112 //\r
113 // Close protocol, don't use device path protocol in the Support() function\r
114 //\r
115 gBS->CloseProtocol (\r
116 ControllerHandle,\r
117 &gEfiDevicePathProtocolGuid,\r
118 This->DriverBindingHandle,\r
119 ControllerHandle\r
120 );\r
121\r
122 return Status;\r
123}\r
124\r
125\r
126EFI_STATUS\r
127EFIAPI\r
128EmuBusDriverBindingStart (\r
129 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
130 IN EFI_HANDLE ControllerHandle,\r
131 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
132 )\r
133{\r
134 EFI_STATUS Status;\r
135 EFI_STATUS InstallStatus;\r
136 EMU_THUNK_PROTOCOL *EmuThunk;\r
137 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
138 EMU_IO_DEVICE *EmuDevice;\r
139 EMU_BUS_DEVICE *EmuBusDevice;\r
140 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;\r
949f388f 141 UINT16 ComponentName[512];\r
142 EMU_VENDOR_DEVICE_PATH_NODE *Node;\r
143 BOOLEAN CreateDevice;\r
949f388f 144\r
54e0b04c 145 InstallStatus = EFI_UNSUPPORTED;\r
949f388f 146 Status = EFI_UNSUPPORTED;\r
147\r
148 //\r
149 // Grab the protocols we need\r
150 //\r
151 Status = gBS->OpenProtocol (\r
152 ControllerHandle,\r
153 &gEfiDevicePathProtocolGuid,\r
154 (VOID **)&ParentDevicePath,\r
155 This->DriverBindingHandle,\r
156 ControllerHandle,\r
157 EFI_OPEN_PROTOCOL_BY_DRIVER\r
158 );\r
159 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
160 return Status;\r
161 }\r
162\r
163 Status = gBS->OpenProtocol (\r
164 ControllerHandle,\r
165 &gEmuThunkProtocolGuid,\r
166 (VOID **)&EmuThunk,\r
167 This->DriverBindingHandle,\r
168 ControllerHandle,\r
169 EFI_OPEN_PROTOCOL_BY_DRIVER\r
170 );\r
171 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
172 return Status;\r
173 }\r
174\r
175 if (Status != EFI_ALREADY_STARTED) {\r
176 EmuBusDevice = AllocatePool (sizeof (EMU_BUS_DEVICE));\r
177 if (EmuBusDevice == NULL) {\r
178 return EFI_OUT_OF_RESOURCES;\r
179 }\r
180\r
181 EmuBusDevice->Signature = EMU_BUS_DEVICE_SIGNATURE;\r
182 EmuBusDevice->ControllerNameTable = NULL;\r
183\r
184 AddUnicodeString2 (\r
185 "eng",\r
186 gEmuBusDriverComponentName.SupportedLanguages,\r
187 &EmuBusDevice->ControllerNameTable,\r
bb89ec1a 188 L"Emulator Bus Controller",\r
949f388f 189 TRUE\r
190 );\r
191 AddUnicodeString2 (\r
192 "en",\r
193 gEmuBusDriverComponentName2.SupportedLanguages,\r
194 &EmuBusDevice->ControllerNameTable,\r
bb89ec1a 195 L"Emulator Bus Controller",\r
949f388f 196 FALSE\r
197 );\r
198\r
199\r
200 Status = gBS->InstallMultipleProtocolInterfaces (\r
201 &ControllerHandle,\r
202 &gEfiCallerIdGuid, EmuBusDevice,\r
203 NULL\r
204 );\r
205 if (EFI_ERROR (Status)) {\r
206 FreeUnicodeStringTable (EmuBusDevice->ControllerNameTable);\r
207 gBS->FreePool (EmuBusDevice);\r
208 return Status;\r
209 }\r
210 }\r
211\r
212\r
213 for (Status = EFI_SUCCESS, EmuIoThunk = NULL; !EFI_ERROR (Status); ) {\r
214 Status = EmuThunk->GetNextProtocol (TRUE, &EmuIoThunk);\r
215 if (EFI_ERROR (Status)) {\r
216 break;\r
217 }\r
218\r
219 CreateDevice = TRUE;\r
220 if (RemainingDevicePath != NULL) {\r
221 CreateDevice = FALSE;\r
222 //\r
d18d8a1d 223 // Check if RemainingDevicePath is the End of Device Path Node,\r
224 // if yes, don't create any child device\r
949f388f 225 //\r
226 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
227 //\r
228 // If RemainingDevicePath isn't the End of Device Path Node,\r
229 // check its validation\r
230 //\r
231 Node = (EMU_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;\r
232 if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&\r
233 Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&\r
234 DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (EMU_VENDOR_DEVICE_PATH_NODE)\r
235 ) {\r
236 if (CompareGuid (&Node->VendorDevicePath.Guid, EmuIoThunk->Protocol) && Node->Instance == EmuIoThunk->Instance) {\r
237 CreateDevice = TRUE;\r
238 }\r
239 }\r
240 }\r
241 }\r
242\r
243 if (CreateDevice) {\r
244 //\r
245 // Allocate instance structure, and fill in parent information.\r
246 //\r
247 EmuDevice = AllocatePool (sizeof (EMU_IO_DEVICE));\r
248 if (EmuDevice == NULL) {\r
249 return EFI_OUT_OF_RESOURCES;\r
250 }\r
251\r
252 EmuDevice->Handle = NULL;\r
253 EmuDevice->ControllerHandle = ControllerHandle;\r
254 EmuDevice->ParentDevicePath = ParentDevicePath;\r
255 CopyMem (&EmuDevice->EmuIoThunk, EmuIoThunk, sizeof (EMU_IO_THUNK_PROTOCOL));\r
d18d8a1d 256\r
949f388f 257 EmuDevice->ControllerNameTable = NULL;\r
258\r
259 StrnCpy (ComponentName, EmuIoThunk->ConfigString, sizeof (ComponentName)/sizeof (CHAR16));\r
260\r
261 EmuDevice->DevicePath = EmuBusCreateDevicePath (\r
262 ParentDevicePath,\r
263 EmuIoThunk->Protocol,\r
264 EmuIoThunk->Instance\r
265 );\r
266 if (EmuDevice->DevicePath == NULL) {\r
267 gBS->FreePool (EmuDevice);\r
268 return EFI_OUT_OF_RESOURCES;\r
269 }\r
270\r
271 AddUnicodeString (\r
272 "eng",\r
273 gEmuBusDriverComponentName.SupportedLanguages,\r
274 &EmuDevice->ControllerNameTable,\r
275 ComponentName\r
276 );\r
277\r
278 EmuDevice->Signature = EMU_IO_DEVICE_SIGNATURE;\r
279\r
280 InstallStatus = gBS->InstallMultipleProtocolInterfaces (\r
281 &EmuDevice->Handle,\r
282 &gEfiDevicePathProtocolGuid, EmuDevice->DevicePath,\r
283 &gEmuIoThunkProtocolGuid, &EmuDevice->EmuIoThunk,\r
284 NULL\r
285 );\r
286 if (EFI_ERROR (InstallStatus)) {\r
287 FreeUnicodeStringTable (EmuDevice->ControllerNameTable);\r
288 gBS->FreePool (EmuDevice);\r
289 } else {\r
290 //\r
291 // Open For Child Device\r
292 //\r
293 Status = gBS->OpenProtocol (\r
294 ControllerHandle,\r
295 &gEmuThunkProtocolGuid,\r
296 (VOID **)&EmuThunk ,\r
297 This->DriverBindingHandle,\r
298 EmuDevice->Handle,\r
299 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
300 );\r
301 if (!EFI_ERROR (Status)) {\r
302 InstallStatus = EFI_SUCCESS;\r
303 }\r
304 }\r
305 }\r
306 }\r
307\r
308 return InstallStatus;\r
309}\r
310\r
311\r
312EFI_STATUS\r
313EFIAPI\r
314EmuBusDriverBindingStop (\r
315 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
316 IN EFI_HANDLE ControllerHandle,\r
317 IN UINTN NumberOfChildren,\r
318 IN EFI_HANDLE *ChildHandleBuffer\r
319 )\r
320{\r
321 EFI_STATUS Status;\r
322 UINTN Index;\r
323 BOOLEAN AllChildrenStopped;\r
324 EMU_IO_THUNK_PROTOCOL *EmuIoThunk;\r
325 EMU_BUS_DEVICE *EmuBusDevice;\r
326 EMU_IO_DEVICE *EmuDevice;\r
327 EMU_THUNK_PROTOCOL *EmuThunk;\r
328\r
329 //\r
330 // Complete all outstanding transactions to Controller.\r
331 // Don't allow any new transaction to Controller to be started.\r
332 //\r
333\r
334 if (NumberOfChildren == 0) {\r
335 //\r
336 // Close the bus driver\r
337 //\r
338 Status = gBS->OpenProtocol (\r
339 ControllerHandle,\r
340 &gEfiCallerIdGuid,\r
341 (VOID **)&EmuBusDevice,\r
342 This->DriverBindingHandle,\r
343 ControllerHandle,\r
344 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
345 );\r
346 if (EFI_ERROR (Status)) {\r
347 return Status;\r
348 }\r
349\r
350 gBS->UninstallMultipleProtocolInterfaces (\r
351 ControllerHandle,\r
352 &gEfiCallerIdGuid, EmuBusDevice,\r
353 NULL\r
354 );\r
355\r
356 FreeUnicodeStringTable (EmuBusDevice->ControllerNameTable);\r
357\r
358 gBS->FreePool (EmuBusDevice);\r
359\r
360 gBS->CloseProtocol (\r
361 ControllerHandle,\r
362 &gEmuThunkProtocolGuid,\r
363 This->DriverBindingHandle,\r
364 ControllerHandle\r
365 );\r
366\r
367 gBS->CloseProtocol (\r
368 ControllerHandle,\r
369 &gEfiDevicePathProtocolGuid,\r
370 This->DriverBindingHandle,\r
371 ControllerHandle\r
372 );\r
373 return EFI_SUCCESS;\r
374 }\r
375\r
376 AllChildrenStopped = TRUE;\r
377\r
378 for (Index = 0; Index < NumberOfChildren; Index++) {\r
379\r
380 Status = gBS->OpenProtocol (\r
381 ChildHandleBuffer[Index],\r
382 &gEmuIoThunkProtocolGuid,\r
383 (VOID **)&EmuIoThunk,\r
384 This->DriverBindingHandle,\r
385 ControllerHandle,\r
386 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
387 );\r
388 if (!EFI_ERROR (Status)) {\r
389 EmuDevice = EMU_IO_DEVICE_FROM_THIS (EmuIoThunk);\r
390\r
391 Status = gBS->CloseProtocol (\r
392 ControllerHandle,\r
393 &gEmuThunkProtocolGuid,\r
394 This->DriverBindingHandle,\r
395 EmuDevice->Handle\r
396 );\r
397\r
398 Status = gBS->UninstallMultipleProtocolInterfaces (\r
399 EmuDevice->Handle,\r
400 &gEfiDevicePathProtocolGuid, EmuDevice->DevicePath,\r
f2a74dae 401 &gEmuIoThunkProtocolGuid, &EmuDevice->EmuIoThunk,\r
949f388f 402 NULL\r
403 );\r
404\r
405 if (EFI_ERROR (Status)) {\r
406 gBS->OpenProtocol (\r
407 ControllerHandle,\r
408 &gEmuThunkProtocolGuid,\r
409 (VOID **) &EmuThunk ,\r
410 This->DriverBindingHandle,\r
411 EmuDevice->Handle,\r
412 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
413 );\r
414 } else {\r
415 //\r
416 // Close the child handle\r
417 //\r
418 FreeUnicodeStringTable (EmuDevice->ControllerNameTable);\r
419 FreePool (EmuDevice);\r
420 }\r
421 }\r
422\r
423 if (EFI_ERROR (Status)) {\r
424 AllChildrenStopped = FALSE;\r
425 }\r
426 }\r
427\r
428 if (!AllChildrenStopped) {\r
429 return EFI_DEVICE_ERROR;\r
430 }\r
431\r
432 return EFI_SUCCESS;\r
433}\r
434\r
435\r
436/*++\r
437\r
438Routine Description:\r
439 Create a device path node using Guid and InstanceNumber and append it to\r
440 the passed in RootDevicePath\r
441\r
442Arguments:\r
443 RootDevicePath - Root of the device path to return.\r
444\r
445 Guid - GUID to use in vendor device path node.\r
446\r
447 InstanceNumber - Instance number to use in the vendor device path. This\r
448 argument is needed to make sure each device path is unique.\r
449\r
450Returns:\r
451\r
d18d8a1d 452 EFI_DEVICE_PATH_PROTOCOL\r
949f388f 453\r
454**/\r
455EFI_DEVICE_PATH_PROTOCOL *\r
456EmuBusCreateDevicePath (\r
457 IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,\r
458 IN EFI_GUID *Guid,\r
459 IN UINT16 InstanceNumber\r
460 )\r
461{\r
462 EMU_VENDOR_DEVICE_PATH_NODE DevicePath;\r
463\r
464 DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;\r
465 DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;\r
466 SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (EMU_VENDOR_DEVICE_PATH_NODE));\r
467\r
468 //\r
469 // The GUID defines the Class\r
470 //\r
471 CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));\r
472\r
473 //\r
474 // Add an instance number so we can make sure there are no Device Path\r
475 // duplication.\r
476 //\r
477 DevicePath.Instance = InstanceNumber;\r
478\r
479 return AppendDevicePathNode (\r
480 RootDevicePath,\r
481 (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath\r
482 );\r
483}\r
484\r
485\r
486\r
487/**\r
488 The user Entry Point for module EmuBusDriver. The user code starts with this function.\r
489\r
d18d8a1d 490 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
949f388f 491 @param[in] SystemTable A pointer to the EFI System Table.\r
d18d8a1d 492\r
949f388f 493 @retval EFI_SUCCESS The entry point is executed successfully.\r
494 @retval other Some error occurs when executing this entry point.\r
495\r
496**/\r
497EFI_STATUS\r
498EFIAPI\r
499InitializeEmuBusDriver (\r
500 IN EFI_HANDLE ImageHandle,\r
501 IN EFI_SYSTEM_TABLE *SystemTable\r
502 )\r
503{\r
504 EFI_STATUS Status;\r
505\r
506 Status = EfiLibInstallAllDriverProtocols (\r
507 ImageHandle,\r
508 SystemTable,\r
509 &gEmuBusDriverBinding,\r
510 ImageHandle,\r
511 &gEmuBusDriverComponentName,\r
512 NULL,\r
513 NULL\r
514 );\r
515 ASSERT_EFI_ERROR (Status);\r
516\r
517\r
518 return Status;\r
519}\r
520\r
521\r
522\r
523\r