]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c
InOsEmuPkg: Rename package to EmulatorPkg & Sec to Host
[mirror_edk2.git] / EmulatorPkg / EmuBusDriverDxe / EmuBusDriverDxe.c
diff --git a/EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c b/EmulatorPkg/EmuBusDriverDxe/EmuBusDriverDxe.c
new file mode 100644 (file)
index 0000000..0430ec3
--- /dev/null
@@ -0,0 +1,529 @@
+/** @file\r
+ Emu Bus driver\r
+\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+Portions copyright (c) 2011, Apple Inc. All rights reserved.\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#include "EmuBusDriverDxe.h"\r
+\r
+\r
+\r
+//\r
+// DriverBinding protocol global\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL           gEmuBusDriverBinding = {\r
+  EmuBusDriverBindingSupported,\r
+  EmuBusDriverBindingStart,\r
+  EmuBusDriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBusDriverBindingSupported (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   ControllerHandle,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_DEVICE_PATH_PROTOCOL  *ParentDevicePath;\r
+  EMU_THUNK_PROTOCOL        *EmuThunk;\r
+\r
+  //\r
+  // Check the contents of the first Device Path Node of RemainingDevicePath to make sure\r
+  // it is a legal Device Path Node for this bus driver's children.\r
+  //\r
+  if (RemainingDevicePath != NULL) {\r
+    //\r
+    // Check if RemainingDevicePath is the End of Device Path Node, \r
+    // if yes, go on checking other conditions\r
+    //\r
+    if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+      //\r
+      // If RemainingDevicePath isn't the End of Device Path Node,\r
+      // check its validation\r
+      //\r
+      if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH ||\r
+          RemainingDevicePath->SubType != HW_VENDOR_DP ||\r
+          DevicePathNodeLength(RemainingDevicePath) != sizeof(EMU_VENDOR_DEVICE_PATH_NODE)) {\r
+        return EFI_UNSUPPORTED;\r
+      }\r
+    }\r
+  }\r
+  \r
+  //\r
+  // Open the IO Abstraction(s) needed to perform the supported test\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEmuThunkProtocolGuid,\r
+                  (VOID **)&EmuThunk   ,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Close the I/O Abstraction(s) used to perform the supported test\r
+  //\r
+  gBS->CloseProtocol (\r
+        ControllerHandle,\r
+        &gEmuThunkProtocolGuid,\r
+        This->DriverBindingHandle,\r
+        ControllerHandle\r
+        );\r
+\r
+  //\r
+  // Open the EFI Device Path protocol needed to perform the supported test\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **)&ParentDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (Status == EFI_ALREADY_STARTED) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+\r
+  //\r
+  // Close protocol, don't use device path protocol in the Support() function\r
+  //\r
+  gBS->CloseProtocol (\r
+        ControllerHandle,\r
+        &gEfiDevicePathProtocolGuid,\r
+        This->DriverBindingHandle,\r
+        ControllerHandle\r
+        );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBusDriverBindingStart (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   ControllerHandle,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_STATUS                      InstallStatus;\r
+  EMU_THUNK_PROTOCOL              *EmuThunk;\r
+  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;\r
+  EMU_IO_DEVICE                   *EmuDevice;\r
+  EMU_BUS_DEVICE                  *EmuBusDevice;\r
+  EMU_IO_THUNK_PROTOCOL           *EmuIoThunk;\r
+  UINT16                          ComponentName[512];\r
+  EMU_VENDOR_DEVICE_PATH_NODE     *Node;\r
+  BOOLEAN                         CreateDevice;\r
+\r
+  InstallStatus = EFI_UNSUPPORTED;\r
+  Status = EFI_UNSUPPORTED;\r
+\r
+  //\r
+  // Grab the protocols we need\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **)&ParentDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEmuThunkProtocolGuid,\r
+                  (VOID **)&EmuThunk,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    return Status;\r
+  }\r
+\r
+  if (Status != EFI_ALREADY_STARTED) {\r
+    EmuBusDevice = AllocatePool (sizeof (EMU_BUS_DEVICE));\r
+    if (EmuBusDevice == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    EmuBusDevice->Signature           = EMU_BUS_DEVICE_SIGNATURE;\r
+    EmuBusDevice->ControllerNameTable = NULL;\r
+\r
+    AddUnicodeString2 (\r
+      "eng",\r
+      gEmuBusDriverComponentName.SupportedLanguages,\r
+      &EmuBusDevice->ControllerNameTable,\r
+      L"Emulator Bus Controller",\r
+      TRUE\r
+      );\r
+    AddUnicodeString2 (\r
+      "en",\r
+      gEmuBusDriverComponentName2.SupportedLanguages,\r
+      &EmuBusDevice->ControllerNameTable,\r
+      L"Emulator Bus Controller",\r
+      FALSE\r
+      );\r
+\r
+\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
+                    &ControllerHandle,\r
+                    &gEfiCallerIdGuid, EmuBusDevice,\r
+                    NULL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      FreeUnicodeStringTable (EmuBusDevice->ControllerNameTable);\r
+      gBS->FreePool (EmuBusDevice);\r
+      return Status;\r
+    }\r
+  }\r
+\r
+\r
+  for (Status = EFI_SUCCESS, EmuIoThunk = NULL; !EFI_ERROR (Status); ) {\r
+    Status = EmuThunk->GetNextProtocol (TRUE, &EmuIoThunk);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
+\r
+    CreateDevice = TRUE;\r
+    if (RemainingDevicePath != NULL) {\r
+      CreateDevice  = FALSE;\r
+      //\r
+      // Check if RemainingDevicePath is the End of Device Path Node, \r
+      // if yes, don't create any child device \r
+      //\r
+      if (!IsDevicePathEnd (RemainingDevicePath)) {\r
+        //\r
+        // If RemainingDevicePath isn't the End of Device Path Node,\r
+        // check its validation\r
+        //\r
+        Node          = (EMU_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath;\r
+        if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH &&\r
+            Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP &&\r
+            DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (EMU_VENDOR_DEVICE_PATH_NODE)\r
+            ) {\r
+          if (CompareGuid (&Node->VendorDevicePath.Guid, EmuIoThunk->Protocol) && Node->Instance == EmuIoThunk->Instance) {\r
+            CreateDevice = TRUE;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    if (CreateDevice) {\r
+      //\r
+      // Allocate instance structure, and fill in parent information.\r
+      //\r
+      EmuDevice = AllocatePool (sizeof (EMU_IO_DEVICE));\r
+      if (EmuDevice == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      EmuDevice->Handle             = NULL;\r
+      EmuDevice->ControllerHandle   = ControllerHandle;\r
+      EmuDevice->ParentDevicePath   = ParentDevicePath;\r
+      CopyMem (&EmuDevice->EmuIoThunk, EmuIoThunk, sizeof (EMU_IO_THUNK_PROTOCOL));\r
+      \r
+      EmuDevice->ControllerNameTable = NULL;\r
+\r
+      StrnCpy (ComponentName, EmuIoThunk->ConfigString, sizeof (ComponentName)/sizeof (CHAR16));\r
+\r
+      EmuDevice->DevicePath = EmuBusCreateDevicePath (\r
+                                  ParentDevicePath,\r
+                                  EmuIoThunk->Protocol,\r
+                                  EmuIoThunk->Instance\r
+                                  );\r
+      if (EmuDevice->DevicePath == NULL) {\r
+        gBS->FreePool (EmuDevice);\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      AddUnicodeString (\r
+        "eng",\r
+        gEmuBusDriverComponentName.SupportedLanguages,\r
+        &EmuDevice->ControllerNameTable,\r
+        ComponentName\r
+        );\r
+\r
+      EmuDevice->Signature = EMU_IO_DEVICE_SIGNATURE;\r
+\r
+      InstallStatus = gBS->InstallMultipleProtocolInterfaces (\r
+                            &EmuDevice->Handle,\r
+                            &gEfiDevicePathProtocolGuid,  EmuDevice->DevicePath,\r
+                            &gEmuIoThunkProtocolGuid,     &EmuDevice->EmuIoThunk,\r
+                            NULL\r
+                            );\r
+      if (EFI_ERROR (InstallStatus)) {\r
+        FreeUnicodeStringTable (EmuDevice->ControllerNameTable);\r
+        gBS->FreePool (EmuDevice);\r
+      } else {\r
+        //\r
+        // Open For Child Device\r
+        //\r
+        Status = gBS->OpenProtocol (\r
+                        ControllerHandle,\r
+                        &gEmuThunkProtocolGuid,\r
+                        (VOID **)&EmuThunk   ,\r
+                        This->DriverBindingHandle,\r
+                        EmuDevice->Handle,\r
+                        EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                        );\r
+        if (!EFI_ERROR (Status)) {\r
+          InstallStatus = EFI_SUCCESS;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return InstallStatus;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+EmuBusDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   ControllerHandle,\r
+  IN  UINTN                        NumberOfChildren,\r
+  IN  EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  UINTN                     Index;\r
+  BOOLEAN                   AllChildrenStopped;\r
+  EMU_IO_THUNK_PROTOCOL     *EmuIoThunk;\r
+  EMU_BUS_DEVICE            *EmuBusDevice;\r
+  EMU_IO_DEVICE             *EmuDevice;\r
+  EMU_THUNK_PROTOCOL        *EmuThunk;\r
+\r
+  //\r
+  // Complete all outstanding transactions to Controller.\r
+  // Don't allow any new transaction to Controller to be started.\r
+  //\r
+\r
+  if (NumberOfChildren == 0) {\r
+    //\r
+    // Close the bus driver\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    ControllerHandle,\r
+                    &gEfiCallerIdGuid,\r
+                    (VOID **)&EmuBusDevice,\r
+                    This->DriverBindingHandle,\r
+                    ControllerHandle,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+          ControllerHandle,\r
+          &gEfiCallerIdGuid,  EmuBusDevice,\r
+          NULL\r
+          );\r
+\r
+    FreeUnicodeStringTable (EmuBusDevice->ControllerNameTable);\r
+\r
+    gBS->FreePool (EmuBusDevice);\r
+\r
+    gBS->CloseProtocol (\r
+          ControllerHandle,\r
+          &gEmuThunkProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+\r
+    gBS->CloseProtocol (\r
+          ControllerHandle,\r
+          &gEfiDevicePathProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  AllChildrenStopped = TRUE;\r
+\r
+  for (Index = 0; Index < NumberOfChildren; Index++) {\r
+\r
+    Status = gBS->OpenProtocol (\r
+                    ChildHandleBuffer[Index],\r
+                    &gEmuIoThunkProtocolGuid,\r
+                    (VOID **)&EmuIoThunk,\r
+                    This->DriverBindingHandle,\r
+                    ControllerHandle,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      EmuDevice = EMU_IO_DEVICE_FROM_THIS (EmuIoThunk);\r
+\r
+      Status = gBS->CloseProtocol (\r
+                      ControllerHandle,\r
+                      &gEmuThunkProtocolGuid,\r
+                      This->DriverBindingHandle,\r
+                      EmuDevice->Handle\r
+                      );\r
+\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      EmuDevice->Handle,\r
+                      &gEfiDevicePathProtocolGuid,  EmuDevice->DevicePath,\r
+                      &gEmuIoThunkProtocolGuid,     EmuDevice->EmuIoThunk,\r
+                      NULL\r
+                      );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        gBS->OpenProtocol (\r
+              ControllerHandle,\r
+              &gEmuThunkProtocolGuid,\r
+              (VOID **) &EmuThunk   ,\r
+              This->DriverBindingHandle,\r
+              EmuDevice->Handle,\r
+              EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+              );\r
+      } else {\r
+        //\r
+        // Close the child handle\r
+        //\r
+        FreeUnicodeStringTable (EmuDevice->ControllerNameTable);\r
+        FreePool (EmuDevice);\r
+      }\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      AllChildrenStopped = FALSE;\r
+    }\r
+  }\r
+\r
+  if (!AllChildrenStopped) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/*++\r
+\r
+Routine Description:\r
+  Create a device path node using Guid and InstanceNumber and append it to\r
+  the passed in RootDevicePath\r
+\r
+Arguments:\r
+  RootDevicePath - Root of the device path to return.\r
+\r
+  Guid           - GUID to use in vendor device path node.\r
+\r
+  InstanceNumber - Instance number to use in the vendor device path. This\r
+                    argument is needed to make sure each device path is unique.\r
+\r
+Returns:\r
+\r
+  EFI_DEVICE_PATH_PROTOCOL \r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+EmuBusCreateDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL  *RootDevicePath,\r
+  IN  EFI_GUID                  *Guid,\r
+  IN  UINT16                    InstanceNumber\r
+  )\r
+{\r
+  EMU_VENDOR_DEVICE_PATH_NODE  DevicePath;\r
+\r
+  DevicePath.VendorDevicePath.Header.Type     = HARDWARE_DEVICE_PATH;\r
+  DevicePath.VendorDevicePath.Header.SubType  = HW_VENDOR_DP;\r
+  SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (EMU_VENDOR_DEVICE_PATH_NODE));\r
+\r
+  //\r
+  // The GUID defines the Class\r
+  //\r
+  CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID));\r
+\r
+  //\r
+  // Add an instance number so we can make sure there are no Device Path\r
+  // duplication.\r
+  //\r
+  DevicePath.Instance = InstanceNumber;\r
+\r
+  return AppendDevicePathNode (\r
+          RootDevicePath,\r
+          (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath\r
+          );\r
+}\r
+\r
+\r
+\r
+/**\r
+  The user Entry Point for module EmuBusDriver. The user code starts with this function.\r
+\r
+  @param[in] ImageHandle    The firmware allocated handle for the EFI image.  \r
+  @param[in] SystemTable    A pointer to the EFI System Table.\r
+  \r
+  @retval EFI_SUCCESS       The entry point is executed successfully.\r
+  @retval other             Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeEmuBusDriver (\r
+  IN EFI_HANDLE           ImageHandle,\r
+  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+\r
+  Status = EfiLibInstallAllDriverProtocols (\r
+             ImageHandle,\r
+             SystemTable,\r
+             &gEmuBusDriverBinding,\r
+             ImageHandle,\r
+             &gEmuBusDriverComponentName,\r
+             NULL,\r
+             NULL\r
+             );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+\r
+\r