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"
16 // DriverBinding protocol global
18 EFI_DRIVER_BINDING_PROTOCOL gEmuBusDriverBinding
= {
19 EmuBusDriverBindingSupported
,
20 EmuBusDriverBindingStart
,
21 EmuBusDriverBindingStop
,
31 EmuBusDriverBindingSupported (
32 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
33 IN EFI_HANDLE ControllerHandle
,
34 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
38 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
39 EMU_THUNK_PROTOCOL
*EmuThunk
;
42 // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
43 // it is a legal Device Path Node for this bus driver's children.
45 if (RemainingDevicePath
!= NULL
) {
47 // Check if RemainingDevicePath is the End of Device Path Node,
48 // if yes, go on checking other conditions
50 if (!IsDevicePathEnd (RemainingDevicePath
)) {
52 // If RemainingDevicePath isn't the End of Device Path Node,
53 // check its validation
55 if (RemainingDevicePath
->Type
!= HARDWARE_DEVICE_PATH
||
56 RemainingDevicePath
->SubType
!= HW_VENDOR_DP
||
57 DevicePathNodeLength(RemainingDevicePath
) != sizeof(EMU_VENDOR_DEVICE_PATH_NODE
)) {
58 return EFI_UNSUPPORTED
;
64 // Open the IO Abstraction(s) needed to perform the supported test
66 Status
= gBS
->OpenProtocol (
68 &gEmuThunkProtocolGuid
,
70 This
->DriverBindingHandle
,
72 EFI_OPEN_PROTOCOL_BY_DRIVER
74 if (Status
== EFI_ALREADY_STARTED
) {
78 if (EFI_ERROR (Status
)) {
83 // Close the I/O Abstraction(s) used to perform the supported test
87 &gEmuThunkProtocolGuid
,
88 This
->DriverBindingHandle
,
93 // Open the EFI Device Path protocol needed to perform the supported test
95 Status
= gBS
->OpenProtocol (
97 &gEfiDevicePathProtocolGuid
,
98 (VOID
**)&ParentDevicePath
,
99 This
->DriverBindingHandle
,
101 EFI_OPEN_PROTOCOL_BY_DRIVER
103 if (Status
== EFI_ALREADY_STARTED
) {
107 if (EFI_ERROR (Status
)) {
113 // Close protocol, don't use device path protocol in the Support() function
117 &gEfiDevicePathProtocolGuid
,
118 This
->DriverBindingHandle
,
128 EmuBusDriverBindingStart (
129 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
130 IN EFI_HANDLE ControllerHandle
,
131 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
135 EFI_STATUS InstallStatus
;
136 EMU_THUNK_PROTOCOL
*EmuThunk
;
137 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
138 EMU_IO_DEVICE
*EmuDevice
;
139 EMU_BUS_DEVICE
*EmuBusDevice
;
140 EMU_IO_THUNK_PROTOCOL
*EmuIoThunk
;
141 UINT16 ComponentName
[512];
142 EMU_VENDOR_DEVICE_PATH_NODE
*Node
;
143 BOOLEAN CreateDevice
;
145 InstallStatus
= EFI_UNSUPPORTED
;
146 Status
= EFI_UNSUPPORTED
;
149 // Grab the protocols we need
151 Status
= gBS
->OpenProtocol (
153 &gEfiDevicePathProtocolGuid
,
154 (VOID
**)&ParentDevicePath
,
155 This
->DriverBindingHandle
,
157 EFI_OPEN_PROTOCOL_BY_DRIVER
159 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
163 Status
= gBS
->OpenProtocol (
165 &gEmuThunkProtocolGuid
,
167 This
->DriverBindingHandle
,
169 EFI_OPEN_PROTOCOL_BY_DRIVER
171 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
175 if (Status
!= EFI_ALREADY_STARTED
) {
176 EmuBusDevice
= AllocatePool (sizeof (EMU_BUS_DEVICE
));
177 if (EmuBusDevice
== NULL
) {
178 return EFI_OUT_OF_RESOURCES
;
181 EmuBusDevice
->Signature
= EMU_BUS_DEVICE_SIGNATURE
;
182 EmuBusDevice
->ControllerNameTable
= NULL
;
186 gEmuBusDriverComponentName
.SupportedLanguages
,
187 &EmuBusDevice
->ControllerNameTable
,
188 L
"Emulator Bus Controller",
193 gEmuBusDriverComponentName2
.SupportedLanguages
,
194 &EmuBusDevice
->ControllerNameTable
,
195 L
"Emulator Bus Controller",
200 Status
= gBS
->InstallMultipleProtocolInterfaces (
202 &gEfiCallerIdGuid
, EmuBusDevice
,
205 if (EFI_ERROR (Status
)) {
206 FreeUnicodeStringTable (EmuBusDevice
->ControllerNameTable
);
207 gBS
->FreePool (EmuBusDevice
);
213 for (Status
= EFI_SUCCESS
, EmuIoThunk
= NULL
; !EFI_ERROR (Status
); ) {
214 Status
= EmuThunk
->GetNextProtocol (TRUE
, &EmuIoThunk
);
215 if (EFI_ERROR (Status
)) {
220 if (RemainingDevicePath
!= NULL
) {
221 CreateDevice
= FALSE
;
223 // Check if RemainingDevicePath is the End of Device Path Node,
224 // if yes, don't create any child device
226 if (!IsDevicePathEnd (RemainingDevicePath
)) {
228 // If RemainingDevicePath isn't the End of Device Path Node,
229 // check its validation
231 Node
= (EMU_VENDOR_DEVICE_PATH_NODE
*) RemainingDevicePath
;
232 if (Node
->VendorDevicePath
.Header
.Type
== HARDWARE_DEVICE_PATH
&&
233 Node
->VendorDevicePath
.Header
.SubType
== HW_VENDOR_DP
&&
234 DevicePathNodeLength (&Node
->VendorDevicePath
.Header
) == sizeof (EMU_VENDOR_DEVICE_PATH_NODE
)
236 if (CompareGuid (&Node
->VendorDevicePath
.Guid
, EmuIoThunk
->Protocol
) && Node
->Instance
== EmuIoThunk
->Instance
) {
245 // Allocate instance structure, and fill in parent information.
247 EmuDevice
= AllocatePool (sizeof (EMU_IO_DEVICE
));
248 if (EmuDevice
== NULL
) {
249 return EFI_OUT_OF_RESOURCES
;
252 EmuDevice
->Handle
= NULL
;
253 EmuDevice
->ControllerHandle
= ControllerHandle
;
254 EmuDevice
->ParentDevicePath
= ParentDevicePath
;
255 CopyMem (&EmuDevice
->EmuIoThunk
, EmuIoThunk
, sizeof (EMU_IO_THUNK_PROTOCOL
));
257 EmuDevice
->ControllerNameTable
= NULL
;
261 sizeof (ComponentName
) / sizeof (CHAR16
),
262 EmuIoThunk
->ConfigString
,
263 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
);