4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2011, Apple Inc. All rights reserved.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include "EmuBusDriverDxe.h"
14 // DriverBinding protocol global
16 EFI_DRIVER_BINDING_PROTOCOL gEmuBusDriverBinding
= {
17 EmuBusDriverBindingSupported
,
18 EmuBusDriverBindingStart
,
19 EmuBusDriverBindingStop
,
27 EmuBusDriverBindingSupported (
28 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
29 IN EFI_HANDLE ControllerHandle
,
30 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
34 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
35 EMU_THUNK_PROTOCOL
*EmuThunk
;
38 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
39 // it is a legal Device Path Node for this bus driver's children.
41 if (RemainingDevicePath
!= NULL
) {
43 // Check if RemainingDevicePath is the End of Device Path Node,
44 // if yes, go on checking other conditions
46 if (!IsDevicePathEnd (RemainingDevicePath
)) {
48 // If RemainingDevicePath isn't the End of Device Path Node,
49 // check its validation
51 if ((RemainingDevicePath
->Type
!= HARDWARE_DEVICE_PATH
) ||
52 (RemainingDevicePath
->SubType
!= HW_VENDOR_DP
) ||
53 (DevicePathNodeLength (RemainingDevicePath
) != sizeof (EMU_VENDOR_DEVICE_PATH_NODE
)))
55 return EFI_UNSUPPORTED
;
61 // Open the IO Abstraction(s) needed to perform the supported test
63 Status
= gBS
->OpenProtocol (
65 &gEmuThunkProtocolGuid
,
67 This
->DriverBindingHandle
,
69 EFI_OPEN_PROTOCOL_BY_DRIVER
71 if (Status
== EFI_ALREADY_STARTED
) {
75 if (EFI_ERROR (Status
)) {
80 // Close the I/O Abstraction(s) used to perform the supported test
84 &gEmuThunkProtocolGuid
,
85 This
->DriverBindingHandle
,
90 // Open the EFI Device Path protocol needed to perform the supported test
92 Status
= gBS
->OpenProtocol (
94 &gEfiDevicePathProtocolGuid
,
95 (VOID
**)&ParentDevicePath
,
96 This
->DriverBindingHandle
,
98 EFI_OPEN_PROTOCOL_BY_DRIVER
100 if (Status
== EFI_ALREADY_STARTED
) {
104 if (EFI_ERROR (Status
)) {
109 // Close protocol, don't use device path protocol in the Support() function
113 &gEfiDevicePathProtocolGuid
,
114 This
->DriverBindingHandle
,
123 EmuBusDriverBindingStart (
124 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
125 IN EFI_HANDLE ControllerHandle
,
126 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
130 EFI_STATUS InstallStatus
;
131 EMU_THUNK_PROTOCOL
*EmuThunk
;
132 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
133 EMU_IO_DEVICE
*EmuDevice
;
134 EMU_BUS_DEVICE
*EmuBusDevice
;
135 EMU_IO_THUNK_PROTOCOL
*EmuIoThunk
;
136 UINT16 ComponentName
[512];
137 EMU_VENDOR_DEVICE_PATH_NODE
*Node
;
138 BOOLEAN CreateDevice
;
140 InstallStatus
= EFI_UNSUPPORTED
;
141 Status
= EFI_UNSUPPORTED
;
144 // Grab the protocols we need
146 Status
= gBS
->OpenProtocol (
148 &gEfiDevicePathProtocolGuid
,
149 (VOID
**)&ParentDevicePath
,
150 This
->DriverBindingHandle
,
152 EFI_OPEN_PROTOCOL_BY_DRIVER
154 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
158 Status
= gBS
->OpenProtocol (
160 &gEmuThunkProtocolGuid
,
162 This
->DriverBindingHandle
,
164 EFI_OPEN_PROTOCOL_BY_DRIVER
166 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
170 if (Status
!= EFI_ALREADY_STARTED
) {
171 EmuBusDevice
= AllocatePool (sizeof (EMU_BUS_DEVICE
));
172 if (EmuBusDevice
== NULL
) {
173 return EFI_OUT_OF_RESOURCES
;
176 EmuBusDevice
->Signature
= EMU_BUS_DEVICE_SIGNATURE
;
177 EmuBusDevice
->ControllerNameTable
= NULL
;
181 gEmuBusDriverComponentName
.SupportedLanguages
,
182 &EmuBusDevice
->ControllerNameTable
,
183 L
"Emulator Bus Controller",
188 gEmuBusDriverComponentName2
.SupportedLanguages
,
189 &EmuBusDevice
->ControllerNameTable
,
190 L
"Emulator Bus Controller",
194 Status
= gBS
->InstallMultipleProtocolInterfaces (
200 if (EFI_ERROR (Status
)) {
201 FreeUnicodeStringTable (EmuBusDevice
->ControllerNameTable
);
202 gBS
->FreePool (EmuBusDevice
);
207 for (Status
= EFI_SUCCESS
, EmuIoThunk
= NULL
; !EFI_ERROR (Status
); ) {
208 Status
= EmuThunk
->GetNextProtocol (TRUE
, &EmuIoThunk
);
209 if (EFI_ERROR (Status
)) {
214 if (RemainingDevicePath
!= NULL
) {
215 CreateDevice
= FALSE
;
217 // Check if RemainingDevicePath is the End of Device Path Node,
218 // if yes, don't create any child device
220 if (!IsDevicePathEnd (RemainingDevicePath
)) {
222 // If RemainingDevicePath isn't the End of Device Path Node,
223 // check its validation
225 Node
= (EMU_VENDOR_DEVICE_PATH_NODE
*)RemainingDevicePath
;
226 if ((Node
->VendorDevicePath
.Header
.Type
== HARDWARE_DEVICE_PATH
) &&
227 (Node
->VendorDevicePath
.Header
.SubType
== HW_VENDOR_DP
) &&
228 (DevicePathNodeLength (&Node
->VendorDevicePath
.Header
) == sizeof (EMU_VENDOR_DEVICE_PATH_NODE
))
231 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, EmuIoThunk
->Protocol
) && (Node
->Instance
== EmuIoThunk
->Instance
)) {
240 // Allocate instance structure, and fill in parent information.
242 EmuDevice
= AllocatePool (sizeof (EMU_IO_DEVICE
));
243 if (EmuDevice
== NULL
) {
244 return EFI_OUT_OF_RESOURCES
;
247 EmuDevice
->Handle
= NULL
;
248 EmuDevice
->ControllerHandle
= ControllerHandle
;
249 EmuDevice
->ParentDevicePath
= ParentDevicePath
;
250 CopyMem (&EmuDevice
->EmuIoThunk
, EmuIoThunk
, sizeof (EMU_IO_THUNK_PROTOCOL
));
252 EmuDevice
->ControllerNameTable
= NULL
;
256 sizeof (ComponentName
) / sizeof (CHAR16
),
257 EmuIoThunk
->ConfigString
,
258 sizeof (ComponentName
) / sizeof (CHAR16
)
261 EmuDevice
->DevicePath
= EmuBusCreateDevicePath (
263 EmuIoThunk
->Protocol
,
266 if (EmuDevice
->DevicePath
== NULL
) {
267 gBS
->FreePool (EmuDevice
);
268 return EFI_OUT_OF_RESOURCES
;
273 gEmuBusDriverComponentName
.SupportedLanguages
,
274 &EmuDevice
->ControllerNameTable
,
278 EmuDevice
->Signature
= EMU_IO_DEVICE_SIGNATURE
;
280 InstallStatus
= gBS
->InstallMultipleProtocolInterfaces (
282 &gEfiDevicePathProtocolGuid
,
283 EmuDevice
->DevicePath
,
284 &gEmuIoThunkProtocolGuid
,
285 &EmuDevice
->EmuIoThunk
,
288 if (EFI_ERROR (InstallStatus
)) {
289 FreeUnicodeStringTable (EmuDevice
->ControllerNameTable
);
290 gBS
->FreePool (EmuDevice
);
293 // Open For Child Device
295 Status
= gBS
->OpenProtocol (
297 &gEmuThunkProtocolGuid
,
299 This
->DriverBindingHandle
,
301 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
303 if (!EFI_ERROR (Status
)) {
304 InstallStatus
= EFI_SUCCESS
;
310 return InstallStatus
;
315 EmuBusDriverBindingStop (
316 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
317 IN EFI_HANDLE ControllerHandle
,
318 IN UINTN NumberOfChildren
,
319 IN EFI_HANDLE
*ChildHandleBuffer
324 BOOLEAN AllChildrenStopped
;
325 EMU_IO_THUNK_PROTOCOL
*EmuIoThunk
;
326 EMU_BUS_DEVICE
*EmuBusDevice
;
327 EMU_IO_DEVICE
*EmuDevice
;
328 EMU_THUNK_PROTOCOL
*EmuThunk
;
331 // Complete all outstanding transactions to Controller.
332 // Don't allow any new transaction to Controller to be started.
335 if (NumberOfChildren
== 0) {
337 // Close the bus driver
339 Status
= gBS
->OpenProtocol (
342 (VOID
**)&EmuBusDevice
,
343 This
->DriverBindingHandle
,
345 EFI_OPEN_PROTOCOL_GET_PROTOCOL
347 if (EFI_ERROR (Status
)) {
351 gBS
->UninstallMultipleProtocolInterfaces (
358 FreeUnicodeStringTable (EmuBusDevice
->ControllerNameTable
);
360 gBS
->FreePool (EmuBusDevice
);
364 &gEmuThunkProtocolGuid
,
365 This
->DriverBindingHandle
,
371 &gEfiDevicePathProtocolGuid
,
372 This
->DriverBindingHandle
,
378 AllChildrenStopped
= TRUE
;
380 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
381 Status
= gBS
->OpenProtocol (
382 ChildHandleBuffer
[Index
],
383 &gEmuIoThunkProtocolGuid
,
384 (VOID
**)&EmuIoThunk
,
385 This
->DriverBindingHandle
,
387 EFI_OPEN_PROTOCOL_GET_PROTOCOL
389 if (!EFI_ERROR (Status
)) {
390 EmuDevice
= EMU_IO_DEVICE_FROM_THIS (EmuIoThunk
);
392 Status
= gBS
->CloseProtocol (
394 &gEmuThunkProtocolGuid
,
395 This
->DriverBindingHandle
,
399 Status
= gBS
->UninstallMultipleProtocolInterfaces (
401 &gEfiDevicePathProtocolGuid
,
402 EmuDevice
->DevicePath
,
403 &gEmuIoThunkProtocolGuid
,
404 &EmuDevice
->EmuIoThunk
,
408 if (EFI_ERROR (Status
)) {
411 &gEmuThunkProtocolGuid
,
413 This
->DriverBindingHandle
,
415 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
419 // Close the child handle
421 FreeUnicodeStringTable (EmuDevice
->ControllerNameTable
);
422 FreePool (EmuDevice
);
426 if (EFI_ERROR (Status
)) {
427 AllChildrenStopped
= FALSE
;
431 if (!AllChildrenStopped
) {
432 return EFI_DEVICE_ERROR
;
441 Create a device path node using Guid and InstanceNumber and append it to
442 the passed in RootDevicePath
445 RootDevicePath - Root of the device path to return.
447 Guid - GUID to use in vendor device path node.
449 InstanceNumber - Instance number to use in the vendor device path. This
450 argument is needed to make sure each device path is unique.
454 EFI_DEVICE_PATH_PROTOCOL
457 EFI_DEVICE_PATH_PROTOCOL
*
458 EmuBusCreateDevicePath (
459 IN EFI_DEVICE_PATH_PROTOCOL
*RootDevicePath
,
461 IN UINT16 InstanceNumber
464 EMU_VENDOR_DEVICE_PATH_NODE DevicePath
;
466 DevicePath
.VendorDevicePath
.Header
.Type
= HARDWARE_DEVICE_PATH
;
467 DevicePath
.VendorDevicePath
.Header
.SubType
= HW_VENDOR_DP
;
468 SetDevicePathNodeLength (&DevicePath
.VendorDevicePath
.Header
, sizeof (EMU_VENDOR_DEVICE_PATH_NODE
));
471 // The GUID defines the Class
473 CopyMem (&DevicePath
.VendorDevicePath
.Guid
, Guid
, sizeof (EFI_GUID
));
476 // Add an instance number so we can make sure there are no Device Path
479 DevicePath
.Instance
= InstanceNumber
;
481 return AppendDevicePathNode (
483 (EFI_DEVICE_PATH_PROTOCOL
*)&DevicePath
488 The user Entry Point for module EmuBusDriver. The user code starts with this function.
490 @param[in] ImageHandle The firmware allocated handle for the EFI image.
491 @param[in] SystemTable A pointer to the EFI System Table.
493 @retval EFI_SUCCESS The entry point is executed successfully.
494 @retval other Some error occurs when executing this entry point.
499 InitializeEmuBusDriver (
500 IN EFI_HANDLE ImageHandle
,
501 IN EFI_SYSTEM_TABLE
*SystemTable
506 Status
= EfiLibInstallAllDriverProtocols (
509 &gEmuBusDriverBinding
,
511 &gEmuBusDriverComponentName
,
515 ASSERT_EFI_ERROR (Status
);