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 Status
= EFI_UNSUPPORTED
;
154 // Grab the protocols we need
156 Status
= gBS
->OpenProtocol (
158 &gEfiDevicePathProtocolGuid
,
159 (VOID
**)&ParentDevicePath
,
160 This
->DriverBindingHandle
,
162 EFI_OPEN_PROTOCOL_BY_DRIVER
164 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
168 Status
= gBS
->OpenProtocol (
170 &gEmuThunkProtocolGuid
,
172 This
->DriverBindingHandle
,
174 EFI_OPEN_PROTOCOL_BY_DRIVER
176 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
180 if (Status
!= EFI_ALREADY_STARTED
) {
181 EmuBusDevice
= AllocatePool (sizeof (EMU_BUS_DEVICE
));
182 if (EmuBusDevice
== NULL
) {
183 return EFI_OUT_OF_RESOURCES
;
186 EmuBusDevice
->Signature
= EMU_BUS_DEVICE_SIGNATURE
;
187 EmuBusDevice
->ControllerNameTable
= NULL
;
191 gEmuBusDriverComponentName
.SupportedLanguages
,
192 &EmuBusDevice
->ControllerNameTable
,
193 L
"InOsEmu Bus Controller",
198 gEmuBusDriverComponentName2
.SupportedLanguages
,
199 &EmuBusDevice
->ControllerNameTable
,
200 L
"InOsEmu Bus Controller",
205 Status
= gBS
->InstallMultipleProtocolInterfaces (
207 &gEfiCallerIdGuid
, EmuBusDevice
,
210 if (EFI_ERROR (Status
)) {
211 FreeUnicodeStringTable (EmuBusDevice
->ControllerNameTable
);
212 gBS
->FreePool (EmuBusDevice
);
218 for (Status
= EFI_SUCCESS
, EmuIoThunk
= NULL
; !EFI_ERROR (Status
); ) {
219 Status
= EmuThunk
->GetNextProtocol (TRUE
, &EmuIoThunk
);
220 if (EFI_ERROR (Status
)) {
225 if (RemainingDevicePath
!= NULL
) {
226 CreateDevice
= FALSE
;
228 // Check if RemainingDevicePath is the End of Device Path Node,
229 // if yes, don't create any child device
231 if (!IsDevicePathEnd (RemainingDevicePath
)) {
233 // If RemainingDevicePath isn't the End of Device Path Node,
234 // check its validation
236 Node
= (EMU_VENDOR_DEVICE_PATH_NODE
*) RemainingDevicePath
;
237 if (Node
->VendorDevicePath
.Header
.Type
== HARDWARE_DEVICE_PATH
&&
238 Node
->VendorDevicePath
.Header
.SubType
== HW_VENDOR_DP
&&
239 DevicePathNodeLength (&Node
->VendorDevicePath
.Header
) == sizeof (EMU_VENDOR_DEVICE_PATH_NODE
)
241 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, EmuIoThunk
->Protocol
) && Node
->Instance
== EmuIoThunk
->Instance
) {
250 // Allocate instance structure, and fill in parent information.
252 EmuDevice
= AllocatePool (sizeof (EMU_IO_DEVICE
));
253 if (EmuDevice
== NULL
) {
254 return EFI_OUT_OF_RESOURCES
;
257 EmuDevice
->Handle
= NULL
;
258 EmuDevice
->ControllerHandle
= ControllerHandle
;
259 EmuDevice
->ParentDevicePath
= ParentDevicePath
;
260 CopyMem (&EmuDevice
->EmuIoThunk
, EmuIoThunk
, sizeof (EMU_IO_THUNK_PROTOCOL
));
262 EmuDevice
->ControllerNameTable
= NULL
;
264 StrnCpy (ComponentName
, EmuIoThunk
->ConfigString
, sizeof (ComponentName
)/sizeof (CHAR16
));
266 EmuDevice
->DevicePath
= EmuBusCreateDevicePath (
268 EmuIoThunk
->Protocol
,
271 if (EmuDevice
->DevicePath
== NULL
) {
272 gBS
->FreePool (EmuDevice
);
273 return EFI_OUT_OF_RESOURCES
;
278 gEmuBusDriverComponentName
.SupportedLanguages
,
279 &EmuDevice
->ControllerNameTable
,
283 EmuDevice
->Signature
= EMU_IO_DEVICE_SIGNATURE
;
285 InstallStatus
= gBS
->InstallMultipleProtocolInterfaces (
287 &gEfiDevicePathProtocolGuid
, EmuDevice
->DevicePath
,
288 &gEmuIoThunkProtocolGuid
, &EmuDevice
->EmuIoThunk
,
291 if (EFI_ERROR (InstallStatus
)) {
292 FreeUnicodeStringTable (EmuDevice
->ControllerNameTable
);
293 gBS
->FreePool (EmuDevice
);
296 // Open For Child Device
298 Status
= gBS
->OpenProtocol (
300 &gEmuThunkProtocolGuid
,
302 This
->DriverBindingHandle
,
304 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
306 if (!EFI_ERROR (Status
)) {
307 InstallStatus
= EFI_SUCCESS
;
313 return InstallStatus
;
319 EmuBusDriverBindingStop (
320 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
321 IN EFI_HANDLE ControllerHandle
,
322 IN UINTN NumberOfChildren
,
323 IN EFI_HANDLE
*ChildHandleBuffer
328 BOOLEAN AllChildrenStopped
;
329 EMU_IO_THUNK_PROTOCOL
*EmuIoThunk
;
330 EMU_BUS_DEVICE
*EmuBusDevice
;
331 EMU_IO_DEVICE
*EmuDevice
;
332 EMU_THUNK_PROTOCOL
*EmuThunk
;
335 // Complete all outstanding transactions to Controller.
336 // Don't allow any new transaction to Controller to be started.
339 if (NumberOfChildren
== 0) {
341 // Close the bus driver
343 Status
= gBS
->OpenProtocol (
346 (VOID
**)&EmuBusDevice
,
347 This
->DriverBindingHandle
,
349 EFI_OPEN_PROTOCOL_GET_PROTOCOL
351 if (EFI_ERROR (Status
)) {
355 gBS
->UninstallMultipleProtocolInterfaces (
357 &gEfiCallerIdGuid
, EmuBusDevice
,
361 FreeUnicodeStringTable (EmuBusDevice
->ControllerNameTable
);
363 gBS
->FreePool (EmuBusDevice
);
367 &gEmuThunkProtocolGuid
,
368 This
->DriverBindingHandle
,
374 &gEfiDevicePathProtocolGuid
,
375 This
->DriverBindingHandle
,
381 AllChildrenStopped
= TRUE
;
383 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
385 Status
= gBS
->OpenProtocol (
386 ChildHandleBuffer
[Index
],
387 &gEmuIoThunkProtocolGuid
,
388 (VOID
**)&EmuIoThunk
,
389 This
->DriverBindingHandle
,
391 EFI_OPEN_PROTOCOL_GET_PROTOCOL
393 if (!EFI_ERROR (Status
)) {
394 EmuDevice
= EMU_IO_DEVICE_FROM_THIS (EmuIoThunk
);
396 Status
= gBS
->CloseProtocol (
398 &gEmuThunkProtocolGuid
,
399 This
->DriverBindingHandle
,
403 Status
= gBS
->UninstallMultipleProtocolInterfaces (
405 &gEfiDevicePathProtocolGuid
, EmuDevice
->DevicePath
,
406 &gEmuIoThunkProtocolGuid
, EmuDevice
->EmuIoThunk
,
410 if (EFI_ERROR (Status
)) {
413 &gEmuThunkProtocolGuid
,
414 (VOID
**) &EmuThunk
,
415 This
->DriverBindingHandle
,
417 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
421 // Close the child handle
423 FreeUnicodeStringTable (EmuDevice
->ControllerNameTable
);
424 FreePool (EmuDevice
);
428 if (EFI_ERROR (Status
)) {
429 AllChildrenStopped
= FALSE
;
433 if (!AllChildrenStopped
) {
434 return EFI_DEVICE_ERROR
;
444 Create a device path node using Guid and InstanceNumber and append it to
445 the passed in RootDevicePath
448 RootDevicePath - Root of the device path to return.
450 Guid - GUID to use in vendor device path node.
452 InstanceNumber - Instance number to use in the vendor device path. This
453 argument is needed to make sure each device path is unique.
457 EFI_DEVICE_PATH_PROTOCOL
460 EFI_DEVICE_PATH_PROTOCOL
*
461 EmuBusCreateDevicePath (
462 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
464 IN UINT16 InstanceNumber
467 EMU_VENDOR_DEVICE_PATH_NODE DevicePath
;
469 DevicePath
.VendorDevicePath
.Header
.Type
= HARDWARE_DEVICE_PATH
;
470 DevicePath
.VendorDevicePath
.Header
.SubType
= HW_VENDOR_DP
;
471 SetDevicePathNodeLength (&DevicePath
.VendorDevicePath
.Header
, sizeof (EMU_VENDOR_DEVICE_PATH_NODE
));
474 // The GUID defines the Class
476 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
479 // Add an instance number so we can make sure there are no Device Path
482 DevicePath
.Instance
= InstanceNumber
;
484 return AppendDevicePathNode (
486 (EFI_DEVICE_PATH_PROTOCOL
*) &DevicePath
493 The user Entry Point for module EmuBusDriver. The user code starts with this function.
495 @param[in] ImageHandle The firmware allocated handle for the EFI image.
496 @param[in] SystemTable A pointer to the EFI System Table.
498 @retval EFI_SUCCESS The entry point is executed successfully.
499 @retval other Some error occurs when executing this entry point.
504 InitializeEmuBusDriver (
505 IN EFI_HANDLE ImageHandle
,
506 IN EFI_SYSTEM_TABLE
*SystemTable
511 Status
= EfiLibInstallAllDriverProtocols (
514 &gEmuBusDriverBinding
,
516 &gEmuBusDriverComponentName
,
520 ASSERT_EFI_ERROR (Status
);