summaryrefslogtreecommitdiff
path: root/EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c
diff options
context:
space:
mode:
Diffstat (limited to 'EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c')
-rw-r--r--EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c529
1 files changed, 529 insertions, 0 deletions
diff --git a/EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c b/EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c
new file mode 100644
index 0000000000..0430ec3dd2
--- /dev/null
+++ b/EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c
@@ -0,0 +1,529 @@
+/** @file
+ Emu Bus driver
+
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2011, Apple Inc. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+
+**/
+
+#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;
+
+ StrnCpy (ComponentName, 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;
+}
+
+
+
+