4 Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2011, Apple Inc. All rights reserved.
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include "EmuBusDriverDxe.h"
22 // DriverBinding protocol global
24 EFI_DRIVER_BINDING_PROTOCOL gEmuBusDriverBinding
= {
25 EmuBusDriverBindingSupported
,
26 EmuBusDriverBindingStart
,
27 EmuBusDriverBindingStop
,
37 EmuBusDriverBindingSupported (
38 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
39 IN EFI_HANDLE ControllerHandle
,
40 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
44 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
45 EMU_THUNK_PROTOCOL
*EmuThunk
;
49 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
50 // it is a legal Device Path Node for this bus driver's children.
52 if (RemainingDevicePath
!= NULL
) {
54 // Check if RemainingDevicePath is the End of Device Path Node,
55 // if yes, go on checking other conditions
57 if (!IsDevicePathEnd (RemainingDevicePath
)) {
59 // If RemainingDevicePath isn't the End of Device Path Node,
60 // check its validation
62 if (RemainingDevicePath
->Type
!= HARDWARE_DEVICE_PATH
||
63 RemainingDevicePath
->SubType
!= HW_VENDOR_DP
||
64 DevicePathNodeLength(RemainingDevicePath
) != sizeof(EMU_VENDOR_DEVICE_PATH_NODE
)) {
65 return EFI_UNSUPPORTED
;
71 // Open the IO Abstraction(s) needed to perform the supported test
73 Status
= gBS
->OpenProtocol (
75 &gEmuThunkProtocolGuid
,
77 This
->DriverBindingHandle
,
79 EFI_OPEN_PROTOCOL_BY_DRIVER
81 if (Status
== EFI_ALREADY_STARTED
) {
85 if (EFI_ERROR (Status
)) {
90 // Close the I/O Abstraction(s) used to perform the supported test
94 &gEmuThunkProtocolGuid
,
95 This
->DriverBindingHandle
,
100 // Open the EFI Device Path protocol needed to perform the supported test
102 Status
= gBS
->OpenProtocol (
104 &gEfiDevicePathProtocolGuid
,
105 (VOID
**)&ParentDevicePath
,
106 This
->DriverBindingHandle
,
108 EFI_OPEN_PROTOCOL_BY_DRIVER
110 if (Status
== EFI_ALREADY_STARTED
) {
114 if (EFI_ERROR (Status
)) {
120 // Close protocol, don't use device path protocol in the Support() function
124 &gEfiDevicePathProtocolGuid
,
125 This
->DriverBindingHandle
,
135 EmuBusDriverBindingStart (
136 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
137 IN EFI_HANDLE ControllerHandle
,
138 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
142 EFI_STATUS InstallStatus
;
143 EMU_THUNK_PROTOCOL
*EmuThunk
;
144 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
145 EMU_IO_DEVICE
*EmuDevice
;
146 EMU_BUS_DEVICE
*EmuBusDevice
;
147 EMU_IO_THUNK_PROTOCOL
*EmuIoThunk
;
152 UINT16 ComponentName
[512];
153 EMU_VENDOR_DEVICE_PATH_NODE
*Node
;
154 BOOLEAN CreateDevice
;
160 Status
= EFI_UNSUPPORTED
;
163 // Grab the protocols we need
165 Status
= gBS
->OpenProtocol (
167 &gEfiDevicePathProtocolGuid
,
168 (VOID
**)&ParentDevicePath
,
169 This
->DriverBindingHandle
,
171 EFI_OPEN_PROTOCOL_BY_DRIVER
173 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
177 Status
= gBS
->OpenProtocol (
179 &gEmuThunkProtocolGuid
,
181 This
->DriverBindingHandle
,
183 EFI_OPEN_PROTOCOL_BY_DRIVER
185 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
189 if (Status
!= EFI_ALREADY_STARTED
) {
190 EmuBusDevice
= AllocatePool (sizeof (EMU_BUS_DEVICE
));
191 if (EmuBusDevice
== NULL
) {
192 return EFI_OUT_OF_RESOURCES
;
195 EmuBusDevice
->Signature
= EMU_BUS_DEVICE_SIGNATURE
;
196 EmuBusDevice
->ControllerNameTable
= NULL
;
200 gEmuBusDriverComponentName
.SupportedLanguages
,
201 &EmuBusDevice
->ControllerNameTable
,
202 L
"InOsEmu Bus Controller",
207 gEmuBusDriverComponentName2
.SupportedLanguages
,
208 &EmuBusDevice
->ControllerNameTable
,
209 L
"InOsEmu Bus Controller",
214 Status
= gBS
->InstallMultipleProtocolInterfaces (
216 &gEfiCallerIdGuid
, EmuBusDevice
,
219 if (EFI_ERROR (Status
)) {
220 FreeUnicodeStringTable (EmuBusDevice
->ControllerNameTable
);
221 gBS
->FreePool (EmuBusDevice
);
227 for (Status
= EFI_SUCCESS
, EmuIoThunk
= NULL
; !EFI_ERROR (Status
); ) {
228 Status
= EmuThunk
->GetNextProtocol (TRUE
, &EmuIoThunk
);
229 if (EFI_ERROR (Status
)) {
234 if (RemainingDevicePath
!= NULL
) {
235 CreateDevice
= FALSE
;
237 // Check if RemainingDevicePath is the End of Device Path Node,
238 // if yes, don't create any child device
240 if (!IsDevicePathEnd (RemainingDevicePath
)) {
242 // If RemainingDevicePath isn't the End of Device Path Node,
243 // check its validation
245 Node
= (EMU_VENDOR_DEVICE_PATH_NODE
*) RemainingDevicePath
;
246 if (Node
->VendorDevicePath
.Header
.Type
== HARDWARE_DEVICE_PATH
&&
247 Node
->VendorDevicePath
.Header
.SubType
== HW_VENDOR_DP
&&
248 DevicePathNodeLength (&Node
->VendorDevicePath
.Header
) == sizeof (EMU_VENDOR_DEVICE_PATH_NODE
)
250 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, EmuIoThunk
->Protocol
) && Node
->Instance
== EmuIoThunk
->Instance
) {
259 // Allocate instance structure, and fill in parent information.
261 EmuDevice
= AllocatePool (sizeof (EMU_IO_DEVICE
));
262 if (EmuDevice
== NULL
) {
263 return EFI_OUT_OF_RESOURCES
;
266 EmuDevice
->Handle
= NULL
;
267 EmuDevice
->ControllerHandle
= ControllerHandle
;
268 EmuDevice
->ParentDevicePath
= ParentDevicePath
;
269 CopyMem (&EmuDevice
->EmuIoThunk
, EmuIoThunk
, sizeof (EMU_IO_THUNK_PROTOCOL
));
271 EmuDevice
->ControllerNameTable
= NULL
;
273 StrnCpy (ComponentName
, EmuIoThunk
->ConfigString
, sizeof (ComponentName
)/sizeof (CHAR16
));
275 EmuDevice
->DevicePath
= EmuBusCreateDevicePath (
277 EmuIoThunk
->Protocol
,
280 if (EmuDevice
->DevicePath
== NULL
) {
281 gBS
->FreePool (EmuDevice
);
282 return EFI_OUT_OF_RESOURCES
;
287 gEmuBusDriverComponentName
.SupportedLanguages
,
288 &EmuDevice
->ControllerNameTable
,
292 EmuDevice
->Signature
= EMU_IO_DEVICE_SIGNATURE
;
294 InstallStatus
= gBS
->InstallMultipleProtocolInterfaces (
296 &gEfiDevicePathProtocolGuid
, EmuDevice
->DevicePath
,
297 &gEmuIoThunkProtocolGuid
, &EmuDevice
->EmuIoThunk
,
300 if (EFI_ERROR (InstallStatus
)) {
301 FreeUnicodeStringTable (EmuDevice
->ControllerNameTable
);
302 gBS
->FreePool (EmuDevice
);
305 // Open For Child Device
307 Status
= gBS
->OpenProtocol (
309 &gEmuThunkProtocolGuid
,
311 This
->DriverBindingHandle
,
313 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
315 if (!EFI_ERROR (Status
)) {
316 InstallStatus
= EFI_SUCCESS
;
322 return InstallStatus
;
328 EmuBusDriverBindingStop (
329 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
330 IN EFI_HANDLE ControllerHandle
,
331 IN UINTN NumberOfChildren
,
332 IN EFI_HANDLE
*ChildHandleBuffer
337 BOOLEAN AllChildrenStopped
;
338 EMU_IO_THUNK_PROTOCOL
*EmuIoThunk
;
339 EMU_BUS_DEVICE
*EmuBusDevice
;
340 EMU_IO_DEVICE
*EmuDevice
;
341 EMU_THUNK_PROTOCOL
*EmuThunk
;
344 // Complete all outstanding transactions to Controller.
345 // Don't allow any new transaction to Controller to be started.
348 if (NumberOfChildren
== 0) {
350 // Close the bus driver
352 Status
= gBS
->OpenProtocol (
355 (VOID
**)&EmuBusDevice
,
356 This
->DriverBindingHandle
,
358 EFI_OPEN_PROTOCOL_GET_PROTOCOL
360 if (EFI_ERROR (Status
)) {
364 gBS
->UninstallMultipleProtocolInterfaces (
366 &gEfiCallerIdGuid
, EmuBusDevice
,
370 FreeUnicodeStringTable (EmuBusDevice
->ControllerNameTable
);
372 gBS
->FreePool (EmuBusDevice
);
376 &gEmuThunkProtocolGuid
,
377 This
->DriverBindingHandle
,
383 &gEfiDevicePathProtocolGuid
,
384 This
->DriverBindingHandle
,
390 AllChildrenStopped
= TRUE
;
392 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
394 Status
= gBS
->OpenProtocol (
395 ChildHandleBuffer
[Index
],
396 &gEmuIoThunkProtocolGuid
,
397 (VOID
**)&EmuIoThunk
,
398 This
->DriverBindingHandle
,
400 EFI_OPEN_PROTOCOL_GET_PROTOCOL
402 if (!EFI_ERROR (Status
)) {
403 EmuDevice
= EMU_IO_DEVICE_FROM_THIS (EmuIoThunk
);
405 Status
= gBS
->CloseProtocol (
407 &gEmuThunkProtocolGuid
,
408 This
->DriverBindingHandle
,
412 Status
= gBS
->UninstallMultipleProtocolInterfaces (
414 &gEfiDevicePathProtocolGuid
, EmuDevice
->DevicePath
,
415 &gEmuIoThunkProtocolGuid
, EmuDevice
->EmuIoThunk
,
419 if (EFI_ERROR (Status
)) {
422 &gEmuThunkProtocolGuid
,
423 (VOID
**) &EmuThunk
,
424 This
->DriverBindingHandle
,
426 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
430 // Close the child handle
432 FreeUnicodeStringTable (EmuDevice
->ControllerNameTable
);
433 FreePool (EmuDevice
);
437 if (EFI_ERROR (Status
)) {
438 AllChildrenStopped
= FALSE
;
442 if (!AllChildrenStopped
) {
443 return EFI_DEVICE_ERROR
;
453 Create a device path node using Guid and InstanceNumber and append it to
454 the passed in RootDevicePath
457 RootDevicePath - Root of the device path to return.
459 Guid - GUID to use in vendor device path node.
461 InstanceNumber - Instance number to use in the vendor device path. This
462 argument is needed to make sure each device path is unique.
466 EFI_DEVICE_PATH_PROTOCOL
469 EFI_DEVICE_PATH_PROTOCOL
*
470 EmuBusCreateDevicePath (
471 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
473 IN UINT16 InstanceNumber
476 EMU_VENDOR_DEVICE_PATH_NODE DevicePath
;
478 DevicePath
.VendorDevicePath
.Header
.Type
= HARDWARE_DEVICE_PATH
;
479 DevicePath
.VendorDevicePath
.Header
.SubType
= HW_VENDOR_DP
;
480 SetDevicePathNodeLength (&DevicePath
.VendorDevicePath
.Header
, sizeof (EMU_VENDOR_DEVICE_PATH_NODE
));
483 // The GUID defines the Class
485 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
488 // Add an instance number so we can make sure there are no Device Path
491 DevicePath
.Instance
= InstanceNumber
;
493 return AppendDevicePathNode (
495 (EFI_DEVICE_PATH_PROTOCOL
*) &DevicePath
502 The user Entry Point for module EmuBusDriver. The user code starts with this function.
504 @param[in] ImageHandle The firmware allocated handle for the EFI image.
505 @param[in] SystemTable A pointer to the EFI System Table.
507 @retval EFI_SUCCESS The entry point is executed successfully.
508 @retval other Some error occurs when executing this entry point.
513 InitializeEmuBusDriver (
514 IN EFI_HANDLE ImageHandle
,
515 IN EFI_SYSTEM_TABLE
*SystemTable
520 Status
= EfiLibInstallAllDriverProtocols (
523 &gEmuBusDriverBinding
,
525 &gEmuBusDriverComponentName
,
529 ASSERT_EFI_ERROR (Status
);