4 Copyright (c) 2006 - 2011, 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
;
48 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
49 // it is a legal Device Path Node for this bus driver's children.
51 if (RemainingDevicePath
!= NULL
) {
53 // Check if RemainingDevicePath is the End of Device Path Node,
54 // if yes, go on checking other conditions
56 if (!IsDevicePathEnd (RemainingDevicePath
)) {
58 // If RemainingDevicePath isn't the End of Device Path Node,
59 // check its validation
61 if (RemainingDevicePath
->Type
!= HARDWARE_DEVICE_PATH
||
62 RemainingDevicePath
->SubType
!= HW_VENDOR_DP
||
63 DevicePathNodeLength(RemainingDevicePath
) != sizeof(EMU_VENDOR_DEVICE_PATH_NODE
)) {
64 return EFI_UNSUPPORTED
;
70 // Open the IO Abstraction(s) needed to perform the supported test
72 Status
= gBS
->OpenProtocol (
74 &gEmuThunkProtocolGuid
,
76 This
->DriverBindingHandle
,
78 EFI_OPEN_PROTOCOL_BY_DRIVER
80 if (Status
== EFI_ALREADY_STARTED
) {
84 if (EFI_ERROR (Status
)) {
89 // Close the I/O Abstraction(s) used to perform the supported test
93 &gEmuThunkProtocolGuid
,
94 This
->DriverBindingHandle
,
99 // Open the EFI Device Path protocol needed to perform the supported test
101 Status
= gBS
->OpenProtocol (
103 &gEfiDevicePathProtocolGuid
,
104 (VOID
**)&ParentDevicePath
,
105 This
->DriverBindingHandle
,
107 EFI_OPEN_PROTOCOL_BY_DRIVER
109 if (Status
== EFI_ALREADY_STARTED
) {
113 if (EFI_ERROR (Status
)) {
119 // Close protocol, don't use device path protocol in the Support() function
123 &gEfiDevicePathProtocolGuid
,
124 This
->DriverBindingHandle
,
134 EmuBusDriverBindingStart (
135 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
136 IN EFI_HANDLE ControllerHandle
,
137 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
141 EFI_STATUS InstallStatus
;
142 EMU_THUNK_PROTOCOL
*EmuThunk
;
143 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
144 EMU_IO_DEVICE
*EmuDevice
;
145 EMU_BUS_DEVICE
*EmuBusDevice
;
146 EMU_IO_THUNK_PROTOCOL
*EmuIoThunk
;
147 UINT16 ComponentName
[512];
148 EMU_VENDOR_DEVICE_PATH_NODE
*Node
;
149 BOOLEAN CreateDevice
;
151 InstallStatus
= EFI_UNSUPPORTED
;
152 Status
= EFI_UNSUPPORTED
;
155 // Grab the protocols we need
157 Status
= gBS
->OpenProtocol (
159 &gEfiDevicePathProtocolGuid
,
160 (VOID
**)&ParentDevicePath
,
161 This
->DriverBindingHandle
,
163 EFI_OPEN_PROTOCOL_BY_DRIVER
165 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
169 Status
= gBS
->OpenProtocol (
171 &gEmuThunkProtocolGuid
,
173 This
->DriverBindingHandle
,
175 EFI_OPEN_PROTOCOL_BY_DRIVER
177 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
181 if (Status
!= EFI_ALREADY_STARTED
) {
182 EmuBusDevice
= AllocatePool (sizeof (EMU_BUS_DEVICE
));
183 if (EmuBusDevice
== NULL
) {
184 return EFI_OUT_OF_RESOURCES
;
187 EmuBusDevice
->Signature
= EMU_BUS_DEVICE_SIGNATURE
;
188 EmuBusDevice
->ControllerNameTable
= NULL
;
192 gEmuBusDriverComponentName
.SupportedLanguages
,
193 &EmuBusDevice
->ControllerNameTable
,
194 L
"Emulator Bus Controller",
199 gEmuBusDriverComponentName2
.SupportedLanguages
,
200 &EmuBusDevice
->ControllerNameTable
,
201 L
"Emulator Bus Controller",
206 Status
= gBS
->InstallMultipleProtocolInterfaces (
208 &gEfiCallerIdGuid
, EmuBusDevice
,
211 if (EFI_ERROR (Status
)) {
212 FreeUnicodeStringTable (EmuBusDevice
->ControllerNameTable
);
213 gBS
->FreePool (EmuBusDevice
);
219 for (Status
= EFI_SUCCESS
, EmuIoThunk
= NULL
; !EFI_ERROR (Status
); ) {
220 Status
= EmuThunk
->GetNextProtocol (TRUE
, &EmuIoThunk
);
221 if (EFI_ERROR (Status
)) {
226 if (RemainingDevicePath
!= NULL
) {
227 CreateDevice
= FALSE
;
229 // Check if RemainingDevicePath is the End of Device Path Node,
230 // if yes, don't create any child device
232 if (!IsDevicePathEnd (RemainingDevicePath
)) {
234 // If RemainingDevicePath isn't the End of Device Path Node,
235 // check its validation
237 Node
= (EMU_VENDOR_DEVICE_PATH_NODE
*) RemainingDevicePath
;
238 if (Node
->VendorDevicePath
.Header
.Type
== HARDWARE_DEVICE_PATH
&&
239 Node
->VendorDevicePath
.Header
.SubType
== HW_VENDOR_DP
&&
240 DevicePathNodeLength (&Node
->VendorDevicePath
.Header
) == sizeof (EMU_VENDOR_DEVICE_PATH_NODE
)
242 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, EmuIoThunk
->Protocol
) && Node
->Instance
== EmuIoThunk
->Instance
) {
251 // Allocate instance structure, and fill in parent information.
253 EmuDevice
= AllocatePool (sizeof (EMU_IO_DEVICE
));
254 if (EmuDevice
== NULL
) {
255 return EFI_OUT_OF_RESOURCES
;
258 EmuDevice
->Handle
= NULL
;
259 EmuDevice
->ControllerHandle
= ControllerHandle
;
260 EmuDevice
->ParentDevicePath
= ParentDevicePath
;
261 CopyMem (&EmuDevice
->EmuIoThunk
, EmuIoThunk
, sizeof (EMU_IO_THUNK_PROTOCOL
));
263 EmuDevice
->ControllerNameTable
= NULL
;
265 StrnCpy (ComponentName
, EmuIoThunk
->ConfigString
, sizeof (ComponentName
)/sizeof (CHAR16
));
267 EmuDevice
->DevicePath
= EmuBusCreateDevicePath (
269 EmuIoThunk
->Protocol
,
272 if (EmuDevice
->DevicePath
== NULL
) {
273 gBS
->FreePool (EmuDevice
);
274 return EFI_OUT_OF_RESOURCES
;
279 gEmuBusDriverComponentName
.SupportedLanguages
,
280 &EmuDevice
->ControllerNameTable
,
284 EmuDevice
->Signature
= EMU_IO_DEVICE_SIGNATURE
;
286 InstallStatus
= gBS
->InstallMultipleProtocolInterfaces (
288 &gEfiDevicePathProtocolGuid
, EmuDevice
->DevicePath
,
289 &gEmuIoThunkProtocolGuid
, &EmuDevice
->EmuIoThunk
,
292 if (EFI_ERROR (InstallStatus
)) {
293 FreeUnicodeStringTable (EmuDevice
->ControllerNameTable
);
294 gBS
->FreePool (EmuDevice
);
297 // Open For Child Device
299 Status
= gBS
->OpenProtocol (
301 &gEmuThunkProtocolGuid
,
303 This
->DriverBindingHandle
,
305 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
307 if (!EFI_ERROR (Status
)) {
308 InstallStatus
= EFI_SUCCESS
;
314 return InstallStatus
;
320 EmuBusDriverBindingStop (
321 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
322 IN EFI_HANDLE ControllerHandle
,
323 IN UINTN NumberOfChildren
,
324 IN EFI_HANDLE
*ChildHandleBuffer
329 BOOLEAN AllChildrenStopped
;
330 EMU_IO_THUNK_PROTOCOL
*EmuIoThunk
;
331 EMU_BUS_DEVICE
*EmuBusDevice
;
332 EMU_IO_DEVICE
*EmuDevice
;
333 EMU_THUNK_PROTOCOL
*EmuThunk
;
336 // Complete all outstanding transactions to Controller.
337 // Don't allow any new transaction to Controller to be started.
340 if (NumberOfChildren
== 0) {
342 // Close the bus driver
344 Status
= gBS
->OpenProtocol (
347 (VOID
**)&EmuBusDevice
,
348 This
->DriverBindingHandle
,
350 EFI_OPEN_PROTOCOL_GET_PROTOCOL
352 if (EFI_ERROR (Status
)) {
356 gBS
->UninstallMultipleProtocolInterfaces (
358 &gEfiCallerIdGuid
, EmuBusDevice
,
362 FreeUnicodeStringTable (EmuBusDevice
->ControllerNameTable
);
364 gBS
->FreePool (EmuBusDevice
);
368 &gEmuThunkProtocolGuid
,
369 This
->DriverBindingHandle
,
375 &gEfiDevicePathProtocolGuid
,
376 This
->DriverBindingHandle
,
382 AllChildrenStopped
= TRUE
;
384 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
386 Status
= gBS
->OpenProtocol (
387 ChildHandleBuffer
[Index
],
388 &gEmuIoThunkProtocolGuid
,
389 (VOID
**)&EmuIoThunk
,
390 This
->DriverBindingHandle
,
392 EFI_OPEN_PROTOCOL_GET_PROTOCOL
394 if (!EFI_ERROR (Status
)) {
395 EmuDevice
= EMU_IO_DEVICE_FROM_THIS (EmuIoThunk
);
397 Status
= gBS
->CloseProtocol (
399 &gEmuThunkProtocolGuid
,
400 This
->DriverBindingHandle
,
404 Status
= gBS
->UninstallMultipleProtocolInterfaces (
406 &gEfiDevicePathProtocolGuid
, EmuDevice
->DevicePath
,
407 &gEmuIoThunkProtocolGuid
, &EmuDevice
->EmuIoThunk
,
411 if (EFI_ERROR (Status
)) {
414 &gEmuThunkProtocolGuid
,
415 (VOID
**) &EmuThunk
,
416 This
->DriverBindingHandle
,
418 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
422 // Close the child handle
424 FreeUnicodeStringTable (EmuDevice
->ControllerNameTable
);
425 FreePool (EmuDevice
);
429 if (EFI_ERROR (Status
)) {
430 AllChildrenStopped
= FALSE
;
434 if (!AllChildrenStopped
) {
435 return EFI_DEVICE_ERROR
;
445 Create a device path node using Guid and InstanceNumber and append it to
446 the passed in RootDevicePath
449 RootDevicePath - Root of the device path to return.
451 Guid - GUID to use in vendor device path node.
453 InstanceNumber - Instance number to use in the vendor device path. This
454 argument is needed to make sure each device path is unique.
458 EFI_DEVICE_PATH_PROTOCOL
461 EFI_DEVICE_PATH_PROTOCOL
*
462 EmuBusCreateDevicePath (
463 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
465 IN UINT16 InstanceNumber
468 EMU_VENDOR_DEVICE_PATH_NODE DevicePath
;
470 DevicePath
.VendorDevicePath
.Header
.Type
= HARDWARE_DEVICE_PATH
;
471 DevicePath
.VendorDevicePath
.Header
.SubType
= HW_VENDOR_DP
;
472 SetDevicePathNodeLength (&DevicePath
.VendorDevicePath
.Header
, sizeof (EMU_VENDOR_DEVICE_PATH_NODE
));
475 // The GUID defines the Class
477 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
480 // Add an instance number so we can make sure there are no Device Path
483 DevicePath
.Instance
= InstanceNumber
;
485 return AppendDevicePathNode (
487 (EFI_DEVICE_PATH_PROTOCOL
*) &DevicePath
494 The user Entry Point for module EmuBusDriver. The user code starts with this function.
496 @param[in] ImageHandle The firmware allocated handle for the EFI image.
497 @param[in] SystemTable A pointer to the EFI System Table.
499 @retval EFI_SUCCESS The entry point is executed successfully.
500 @retval other Some error occurs when executing this entry point.
505 InitializeEmuBusDriver (
506 IN EFI_HANDLE ImageHandle
,
507 IN EFI_SYSTEM_TABLE
*SystemTable
512 Status
= EfiLibInstallAllDriverProtocols (
515 &gEmuBusDriverBinding
,
517 &gEmuBusDriverComponentName
,
521 ASSERT_EFI_ERROR (Status
);