123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518 |
- /** @file
- Emu Bus driver
- Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
- Portions copyright (c) 2011, Apple Inc. All rights reserved.
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "EmuBusDriverDxe.h"
- //
- // DriverBinding protocol global
- //
- EFI_DRIVER_BINDING_PROTOCOL gEmuBusDriverBinding = {
- EmuBusDriverBindingSupported,
- EmuBusDriverBindingStart,
- EmuBusDriverBindingStop,
- 0xa,
- NULL,
- NULL
- };
- EFI_STATUS
- EFIAPI
- EmuBusDriverBindingSupported (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
- {
- EFI_STATUS Status;
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
- EMU_THUNK_PROTOCOL *EmuThunk;
- //
- // Check the contents of the first Device Path Node of RemainingDevicePath to make sure
- // it is a legal Device Path Node for this bus driver's children.
- //
- if (RemainingDevicePath != NULL) {
- //
- // Check if RemainingDevicePath is the End of Device Path Node,
- // if yes, go on checking other conditions
- //
- if (!IsDevicePathEnd (RemainingDevicePath)) {
- //
- // If RemainingDevicePath isn't the End of Device Path Node,
- // check its validation
- //
- if ((RemainingDevicePath->Type != HARDWARE_DEVICE_PATH) ||
- (RemainingDevicePath->SubType != HW_VENDOR_DP) ||
- (DevicePathNodeLength (RemainingDevicePath) != sizeof (EMU_VENDOR_DEVICE_PATH_NODE)))
- {
- return EFI_UNSUPPORTED;
- }
- }
- }
- //
- // Open the IO Abstraction(s) needed to perform the supported test
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEmuThunkProtocolGuid,
- (VOID **)&EmuThunk,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (Status == EFI_ALREADY_STARTED) {
- return EFI_SUCCESS;
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Close the I/O Abstraction(s) used to perform the supported test
- //
- gBS->CloseProtocol (
- ControllerHandle,
- &gEmuThunkProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- //
- // Open the EFI Device Path protocol needed to perform the supported test
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **)&ParentDevicePath,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (Status == EFI_ALREADY_STARTED) {
- return EFI_SUCCESS;
- }
- if (EFI_ERROR (Status)) {
- return Status;
- }
- //
- // Close protocol, don't use device path protocol in the Support() function
- //
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- return Status;
- }
- EFI_STATUS
- EFIAPI
- EmuBusDriverBindingStart (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
- )
- {
- EFI_STATUS Status;
- EFI_STATUS InstallStatus;
- EMU_THUNK_PROTOCOL *EmuThunk;
- EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
- EMU_IO_DEVICE *EmuDevice;
- EMU_BUS_DEVICE *EmuBusDevice;
- EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
- UINT16 ComponentName[512];
- EMU_VENDOR_DEVICE_PATH_NODE *Node;
- BOOLEAN CreateDevice;
- InstallStatus = EFI_UNSUPPORTED;
- Status = EFI_UNSUPPORTED;
- //
- // Grab the protocols we need
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- (VOID **)&ParentDevicePath,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
- return Status;
- }
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEmuThunkProtocolGuid,
- (VOID **)&EmuThunk,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
- return Status;
- }
- if (Status != EFI_ALREADY_STARTED) {
- EmuBusDevice = AllocatePool (sizeof (EMU_BUS_DEVICE));
- if (EmuBusDevice == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- EmuBusDevice->Signature = EMU_BUS_DEVICE_SIGNATURE;
- EmuBusDevice->ControllerNameTable = NULL;
- AddUnicodeString2 (
- "eng",
- gEmuBusDriverComponentName.SupportedLanguages,
- &EmuBusDevice->ControllerNameTable,
- L"Emulator Bus Controller",
- TRUE
- );
- AddUnicodeString2 (
- "en",
- gEmuBusDriverComponentName2.SupportedLanguages,
- &EmuBusDevice->ControllerNameTable,
- L"Emulator Bus Controller",
- FALSE
- );
- Status = gBS->InstallMultipleProtocolInterfaces (
- &ControllerHandle,
- &gEfiCallerIdGuid,
- EmuBusDevice,
- NULL
- );
- if (EFI_ERROR (Status)) {
- FreeUnicodeStringTable (EmuBusDevice->ControllerNameTable);
- gBS->FreePool (EmuBusDevice);
- return Status;
- }
- }
- for (Status = EFI_SUCCESS, EmuIoThunk = NULL; !EFI_ERROR (Status); ) {
- Status = EmuThunk->GetNextProtocol (TRUE, &EmuIoThunk);
- if (EFI_ERROR (Status)) {
- break;
- }
- CreateDevice = TRUE;
- if (RemainingDevicePath != NULL) {
- CreateDevice = FALSE;
- //
- // Check if RemainingDevicePath is the End of Device Path Node,
- // if yes, don't create any child device
- //
- if (!IsDevicePathEnd (RemainingDevicePath)) {
- //
- // If RemainingDevicePath isn't the End of Device Path Node,
- // check its validation
- //
- Node = (EMU_VENDOR_DEVICE_PATH_NODE *)RemainingDevicePath;
- if ((Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH) &&
- (Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP) &&
- (DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (EMU_VENDOR_DEVICE_PATH_NODE))
- )
- {
- if (CompareGuid (&Node->VendorDevicePath.Guid, EmuIoThunk->Protocol) && (Node->Instance == EmuIoThunk->Instance)) {
- CreateDevice = TRUE;
- }
- }
- }
- }
- if (CreateDevice) {
- //
- // Allocate instance structure, and fill in parent information.
- //
- EmuDevice = AllocatePool (sizeof (EMU_IO_DEVICE));
- if (EmuDevice == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- EmuDevice->Handle = NULL;
- EmuDevice->ControllerHandle = ControllerHandle;
- EmuDevice->ParentDevicePath = ParentDevicePath;
- CopyMem (&EmuDevice->EmuIoThunk, EmuIoThunk, sizeof (EMU_IO_THUNK_PROTOCOL));
- EmuDevice->ControllerNameTable = NULL;
- StrnCpyS (
- ComponentName,
- sizeof (ComponentName) / sizeof (CHAR16),
- EmuIoThunk->ConfigString,
- sizeof (ComponentName) / sizeof (CHAR16)
- );
- EmuDevice->DevicePath = EmuBusCreateDevicePath (
- ParentDevicePath,
- EmuIoThunk->Protocol,
- EmuIoThunk->Instance
- );
- if (EmuDevice->DevicePath == NULL) {
- gBS->FreePool (EmuDevice);
- return EFI_OUT_OF_RESOURCES;
- }
- AddUnicodeString (
- "eng",
- gEmuBusDriverComponentName.SupportedLanguages,
- &EmuDevice->ControllerNameTable,
- ComponentName
- );
- EmuDevice->Signature = EMU_IO_DEVICE_SIGNATURE;
- InstallStatus = gBS->InstallMultipleProtocolInterfaces (
- &EmuDevice->Handle,
- &gEfiDevicePathProtocolGuid,
- EmuDevice->DevicePath,
- &gEmuIoThunkProtocolGuid,
- &EmuDevice->EmuIoThunk,
- NULL
- );
- if (EFI_ERROR (InstallStatus)) {
- FreeUnicodeStringTable (EmuDevice->ControllerNameTable);
- gBS->FreePool (EmuDevice);
- } else {
- //
- // Open For Child Device
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEmuThunkProtocolGuid,
- (VOID **)&EmuThunk,
- This->DriverBindingHandle,
- EmuDevice->Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- if (!EFI_ERROR (Status)) {
- InstallStatus = EFI_SUCCESS;
- }
- }
- }
- }
- return InstallStatus;
- }
- EFI_STATUS
- EFIAPI
- EmuBusDriverBindingStop (
- IN EFI_DRIVER_BINDING_PROTOCOL *This,
- IN EFI_HANDLE ControllerHandle,
- IN UINTN NumberOfChildren,
- IN EFI_HANDLE *ChildHandleBuffer
- )
- {
- EFI_STATUS Status;
- UINTN Index;
- BOOLEAN AllChildrenStopped;
- EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
- EMU_BUS_DEVICE *EmuBusDevice;
- EMU_IO_DEVICE *EmuDevice;
- EMU_THUNK_PROTOCOL *EmuThunk;
- //
- // Complete all outstanding transactions to Controller.
- // Don't allow any new transaction to Controller to be started.
- //
- if (NumberOfChildren == 0) {
- //
- // Close the bus driver
- //
- Status = gBS->OpenProtocol (
- ControllerHandle,
- &gEfiCallerIdGuid,
- (VOID **)&EmuBusDevice,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- gBS->UninstallMultipleProtocolInterfaces (
- ControllerHandle,
- &gEfiCallerIdGuid,
- EmuBusDevice,
- NULL
- );
- FreeUnicodeStringTable (EmuBusDevice->ControllerNameTable);
- gBS->FreePool (EmuBusDevice);
- gBS->CloseProtocol (
- ControllerHandle,
- &gEmuThunkProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- gBS->CloseProtocol (
- ControllerHandle,
- &gEfiDevicePathProtocolGuid,
- This->DriverBindingHandle,
- ControllerHandle
- );
- return EFI_SUCCESS;
- }
- AllChildrenStopped = TRUE;
- for (Index = 0; Index < NumberOfChildren; Index++) {
- Status = gBS->OpenProtocol (
- ChildHandleBuffer[Index],
- &gEmuIoThunkProtocolGuid,
- (VOID **)&EmuIoThunk,
- This->DriverBindingHandle,
- ControllerHandle,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL
- );
- if (!EFI_ERROR (Status)) {
- EmuDevice = EMU_IO_DEVICE_FROM_THIS (EmuIoThunk);
- Status = gBS->CloseProtocol (
- ControllerHandle,
- &gEmuThunkProtocolGuid,
- This->DriverBindingHandle,
- EmuDevice->Handle
- );
- Status = gBS->UninstallMultipleProtocolInterfaces (
- EmuDevice->Handle,
- &gEfiDevicePathProtocolGuid,
- EmuDevice->DevicePath,
- &gEmuIoThunkProtocolGuid,
- &EmuDevice->EmuIoThunk,
- NULL
- );
- if (EFI_ERROR (Status)) {
- gBS->OpenProtocol (
- ControllerHandle,
- &gEmuThunkProtocolGuid,
- (VOID **)&EmuThunk,
- This->DriverBindingHandle,
- EmuDevice->Handle,
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
- );
- } else {
- //
- // Close the child handle
- //
- FreeUnicodeStringTable (EmuDevice->ControllerNameTable);
- FreePool (EmuDevice);
- }
- }
- if (EFI_ERROR (Status)) {
- AllChildrenStopped = FALSE;
- }
- }
- if (!AllChildrenStopped) {
- return EFI_DEVICE_ERROR;
- }
- return EFI_SUCCESS;
- }
- /*++
- Routine Description:
- Create a device path node using Guid and InstanceNumber and append it to
- the passed in RootDevicePath
- Arguments:
- RootDevicePath - Root of the device path to return.
- Guid - GUID to use in vendor device path node.
- InstanceNumber - Instance number to use in the vendor device path. This
- argument is needed to make sure each device path is unique.
- Returns:
- EFI_DEVICE_PATH_PROTOCOL
- **/
- EFI_DEVICE_PATH_PROTOCOL *
- EmuBusCreateDevicePath (
- IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath,
- IN EFI_GUID *Guid,
- IN UINT16 InstanceNumber
- )
- {
- EMU_VENDOR_DEVICE_PATH_NODE DevicePath;
- DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH;
- DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP;
- SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (EMU_VENDOR_DEVICE_PATH_NODE));
- //
- // The GUID defines the Class
- //
- CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));
- //
- // Add an instance number so we can make sure there are no Device Path
- // duplication.
- //
- DevicePath.Instance = InstanceNumber;
- return AppendDevicePathNode (
- RootDevicePath,
- (EFI_DEVICE_PATH_PROTOCOL *)&DevicePath
- );
- }
- /**
- The user Entry Point for module EmuBusDriver. The user code starts with this function.
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval other Some error occurs when executing this entry point.
- **/
- EFI_STATUS
- EFIAPI
- InitializeEmuBusDriver (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
- {
- EFI_STATUS Status;
- Status = EfiLibInstallAllDriverProtocols (
- ImageHandle,
- SystemTable,
- &gEmuBusDriverBinding,
- ImageHandle,
- &gEmuBusDriverComponentName,
- NULL,
- NULL
- );
- ASSERT_EFI_ERROR (Status);
- return Status;
- }
|