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