]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg: Add an Super IO bus driver
authorHao Wu <hao.a.wu@intel.com>
Mon, 18 Mar 2019 02:43:27 +0000 (10:43 +0800)
committerHao Wu <hao.a.wu@intel.com>
Wed, 27 Mar 2019 05:13:56 +0000 (13:13 +0800)
REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1495

There is a plan to remove the IntelFrameworkModulePkg:
https://bugzilla.tianocore.org/show_bug.cgi?id=1605

This patch will a new OVMF Super I/O bus driver which will create the
below child devices:

* COM 1 UART
* COM 2 UART
* PS/2 Keyboard

and installs the Super I/O Protocol on them.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Anthony PERARD <anthony.perard@citrix.com>
OvmfPkg/OvmfPkgIa32.dsc
OvmfPkg/OvmfPkgIa32X64.dsc
OvmfPkg/OvmfPkgX64.dsc
OvmfPkg/SioBusDxe/ComponentName.c [new file with mode: 0644]
OvmfPkg/SioBusDxe/SioBusDxe.c [new file with mode: 0644]
OvmfPkg/SioBusDxe/SioBusDxe.h [new file with mode: 0644]
OvmfPkg/SioBusDxe/SioBusDxe.inf [new file with mode: 0644]
OvmfPkg/SioBusDxe/SioBusDxe.uni [new file with mode: 0644]
OvmfPkg/SioBusDxe/SioService.c [new file with mode: 0644]
OvmfPkg/SioBusDxe/SioService.h [new file with mode: 0644]

index 1710ab5a88d5e4175b4141e849ace5bdb53673c7..3be03141466ce4d75facce6d011e222d271a4a64 100644 (file)
   #\r
   # ISA Support\r
   #\r
+  OvmfPkg/SioBusDxe/SioBusDxe.inf\r
   PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf\r
   IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf\r
   IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf\r
index 5bceef3116a9fd3a41d177b0823980d6dbbb540f..3b85c2e6afb71543651c907bc051ee2a4a1ea48f 100644 (file)
   #\r
   # ISA Support\r
   #\r
+  OvmfPkg/SioBusDxe/SioBusDxe.inf\r
   PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf\r
   IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf\r
   IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf\r
index 3f5d948dbb14fb8991801c96920326b9a58fa634..104b2e79a50a2a7f2f90f52f460b0dcbfea4edec 100644 (file)
   #\r
   # ISA Support\r
   #\r
+  OvmfPkg/SioBusDxe/SioBusDxe.inf\r
   PcAtChipsetPkg/IsaAcpiDxe/IsaAcpi.inf\r
   IntelFrameworkModulePkg/Bus/Isa/IsaBusDxe/IsaBusDxe.inf\r
   IntelFrameworkModulePkg/Bus/Isa/IsaSerialDxe/IsaSerialDxe.inf\r
diff --git a/OvmfPkg/SioBusDxe/ComponentName.c b/OvmfPkg/SioBusDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..668a2c6
--- /dev/null
@@ -0,0 +1,167 @@
+/** @file\r
+  UEFI Component Name(2) protocol implementation for SioBusDxe driver.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions\r
+  of the BSD License which accompanies this distribution.  The\r
+  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
+#include "SioBusDxe.h"\r
+\r
+//\r
+// Driver name table\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSioBusDriverNameTable[] = {\r
+  { "eng;en", L"OVMF Sio Bus Driver" },\r
+  { NULL , NULL }\r
+};\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gSioBusComponentName = {\r
+  SioBusComponentNameGetDriverName,\r
+  SioBusComponentNameGetControllerName,\r
+  "eng"\r
+};\r
+\r
+//\r
+// EFI Component Name 2 Protocol\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSioBusComponentName2 = {\r
+  (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SioBusComponentNameGetDriverName,\r
+  (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SioBusComponentNameGetControllerName,\r
+  "en"\r
+};\r
+\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language, then\r
+  EFI_UNSUPPORTED is returned.\r
+\r
+  @param[in]  This              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL\r
+                                or EFI_COMPONENT_NAME_PROTOCOL instance.\r
+  @param[in]  Language          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 4646 or ISO 639-2 language code format.\r
+  @param[out] DriverName        A pointer to the Unicode string to return. This\r
+                                Unicode string is the name of the driver\r
+                                specified by This in the language specified by\r
+                                Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioBusComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL    *This,\r
+  IN  CHAR8                          *Language,\r
+  OUT CHAR16                         **DriverName\r
+  )\r
+{\r
+  return LookupUnicodeString2 (\r
+           Language,\r
+           This->SupportedLanguages,\r
+           mSioBusDriverNameTable,\r
+           DriverName,\r
+           (BOOLEAN)(This == &gSioBusComponentName)\r
+           );\r
+}\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified\r
+  by Language, then a pointer to the controller name is returned in\r
+  ControllerName, and EFI_SUCCESS is returned.  If the driver specified by This\r
+  is not currently managing the controller specified by ControllerHandle and\r
+  ChildHandle, then EFI_UNSUPPORTED is returned.  If the driver specified by\r
+  This does not support the language specified by Language, then\r
+  EFI_UNSUPPORTED is returned.\r
+\r
+  @param[in]  This              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL\r
+                                or EFI_COMPONENT_NAME_PROTOCOL instance.\r
+  @param[in]  ControllerHandle  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+  @param[in]  ChildHandle       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter\r
+                                that may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus\r
+                                drivers that wish to retrieve the name of the\r
+                                bus controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+  @param[in]  Language          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 4646 or ISO 639-2 language code format.\r
+  @param[out] ControllerName    A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name\r
+                                in the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioBusComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL    *This,\r
+  IN  EFI_HANDLE                     ControllerHandle,\r
+  IN  EFI_HANDLE                     ChildHandle        OPTIONAL,\r
+  IN  CHAR8                          *Language,\r
+  OUT CHAR16                         **ControllerName\r
+  )\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
diff --git a/OvmfPkg/SioBusDxe/SioBusDxe.c b/OvmfPkg/SioBusDxe/SioBusDxe.c
new file mode 100644 (file)
index 0000000..0cf9a2b
--- /dev/null
@@ -0,0 +1,622 @@
+/** @file\r
+  The SioBusDxe driver is used to create child devices on the ISA bus and\r
+  installs the Super I/O protocols on them.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions\r
+  of the BSD License which accompanies this distribution.  The\r
+  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
+#include "SioBusDxe.h"\r
+\r
+//\r
+// SioBus Driver Binding Protocol\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gSioBusDriverBinding = {\r
+  SioBusDriverBindingSupported,\r
+  SioBusDriverBindingStart,\r
+  SioBusDriverBindingStop,\r
+  0x10,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+\r
+/**\r
+  Tests to see if this driver supports a given controller. If a child device is\r
+  provided, it further tests to see if this driver supports creating a handle\r
+  for the specified child device.\r
+\r
+  This function checks to see if the driver specified by This supports the\r
+  device specified by ControllerHandle. Drivers will typically use the device\r
+  path attached to ControllerHandle and/or the services from the bus I/O\r
+  abstraction attached to ControllerHandle to determine if the driver supports\r
+  ControllerHandle. This function may be called many times during platform\r
+  initialization. In order to reduce boot times, the tests performed by this\r
+  function must be very small, and take as little time as possible to execute.\r
+  This function must not change the state of any hardware devices, and this\r
+  function must be aware that the device specified by ControllerHandle may\r
+  already be managed by the same driver or a different driver. This function\r
+  must match its calls to AllocatePages() with FreePages(), AllocatePool() with\r
+  FreePool(), and OpenProtocol() with CloseProtocol(). Since ControllerHandle\r
+  may have been previously started by the same driver, if a protocol is already\r
+  in the opened state, then it must not be closed with CloseProtocol(). This is\r
+  required to guarantee the state of ControllerHandle is not modified by this\r
+  function.\r
+\r
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL\r
+                                   instance.\r
+  @param[in]  ControllerHandle     The handle of the controller to test. This\r
+                                   handle must support a protocol interface\r
+                                   that supplies an I/O abstraction to the\r
+                                   driver.\r
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a\r
+                                   device path.  This parameter is ignored by\r
+                                   device drivers, and is optional for bus\r
+                                   drivers. For bus drivers, if this parameter\r
+                                   is not NULL, then the bus driver must\r
+                                   determine if the bus controller specified by\r
+                                   ControllerHandle and the child controller\r
+                                   specified by RemainingDevicePath are both\r
+                                   supported by this bus driver.\r
+\r
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and\r
+                                   RemainingDevicePath is supported by the\r
+                                   driver specified by This.\r
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and\r
+                                   RemainingDevicePath is already being managed\r
+                                   by the driver specified by This.\r
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and\r
+                                   RemainingDevicePath is already being managed\r
+                                   by a different driver or an application that\r
+                                   requires exclusive access.\r
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and\r
+                                   RemainingDevicePath is not supported by the\r
+                                   driver specified by This.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioBusDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS             Status;\r
+  EFI_PCI_IO_PROTOCOL    *PciIo;\r
+  PCI_TYPE00             Pci;\r
+  UINTN                  SegmentNumber;\r
+  UINTN                  BusNumber;\r
+  UINTN                  DeviceNumber;\r
+  UINTN                  FunctionNumber;\r
+\r
+  //\r
+  // Get PciIo protocol instance\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID**)&PciIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciIo->Pci.Read (\r
+                    PciIo,\r
+                    EfiPciIoWidthUint32,\r
+                    0,\r
+                    sizeof(Pci) / sizeof(UINT32),\r
+                    &Pci);\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    if ((Pci.Hdr.Command & 0x03) == 0x03) {\r
+      if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {\r
+        //\r
+        // See if this is a standard PCI to ISA Bridge from the Base Code and\r
+        // Class Code\r
+        //\r
+        if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) {\r
+          Status = EFI_SUCCESS;\r
+        }\r
+\r
+        //\r
+        // See if this is an Intel PCI to ISA bridge in Positive Decode Mode\r
+        //\r
+        if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE &&\r
+            Pci.Hdr.VendorId     == 0x8086) {\r
+          //\r
+          // See if this is on Function #0 to avoid false positives on\r
+          // PCI_CLASS_BRIDGE_OTHER that has the same value as\r
+          // PCI_CLASS_BRIDGE_ISA_PDECODE\r
+          //\r
+          Status = PciIo->GetLocation (\r
+                            PciIo,\r
+                            &SegmentNumber,\r
+                            &BusNumber,\r
+                            &DeviceNumber,\r
+                            &FunctionNumber\r
+                            );\r
+          if (!EFI_ERROR (Status) && FunctionNumber == 0) {\r
+            Status = EFI_SUCCESS;\r
+          } else {\r
+            Status = EFI_UNSUPPORTED;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  gBS->CloseProtocol (\r
+         Controller,\r
+         &gEfiPciIoProtocolGuid,\r
+         This->DriverBindingHandle,\r
+         Controller\r
+         );\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Starts a device controller or a bus controller.\r
+\r
+  The Start() function is designed to be invoked from the EFI boot service\r
+  ConnectController(). As a result, much of the error checking on the\r
+  parameters to Start() has been moved into this common boot service. It is\r
+  legal to call Start() from other locations, but the following calling\r
+  restrictions must be followed or the system behavior will not be\r
+  deterministic.\r
+  1. ControllerHandle must be a valid EFI_HANDLE.\r
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a\r
+     naturally aligned EFI_DEVICE_PATH_PROTOCOL.\r
+  3. Prior to calling Start(), the Supported() function for the driver\r
+     specified by This must have been called with the same calling parameters,\r
+     and Supported() must have returned EFI_SUCCESS.\r
+\r
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL\r
+                                   instance.\r
+  @param[in]  ControllerHandle     The handle of the controller to start. This\r
+                                   handle must support a protocol interface\r
+                                   that supplies an I/O abstraction to the\r
+                                   driver.\r
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a\r
+                                   device path.  This parameter is ignored by\r
+                                   device drivers, and is optional for bus\r
+                                   drivers. For a bus driver, if this parameter\r
+                                   is NULL, then handles for all the children\r
+                                   of Controller are created by this driver. If\r
+                                   this parameter is not NULL and the first\r
+                                   Device Path Node is not the End of Device\r
+                                   Path Node, then only the handle for the\r
+                                   child device specified by the first Device\r
+                                   Path Node of RemainingDevicePath is created\r
+                                   by this driver. If the first Device Path\r
+                                   Node of RemainingDevicePath is the End of\r
+                                   Device Path Node, no child handle is created\r
+                                   by this driver.\r
+\r
+  @retval EFI_SUCCESS              The device was started.\r
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a\r
+                                   device error.\r
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a\r
+                                   lack of resources.\r
+  @retval Others                   The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioBusDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  EFI_PCI_IO_PROTOCOL            *PciIo;\r
+  EFI_DEVICE_PATH_PROTOCOL       *ParentDevicePath;\r
+  UINT64                         Supports;\r
+  UINT64                         OriginalAttributes;\r
+  UINT64                         Attributes;\r
+  BOOLEAN                        Enabled;\r
+  SIO_BUS_DRIVER_PRIVATE_DATA    *Private;\r
+  UINT32                         ChildDeviceNumber;\r
+\r
+  Enabled            = FALSE;\r
+  Supports           = 0;\r
+  OriginalAttributes = 0;\r
+  Private            = NULL;\r
+\r
+  //\r
+  // Open the PCI I/O Protocol Interface\r
+  //\r
+  PciIo = NULL;\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID**) &PciIo,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Open Device Path Protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath,\r
+                  This->DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiPciIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Get supported PCI attributes\r
+  //\r
+  Status = PciIo->Attributes (\r
+                    PciIo,\r
+                    EfiPciIoAttributeOperationSupported,\r
+                    0,\r
+                    &Supports\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Supports &= (UINT64) (EFI_PCI_IO_ATTRIBUTE_ISA_IO |\r
+                        EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);\r
+  if (Supports == 0 ||\r
+      Supports == (EFI_PCI_IO_ATTRIBUTE_ISA_IO |\r
+                   EFI_PCI_IO_ATTRIBUTE_ISA_IO_16)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Done;\r
+  }\r
+\r
+  Status = PciIo->Attributes (\r
+                    PciIo,\r
+                    EfiPciIoAttributeOperationGet,\r
+                    0,\r
+                    &OriginalAttributes\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Attributes = EFI_PCI_DEVICE_ENABLE |\r
+               Supports |\r
+               EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
+  Status = PciIo->Attributes (\r
+                    PciIo,\r
+                    EfiPciIoAttributeOperationEnable,\r
+                    Attributes,\r
+                    NULL\r
+                    );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Enabled = TRUE;\r
+\r
+  //\r
+  // Store the OriginalAttributes for the restore in BindingStop()\r
+  //\r
+  Private = AllocateZeroPool (sizeof (SIO_BUS_DRIVER_PRIVATE_DATA));\r
+  if (Private == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+  Private->PciIo              = PciIo;\r
+  Private->OriginalAttributes = OriginalAttributes;\r
+\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &Controller,\r
+                  &gEfiCallerIdGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  Private\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Report status code for the start of general controller initialization\r
+  //\r
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+    EFI_PROGRESS_CODE,\r
+    (EFI_IO_BUS_LPC | EFI_IOB_PC_INIT),\r
+    ParentDevicePath\r
+    );\r
+\r
+  //\r
+  // Report status code for the start of enabling devices on the bus\r
+  //\r
+  REPORT_STATUS_CODE_WITH_DEVICE_PATH (\r
+    EFI_PROGRESS_CODE,\r
+    (EFI_IO_BUS_LPC | EFI_IOB_PC_ENABLE),\r
+    ParentDevicePath\r
+    );\r
+\r
+  //\r
+  // Create all the children upon the first entrance\r
+  //\r
+  ChildDeviceNumber = SioCreateAllChildDevices (\r
+                        This,\r
+                        Controller,\r
+                        PciIo,\r
+                        ParentDevicePath\r
+                        );\r
+  if (ChildDeviceNumber == 0) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
+\r
+Done:\r
+  if (EFI_ERROR (Status)) {\r
+    if (PciIo != NULL && Enabled) {\r
+      PciIo->Attributes (\r
+               PciIo,\r
+               EfiPciIoAttributeOperationSet,\r
+               OriginalAttributes,\r
+               NULL\r
+               );\r
+    }\r
+\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiDevicePathProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+\r
+    gBS->CloseProtocol (\r
+           Controller,\r
+           &gEfiPciIoProtocolGuid,\r
+           This->DriverBindingHandle,\r
+           Controller\r
+           );\r
+\r
+    if (Private != NULL) {\r
+      gBS->UninstallMultipleProtocolInterfaces (\r
+             Controller,\r
+             &gEfiCallerIdGuid,\r
+             Private,\r
+             NULL\r
+             );\r
+      FreePool (Private);\r
+    }\r
+\r
+    return Status;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Stops a device controller or a bus controller.\r
+\r
+  The Stop() function is designed to be invoked from the EFI boot service\r
+  DisconnectController(). As a result, much of the error checking on the\r
+  parameters to Stop() has been moved into this common boot service. It is\r
+  legal to call Stop() from other locations, but the following calling\r
+  restrictions must be followed or the system behavior will not be\r
+  deterministic.\r
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous\r
+     call to this same driver's Start() function.\r
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a\r
+     valid EFI_HANDLE. In addition, all of these handles must have been created\r
+     in this driver's Start() function, and the Start() function must have\r
+     called OpenProtocol() on ControllerHandle with an Attribute of\r
+     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+\r
+  @param[in]  This               A pointer to the EFI_DRIVER_BINDING_PROTOCOL\r
+                                 instance.\r
+  @param[in]  ControllerHandle   A handle to the device being stopped. The\r
+                                 handle must support a bus specific I/O\r
+                                 protocol for the driver to use to stop the\r
+                                 device.\r
+  @param[in]  NumberOfChildren   The number of child device handles in\r
+                                 ChildHandleBuffer.\r
+  @param[in]  ChildHandleBuffer  An array of child handles to be freed. May be\r
+                                 NULL if NumberOfChildren is 0.\r
+\r
+  @retval EFI_SUCCESS            The device was stopped.\r
+  @retval EFI_DEVICE_ERROR       The device could not be stopped due to a\r
+                                 device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioBusDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN  EFI_HANDLE                     Controller,\r
+  IN  UINTN                          NumberOfChildren,\r
+  IN  EFI_HANDLE                     *ChildHandleBuffer\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  SIO_BUS_DRIVER_PRIVATE_DATA    *Private;\r
+  UINTN                          Index;\r
+  BOOLEAN                        AllChildrenStopped;\r
+  EFI_SIO_PROTOCOL               *Sio;\r
+  SIO_DEV                        *SioDevice;\r
+  EFI_PCI_IO_PROTOCOL            *PciIo;\r
+\r
+  if (NumberOfChildren == 0) {\r
+    //\r
+    // Restore PCI attributes\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    Controller,\r
+                    &gEfiCallerIdGuid,\r
+                    (VOID **) &Private,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = Private->PciIo->Attributes (\r
+                               Private->PciIo,\r
+                               EfiPciIoAttributeOperationSet,\r
+                               Private->OriginalAttributes,\r
+                               NULL\r
+                               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    gBS->UninstallProtocolInterface (\r
+          Controller,\r
+          &gEfiCallerIdGuid,\r
+          Private\r
+          );\r
+    FreePool (Private);\r
+\r
+    //\r
+    // Close the bus driver\r
+    //\r
+    Status = gBS->CloseProtocol (\r
+                    Controller,\r
+                    &gEfiDevicePathProtocolGuid,\r
+                    This->DriverBindingHandle,\r
+                    Controller\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Status = gBS->CloseProtocol (\r
+                    Controller,\r
+                    &gEfiPciIoProtocolGuid,\r
+                    This->DriverBindingHandle,\r
+                    Controller\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Stop all the children\r
+  //\r
+  AllChildrenStopped = TRUE;\r
+\r
+  for (Index = 0; Index < NumberOfChildren; Index++) {\r
+    Status = gBS->OpenProtocol (\r
+                    ChildHandleBuffer[Index],\r
+                    &gEfiSioProtocolGuid,\r
+                    (VOID **) &Sio,\r
+                    This->DriverBindingHandle,\r
+                    Controller,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    if (!EFI_ERROR (Status)) {\r
+      SioDevice = SIO_DEV_FROM_SIO (Sio);\r
+\r
+      //\r
+      // Close the child handle\r
+      //\r
+      Status = gBS->CloseProtocol (\r
+                      Controller,\r
+                      &gEfiPciIoProtocolGuid,\r
+                      This->DriverBindingHandle,\r
+                      ChildHandleBuffer[Index]\r
+                      );\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                      ChildHandleBuffer[Index],\r
+                      &gEfiDevicePathProtocolGuid,\r
+                      SioDevice->DevicePath,\r
+                      &gEfiSioProtocolGuid,\r
+                      &SioDevice->Sio,\r
+                      NULL\r
+                      );\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+        FreePool (SioDevice->DevicePath);\r
+        FreePool (SioDevice);\r
+      } else {\r
+        //\r
+        // Re-open PCI IO Protocol on behalf of the child device\r
+        // because of failure of destroying the child device handle\r
+        //\r
+        gBS->OpenProtocol (\r
+               Controller,\r
+               &gEfiPciIoProtocolGuid,\r
+               (VOID **) &PciIo,\r
+               This->DriverBindingHandle,\r
+               ChildHandleBuffer[Index],\r
+               EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+               );\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
+  The entry point for the SioBusDxe driver.\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
+SioBusDxeDriverEntryPoint (\r
+  IN EFI_HANDLE          ImageHandle,\r
+  IN EFI_SYSTEM_TABLE    *SystemTable\r
+  )\r
+{\r
+  //\r
+  // Install driver model protocol(s).\r
+  //\r
+  return EfiLibInstallDriverBindingComponentName2 (\r
+           ImageHandle,\r
+           SystemTable,\r
+           &gSioBusDriverBinding,\r
+           ImageHandle,\r
+           &gSioBusComponentName,\r
+           &gSioBusComponentName2\r
+           );\r
+}\r
diff --git a/OvmfPkg/SioBusDxe/SioBusDxe.h b/OvmfPkg/SioBusDxe/SioBusDxe.h
new file mode 100644 (file)
index 0000000..1455c48
--- /dev/null
@@ -0,0 +1,332 @@
+/** @file\r
+  The SioBusDxe driver is used to create child devices on the ISA bus and\r
+  installs the Super I/O protocols on them.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions\r
+  of the BSD License which accompanies this distribution.  The\r
+  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
+#ifndef __SIO_BUS_DXE_H__\r
+#define __SIO_BUS_DXE_H__\r
+\r
+#include <Uefi.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/SuperIo.h>\r
+\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DevicePathLib.h>\r
+\r
+#include "SioService.h"\r
+\r
+//\r
+// SIO Bus driver private data structure\r
+//\r
+typedef struct {\r
+  EFI_PCI_IO_PROTOCOL    *PciIo;\r
+  UINT64                 OriginalAttributes;\r
+} SIO_BUS_DRIVER_PRIVATE_DATA;\r
+\r
+\r
+//\r
+// Global Variables\r
+//\r
+extern EFI_COMPONENT_NAME_PROTOCOL  gSioBusComponentName;\r
+extern EFI_COMPONENT_NAME2_PROTOCOL gSioBusComponentName2;\r
+\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the driver.\r
+\r
+  This function retrieves the user readable name of a driver in the form of a\r
+  Unicode string. If the driver specified by This has a user readable name in\r
+  the language specified by Language, then a pointer to the driver name is\r
+  returned in DriverName, and EFI_SUCCESS is returned. If the driver specified\r
+  by This does not support the language specified by Language, then\r
+  EFI_UNSUPPORTED is returned.\r
+\r
+  @param[in]  This              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL\r
+                                or EFI_COMPONENT_NAME_PROTOCOL instance.\r
+  @param[in]  Language          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language. This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified\r
+                                in RFC 4646 or ISO 639-2 language code format.\r
+  @param[out] DriverName        A pointer to the Unicode string to return. This\r
+                                Unicode string is the name of the driver\r
+                                specified by This in the language specified by\r
+                                Language.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the Driver specified by\r
+                                This and the language specified by Language was\r
+                                returned in DriverName.\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+  @retval EFI_INVALID_PARAMETER DriverName is NULL.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioBusComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL    *This,\r
+  IN  CHAR8                          *Language,\r
+  OUT CHAR16                         **DriverName\r
+  );\r
+\r
+/**\r
+  Retrieves a Unicode string that is the user readable name of the controller\r
+  that is being managed by a driver.\r
+\r
+  This function retrieves the user readable name of the controller specified by\r
+  ControllerHandle and ChildHandle in the form of a Unicode string. If the\r
+  driver specified by This has a user readable name in the language specified\r
+  by Language, then a pointer to the controller name is returned in\r
+  ControllerName, and EFI_SUCCESS is returned.  If the driver specified by This\r
+  is not currently managing the controller specified by ControllerHandle and\r
+  ChildHandle, then EFI_UNSUPPORTED is returned.  If the driver specified by\r
+  This does not support the language specified by Language, then\r
+  EFI_UNSUPPORTED is returned.\r
+\r
+  @param[in]  This              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL\r
+                                or EFI_COMPONENT_NAME_PROTOCOL instance.\r
+  @param[in]  ControllerHandle  The handle of a controller that the driver\r
+                                specified by This is managing.  This handle\r
+                                specifies the controller whose name is to be\r
+                                returned.\r
+  @param[in]  ChildHandle       The handle of the child controller to retrieve\r
+                                the name of.  This is an optional parameter\r
+                                that may be NULL.  It will be NULL for device\r
+                                drivers.  It will also be NULL for a bus\r
+                                drivers that wish to retrieve the name of the\r
+                                bus controller.  It will not be NULL for a bus\r
+                                driver that wishes to retrieve the name of a\r
+                                child controller.\r
+  @param[in]  Language          A pointer to a Null-terminated ASCII string\r
+                                array indicating the language.  This is the\r
+                                language of the driver name that the caller is\r
+                                requesting, and it must match one of the\r
+                                languages specified in SupportedLanguages. The\r
+                                number of languages supported by a driver is up\r
+                                to the driver writer. Language is specified in\r
+                                RFC 4646 or ISO 639-2 language code format.\r
+  @param[out] ControllerName    A pointer to the Unicode string to return.\r
+                                This Unicode string is the name of the\r
+                                controller specified by ControllerHandle and\r
+                                ChildHandle in the language specified by\r
+                                Language from the point of view of the driver\r
+                                specified by This.\r
+\r
+  @retval EFI_SUCCESS           The Unicode string for the user readable name\r
+                                in the language specified by Language for the\r
+                                driver specified by This was returned in\r
+                                DriverName.\r
+  @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid\r
+                                EFI_HANDLE.\r
+  @retval EFI_INVALID_PARAMETER Language is NULL.\r
+  @retval EFI_INVALID_PARAMETER ControllerName is NULL.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This is not currently\r
+                                managing the controller specified by\r
+                                ControllerHandle and ChildHandle.\r
+  @retval EFI_UNSUPPORTED       The driver specified by This does not support\r
+                                the language specified by Language.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioBusComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL    *This,\r
+  IN  EFI_HANDLE                     ControllerHandle,\r
+  IN  EFI_HANDLE                     ChildHandle        OPTIONAL,\r
+  IN  CHAR8                          *Language,\r
+  OUT CHAR16                         **ControllerName\r
+  );\r
+\r
+\r
+//\r
+// Driver Binding Protocol interfaces\r
+//\r
+\r
+/**\r
+  Tests to see if this driver supports a given controller. If a child device is\r
+  provided, it further tests to see if this driver supports creating a handle\r
+  for the specified child device.\r
+\r
+  This function checks to see if the driver specified by This supports the\r
+  device specified by ControllerHandle. Drivers will typically use the device\r
+  path attached to ControllerHandle and/or the services from the bus I/O\r
+  abstraction attached to ControllerHandle to determine if the driver supports\r
+  ControllerHandle. This function may be called many times during platform\r
+  initialization. In order to reduce boot times, the tests performed by this\r
+  function must be very small, and take as little time as possible to execute.\r
+  This function must not change the state of any hardware devices, and this\r
+  function must be aware that the device specified by ControllerHandle may\r
+  already be managed by the same driver or a different driver. This function\r
+  must match its calls to AllocatePages() with FreePages(), AllocatePool() with\r
+  FreePool(), and OpenProtocol() with CloseProtocol(). Since ControllerHandle\r
+  may have been previously started by the same driver, if a protocol is already\r
+  in the opened state, then it must not be closed with CloseProtocol(). This is\r
+  required to guarantee the state of ControllerHandle is not modified by this\r
+  function.\r
+\r
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL\r
+                                   instance.\r
+  @param[in]  ControllerHandle     The handle of the controller to test. This\r
+                                   handle must support a protocol interface\r
+                                   that supplies an I/O abstraction to the\r
+                                   driver.\r
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a\r
+                                   device path.  This parameter is ignored by\r
+                                   device drivers, and is optional for bus\r
+                                   drivers. For bus drivers, if this parameter\r
+                                   is not NULL, then the bus driver must\r
+                                   determine if the bus controller specified by\r
+                                   ControllerHandle and the child controller\r
+                                   specified by RemainingDevicePath are both\r
+                                   supported by this bus driver.\r
+\r
+  @retval EFI_SUCCESS              The device specified by ControllerHandle and\r
+                                   RemainingDevicePath is supported by the\r
+                                   driver specified by This.\r
+  @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and\r
+                                   RemainingDevicePath is already being managed\r
+                                   by the driver specified by This.\r
+  @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and\r
+                                   RemainingDevicePath is already being managed\r
+                                   by a different driver or an application that\r
+                                   requires exclusive access.\r
+  @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and\r
+                                   RemainingDevicePath is not supported by the\r
+                                   driver specified by This.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioBusDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Starts a device controller or a bus controller.\r
+\r
+  The Start() function is designed to be invoked from the EFI boot service\r
+  ConnectController(). As a result, much of the error checking on the\r
+  parameters to Start() has been moved into this common boot service. It is\r
+  legal to call Start() from other locations, but the following calling\r
+  restrictions must be followed or the system behavior will not be\r
+  deterministic.\r
+  1. ControllerHandle must be a valid EFI_HANDLE.\r
+  2. If RemainingDevicePath is not NULL, then it must be a pointer to a\r
+     naturally aligned EFI_DEVICE_PATH_PROTOCOL.\r
+  3. Prior to calling Start(), the Supported() function for the driver\r
+     specified by This must have been called with the same calling parameters,\r
+     and Supported() must have returned EFI_SUCCESS.\r
+\r
+  @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL\r
+                                   instance.\r
+  @param[in]  ControllerHandle     The handle of the controller to start. This\r
+                                   handle must support a protocol interface\r
+                                   that supplies an I/O abstraction to the\r
+                                   driver.\r
+  @param[in]  RemainingDevicePath  A pointer to the remaining portion of a\r
+                                   device path.  This parameter is ignored by\r
+                                   device drivers, and is optional for bus\r
+                                   drivers. For a bus driver, if this parameter\r
+                                   is NULL, then handles for all the children\r
+                                   of Controller are created by this driver. If\r
+                                   this parameter is not NULL and the first\r
+                                   Device Path Node is not the End of Device\r
+                                   Path Node, then only the handle for the\r
+                                   child device specified by the first Device\r
+                                   Path Node of RemainingDevicePath is created\r
+                                   by this driver. If the first Device Path\r
+                                   Node of RemainingDevicePath is the End of\r
+                                   Device Path Node, no child handle is created\r
+                                   by this driver.\r
+\r
+  @retval EFI_SUCCESS              The device was started.\r
+  @retval EFI_DEVICE_ERROR         The device could not be started due to a\r
+                                   device error.\r
+  @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a\r
+                                   lack of resources.\r
+  @retval Others                   The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioBusDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN EFI_HANDLE                     Controller,\r
+  IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath\r
+  );\r
+\r
+/**\r
+  Stops a device controller or a bus controller.\r
+\r
+  The Stop() function is designed to be invoked from the EFI boot service\r
+  DisconnectController(). As a result, much of the error checking on the\r
+  parameters to Stop() has been moved into this common boot service. It is\r
+  legal to call Stop() from other locations, but the following calling\r
+  restrictions must be followed or the system behavior will not be\r
+  deterministic.\r
+  1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous\r
+     call to this same driver's Start() function.\r
+  2. The first NumberOfChildren handles of ChildHandleBuffer must all be a\r
+     valid EFI_HANDLE. In addition, all of these handles must have been created\r
+     in this driver's Start() function, and the Start() function must have\r
+     called OpenProtocol() on ControllerHandle with an Attribute of\r
+     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+\r
+  @param[in]  This               A pointer to the EFI_DRIVER_BINDING_PROTOCOL\r
+                                 instance.\r
+  @param[in]  ControllerHandle   A handle to the device being stopped. The\r
+                                 handle must support a bus specific I/O\r
+                                 protocol for the driver to use to stop the\r
+                                 device.\r
+  @param[in]  NumberOfChildren   The number of child device handles in\r
+                                 ChildHandleBuffer.\r
+  @param[in]  ChildHandleBuffer  An array of child handles to be freed. May be\r
+                                 NULL if NumberOfChildren is 0.\r
+\r
+  @retval EFI_SUCCESS            The device was stopped.\r
+  @retval EFI_DEVICE_ERROR       The device could not be stopped due to a\r
+                                 device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioBusDriverBindingStop (\r
+  IN  EFI_DRIVER_BINDING_PROTOCOL    *This,\r
+  IN  EFI_HANDLE                     Controller,\r
+  IN  UINTN                          NumberOfChildren,\r
+  IN  EFI_HANDLE                     *ChildHandleBuffer\r
+  );\r
+\r
+#endif  // __SIO_BUS_DXE_H__\r
diff --git a/OvmfPkg/SioBusDxe/SioBusDxe.inf b/OvmfPkg/SioBusDxe/SioBusDxe.inf
new file mode 100644 (file)
index 0000000..5c462f1
--- /dev/null
@@ -0,0 +1,54 @@
+## @file\r
+#  The SioBusDxe driver is used to create child devices on the ISA bus and\r
+#  installs the Super I/O protocols on them.\r
+#\r
+#  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+#\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
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = SioBusDxe\r
+  MODULE_UNI_FILE                = SioBusDxe.uni\r
+  FILE_GUID                      = 864E1CA8-85EB-4D63-9DCC-6E0FC90FFD55\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  ENTRY_POINT                    = SioBusDxeDriverEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 EBC\r
+#\r
+\r
+[Sources]\r
+  ComponentName.c\r
+  SioService.c\r
+  SioService.h\r
+  SioBusDxe.c\r
+  SioBusDxe.h\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiDriverEntryPoint\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  DebugLib\r
+  ReportStatusCodeLib\r
+  MemoryAllocationLib\r
+  BaseMemoryLib\r
+  DevicePathLib\r
+\r
+[Protocols]\r
+  gEfiPciIoProtocolGuid    ## TO_START\r
+  gEfiSioProtocolGuid      ## BY_START\r
diff --git a/OvmfPkg/SioBusDxe/SioBusDxe.uni b/OvmfPkg/SioBusDxe/SioBusDxe.uni
new file mode 100644 (file)
index 0000000..4793180
--- /dev/null
@@ -0,0 +1,21 @@
+// /** @file\r
+// The SioBusDxe driver is used to create child devices on the ISA bus and\r
+// installs the Super I/O protocols on them.\r
+//\r
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+//\r
+// This program and the accompanying materials\r
+// are licensed and made available under the terms and conditions\r
+// of the BSD License which accompanies this distribution.  The\r
+// 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
+#string STR_MODULE_ABSTRACT       #language en-US "Manage ISA devices on the ISA bus"\r
+\r
+#string STR_MODULE_DESCRIPTION    #language en-US "The SioBusDxe driver is used to create child devices on the ISA bus and installs the Super I/O protocols on them."\r
diff --git a/OvmfPkg/SioBusDxe/SioService.c b/OvmfPkg/SioBusDxe/SioService.c
new file mode 100644 (file)
index 0000000..6a97a4a
--- /dev/null
@@ -0,0 +1,405 @@
+/** @file\r
+  The SioBusDxe driver is used to create child devices on the ISA bus and\r
+  installs the Super I/O protocols on them.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions\r
+  of the BSD License which accompanies this distribution.  The\r
+  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
+#include "SioBusDxe.h"\r
+\r
+//\r
+// Super I/O Protocol interfaces\r
+//\r
+EFI_SIO_PROTOCOL mSioInterface = {\r
+  SioRegisterAccess,\r
+  SioGetResources,\r
+  SioSetResources,\r
+  SioPossibleResources,\r
+  SioModify\r
+};\r
+\r
+//\r
+// COM 1 UART Controller\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED\r
+SIO_RESOURCES_IO mCom1Resources = {\r
+  { { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x3F8, 8 },\r
+  { ACPI_END_TAG_DESCRIPTOR,                    0        }\r
+};\r
+\r
+//\r
+// COM 2 UART Controller\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED\r
+SIO_RESOURCES_IO mCom2Resources = {\r
+  { { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x2F8, 8 },\r
+  { ACPI_END_TAG_DESCRIPTOR,                    0        }\r
+};\r
+\r
+//\r
+// PS/2 Keyboard Controller\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED\r
+SIO_RESOURCES_IO mPs2KeyboardDeviceResources = {\r
+  { { ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR }, 0x60, 5 },\r
+  { ACPI_END_TAG_DESCRIPTOR,                    0       }\r
+};\r
+\r
+//\r
+// Table of SIO Controllers\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED\r
+SIO_DEVICE_INFO mDevicesInfo[] = {\r
+  {\r
+    EISA_PNP_ID (0x501),\r
+    0,\r
+    { (ACPI_SMALL_RESOURCE_HEADER *) &mCom1Resources }\r
+  },  // COM 1 UART Controller\r
+  {\r
+    EISA_PNP_ID (0x501),\r
+    1,\r
+    { (ACPI_SMALL_RESOURCE_HEADER *) &mCom2Resources }\r
+  },  // COM 2 UART Controller\r
+  {\r
+    EISA_PNP_ID(0x303),\r
+    0,\r
+    { (ACPI_SMALL_RESOURCE_HEADER *) &mPs2KeyboardDeviceResources }\r
+  }   // PS/2 Keyboard Controller\r
+};\r
+\r
+//\r
+// ACPI Device Path Node template\r
+//\r
+GLOBAL_REMOVE_IF_UNREFERENCED\r
+ACPI_HID_DEVICE_PATH mAcpiDeviceNodeTemplate = {\r
+  {        // Header\r
+    ACPI_DEVICE_PATH,\r
+    ACPI_DP,\r
+    {\r
+      (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),\r
+      (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)\r
+    }\r
+  },\r
+  0x0,     // HID\r
+  0x0      // UID\r
+};\r
+\r
+\r
+/**\r
+  Provides a low level access to the registers for the Super I/O.\r
+\r
+  @param[in]     This           Indicates a pointer to the calling context.\r
+  @param[in]     Write          Specifies the type of the register operation.\r
+                                If this parameter is TRUE, Value is interpreted\r
+                                as an input parameter and the operation is a\r
+                                register write. If this parameter is FALSE,\r
+                                Value is interpreted as an output parameter and\r
+                                the operation is a register read.\r
+  @param[in]     ExitCfgMode    Exit Configuration Mode Indicator. If this\r
+                                parameter is set to TRUE, the Super I/O driver\r
+                                will turn off configuration mode of the Super\r
+                                I/O prior to returning from this function. If\r
+                                this parameter is set to FALSE, the Super I/O\r
+                                driver will leave Super I/O in the\r
+                                configuration mode. The Super I/O driver must\r
+                                track the current state of the Super I/O and\r
+                                enable the configuration mode of Super I/O if\r
+                                necessary prior to register access.\r
+  @param[in]     Register       Register number.\r
+  @param[in,out] Value          If Write is TRUE, Value is a pointer to the\r
+                                buffer containing the byte of data to be\r
+                                written to the Super I/O register. If Write is\r
+                                FALSE, Value is a pointer to the destination\r
+                                buffer for the byte of data to be read from the\r
+                                Super I/O register.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER The Value is NULL.\r
+  @retval EFI_INVALID_PARAMETER Invalid Register number.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioRegisterAccess (\r
+  IN CONST EFI_SIO_PROTOCOL    *This,\r
+  IN       BOOLEAN             Write,\r
+  IN       BOOLEAN             ExitCfgMode,\r
+  IN       UINT8               Register,\r
+  IN OUT   UINT8               *Value\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Provides an interface to get a list of the current resources consumed by the\r
+  device in the ACPI Resource Descriptor format.\r
+\r
+  GetResources() returns a list of resources currently consumed by the device.\r
+  The ResourceList is a pointer to the buffer containing resource descriptors\r
+  for the device. The descriptors are in the format of Small or Large ACPI\r
+  resource descriptor as defined by ACPI specification (2.0 & 3.0). The buffer\r
+  of resource descriptors is terminated with the 'End tag' resource descriptor.\r
+\r
+  @param[in]  This              Indicates a pointer to the calling context.\r
+  @param[out] ResourceList      A pointer to an ACPI resource descriptor list\r
+                                that defines the current resources used by the\r
+                                device.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER ResourceList is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioGetResources (\r
+  IN CONST EFI_SIO_PROTOCOL            *This,\r
+  OUT      ACPI_RESOURCE_HEADER_PTR    *ResourceList\r
+  )\r
+{\r
+  SIO_DEV    *SioDevice;\r
+\r
+  if (ResourceList == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  SioDevice = SIO_DEV_FROM_SIO (This);\r
+  if (SioDevice->DeviceIndex < ARRAY_SIZE (mDevicesInfo)) {\r
+    *ResourceList = mDevicesInfo[SioDevice->DeviceIndex].Resources;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Sets the resources for the device.\r
+\r
+  @param[in] This               Indicates a pointer to the calling context.\r
+  @param[in] ResourceList       Pointer to the ACPI resource descriptor list.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER ResourceList is invalid.\r
+  @retval EFI_ACCESS_DENIED     Some of the resources in ResourceList are in\r
+                                use.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioSetResources (\r
+  IN CONST EFI_SIO_PROTOCOL            *This,\r
+  IN       ACPI_RESOURCE_HEADER_PTR    ResourceList\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Provides a collection of resource descriptor lists. Each resource descriptor\r
+  list in the collection defines a combination of resources that can\r
+  potentially be used by the device.\r
+\r
+  @param[in]  This                  Indicates a pointer to the calling context.\r
+  @param[out] ResourceCollection    Collection of the resource descriptor\r
+                                    lists.\r
+\r
+  @retval EFI_SUCCESS               The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER     ResourceCollection is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioPossibleResources (\r
+  IN CONST EFI_SIO_PROTOCOL            *This,\r
+  OUT      ACPI_RESOURCE_HEADER_PTR    *ResourceCollection\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Provides an interface for a table based programming of the Super I/O\r
+  registers.\r
+\r
+  The Modify() function provides an interface for table based programming of\r
+  the Super I/O registers. This function can be used to perform programming of\r
+  multiple Super I/O registers with a single function call. For each table\r
+  entry, the Register is read, its content is bitwise ANDed with AndMask, and\r
+  then ORed with OrMask before being written back to the Register. The Super\r
+  I/O driver must track the current state of the Super I/O and enable the\r
+  configuration mode of Super I/O if necessary prior to table processing. Once\r
+  the table is processed, the Super I/O device has to be returned to the\r
+  original state.\r
+\r
+  @param[in] This               Indicates a pointer to the calling context.\r
+  @param[in] Command            A pointer to an array of NumberOfCommands\r
+                                EFI_SIO_REGISTER_MODIFY structures. Each\r
+                                structure specifies a single Super I/O register\r
+                                modify operation.\r
+  @param[in] NumberOfCommands   Number of elements in the Command array.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER Command is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioModify (\r
+  IN CONST EFI_SIO_PROTOCOL           *This,\r
+  IN CONST EFI_SIO_REGISTER_MODIFY    *Command,\r
+  IN       UINTN                      NumberOfCommands\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Create the child device with a given device index.\r
+\r
+  @param[in] This              The EFI_DRIVER_BINDING_PROTOCOL instance.\r
+  @param[in] Controller        The handle of ISA bus controller.\r
+  @param[in] PciIo             The pointer to the PCI protocol.\r
+  @param[in] ParentDevicePath  Device path of the ISA bus controller.\r
+  @param[in] DeviceIndex       Index of the device supported by this driver.\r
+\r
+  @retval EFI_SUCCESS          The child device has been created successfully.\r
+  @retval Others               Error occured during the child device creation.\r
+\r
+**/\r
+EFI_STATUS\r
+SioCreateChildDevice (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_PCI_IO_PROTOCOL          *PciIo,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath,\r
+  IN UINT32                       DeviceIndex\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  SIO_DEV       *SioDevice;\r
+\r
+  //\r
+  // Initialize the SIO_DEV structure\r
+  //\r
+  SioDevice = AllocateZeroPool (sizeof (SIO_DEV));\r
+  if (SioDevice == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  SioDevice->Signature  = SIO_DEV_SIGNATURE;\r
+  SioDevice->Handle     = NULL;\r
+  SioDevice->PciIo      = PciIo;\r
+\r
+  //\r
+  // Construct the child device path\r
+  //\r
+  mAcpiDeviceNodeTemplate.HID = mDevicesInfo[DeviceIndex].Hid;\r
+  mAcpiDeviceNodeTemplate.UID = mDevicesInfo[DeviceIndex].Uid;\r
+  SioDevice->DevicePath = AppendDevicePathNode (\r
+                            ParentDevicePath,\r
+                            (EFI_DEVICE_PATH_PROTOCOL *) &mAcpiDeviceNodeTemplate\r
+                            );\r
+  if (SioDevice->DevicePath == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  CopyMem (&SioDevice->Sio, &mSioInterface, sizeof (EFI_SIO_PROTOCOL));\r
+  SioDevice->DeviceIndex = DeviceIndex;\r
+\r
+  //\r
+  // Create a child handle and install Device Path and Super I/O protocols\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &SioDevice->Handle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  SioDevice->DevicePath,\r
+                  &gEfiSioProtocolGuid,\r
+                  &SioDevice->Sio,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciIoProtocolGuid,\r
+                  (VOID **) &PciIo,\r
+                  This->DriverBindingHandle,\r
+                  SioDevice->Handle,\r
+                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+           SioDevice->Handle,\r
+           &gEfiDevicePathProtocolGuid,\r
+           SioDevice->DevicePath,\r
+           &gEfiSioProtocolGuid,\r
+           &SioDevice->Sio,\r
+           NULL\r
+           );\r
+  }\r
+\r
+Done:\r
+  if (EFI_ERROR (Status)) {\r
+    if (SioDevice->DevicePath != NULL) {\r
+      FreePool (SioDevice->DevicePath);\r
+    }\r
+\r
+    FreePool (SioDevice);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Create all the ISA child devices on the ISA bus controller (PCI to ISA\r
+  bridge).\r
+\r
+  @param[in] This              The EFI_DRIVER_BINDING_PROTOCOL instance.\r
+  @param[in] Controller        The handle of ISA bus controller.\r
+  @param[in] PciIo             The pointer to the PCI protocol.\r
+  @param[in] ParentDevicePath  Device path of the ISA bus controller.\r
+\r
+  @retval The number of child device that is successfully created.\r
+\r
+**/\r
+UINT32\r
+SioCreateAllChildDevices (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_PCI_IO_PROTOCOL          *PciIo,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath\r
+  )\r
+{\r
+  UINT32        Index;\r
+  UINT32        ChildDeviceNumber;\r
+  EFI_STATUS    Status;\r
+\r
+  ChildDeviceNumber = 0;\r
+\r
+  for (Index = 0; Index < ARRAY_SIZE (mDevicesInfo); Index++) {\r
+    Status = SioCreateChildDevice (\r
+               This,\r
+               Controller,\r
+               PciIo,\r
+               ParentDevicePath,\r
+               Index\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      ChildDeviceNumber++;\r
+    }\r
+  }\r
+\r
+  return ChildDeviceNumber;\r
+}\r
diff --git a/OvmfPkg/SioBusDxe/SioService.h b/OvmfPkg/SioBusDxe/SioService.h
new file mode 100644 (file)
index 0000000..758703d
--- /dev/null
@@ -0,0 +1,221 @@
+/** @file\r
+  The SioBusDxe driver is used to create child devices on the ISA bus and\r
+  installs the Super I/O protocols on them.\r
+\r
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions\r
+  of the BSD License which accompanies this distribution.  The\r
+  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
+#ifndef __SIO_SERVICE_H__\r
+#define __SIO_SERVICE_H__\r
+\r
+#pragma pack(1)\r
+\r
+typedef struct {\r
+  EFI_ACPI_FIXED_LOCATION_IO_PORT_DESCRIPTOR  Io;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR                 End;\r
+} SIO_RESOURCES_IO;\r
+\r
+#pragma pack()\r
+\r
+typedef struct {\r
+  UINT32                      Hid;\r
+  UINT32                      Uid;\r
+  ACPI_RESOURCE_HEADER_PTR    Resources;\r
+} SIO_DEVICE_INFO;\r
+\r
+//\r
+// SIO device private data structure\r
+//\r
+typedef struct {\r
+  UINT32                      Signature;\r
+  EFI_HANDLE                  Handle;\r
+  EFI_PCI_IO_PROTOCOL         *PciIo;\r
+  EFI_DEVICE_PATH_PROTOCOL    *DevicePath;\r
+\r
+  EFI_SIO_PROTOCOL            Sio;\r
+  UINT32                      DeviceIndex;\r
+} SIO_DEV;\r
+#define SIO_DEV_SIGNATURE      SIGNATURE_32 ('S', 'I', 'O', 'D')\r
+#define SIO_DEV_FROM_SIO(a)    CR (a, SIO_DEV, Sio, SIO_DEV_SIGNATURE)\r
+\r
+\r
+//\r
+// Super I/O Protocol interfaces\r
+//\r
+\r
+/**\r
+  Provides a low level access to the registers for the Super I/O.\r
+\r
+  @param[in]     This           Indicates a pointer to the calling context.\r
+  @param[in]     Write          Specifies the type of the register operation.\r
+                                If this parameter is TRUE, Value is interpreted\r
+                                as an input parameter and the operation is a\r
+                                register write. If this parameter is FALSE,\r
+                                Value is interpreted as an output parameter and\r
+                                the operation is a register read.\r
+  @param[in]     ExitCfgMode    Exit Configuration Mode Indicator. If this\r
+                                parameter is set to TRUE, the Super I/O driver\r
+                                will turn off configuration mode of the Super\r
+                                I/O prior to returning from this function. If\r
+                                this parameter is set to FALSE, the Super I/O\r
+                                driver will leave Super I/O in the\r
+                                configuration mode. The Super I/O driver must\r
+                                track the current state of the Super I/O and\r
+                                enable the configuration mode of Super I/O if\r
+                                necessary prior to register access.\r
+  @param[in]     Register       Register number.\r
+  @param[in,out] Value          If Write is TRUE, Value is a pointer to the\r
+                                buffer containing the byte of data to be\r
+                                written to the Super I/O register. If Write is\r
+                                FALSE, Value is a pointer to the destination\r
+                                buffer for the byte of data to be read from the\r
+                                Super I/O register.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER The Value is NULL.\r
+  @retval EFI_INVALID_PARAMETER Invalid Register number.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioRegisterAccess (\r
+  IN CONST EFI_SIO_PROTOCOL    *This,\r
+  IN       BOOLEAN             Write,\r
+  IN       BOOLEAN             ExitCfgMode,\r
+  IN       UINT8               Register,\r
+  IN OUT   UINT8               *Value\r
+  );\r
+\r
+/**\r
+  Provides an interface to get a list of the current resources consumed by the\r
+  device in the ACPI Resource Descriptor format.\r
+\r
+  GetResources() returns a list of resources currently consumed by the device.\r
+  The ResourceList is a pointer to the buffer containing resource descriptors\r
+  for the device. The descriptors are in the format of Small or Large ACPI\r
+  resource descriptor as defined by ACPI specification (2.0 & 3.0). The buffer\r
+  of resource descriptors is terminated with the 'End tag' resource descriptor.\r
+\r
+  @param[in]  This              Indicates a pointer to the calling context.\r
+  @param[out] ResourceList      A pointer to an ACPI resource descriptor list\r
+                                that defines the current resources used by the\r
+                                device.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER ResourceList is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioGetResources (\r
+  IN CONST EFI_SIO_PROTOCOL            *This,\r
+  OUT      ACPI_RESOURCE_HEADER_PTR    *ResourceList\r
+  );\r
+\r
+/**\r
+  Sets the resources for the device.\r
+\r
+  @param[in] This               Indicates a pointer to the calling context.\r
+  @param[in] ResourceList       Pointer to the ACPI resource descriptor list.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER ResourceList is invalid.\r
+  @retval EFI_ACCESS_DENIED     Some of the resources in ResourceList are in\r
+                                use.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioSetResources (\r
+  IN CONST EFI_SIO_PROTOCOL            *This,\r
+  IN       ACPI_RESOURCE_HEADER_PTR    ResourceList\r
+  );\r
+\r
+/**\r
+  Provides a collection of resource descriptor lists. Each resource descriptor\r
+  list in the collection defines a combination of resources that can\r
+  potentially be used by the device.\r
+\r
+  @param[in]  This                  Indicates a pointer to the calling context.\r
+  @param[out] ResourceCollection    Collection of the resource descriptor\r
+                                    lists.\r
+\r
+  @retval EFI_SUCCESS               The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER     ResourceCollection is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioPossibleResources (\r
+  IN CONST EFI_SIO_PROTOCOL            *This,\r
+  OUT      ACPI_RESOURCE_HEADER_PTR    *ResourceCollection\r
+  );\r
+\r
+/**\r
+  Provides an interface for a table based programming of the Super I/O\r
+  registers.\r
+\r
+  The Modify() function provides an interface for table based programming of\r
+  the Super I/O registers. This function can be used to perform programming of\r
+  multiple Super I/O registers with a single function call. For each table\r
+  entry, the Register is read, its content is bitwise ANDed with AndMask, and\r
+  then ORed with OrMask before being written back to the Register. The Super\r
+  I/O driver must track the current state of the Super I/O and enable the\r
+  configuration mode of Super I/O if necessary prior to table processing. Once\r
+  the table is processed, the Super I/O device has to be returned to the\r
+  original state.\r
+\r
+  @param[in] This               Indicates a pointer to the calling context.\r
+  @param[in] Command            A pointer to an array of NumberOfCommands\r
+                                EFI_SIO_REGISTER_MODIFY structures. Each\r
+                                structure specifies a single Super I/O register\r
+                                modify operation.\r
+  @param[in] NumberOfCommands   Number of elements in the Command array.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER Command is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SioModify (\r
+  IN CONST EFI_SIO_PROTOCOL           *This,\r
+  IN CONST EFI_SIO_REGISTER_MODIFY    *Command,\r
+  IN       UINTN                      NumberOfCommands\r
+  );\r
+\r
+//\r
+// Internal functions\r
+//\r
+\r
+/**\r
+  Create all the ISA child devices on the ISA bus controller (PCI to ISA\r
+  bridge).\r
+\r
+  @param[in] This              The EFI_DRIVER_BINDING_PROTOCOL instance.\r
+  @param[in] Controller        The handle of ISA bus controller.\r
+  @param[in] PciIo             The pointer to the PCI protocol.\r
+  @param[in] ParentDevicePath  Device path of the ISA bus controller.\r
+\r
+  @retval The number of child device that is successfully created.\r
+\r
+**/\r
+UINT32\r
+SioCreateAllChildDevices (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   Controller,\r
+  IN EFI_PCI_IO_PROTOCOL          *PciIo,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *ParentDevicePath\r
+  );\r
+\r
+#endif  // __SIO_SERVICE_H__\r