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