summaryrefslogtreecommitdiff
path: root/ReferenceCode/ME/ActiveManagement/Sol
diff options
context:
space:
mode:
authorraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
committerraywu <raywu0301@gmail.com>2018-06-15 00:00:50 +0800
commitb7c51c9cf4864df6aabb99a1ae843becd577237c (patch)
treeeebe9b0d0ca03062955223097e57da84dd618b9a /ReferenceCode/ME/ActiveManagement/Sol
downloadzprj-master.tar.xz
init. 1AQQW051HEADmaster
Diffstat (limited to 'ReferenceCode/ME/ActiveManagement/Sol')
-rw-r--r--ReferenceCode/ME/ActiveManagement/Sol/Dxe/ComponentName.c187
-rw-r--r--ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.c1807
-rw-r--r--ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.cif13
-rw-r--r--ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.h787
-rw-r--r--ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.inf87
-rw-r--r--ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.mak55
-rw-r--r--ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.sdl24
7 files changed, 2960 insertions, 0 deletions
diff --git a/ReferenceCode/ME/ActiveManagement/Sol/Dxe/ComponentName.c b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/ComponentName.c
new file mode 100644
index 0000000..3e6ba9f
--- /dev/null
+++ b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/ComponentName.c
@@ -0,0 +1,187 @@
+/** @file
+ This portion is to register the Serial over Lan Controller Driver name
+
+@copyright
+ Copyright (c) 2004 - 2012 Intel Corporation. All rights
+ reserved This software and associated documentation (if any)
+ is furnished under a license and may only be used or copied in
+ accordance with the terms of the license. Except as permitted
+ by such license, no part of this software or documentation may
+ be reproduced, stored in a retrieval system, or transmitted in
+ any form or by any means without the express written consent
+ of Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+**/
+
+//
+// External include files do NOT need to be explicitly specified in real EDKII
+// environment
+//
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "PciSerial.h"
+#endif
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+PciSerialComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+PciSerialComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL mPciSerialComponentName = {
+ PciSerialComponentNameGetDriverName,
+ PciSerialComponentNameGetControllerName,
+ "eng"
+};
+
+static EFI_UNICODE_STRING_TABLE mPciSerialDriverNameTable[] = {
+ {
+ "eng",
+ L"PCI Serial Driver"
+ },
+ {
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[in] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER Language or DriverName is NULL.
+ @exception EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+**/
+EFI_STATUS
+EFIAPI
+PciSerialComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString (
+ Language,
+ mPciSerialComponentName.SupportedLanguages,
+ mPciSerialDriverNameTable,
+ DriverName
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[in] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language
+ specified by Language from the point of view of the
+ driver specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. Language or
+ ControllerName is NULL.
+ @exception EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle. The driver specified by This
+ does not support the language specified by Language.
+**/
+EFI_STATUS
+EFIAPI
+PciSerialComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ EFI_STATUS Status;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ SERIAL_DEV *SerialDevice;
+
+ ///
+ /// This is a device driver, so ChildHandle must be NULL.
+ ///
+ if (ChildHandle != NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ ///
+ /// Get the Block I/O Protocol on Controller
+ ///
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo,
+ mPciSerialControllerDriverBinding.DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Get the Serial Controller's Device structure
+ ///
+ SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo);
+
+ return LookupUnicodeString (
+ Language,
+ mPciSerialComponentName.SupportedLanguages,
+ SerialDevice->ControllerNameTable,
+ ControllerName
+ );
+}
diff --git a/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.c b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.c
new file mode 100644
index 0000000..6dba7fa
--- /dev/null
+++ b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.c
@@ -0,0 +1,1807 @@
+/** @file
+ PCI Serial driver for standard UARTS on an PCI bus.
+ Customized for Intel AMT SErial OVer LAN (82573E-Tekoa) 16550 UART Driver.
+
+@copyright
+ Copyright (c) 2004 - 2012 Intel Corporation. All rights
+ reserved This software and associated documentation (if any)
+ is furnished under a license and may only be used or copied in
+ accordance with the terms of the license. Except as permitted
+ by such license, no part of this software or documentation may
+ be reproduced, stored in a retrieval system, or transmitted in
+ any form or by any means without the express written consent
+ of Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+
+//
+// External include files do NOT need to be explicitly specified in real EDKII
+// environment
+//
+#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000)
+#include "EdkIIGlueDxe.h"
+#include "PciSerial.h"
+#include "MeAccess.h"
+#endif
+
+//
+// PCI Serial Driver Binding Protocol
+//
+EFI_DRIVER_BINDING_PROTOCOL mPciSerialControllerDriverBinding = {
+ PciSerialControllerDriverSupported,
+ PciSerialControllerDriverStart,
+ PciSerialControllerDriverStop,
+ 0x10,
+ NULL,
+ NULL
+};
+
+/**
+ This function checks to see if the driver supports a device specified by
+ "Controller handle" parameter. It is called by DXE Core StartImage() or
+ ConnectController() routines. The driver uses 'device path' and/or
+ 'services' from the Bus I/O abstraction attached to the controller handle
+ to determine if the driver support this controller handle.
+
+ Note: In the BDS (Boot Device Selection) phase, the DXE core enumerate all
+ devices (or, controller) and assigns GUIDs to them.
+
+ @param[in] This a pointer points to the Binding Protocol instance
+ @param[in] Controller The handle of controller to be tested.
+ @param[in] RemainingDevicePath A pointer to the device path. Ignored by device
+ driver but used by bus driver
+
+ @retval EFI_SUCCESS Have device to support
+ @retval EFI_NOT_FOUND The device doesn't support or relative environment not ready
+**/
+EFI_STATUS
+EFIAPI
+PciSerialControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UART_DEVICE_PATH UartNode;
+ UINT16 Buffer[2];
+ UINT16 Temp;
+ UINT8 *ByteBuffer;
+
+ ///
+ /// Init AMT library
+ ///
+ Status = AmtLibInit ();
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// We don't want the SOL Controller enabled unless
+ /// there is an remote control request. The AMT usage model
+ /// dictates this. Thus here we check for the ASF Remote
+ /// Control command wants SOL before we start the controller.
+ ///
+ if (ActiveManagementEnableSol () == FALSE) {
+ return EFI_NOT_FOUND;
+ }
+ ///
+ /// Open the IO Abstraction(s) needed to perform the supported test
+ ///
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ ///
+ /// Now test the EfiPciIoProtocol
+ ///
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+
+ if (Status == EFI_ALREADY_STARTED) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ///
+ /// Use the PCI I/O Protocol to see if Controller is standard ISA UART that
+ /// can be managed by this driver.
+ ///
+ Status = EFI_SUCCESS;
+
+ ///
+ /// Looks for a PCI CLASS / SUBCLASS / INTERFACE of 0x07 / 0x00 / 0x02
+ /// To allow supportting all PCI Devices that are 16550 compatible UARTS.
+ ///
+ /// This is point where Tekoa iAMT SOL support enabling via
+ /// Get Boot Options ASF info is used to customize PCISerial
+ /// to work for iAMT.
+ ///
+ /// Also if want general PCI Serial com devices to work as well
+ /// can duplicate this driver one for tekoa and iAMT and the other
+ /// for general serial devices.
+ ///
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (UINT32) PCI_VENDOR_ID_OFFSET,
+ (UINTN) 1,
+ (VOID *) &Buffer
+ );
+ ///
+ /// If Buffer is Not Valid (no setup info in NVRAM/FLASH) use auto mode for PTBx cfg.
+ ///
+ if ((Buffer[0] != V_ME_SOL_VENDOR_ID) || !IS_PCH_LPT_SOL_DEVICE_ID(Buffer[1])
+ ) {
+ Status = EFI_UNSUPPORTED;
+ goto Error;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ (UINT32) PCI_REVISION_ID_OFFSET,
+ (UINTN) 1,
+ (VOID *) &Buffer
+ );
+ ByteBuffer = (UINT8 *) Buffer;
+ if ((ByteBuffer[3] != PCI_CLASS_SCC) || (ByteBuffer[2] != PCI_SUBCLASS_SERIAL) || (ByteBuffer[1] != PCI_IF_16550)) {
+ Status = EFI_UNSUPPORTED;
+ goto Error;
+ }
+ ///
+ /// Make sure the PCI io space is enabled
+ ///
+ Temp = 0x0003;
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PCI_COMMAND_OFFSET,
+ 0x01,
+ (VOID*) &Temp
+ );
+
+ ///
+ /// Make sure RemainingDevicePath is valid
+ ///
+ if (RemainingDevicePath != NULL) {
+ Status = EFI_UNSUPPORTED;
+ CopyMem (&UartNode, (UART_DEVICE_PATH *) RemainingDevicePath, sizeof (UART_DEVICE_PATH));
+ if (UartNode.Header.Type != MESSAGING_DEVICE_PATH ||
+ UartNode.Header.SubType != MSG_UART_DP ||
+ DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &UartNode) != sizeof (UART_DEVICE_PATH)
+ ) {
+ goto Error;
+ }
+
+ if (UartNode.BaudRate > SERIAL_PORT_MAX_BAUD_RATE) {
+ goto Error;
+ }
+
+ if (UartNode.Parity < NoParity || UartNode.Parity > SpaceParity) {
+ goto Error;
+ }
+
+ if (UartNode.DataBits < 5 || UartNode.DataBits > 8) {
+ goto Error;
+ }
+
+ if (UartNode.StopBits < OneStopBit || UartNode.StopBits > TwoStopBits) {
+ goto Error;
+ }
+
+ if ((UartNode.DataBits == 5) && (UartNode.StopBits == TwoStopBits)) {
+ goto Error;
+ }
+
+ if ((UartNode.DataBits >= 6) && (UartNode.DataBits <= 8) && (UartNode.StopBits == OneFiveStopBits)) {
+ goto Error;
+ }
+
+ Status = EFI_SUCCESS;
+ }
+
+Error:
+ ///
+ /// Close the I/O Abstraction(s) used to perform the supported test
+ ///
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+}
+
+/**
+ This routine is called right after the .Supported() called
+ and return EFI_SUCCESS. Notes: The supported protocols are
+ checked but the Protocols are closed.
+
+ @param[in] This A pointer points to the Binding Protocol instance
+ @param[in] Controller The handle of controller to be tested. Parameter
+ passed by the caller
+ @param[in] RemainingDevicePath A pointer to the device path. Should be ignored by
+ device driver
+
+ @retval EFI_SUCCESS The driver ready and initial complete.
+ @retval Other The device doesn't initial.
+**/
+EFI_STATUS
+EFIAPI
+PciSerialControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ SERIAL_DEV *SerialDevice;
+ UINTN Index;
+ UART_DEVICE_PATH Node;
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ CHAR16 SerialPortName[sizeof (PCI_SERIAL_PORT_NAME)];
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer;
+ UINTN EntryCount;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ UINT64 *Supports;
+ UINT64 Temp;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
+ VOID **Resources;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR Temp1;
+
+ SerialDevice = NULL;
+
+ ///
+ /// Get the Parent Device Path
+ ///
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &ParentDevicePath,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ return Status;
+ }
+ ///
+ /// Grab the IO abstraction we need to get any work done
+ ///
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ goto Error;
+ }
+
+ if (Status == EFI_ALREADY_STARTED) {
+
+ if (RemainingDevicePath == NULL) {
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Make sure a child handle does not already exist. This driver can only
+ /// produce one child per serial port.
+ ///
+ Status = gBS->OpenProtocolInformation (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ &OpenInfoBuffer,
+ &EntryCount
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = EFI_ALREADY_STARTED;
+ for (Index = 0; Index < EntryCount; Index++) {
+ if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
+ Status = gBS->OpenProtocol (
+ OpenInfoBuffer[Index].ControllerHandle,
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ CopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
+ Status = SerialIo->SetAttributes (
+ SerialIo,
+ Node.BaudRate,
+ SerialIo->Mode->ReceiveFifoDepth,
+ SerialIo->Mode->Timeout,
+ Node.Parity,
+ Node.DataBits,
+ Node.StopBits
+ );
+ }
+ break;
+ }
+ }
+
+ FreePool (OpenInfoBuffer);
+ return Status;
+ }
+ ///
+ /// Initialize the serial device instance
+ ///
+ SerialDevice = AllocatePool (sizeof (SERIAL_DEV));
+ if (SerialDevice == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ ZeroMem (SerialDevice, sizeof (SERIAL_DEV));
+
+ SerialDevice->PciIo = PciIo;
+ SerialDevice->ParentDevicePath = ParentDevicePath;
+ SerialDevice->ControllerNameTable = NULL;
+
+ StrCpy (SerialPortName, L"PCI Serial Port # ");
+ SerialPortName[sizeof (PCI_SERIAL_PORT_NAME) - 2] = (CHAR16) (L'0');
+ AddUnicodeString (
+ "eng",
+ mPciSerialComponentName.SupportedLanguages,
+ &SerialDevice->ControllerNameTable,
+ (CHAR16 *) SerialPortName
+ );
+
+ Ptr = &Temp1;
+ Resources = (VOID **) &Ptr;
+ Supports = &Temp;
+ *Supports = 0x01;
+ for (Index = 0; Index < PCI_MAX_BAR; Index++) {
+ Status = SerialDevice->PciIo->GetBarAttributes (
+ PciIo,
+ (UINT8) Index,
+ Supports,
+ Resources
+ );
+ Ptr = *Resources;
+ if (Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
+ SerialDevice->BarIndex = (UINT16) Index;
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+
+ if (PciSerialPortPresent (SerialDevice) != TRUE) {
+ Status = EFI_DEVICE_ERROR;
+ goto Error;
+ }
+
+ SerialDevice->Signature = SERIAL_DEV_SIGNATURE;
+ SerialDevice->Type = UART16450;
+ SerialDevice->SoftwareLoopbackEnable = FALSE;
+ SerialDevice->HardwareFlowControl = FALSE;
+ SerialDevice->Handle = NULL;
+ SerialDevice->Receive.First = 0;
+ SerialDevice->Receive.Last = 0;
+ SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;
+ SerialDevice->Transmit.First = 0;
+ SerialDevice->Transmit.Last = 0;
+ SerialDevice->Transmit.Surplus = SERIAL_MAX_BUFFER_SIZE;
+
+ ///
+ /// Serial I/O
+ ///
+ SerialDevice->SerialIo.Revision = EFI_SERIAL_IO_PROTOCOL_REVISION;
+ SerialDevice->SerialIo.Reset = PciSerialReset;
+ SerialDevice->SerialIo.SetAttributes = PciSerialSetAttributes;
+ SerialDevice->SerialIo.SetControl = PciSerialSetControl;
+ SerialDevice->SerialIo.GetControl = PciSerialGetControl;
+ SerialDevice->SerialIo.Write = PciSerialWrite;
+ SerialDevice->SerialIo.Read = PciSerialRead;
+ SerialDevice->SerialIo.Mode = &(SerialDevice->SerialMode);
+
+ if (RemainingDevicePath != NULL) {
+ ///
+ /// Match the configuration of the RemainingDevicePath. IsHandleSupported()
+ /// already checked to make sure the RemainingDevicePath contains settings
+ /// that we can support.
+ ///
+ CopyMem (&SerialDevice->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH));
+ } else {
+ ///
+ /// Build the device path by appending the UART node to the ParentDevicePath
+ /// from the WinNtIo handle. The Uart setings are zero here, since
+ /// SetAttribute() will update them to match the default setings.
+ ///
+ ZeroMem (&SerialDevice->UartDevicePath, sizeof (UART_DEVICE_PATH));
+ SerialDevice->UartDevicePath.Header.Type = MESSAGING_DEVICE_PATH;
+ SerialDevice->UartDevicePath.Header.SubType = MSG_UART_DP;
+ SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath, sizeof (UART_DEVICE_PATH));
+ }
+ ///
+ /// Build the device path by appending the UART node to the ParentDevicePath
+ /// from the WinNtIo handle. The Uart setings are zero here, since
+ /// SetAttribute() will update them to match the current setings.
+ ///
+ SerialDevice->DevicePath = AppendDevicePathNode (
+ ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath
+ );
+
+ if (SerialDevice->DevicePath == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto Error;
+ }
+ ///
+ /// Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults.
+ ///
+ SerialDevice->SerialMode.ControlMask = SERIAL_PORT_DEFAULT_CONTROL_MASK;
+ SerialDevice->SerialMode.Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;
+ SerialDevice->SerialMode.BaudRate = SerialDevice->UartDevicePath.BaudRate;
+ SerialDevice->SerialMode.ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;
+ SerialDevice->SerialMode.DataBits = SerialDevice->UartDevicePath.DataBits;
+ SerialDevice->SerialMode.Parity = SerialDevice->UartDevicePath.Parity;
+ SerialDevice->SerialMode.StopBits = SerialDevice->UartDevicePath.StopBits;
+
+ ///
+ /// Issue a reset to initialize the COM port
+ ///
+ Status = SerialDevice->SerialIo.Reset (&SerialDevice->SerialIo);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_SUCCESS;
+ goto Error;
+ }
+ ///
+ /// Install protocol interfaces for the serial device.
+ ///
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &SerialDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ SerialDevice->DevicePath,
+ &gEfiSerialIoProtocolGuid,
+ &SerialDevice->SerialIo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ ///
+ /// Open For Child Device
+ ///
+ Status = gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ SerialDevice->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+
+Error:
+ if (EFI_ERROR (Status)) {
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ if (SerialDevice) {
+ if (SerialDevice->DevicePath) {
+ FreePool (SerialDevice->DevicePath);
+ }
+
+ FreeUnicodeStringTable (SerialDevice->ControllerNameTable);
+ FreePool (SerialDevice);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Stop.
+
+ @param[in] This Pointer to driver binding protocol
+ @param[in] Controller Controller handle to connect
+ @param[in] NumberOfChildren Number of children handle created by this driver
+ @param[in] ChildHandleBuffer Buffer containing child handle created
+
+ @retval EFI_SUCCESS Driver disconnected successfully from controller
+ @retval EFI_DEVICE_ERROR Cannot find BIOS_VIDEO_DEV structure
+**/
+EFI_STATUS
+EFIAPI
+PciSerialControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ BOOLEAN AllChildrenStopped;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ SERIAL_DEV *SerialDevice;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **) &DevicePath
+ );
+
+ ///
+ /// Complete all outstanding transactions to Controller.
+ /// Don't allow any new transaction to Controller to be started.
+ ///
+ if (NumberOfChildren == 0) {
+ ///
+ /// Close the bus driver
+ ///
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiDevicePathProtocolGuid,
+ This->DriverBindingHandle,
+ Controller
+ );
+ return Status;
+ }
+
+ AllChildrenStopped = TRUE;
+
+ for (Index = 0; Index < NumberOfChildren; Index++) {
+ Status = gBS->OpenProtocol (
+ ChildHandleBuffer[Index],
+ &gEfiSerialIoProtocolGuid,
+ (VOID **) &SerialIo,
+ This->DriverBindingHandle,
+ Controller,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (SerialIo);
+
+ Status = gBS->CloseProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index]
+ );
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid,
+ SerialDevice->DevicePath,
+ &gEfiSerialIoProtocolGuid,
+ &SerialDevice->SerialIo,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->OpenProtocol (
+ Controller,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ ChildHandleBuffer[Index],
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ } else {
+ if (SerialDevice->DevicePath) {
+ FreePool (SerialDevice->DevicePath);
+ }
+
+ FreeUnicodeStringTable (SerialDevice->ControllerNameTable);
+ FreePool (SerialDevice);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ AllChildrenStopped = FALSE;
+ }
+ }
+
+ if (AllChildrenStopped == FALSE) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Detect whether specific FIFO is full or not
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+
+ @retval TRUE The FIFO is full
+ @retval FALSE The FIFO is not full
+**/
+BOOLEAN
+PciSerialFifoFull (
+ IN SERIAL_DEV_FIFO *Fifo
+ )
+{
+ if (Fifo->Surplus == 0) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Detect whether specific FIFO is empty or not
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+
+ @retval TRUE The FIFO is empty
+ @retval FALSE The FIFO is not empty
+**/
+BOOLEAN
+PciSerialFifoEmpty (
+ IN SERIAL_DEV_FIFO *Fifo
+ )
+{
+ if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Add data to specific FIFO
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param[in] Data The data added to FIFO
+
+ @retval EFI_SUCCESS Add data to specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCES Failed to add data because FIFO is already full
+**/
+EFI_STATUS
+PciSerialFifoAdd (
+ IN SERIAL_DEV_FIFO *Fifo,
+ IN UINT8 Data
+ )
+{
+ ///
+ /// if FIFO full can not add data
+ ///
+ if (PciSerialFifoFull (Fifo)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ///
+ /// FIFO is not full can add data
+ ///
+ Fifo->Data[Fifo->Last] = Data;
+ Fifo->Surplus--;
+ Fifo->Last++;
+ if (Fifo->Last == SERIAL_MAX_BUFFER_SIZE) {
+ Fifo->Last = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Remove data from specific FIFO
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param[in] Data The data removed from FIFO
+
+ @retval EFI_SUCCESS Remove data from specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCES Failed to remove data because FIFO is empty
+**/
+EFI_STATUS
+PciSerialFifoRemove (
+ IN SERIAL_DEV_FIFO *Fifo,
+ OUT UINT8 *Data
+ )
+{
+ ///
+ /// if FIFO is empty, no data can remove
+ ///
+ if (PciSerialFifoEmpty (Fifo)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ///
+ /// FIFO is not empty, can remove data
+ ///
+ *Data = Fifo->Data[Fifo->First];
+ Fifo->Surplus++;
+ Fifo->First++;
+ if (Fifo->First == SERIAL_MAX_BUFFER_SIZE) {
+ Fifo->First = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads and writes all avaliable data.
+
+ @param[in] SerialDevice The device to flush
+
+ @retval EFI_SUCCESS Data was read/written successfully.
+ @retval EFI_OUT_OF_RESOURCES Failed because software receive FIFO is full. Note, when
+ this happens, pending writes are not done.
+**/
+EFI_STATUS
+PciSerialReceiveTransmit (
+ IN SERIAL_DEV *SerialDevice
+ )
+{
+ SERIAL_PORT_LSR Lsr;
+ UINT8 Data;
+ BOOLEAN ReceiveFifoFull;
+ SERIAL_PORT_MSR Msr;
+ SERIAL_PORT_MCR Mcr;
+ UINTN TimeOut;
+
+ Data = 0;
+
+ ///
+ /// Begin the read or write
+ ///
+ if (SerialDevice->SoftwareLoopbackEnable) {
+ do {
+ ReceiveFifoFull = PciSerialFifoFull (&SerialDevice->Receive);
+ if (!PciSerialFifoEmpty (&SerialDevice->Transmit)) {
+ PciSerialFifoRemove (&SerialDevice->Transmit, &Data);
+ if (ReceiveFifoFull) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ PciSerialFifoAdd (&SerialDevice->Receive, Data);
+ }
+ } while (!PciSerialFifoEmpty (&SerialDevice->Transmit));
+ } else {
+ ReceiveFifoFull = PciSerialFifoFull (&SerialDevice->Receive);
+ do {
+ Lsr.Data = READ_LSR (SerialDevice->PciIo, SerialDevice->BarIndex);
+#ifdef EFI_NT_EMULATOR
+ ///
+ /// This is required for NT to avoid a forever-spin...
+ /// This would be better if READ_LSR was a polling operation
+ /// that would timeout.
+ ///
+ Lsr.Bits.THRE = 1;
+#endif
+ ///
+ /// Flush incomming data to prevent a an overrun during a long write
+ ///
+ if (Lsr.Bits.DR && !ReceiveFifoFull) {
+ ReceiveFifoFull = PciSerialFifoFull (&SerialDevice->Receive);
+ if (!ReceiveFifoFull) {
+ if (Lsr.Bits.FIFOE || Lsr.Bits.OE || Lsr.Bits.PE || Lsr.Bits.FE || Lsr.Bits.BI) {
+ if (Lsr.Bits.FIFOE || Lsr.Bits.PE || Lsr.Bits.FE || Lsr.Bits.BI) {
+ Data = READ_RBR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ continue;
+ }
+ }
+ ///
+ /// Make sure the receive data will not be missed, Assert DTR
+ ///
+ if (SerialDevice->HardwareFlowControl) {
+ Mcr.Data = READ_MCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ Mcr.Bits.DTRC &= 0;
+ WRITE_MCR (SerialDevice->PciIo, SerialDevice->BarIndex, Mcr.Data);
+ }
+
+ Data = READ_RBR (SerialDevice->PciIo, SerialDevice->BarIndex);
+
+ ///
+ /// Deassert DTR
+ ///
+ if (SerialDevice->HardwareFlowControl) {
+ Mcr.Data = READ_MCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ Mcr.Bits.DTRC |= 1;
+ WRITE_MCR (SerialDevice->PciIo, SerialDevice->BarIndex, Mcr.Data);
+ }
+
+ PciSerialFifoAdd (&SerialDevice->Receive, Data);
+
+ continue;
+ }
+ }
+ ///
+ /// Do the write
+ ///
+ if (Lsr.Bits.THRE && !PciSerialFifoEmpty (&SerialDevice->Transmit)) {
+ ///
+ /// Make sure the transmit data will not be missed
+ ///
+ if (SerialDevice->HardwareFlowControl) {
+ ///
+ /// Send RTS
+ ///
+ Mcr.Data = READ_MCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ Mcr.Bits.RTS |= 1;
+ WRITE_MCR (SerialDevice->PciIo, SerialDevice->BarIndex, Mcr.Data);
+ ///
+ /// Wait for CTS
+ ///
+ TimeOut = 0;
+ Msr.Data = READ_MSR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ while (!Msr.Bits.CTS) {
+ gBS->Stall (TIMEOUT_STALL_INTERVAL);
+ TimeOut++;
+ if (TimeOut > 5) {
+ break;
+ }
+
+ Msr.Data = READ_MSR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ }
+
+ if (Msr.Bits.CTS) {
+ PciSerialFifoRemove (&SerialDevice->Transmit, &Data);
+ WRITE_THR (SerialDevice->PciIo, SerialDevice->BarIndex, Data);
+ }
+ }
+ ///
+ /// write the data out
+ ///
+ if (!SerialDevice->HardwareFlowControl) {
+ PciSerialFifoRemove (&SerialDevice->Transmit, &Data);
+ WRITE_THR (SerialDevice->PciIo, SerialDevice->BarIndex, Data);
+ }
+ ///
+ /// Make sure the transmit data will not be missed
+ ///
+ if (SerialDevice->HardwareFlowControl) {
+ ///
+ /// Assert RTS
+ ///
+ Mcr.Data = READ_MCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ Mcr.Bits.RTS &= 0;
+ WRITE_MCR (SerialDevice->PciIo, SerialDevice->BarIndex, Mcr.Data);
+ }
+ }
+ } while (Lsr.Bits.THRE && !PciSerialFifoEmpty (&SerialDevice->Transmit));
+ }
+
+ return EFI_SUCCESS;
+}
+
+///
+/// Interface Functions
+///
+
+/**
+ Reset serial device
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+
+ @retval EFI_SUCCESS Reset successfully
+ @retval EFI_DEVICE_ERROR Failed to reset
+**/
+EFI_STATUS
+EFIAPI
+PciSerialReset (
+ IN EFI_SERIAL_IO_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ SERIAL_DEV *SerialDevice;
+ SERIAL_PORT_LCR Lcr;
+ SERIAL_PORT_IER Ier;
+ SERIAL_PORT_MCR Mcr;
+ SERIAL_PORT_FCR Fcr;
+ EFI_TPL Tpl;
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ ///
+ /// Make sure DLAB is 0.
+ ///
+ Lcr.Data = READ_LCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ Lcr.Bits.DLAB = 0;
+ WRITE_LCR (SerialDevice->PciIo, SerialDevice->BarIndex, Lcr.Data);
+
+ ///
+ /// Turn off all interrupts
+ ///
+ Ier.Data = READ_IER (SerialDevice->PciIo, SerialDevice->BarIndex);
+ Ier.Bits.RAVIE = 0;
+ Ier.Bits.THEIE = 0;
+ Ier.Bits.RIE = 0;
+ Ier.Bits.MIE = 0;
+ WRITE_IER (SerialDevice->PciIo, SerialDevice->BarIndex, Ier.Data);
+
+ ///
+ /// Disable the FIFO.
+ ///
+ Fcr.Bits.TRFIFOE = 0;
+ WRITE_FCR (SerialDevice->PciIo, SerialDevice->BarIndex, Fcr.Data);
+
+ ///
+ /// Turn off loopback and disable device interrupt.
+ ///
+ Mcr.Data = READ_MCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ Mcr.Bits.OUT1 = 0;
+ Mcr.Bits.OUT2 = 0;
+ Mcr.Bits.LME = 0;
+ WRITE_MCR (SerialDevice->PciIo, SerialDevice->BarIndex, Mcr.Data);
+
+ ///
+ /// Clear the scratch pad register
+ ///
+ WRITE_SCR (SerialDevice->PciIo, SerialDevice->BarIndex, 0);
+
+ ///
+ /// Go set the current attributes
+ ///
+ Status = This->SetAttributes (
+ This,
+ This->Mode->BaudRate,
+ This->Mode->ReceiveFifoDepth,
+ This->Mode->Timeout,
+ This->Mode->Parity,
+ (UINT8) This->Mode->DataBits,
+ This->Mode->StopBits
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// Go set the current control bits
+ ///
+ Status = This->SetControl (
+ This,
+ This->Mode->ControlMask
+ );
+
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_DEVICE_ERROR;
+ }
+
+ gBS->RestoreTPL (Tpl);
+
+ ///
+ /// Device reset is complete
+ ///
+ return EFI_SUCCESS;
+}
+
+/**
+ Set new attributes to a serial device
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] BaudRate The baudrate of the serial device
+ @param[in] ReceiveFifoDepth Fifo depth
+ @param[in] Timeout The request timeout for a single char
+ @param[in] Parity The type of parity used in serial device
+ @param[in] DataBits Number of databits used in serial device
+ @param[in] StopBits Number of stopbits used in serial device
+
+ @retval EFI_SUCCESS The new attributes were set
+ @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
+ @exception EFI_UNSUPPORTED Data Bits can not set to 5 or 6
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
+**/
+EFI_STATUS
+EFIAPI
+PciSerialSetAttributes (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT64 BaudRate,
+ IN UINT32 ReceiveFifoDepth,
+ IN UINT32 Timeout,
+ IN EFI_PARITY_TYPE Parity,
+ IN UINT8 DataBits,
+ IN EFI_STOP_BITS_TYPE StopBits
+ )
+{
+ EFI_STATUS Status;
+ SERIAL_DEV *SerialDevice;
+ UINT32 Divisor;
+ UINT32 Remained;
+ SERIAL_PORT_LCR Lcr;
+ EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
+ EFI_TPL Tpl;
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ ///
+ /// DEBUG ((EFI_D_ERROR, "Info: Timeout = %d\n", Timeout));
+ ///
+ /// Increase timeout by a factor of 3 to fix character drop-out with SOL.
+ ///
+ Timeout = Timeout * 100;
+
+ ///
+ /// Check for default settings and fill in actual values.
+ ///
+ if (BaudRate == 0) {
+ BaudRate = SERIAL_PORT_DEFAULT_BAUD_RATE;
+ }
+
+ if (ReceiveFifoDepth == 0) {
+ ReceiveFifoDepth = SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH;
+ }
+
+ if (Timeout == 0) {
+ Timeout = SERIAL_PORT_DEFAULT_TIMEOUT;
+ }
+
+ if (Parity == DefaultParity) {
+ Parity = SERIAL_PORT_DEFAULT_PARITY;
+ }
+
+ if (DataBits == 0) {
+ DataBits = SERIAL_PORT_DEFAULT_DATA_BITS;
+ }
+
+ if (StopBits == DefaultStopBits) {
+ StopBits = SERIAL_PORT_DEFAULT_STOP_BITS;
+ }
+ ///
+ /// 5 and 6 data bits can not be verified on a 16550A UART
+ /// Return EFI_INVALID_PARAMETER if an attempt is made to use these settings.
+ ///
+ if ((DataBits == 5) || (DataBits == 6)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// Make sure all parameters are valid
+ ///
+ if ((BaudRate > SERIAL_PORT_MAX_BAUD_RATE) || (BaudRate < SERIAL_PORT_MIN_BAUD_RATE)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// 50,75,110,134,150,300,600,1200,1800,2000,2400,3600,4800,7200,9600,19200,
+ /// 38400,57600,115200
+ ///
+ if (BaudRate < 75) {
+ BaudRate = 50;
+ } else if (BaudRate < 110) {
+ BaudRate = 75;
+ } else if (BaudRate < 134) {
+ BaudRate = 110;
+ } else if (BaudRate < 150) {
+ BaudRate = 134;
+ } else if (BaudRate < 300) {
+ BaudRate = 150;
+ } else if (BaudRate < 600) {
+ BaudRate = 300;
+ } else if (BaudRate < 1200) {
+ BaudRate = 600;
+ } else if (BaudRate < 1800) {
+ BaudRate = 1200;
+ } else if (BaudRate < 2000) {
+ BaudRate = 1800;
+ } else if (BaudRate < 2400) {
+ BaudRate = 2000;
+ } else if (BaudRate < 3600) {
+ BaudRate = 2400;
+ } else if (BaudRate < 4800) {
+ BaudRate = 3600;
+ } else if (BaudRate < 7200) {
+ BaudRate = 4800;
+ } else if (BaudRate < 9600) {
+ BaudRate = 7200;
+ } else if (BaudRate < 19200) {
+ BaudRate = 9600;
+ } else if (BaudRate < 38400) {
+ BaudRate = 19200;
+ } else if (BaudRate < 57600) {
+ BaudRate = 38400;
+ } else if (BaudRate < 115200) {
+ BaudRate = 57600;
+ } else if (BaudRate <= SERIAL_PORT_MAX_BAUD_RATE) {
+ BaudRate = 115200;
+ }
+
+ if ((ReceiveFifoDepth < 1) || (ReceiveFifoDepth > SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Timeout < SERIAL_PORT_MIN_TIMEOUT) || (Timeout > SERIAL_PORT_MAX_TIMEOUT)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Parity < NoParity) || (Parity > SpaceParity)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((DataBits < 5) || (DataBits > 8)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((StopBits < OneStopBit) || (StopBits > TwoStopBits)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// for DataBits = 5, StopBits can not set TwoStopBits
+ ///
+ /// if ((DataBits == 5) && (StopBits == TwoStopBits)) {
+ /// return EFI_INVALID_PARAMETER;
+ /// }
+ ///
+ /// for DataBits = 6,7,8, StopBits can not set OneFiveStopBits
+ ///
+ if ((DataBits >= 6) && (DataBits <= 8) && (StopBits == OneFiveStopBits)) {
+ return EFI_INVALID_PARAMETER;
+ }
+ ///
+ /// See if the new attributes already match the current attributes
+ ///
+ if (SerialDevice->UartDevicePath.BaudRate == BaudRate &&
+ SerialDevice->UartDevicePath.DataBits == DataBits &&
+ SerialDevice->UartDevicePath.Parity == Parity &&
+ SerialDevice->UartDevicePath.StopBits == StopBits &&
+ SerialDevice->SerialMode.ReceiveFifoDepth == ReceiveFifoDepth &&
+ SerialDevice->SerialMode.Timeout == Timeout
+ ) {
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Compute divisor use to program the baud rate using a round determination
+ ///
+ Divisor = (UINT32) DivU64x32Remainder (SERIAL_PORT_INPUT_CLOCK, ((UINT32) BaudRate * 16), &Remained);
+ if (Remained) {
+ Divisor += 1;
+ }
+
+ if ((Divisor == 0) || (Divisor & 0xffff0000)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ ///
+ /// Compute the actual baud rate that the serial port will be programmed for.
+ ///
+ BaudRate = SERIAL_PORT_INPUT_CLOCK / Divisor / 16;
+
+ ///
+ /// Put serial port on Divisor Latch Mode
+ ///
+ Lcr.Data = READ_LCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ Lcr.Bits.DLAB = 1;
+ WRITE_LCR (SerialDevice->PciIo, SerialDevice->BarIndex, Lcr.Data);
+
+ ///
+ /// Write the divisor to the serial port
+ ///
+ WRITE_DLL (SerialDevice->PciIo, SerialDevice->BarIndex, (UINT8) (Divisor & 0xff));
+ WRITE_DLM (SerialDevice->PciIo, SerialDevice->BarIndex, (UINT8) ((Divisor >> 8) & 0xff));
+
+ ///
+ /// Put serial port back in normal mode and set remaining attributes.
+ ///
+ Lcr.Bits.DLAB = 0;
+
+ switch (Parity) {
+ case NoParity:
+ Lcr.Bits.PAREN = 0;
+ Lcr.Bits.EVENPAR = 0;
+ Lcr.Bits.STICPAR = 0;
+ break;
+
+ case EvenParity:
+ Lcr.Bits.PAREN = 1;
+ Lcr.Bits.EVENPAR = 1;
+ Lcr.Bits.STICPAR = 0;
+ break;
+
+ case OddParity:
+ Lcr.Bits.PAREN = 1;
+ Lcr.Bits.EVENPAR = 0;
+ Lcr.Bits.STICPAR = 0;
+ break;
+
+ case SpaceParity:
+ Lcr.Bits.PAREN = 1;
+ Lcr.Bits.EVENPAR = 1;
+ Lcr.Bits.STICPAR = 1;
+ break;
+
+ case MarkParity:
+ Lcr.Bits.PAREN = 1;
+ Lcr.Bits.EVENPAR = 0;
+ Lcr.Bits.STICPAR = 1;
+ break;
+ default:
+ break;
+ }
+
+ switch (StopBits) {
+ case OneStopBit:
+ Lcr.Bits.STOPB = 0;
+ break;
+
+ case OneFiveStopBits:
+ case TwoStopBits:
+ Lcr.Bits.STOPB = 1;
+ break;
+ default:
+ break;
+ }
+ ///
+ /// DataBits
+ ///
+ Lcr.Bits.SERIALDB = (UINT8) ((DataBits - 5) & 0x03);
+ WRITE_LCR (SerialDevice->PciIo, SerialDevice->BarIndex, Lcr.Data);
+
+ ///
+ /// Set the Serial I/O mode
+ ///
+ This->Mode->BaudRate = BaudRate;
+ This->Mode->ReceiveFifoDepth = ReceiveFifoDepth;
+ This->Mode->Timeout = Timeout;
+ This->Mode->Parity = Parity;
+ This->Mode->DataBits = DataBits;
+ This->Mode->StopBits = StopBits;
+
+ ///
+ /// See if Device Path Node has actually changed
+ ///
+ if (SerialDevice->UartDevicePath.BaudRate == BaudRate &&
+ SerialDevice->UartDevicePath.DataBits == DataBits &&
+ SerialDevice->UartDevicePath.Parity == Parity &&
+ SerialDevice->UartDevicePath.StopBits == StopBits
+ ) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_SUCCESS;
+ }
+ ///
+ /// Update the device path
+ ///
+ SerialDevice->UartDevicePath.BaudRate = BaudRate;
+ SerialDevice->UartDevicePath.DataBits = DataBits;
+ SerialDevice->UartDevicePath.Parity = (UINT8) Parity;
+ SerialDevice->UartDevicePath.StopBits = (UINT8) StopBits;
+
+ NewDevicePath = AppendDevicePathNode (
+ SerialDevice->ParentDevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &SerialDevice->UartDevicePath
+ );
+ if (NewDevicePath == NULL) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (SerialDevice->Handle != NULL) {
+ Status = gBS->ReinstallProtocolInterface (
+ SerialDevice->Handle,
+ &gEfiDevicePathProtocolGuid,
+ SerialDevice->DevicePath,
+ NewDevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (Tpl);
+ return Status;
+ }
+ }
+
+ if (SerialDevice->DevicePath) {
+ FreePool (SerialDevice->DevicePath);
+ }
+
+ SerialDevice->DevicePath = NewDevicePath;
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set ControlBits
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] Control Control bits that can be settable
+
+ @retval EFI_SUCCESS New Control bits were set successfully
+ @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
+**/
+EFI_STATUS
+EFIAPI
+PciSerialSetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT32 Control
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ SERIAL_PORT_MCR Mcr;
+ EFI_TPL Tpl;
+
+ ///
+ /// The control bits that can be set are :
+ /// EFI_SERIAL_DATA_TERMINAL_READY: 0x0001 // WO
+ /// EFI_SERIAL_REQUEST_TO_SEND: 0x0002 // WO
+ /// EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE: 0x1000 // RW
+ /// EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE: 0x2000 // RW
+ ///
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ ///
+ /// first determine the parameter is invalid
+ ///
+ if (Control & 0xffff8ffc) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Mcr.Data = READ_MCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ Mcr.Bits.DTRC = 0;
+ Mcr.Bits.RTS = 0;
+ Mcr.Bits.LME = 0;
+ SerialDevice->SoftwareLoopbackEnable = FALSE;
+ SerialDevice->HardwareFlowControl = FALSE;
+
+ if (Control & EFI_SERIAL_DATA_TERMINAL_READY) {
+ Mcr.Bits.DTRC = 1;
+ }
+
+ if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
+ Mcr.Bits.RTS = 1;
+ }
+
+ if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
+ Mcr.Bits.LME = 1;
+ }
+
+ if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
+ SerialDevice->HardwareFlowControl = TRUE;
+ }
+
+ WRITE_MCR (SerialDevice->PciIo, SerialDevice->BarIndex, Mcr.Data);
+
+ if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) {
+ SerialDevice->SoftwareLoopbackEnable = TRUE;
+ }
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get ControlBits
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] Control Control signals of the serial device
+
+ @retval EFI_SUCCESS Get Control signals successfully
+**/
+EFI_STATUS
+EFIAPI
+PciSerialGetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ OUT UINT32 *Control
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ SERIAL_PORT_MSR Msr;
+ SERIAL_PORT_MCR Mcr;
+ EFI_TPL Tpl;
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+
+ *Control = 0;
+
+ ///
+ /// Read the Modem Status Register
+ ///
+ Msr.Data = READ_MSR (SerialDevice->PciIo, SerialDevice->BarIndex);
+
+ if (Msr.Bits.CTS) {
+ *Control |= EFI_SERIAL_CLEAR_TO_SEND;
+ }
+
+ if (Msr.Bits.DSR) {
+ *Control |= EFI_SERIAL_DATA_SET_READY;
+ }
+
+ if (Msr.Bits.RI) {
+ *Control |= EFI_SERIAL_RING_INDICATE;
+ }
+
+ if (Msr.Bits.DCD) {
+ *Control |= EFI_SERIAL_CARRIER_DETECT;
+ }
+ ///
+ /// Read the Modem Control Register
+ ///
+ Mcr.Data = READ_MCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+
+ if (Mcr.Bits.DTRC) {
+ *Control |= EFI_SERIAL_DATA_TERMINAL_READY;
+ }
+
+ if (Mcr.Bits.RTS) {
+ *Control |= EFI_SERIAL_REQUEST_TO_SEND;
+ }
+
+ if (Mcr.Bits.LME) {
+ *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
+ }
+
+ if (SerialDevice->HardwareFlowControl) {
+ *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
+ }
+ ///
+ /// See if the Transmit FIFO is empty
+ ///
+ PciSerialReceiveTransmit (SerialDevice);
+
+ if (PciSerialFifoEmpty (&SerialDevice->Transmit)) {
+ *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
+ }
+ ///
+ /// See if the Receive FIFO is empty.
+ ///
+ PciSerialReceiveTransmit (SerialDevice);
+
+ if (PciSerialFifoEmpty (&SerialDevice->Receive)) {
+ *Control |= EFI_SERIAL_INPUT_BUFFER_EMPTY;
+ }
+
+ if (SerialDevice->SoftwareLoopbackEnable) {
+ *Control |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE;
+ }
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write the specified number of bytes to serial device
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] BufferSize On input the size of Buffer, on output the amount of data actually written
+ @param[in] Buffer The buffer of data to write
+
+ @retval EFI_SUCCESS The data were written successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The write operation was stopped due to timeout
+**/
+EFI_STATUS
+EFIAPI
+PciSerialWrite (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ UINT8 *CharBuffer;
+ UINT32 Index;
+ UINTN Elapsed;
+ UINTN ActualWrite;
+ EFI_TPL Tpl;
+ SERIAL_PORT_MCR Mcr;
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+ Elapsed = 0;
+ ActualWrite = 0;
+
+ if (*BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (!Buffer) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ CharBuffer = (UINT8 *) Buffer;
+
+ for (Index = 0; Index < *BufferSize; Index++) {
+ PciSerialFifoAdd (&SerialDevice->Transmit, CharBuffer[Index]);
+
+ while
+ (
+ PciSerialReceiveTransmit (SerialDevice) != EFI_SUCCESS ||
+ PciSerialFifoEmpty (&SerialDevice->Transmit) == FALSE
+ ) {
+ ///
+ /// Unsuccessful write so check if timeout has expired, if not,
+ /// stall for a bit, increment time elapsed, and try again
+ ///
+ if (Elapsed >= This->Mode->Timeout) {
+ *BufferSize = ActualWrite;
+ if (PciSerialFifoEmpty (&SerialDevice->Transmit)) {
+ gBS->RestoreTPL (Tpl);
+ return EFI_TIMEOUT;
+ }
+ }
+
+ gBS->Stall (TIMEOUT_STALL_INTERVAL);
+
+ Elapsed += TIMEOUT_STALL_INTERVAL;
+ } // end while
+ ActualWrite++;
+ ///
+ /// Successful write so reset timeout
+ ///
+ Elapsed = 0;
+
+ } // end for
+ ///
+ /// FW expects DTR bit to be SET before sending data. So enable DTR bit always.
+ ///
+ Mcr.Data = READ_MCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ Mcr.Bits.DTRC |= 1;
+ WRITE_MCR (SerialDevice->PciIo, SerialDevice->BarIndex, Mcr.Data);
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read the specified number of bytes from serial device
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] BufferSize On input the size of Buffer, on output the amount of data returned in buffer
+ @param[in] Buffer The buffer to return the data into
+
+ @retval EFI_SUCCESS The data were read successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The read operation was stopped due to timeout
+**/
+EFI_STATUS
+EFIAPI
+PciSerialRead (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ SERIAL_DEV *SerialDevice;
+ UINT32 Index;
+ UINT8 *CharBuffer;
+ UINTN Elapsed;
+ EFI_STATUS Status;
+ EFI_TPL Tpl;
+
+ SerialDevice = SERIAL_DEV_FROM_THIS (This);
+ Elapsed = 0;
+
+ if (*BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (!Buffer) {
+ return EFI_DEVICE_ERROR;
+ }
+ ///
+ /// SerialDevice->Receive.First = 0;
+ /// SerialDevice->Receive.Last = 0;
+ /// SerialDevice->Receive.Surplus = SERIAL_MAX_BUFFER_SIZE;
+ ///
+ Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Status = PciSerialReceiveTransmit (SerialDevice);
+
+ if (EFI_ERROR (Status)) {
+ *BufferSize = 0;
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_DEVICE_ERROR;
+ }
+
+ CharBuffer = (UINT8 *) Buffer;
+ for (Index = 0; Index < *BufferSize; Index++) {
+ while (PciSerialFifoRemove (&SerialDevice->Receive, &(CharBuffer[Index])) != EFI_SUCCESS) {
+ ///
+ /// Unsuccessful read so check if timeout has expired, if not,
+ /// stall for a bit, increment time elapsed, and try again
+ /// Need this time out to get conspliter to work.
+ ///
+ if (Elapsed >= This->Mode->Timeout) {
+ *BufferSize = Index;
+ gBS->RestoreTPL (Tpl);
+ return EFI_TIMEOUT;
+ }
+
+ gBS->Stall (TIMEOUT_STALL_INTERVAL);
+ Elapsed += TIMEOUT_STALL_INTERVAL;
+
+ Status = PciSerialReceiveTransmit (SerialDevice);
+ if (Status == EFI_DEVICE_ERROR) {
+ *BufferSize = Index;
+ gBS->RestoreTPL (Tpl);
+ return EFI_DEVICE_ERROR;
+ }
+ } // end while
+ ///
+ /// Successful read so reset timeout
+ ///
+ Elapsed = 0;
+ } // end for
+ PciSerialReceiveTransmit (SerialDevice);
+
+ gBS->RestoreTPL (Tpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check serial port status.
+
+ @param[in] SerialDevice The serial device instance
+
+ @retval True It is present.
+ @retval False No present.
+**/
+BOOLEAN
+PciSerialPortPresent (
+ IN SERIAL_DEV *SerialDevice
+ )
+{
+ UINT8 Temp;
+ BOOLEAN Status;
+
+ Status = TRUE;
+
+ ///
+ /// Save SCR reg
+ ///
+ Temp = READ_SCR (SerialDevice->PciIo, SerialDevice->BarIndex);
+ WRITE_SCR (SerialDevice->PciIo, SerialDevice->BarIndex, 0xAA);
+
+ if (READ_SCR (SerialDevice->PciIo, SerialDevice->BarIndex) != 0xAA) {
+#ifndef EFI_NT_EMULATOR
+ Status = FALSE;
+#endif
+ }
+
+ WRITE_SCR (SerialDevice->PciIo, SerialDevice->BarIndex, 0x55);
+
+ if (READ_SCR (SerialDevice->PciIo, SerialDevice->BarIndex) != 0x55) {
+#ifndef EFI_NT_EMULATOR
+ Status = FALSE;
+#endif
+ }
+ ///
+ /// Restore SCR
+ ///
+ WRITE_SCR (SerialDevice->PciIo, SerialDevice->BarIndex, Temp);
+ return Status;
+}
+
+/**
+ PCI I/O read for byte only
+
+ @param[in] PciIo Pointer of Pci IO protocol
+ @param[in] BarIndex Index of the BAR within PCI device
+ @param[in] Offset Offset of the BARIndex within PCI device
+
+ @retval Return value read
+**/
+UINT8
+PciSerialReadPort (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 BarIndex,
+ IN UINT16 Offset
+ )
+{
+ UINT8 Data;
+
+ ///
+ /// Use PciIo to access IO
+ ///
+ PciIo->Io.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ (UINT8) BarIndex,
+ (UINT16) Offset,
+ (UINTN) 1,
+ &Data
+ );
+ return Data;
+}
+
+/**
+ PCI I/O - write a byte
+
+ @param[in] PciIo Pointer of Pci IO protocol
+ @param[in] BarIndex Index of the BAR within PCI device
+ @param[in] Offset Offset of the BARIndex within PCI device
+ @param[in] Data Written value
+**/
+VOID
+PciSerialWritePort (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 BarIndex,
+ IN UINT16 Offset,
+ IN UINT8 Data
+ )
+{
+ ///
+ /// Use PciIo to access IO
+ ///
+ PciIo->Io.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ (UINT8) BarIndex,
+ (UINT16) Offset,
+ (UINTN) 1,
+ &Data
+ );
+}
+
+/**
+ Sol driver entry
+
+ @param[in] ImageHandle Handle for this drivers loaded image protocol.
+ @param[in] SystemTable EFI system table.
+
+ @retval EFI_SUCCESS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+PciSerialControllerDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EFI_SUCCESS;
+}
diff --git a/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.cif b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.cif
new file mode 100644
index 0000000..950205e
--- /dev/null
+++ b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.cif
@@ -0,0 +1,13 @@
+<component>
+ name = "PciSerial"
+ category = ModulePart
+ LocalRoot = "ReferenceCode\ME\ActiveManagement\Sol\Dxe\"
+ RefName = "PciSerial"
+[files]
+"PciSerial.sdl"
+"PciSerial.mak"
+"PciSerial.c"
+"ComponentName.c"
+"PciSerial.h"
+"PciSerial.inf"
+<endComponent>
diff --git a/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.h b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.h
new file mode 100644
index 0000000..320de88
--- /dev/null
+++ b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.h
@@ -0,0 +1,787 @@
+/** @file
+ Include for Pci Serial Driver
+
+@copyright
+ Copyright (c) 2004 - 2012 Intel Corporation. All rights
+ reserved This software and associated documentation (if any)
+ is furnished under a license and may only be used or copied in
+ accordance with the terms of the license. Except as permitted
+ by such license, no part of this software or documentation may
+ be reproduced, stored in a retrieval system, or transmitted in
+ any form or by any means without the express written consent
+ of Intel Corporation.
+
+ This file contains an 'Intel Peripheral Driver' and uniquely
+ identified as "Intel Reference Module" and is
+ licensed for Intel CPUs and chipsets under the terms of your
+ license agreement with Intel or your vendor. This file may
+ be modified by the user, subject to additional terms of the
+ license agreement
+
+**/
+#ifndef _PCI_SERIAL_H
+#define _PCI_SERIAL_H
+#include "Pci22.h"
+#include "Acpi.h"
+#include "AmtLib.h"
+
+//
+// Driver Consumed Protocol Prototypes
+//
+#include EFI_PROTOCOL_DEFINITION (PciIo)
+#include EFI_PROTOCOL_DEFINITION (DevicePath)
+#include EFI_PROTOCOL_CONSUMER (PciRootBridgeIo)
+
+//
+// Driver Produced Protocol Prototypes
+//
+#include EFI_PROTOCOL_DEFINITION (DriverBinding)
+#include EFI_PROTOCOL_DEFINITION (ComponentName)
+#include EFI_PROTOCOL_DEFINITION (SerialIo)
+
+//
+// Status code GUID
+//
+#include EFI_GUID_DEFINITION (StatusCodeDataTypeId)
+
+//
+// Internal Data Structures
+//
+#define SERIAL_DEV_SIGNATURE EFI_SIGNATURE_32 ('s', 'e', 'r', 'd')
+#define SERIAL_MAX_BUFFER_SIZE 16
+#define TIMEOUT_STALL_INTERVAL 300
+
+///
+/// Name: SERIAL_DEV_FIFO
+/// Purpose: To define Receive FIFO and Transmit FIFO
+/// Context: Used by serial data transmit and receive
+/// Fields:
+/// First UINT32: The index of the first data in array Data[]
+/// Last UINT32: The index, which you can put a new data into array Data[]
+/// Surplus UINT32: Identify how many data you can put into array Data[]
+/// Data[] UINT8 : An array, which used to store data
+///
+typedef struct {
+ UINT32 First;
+ UINT32 Last;
+ UINT32 Surplus;
+ UINT8 Data[SERIAL_MAX_BUFFER_SIZE];
+} SERIAL_DEV_FIFO;
+
+typedef enum {
+ UART8250 = 0,
+ UART16450 = 1,
+ UART16550 = 2,
+ UART16550A= 3
+} EFI_UART_TYPE;
+
+///
+/// Name: SERIAL_DEV
+/// Purpose: To provide device specific information
+/// Context:
+/// Fields:
+/// Signature UINTN: The identity of the serial device
+/// SerialIo SERIAL_IO_PROTOCOL: Serial I/O protocol interface
+/// SerialMode SERIAL_IO_MODE:
+/// DevicePath EFI_DEVICE_PATH_PROTOCOL *: Device path of the serial device
+/// Handle EFI_HANDLE: The handle instance attached to serial device
+/// BarIndex UINT16: The bar index in pci cfg space that contains the base address
+/// of specific serial device
+/// Receive SERIAL_DEV_FIFO: The FIFO used to store data,
+/// which is received by UART
+/// Transmit SERIAL_DEV_FIFO: The FIFO used to store data,
+/// which you want to transmit by UART
+/// SoftwareLoopbackEnable BOOLEAN:
+/// Type EFI_UART_TYPE: Specify the UART type of certain serial device
+///
+typedef struct {
+ UINTN Signature;
+
+ EFI_HANDLE Handle;
+ EFI_SERIAL_IO_PROTOCOL SerialIo;
+ EFI_SERIAL_IO_MODE SerialMode;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
+ UART_DEVICE_PATH UartDevicePath;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+
+ UINT16 BarIndex;
+ SERIAL_DEV_FIFO Receive;
+ SERIAL_DEV_FIFO Transmit;
+ BOOLEAN SoftwareLoopbackEnable;
+ BOOLEAN HardwareFlowControl;
+ EFI_UART_TYPE Type;
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+} SERIAL_DEV;
+
+#define SERIAL_DEV_FROM_THIS(a) CR (a, SERIAL_DEV, SerialIo, SERIAL_DEV_SIGNATURE)
+
+//
+// Globale Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL mPciSerialControllerDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL mPciSerialComponentName;
+
+//
+// Serial Driver Defaults
+//
+#define SERIAL_PORT_DEFAULT_BAUD_RATE 115200
+#define SERIAL_PORT_DEFAULT_RECEIVE_FIFO_DEPTH 1
+#define SERIAL_PORT_DEFAULT_TIMEOUT 1000000 ///< 1 seconds
+#define SERIAL_PORT_DEFAULT_PARITY NoParity
+#define SERIAL_PORT_DEFAULT_DATA_BITS 8
+#define SERIAL_PORT_DEFAULT_STOP_BITS 1
+#define SERIAL_PORT_DEFAULT_CONTROL_MASK EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE
+
+///
+/// (24000000/13)MHz input clock
+///
+#define SERIAL_PORT_INPUT_CLOCK 1843200
+
+///
+/// 115200 baud with rounding errors
+///
+#define SERIAL_PORT_MAX_BAUD_RATE 115400
+#define SERIAL_PORT_MIN_BAUD_RATE 50
+
+#define SERIAL_PORT_MAX_RECEIVE_FIFO_DEPTH 16
+#define SERIAL_PORT_MIN_TIMEOUT 1 ///< 1 uS
+#define SERIAL_PORT_MAX_TIMEOUT 10000000000 ///< 10000 seconds
+//
+// UART Registers
+//
+#define SERIAL_REGISTER_THR 0 ///< WO Transmit Holding Register
+#define SERIAL_REGISTER_RBR 0 ///< RO Receive Buffer Register
+#define SERIAL_REGISTER_DLL 0 ///< R/W Divisor Latch LSB
+#define SERIAL_REGISTER_DLM 1 ///< R/W Divisor Latch MSB
+#define SERIAL_REGISTER_IER 1 ///< R/W Interrupt Enable Register
+#define SERIAL_REGISTER_IIR 2 ///< RO Interrupt Identification Register
+#define SERIAL_REGISTER_FCR 2 ///< WO FIFO Cotrol Register
+#define SERIAL_REGISTER_LCR 3 ///< R/W Line Control Register
+#define SERIAL_REGISTER_MCR 4 ///< R/W Modem Control Register
+#define SERIAL_REGISTER_LSR 5 ///< R/W Line Status Register
+#define SERIAL_REGISTER_MSR 6 ///< R/W Modem Status Register
+#define SERIAL_REGISTER_SCR 7 ///< R/W Scratch Pad Register
+#define TEKOA_SOL_VENDOR_ID 0x8086
+#define TEKOA_SOL_DEVICE_ID 0x108F
+
+#define PCI_CLASS_SCC 0x07
+#define PCI_SUBCLASS_SERIAL 0x00
+#define PCI_IF_GENERIC_XT 0x00
+#define PCI_IF_16450 0x01
+#define PCI_IF_16550 0x02
+#define PCI_IF_16650 0x03
+#define PCI_IF_16750 0x04
+#define PCI_IF_16850 0x05
+#define PCI_IF_16950 0x06
+#define PCI_SUBCLASS_PARALLEL 0x01
+#define PCI_SUBCLASS_MULTIPORT_SERIAL 0x02
+#define PCI_SUBCLASS_MODEM 0x03
+#define PCI_SUBCLASS_OTHER 0x80
+
+#pragma pack(1)
+///
+/// Name: SERIAL_PORT_IER_BITS
+/// Purpose: Define each bit in Interrupt Enable Register
+/// Context:
+/// Fields:
+/// RAVIE Bit0: Receiver Data Available Interrupt Enable
+/// THEIE Bit1: Transmistter Holding Register Empty Interrupt Enable
+/// RIE Bit2: Receiver Interrupt Enable
+/// MIE Bit3: Modem Interrupt Enable
+/// Reserved Bit4-Bit7: Reserved
+///
+typedef struct {
+ UINT8 RAVIE : 1;
+ UINT8 THEIE : 1;
+ UINT8 RIE : 1;
+ UINT8 MIE : 1;
+ UINT8 Reserved : 4;
+} SERIAL_PORT_IER_BITS;
+
+///
+/// Name: SERIAL_PORT_IER
+/// Purpose:
+/// Context:
+/// Fields:
+/// Bits SERIAL_PORT_IER_BITS: Bits of the IER
+/// Data UINT8: the value of the IER
+///
+typedef union {
+ SERIAL_PORT_IER_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_IER;
+
+///
+/// Name: SERIAL_PORT_IIR_BITS
+/// Purpose: Define each bit in Interrupt Identification Register
+/// Context:
+/// Fields:
+/// IPS Bit0: Interrupt Pending Status
+/// IIB Bit1-Bit3: Interrupt ID Bits
+/// Reserved Bit4-Bit5: Reserved
+/// FIFOES Bit6-Bit7: FIFO Mode Enable Status
+///
+typedef struct {
+ UINT8 IPS : 1;
+ UINT8 IIB : 3;
+ UINT8 Reserved : 2;
+ UINT8 FIFOES : 2;
+} SERIAL_PORT_IIR_BITS;
+
+///
+/// Name: SERIAL_PORT_IIR
+/// Purpose:
+/// Context:
+/// Fields:
+/// Bits SERIAL_PORT_IIR_BITS: Bits of the IIR
+/// Data UINT8: the value of the IIR
+///
+typedef union {
+ SERIAL_PORT_IIR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_IIR;
+
+///
+/// Name: SERIAL_PORT_FCR_BITS
+/// Purpose: Define each bit in FIFO Control Register
+/// Context:
+/// Fields:
+/// TRFIFOE Bit0: Transmit and Receive FIFO Enable
+/// RESETRF Bit1: Reset Reciever FIFO
+/// RESETTF Bit2: Reset Transmistter FIFO
+/// DMS Bit3: DMA Mode Select
+/// Reserved Bit4-Bit5: Reserved
+/// RTB Bit6-Bit7: Receive Trigger Bits
+///
+typedef struct {
+ UINT8 TRFIFOE : 1;
+ UINT8 RESETRF : 1;
+ UINT8 RESETTF : 1;
+ UINT8 DMS : 1;
+ UINT8 Reserved : 2;
+ UINT8 RTB : 2;
+} SERIAL_PORT_FCR_BITS;
+
+///
+/// Name: SERIAL_PORT_FCR
+/// Purpose:
+/// Context:
+/// Fields:
+/// Bits SERIAL_PORT_FCR_BITS: Bits of the FCR
+/// Data UINT8: the value of the FCR
+///
+typedef union {
+ SERIAL_PORT_FCR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_FCR;
+
+///
+/// Name: SERIAL_PORT_LCR_BITS
+/// Purpose: Define each bit in Line Control Register
+/// Context:
+/// Fields:
+/// SERIALDB Bit0-Bit1: Number of Serial Data Bits
+/// STOPB Bit2: Number of Stop Bits
+/// PAREN Bit3: Parity Enable
+/// EVENPAR Bit4: Even Parity Select
+/// STICPAR Bit5: Sticky Parity
+/// BRCON Bit6: Break Control
+/// DLAB Bit7: Divisor Latch Access Bit
+///
+typedef struct {
+ UINT8 SERIALDB : 2;
+ UINT8 STOPB : 1;
+ UINT8 PAREN : 1;
+ UINT8 EVENPAR : 1;
+ UINT8 STICPAR : 1;
+ UINT8 BRCON : 1;
+ UINT8 DLAB : 1;
+} SERIAL_PORT_LCR_BITS;
+
+///
+/// Name: SERIAL_PORT_LCR
+/// Purpose:
+/// Context:
+/// Fields:
+/// Bits SERIAL_PORT_LCR_BITS: Bits of the LCR
+/// Data UINT8: the value of the LCR
+///
+typedef union {
+ SERIAL_PORT_LCR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_LCR;
+
+///
+/// Name: SERIAL_PORT_MCR_BITS
+/// Purpose: Define each bit in Modem Control Register
+/// Context:
+/// Fields:
+/// DTRC Bit0: Data Terminal Ready Control
+/// RTS Bit1: Request To Send Control
+/// OUT1 Bit2: Output1
+/// OUT2 Bit3: Output2, used to disable interrupt
+/// LME; Bit4: Loopback Mode Enable
+/// Reserved Bit5-Bit7: Reserved
+///
+typedef struct {
+ UINT8 DTRC : 1;
+ UINT8 RTS : 1;
+ UINT8 OUT1 : 1;
+ UINT8 OUT2 : 1;
+ UINT8 LME : 1;
+ UINT8 Reserved : 3;
+} SERIAL_PORT_MCR_BITS;
+
+///
+/// Name: SERIAL_PORT_MCR
+/// Purpose:
+/// Context:
+/// Fields:
+/// Bits SERIAL_PORT_MCR_BITS: Bits of the MCR
+/// Data UINT8: the value of the MCR
+///
+typedef union {
+ SERIAL_PORT_MCR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_MCR;
+
+///
+/// Name: SERIAL_PORT_LSR_BITS
+/// Purpose: Define each bit in Line Status Register
+/// Context:
+/// Fields:
+/// DR Bit0: Receiver Data Ready Status
+/// OE Bit1: Overrun Error Status
+/// PE Bit2: Parity Error Status
+/// FE Bit3: Framing Error Status
+/// BI Bit4: Break Interrupt Status
+/// THRE Bit5: Transmistter Holding Register Status
+/// TEMT Bit6: Transmitter Empty Status
+/// FIFOE Bit7: FIFO Error Status
+///
+typedef struct {
+ UINT8 DR : 1;
+ UINT8 OE : 1;
+ UINT8 PE : 1;
+ UINT8 FE : 1;
+ UINT8 BI : 1;
+ UINT8 THRE : 1;
+ UINT8 TEMT : 1;
+ UINT8 FIFOE : 1;
+} SERIAL_PORT_LSR_BITS;
+
+///
+/// Name: SERIAL_PORT_LSR
+/// Purpose:
+/// Context:
+/// Fields:
+/// Bits SERIAL_PORT_LSR_BITS: Bits of the LSR
+/// Data UINT8: the value of the LSR
+///
+typedef union {
+ SERIAL_PORT_LSR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_LSR;
+
+///
+/// Name: SERIAL_PORT_MSR_BITS
+/// Purpose: Define each bit in Modem Status Register
+/// Context:
+/// Fields:
+/// DeltaCTS Bit0: Delta Clear To Send Status
+/// DeltaDSR Bit1: Delta Data Set Ready Status
+/// TrailingEdgeRI Bit2: Trailing Edge of Ring Indicator Status
+/// DeltaDCD Bit3: Delta Data Carrier Detect Status
+/// CTS Bit4: Clear To Send Status
+/// DSR Bit5: Data Set Ready Status
+/// RI Bit6: Ring Indicator Status
+/// DCD Bit7: Data Carrier Detect Status
+///
+typedef struct {
+ UINT8 DeltaCTS : 1;
+ UINT8 DeltaDSR : 1;
+ UINT8 TrailingEdgeRI : 1;
+ UINT8 DeltaDCD : 1;
+ UINT8 CTS : 1;
+ UINT8 DSR : 1;
+ UINT8 RI : 1;
+ UINT8 DCD : 1;
+} SERIAL_PORT_MSR_BITS;
+
+///
+/// Name: SERIAL_PORT_MSR
+/// Purpose:
+/// Context:
+/// Fields:
+/// Bits SERIAL_PORT_MSR_BITS: Bits of the MSR
+/// Data UINT8: the value of the MSR
+///
+typedef union {
+ SERIAL_PORT_MSR_BITS Bits;
+ UINT8 Data;
+} SERIAL_PORT_MSR;
+
+#pragma pack()
+//
+// Define serial register I/O macros
+//
+#define READ_RBR(IO, B) PciSerialReadPort (IO, B, SERIAL_REGISTER_RBR)
+#define READ_DLL(IO, B) PciSerialReadPort (IO, B, SERIAL_REGISTER_DLL)
+#define READ_DLM(IO, B) PciSerialReadPort (IO, B, SERIAL_REGISTER_DLM)
+#define READ_IER(IO, B) PciSerialReadPort (IO, B, SERIAL_REGISTER_IER)
+#define READ_IIR(IO, B) PciSerialReadPort (IO, B, SERIAL_REGISTER_IIR)
+#define READ_LCR(IO, B) PciSerialReadPort (IO, B, SERIAL_REGISTER_LCR)
+#define READ_MCR(IO, B) PciSerialReadPort (IO, B, SERIAL_REGISTER_MCR)
+#define READ_LSR(IO, B) PciSerialReadPort (IO, B, SERIAL_REGISTER_LSR)
+#define READ_MSR(IO, B) PciSerialReadPort (IO, B, SERIAL_REGISTER_MSR)
+#define READ_SCR(IO, B) PciSerialReadPort (IO, B, SERIAL_REGISTER_SCR)
+
+#define WRITE_THR(IO, B, D) PciSerialWritePort (IO, B, SERIAL_REGISTER_THR, D)
+#define WRITE_DLL(IO, B, D) PciSerialWritePort (IO, B, SERIAL_REGISTER_DLL, D)
+#define WRITE_DLM(IO, B, D) PciSerialWritePort (IO, B, SERIAL_REGISTER_DLM, D)
+#define WRITE_IER(IO, B, D) PciSerialWritePort (IO, B, SERIAL_REGISTER_IER, D)
+#define WRITE_FCR(IO, B, D) PciSerialWritePort (IO, B, SERIAL_REGISTER_FCR, D)
+#define WRITE_LCR(IO, B, D) PciSerialWritePort (IO, B, SERIAL_REGISTER_LCR, D)
+#define WRITE_MCR(IO, B, D) PciSerialWritePort (IO, B, SERIAL_REGISTER_MCR, D)
+#define WRITE_LSR(IO, B, D) PciSerialWritePort (IO, B, SERIAL_REGISTER_LSR, D)
+#define WRITE_MSR(IO, B, D) PciSerialWritePort (IO, B, SERIAL_REGISTER_MSR, D)
+#define WRITE_SCR(IO, B, D) PciSerialWritePort (IO, B, SERIAL_REGISTER_SCR, D)
+
+#define PCI_SERIAL_PORT_NAME "PCI Serial Port # "
+
+#define R_PCI_SVID 0x2C
+
+/**
+ This function checks to see if the driver supports a device specified by
+ "Controller handle" parameter. It is called by DXE Core StartImage() or
+ ConnectController() routines. The driver uses 'device path' and/or
+ 'services' from the Bus I/O abstraction attached to the controller handle
+ to determine if the driver support this controller handle.
+
+ Note: In the BDS (Boot Device Selection) phase, the DXE core enumerate all
+ devices (or, controller) and assigns GUIDs to them.
+
+ @param[in] This a pointer points to the Binding Protocol instance
+ @param[in] Controller The handle of controller to be tested.
+ @param[in] RemainingDevicePath A pointer to the device path. Ignored by device
+ driver but used by bus driver
+
+ @retval EFI_SUCCESS Have device to support
+ @retval EFI_NOT_FOUND The device doesn't support or relative environment not ready
+**/
+EFI_STATUS
+EFIAPI
+PciSerialControllerDriverSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+;
+
+/**
+ This routine is called right after the .Supported() called
+ and return EFI_SUCCESS. Notes: The supported protocols are
+ checked but the Protocols are closed.
+
+ @param[in] This A pointer points to the Binding Protocol instance
+ @param[in] Controller The handle of controller to be tested. Parameter
+ passed by the caller
+ @param[in] RemainingDevicePath A pointer to the device path. Should be ignored by
+ device driver
+
+ @retval EFI_SUCCESS The driver ready and initial complete.
+ @retval Other The device doesn't initial.
+**/
+EFI_STATUS
+EFIAPI
+PciSerialControllerDriverStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+;
+
+/**
+ Stop.
+
+ @param[in] This Pointer to driver binding protocol
+ @param[in] Controller Controller handle to connect
+ @param[in] NumberOfChildren Number of children handle created by this driver
+ @param[in] ChildHandleBuffer Buffer containing child handle created
+
+ @retval EFI_SUCCESS Driver disconnected successfully from controller
+ @retval EFI_DEVICE_ERROR Cannot find BIOS_VIDEO_DEV structure
+**/
+EFI_STATUS
+EFIAPI
+PciSerialControllerDriverStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Controller,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+;
+
+/**
+ Detect whether specific FIFO is full or not
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+
+ @retval TRUE The FIFO is full
+ @retval FALSE The FIFO is not full
+**/
+BOOLEAN
+PciSerialFifoFull (
+ IN SERIAL_DEV_FIFO *Fifo
+ )
+;
+
+/**
+ Detect whether specific FIFO is empty or not
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+
+ @retval TRUE The FIFO is empty
+ @retval FALSE The FIFO is not empty
+**/
+BOOLEAN
+PciSerialFifoEmpty (
+ IN SERIAL_DEV_FIFO *Fifo
+ )
+;
+
+/**
+ Add data to specific FIFO
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param[in] Data The data added to FIFO
+
+ @retval EFI_SUCCESS Add data to specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCES Failed to add data because FIFO is already full
+**/
+EFI_STATUS
+PciSerialFifoAdd (
+ IN SERIAL_DEV_FIFO *Fifo,
+ IN UINT8 Data
+ )
+;
+
+/**
+ Remove data from specific FIFO
+
+ @param[in] Fifo A pointer to the Data Structure SERIAL_DEV_FIFO
+ @param[in] Data The data removed from FIFO
+
+ @retval EFI_SUCCESS Remove data from specific FIFO successfully
+ @retval EFI_OUT_OF_RESOURCES Failed to remove data because FIFO is empty
+**/
+EFI_STATUS
+PciSerialFifoRemove (
+ IN SERIAL_DEV_FIFO *Fifo,
+ OUT UINT8 *Data
+ )
+;
+
+/**
+ Reads and writes all avaliable data.
+
+ @param[in] SerialDevice The device to flush
+
+ @retval EFI_SUCCESS Data was read/written successfully.
+ @retval EFI_OUT_OF_RESOURCES Failed because software receive FIFO is full. Note, when
+ this happens, pending writes are not done.
+**/
+EFI_STATUS
+PciSerialReceiveTransmit (
+ IN SERIAL_DEV *SerialDevice
+ )
+;
+///
+/// Serial I/O Protocol Interface
+///
+/**
+ Reset serial device
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+
+ @retval EFI_SUCCESS Reset successfully
+ @retval EFI_DEVICE_ERROR Failed to reset
+**/
+EFI_STATUS
+EFIAPI
+PciSerialReset (
+ IN EFI_SERIAL_IO_PROTOCOL *This
+ )
+;
+
+/**
+ Set new attributes to a serial device
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] BaudRate The baudrate of the serial device
+ @param[in] ReceiveFifoDepth Fifo depth
+ @param[in] Timeout The request timeout for a single char
+ @param[in] Parity The type of parity used in serial device
+ @param[in] DataBits Number of databits used in serial device
+ @param[in] StopBits Number of stopbits used in serial device
+
+ @retval EFI_SUCCESS The new attributes were set
+ @retval EFI_INVALID_PARAMETERS One or more attributes have an unsupported value
+ @exception EFI_UNSUPPORTED Data Bits can not set to 5 or 6
+ @retval EFI_DEVICE_ERROR The serial device is not functioning correctly (no return)
+**/
+EFI_STATUS
+EFIAPI
+PciSerialSetAttributes (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT64 BaudRate,
+ IN UINT32 ReceiveFifoDepth,
+ IN UINT32 Timeout,
+ IN EFI_PARITY_TYPE Parity,
+ IN UINT8 DataBits,
+ IN EFI_STOP_BITS_TYPE StopBits
+ )
+;
+
+/**
+ Set ControlBits
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] Control Control bits that can be settable
+
+ @retval EFI_SUCCESS New Control bits were set successfully
+ @retval EFI_UNSUPPORTED The Control bits wanted to set are not supported
+**/
+EFI_STATUS
+EFIAPI
+PciSerialSetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN UINT32 Control
+ )
+;
+
+/**
+ Get ControlBits
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] Control Control signals of the serial device
+
+ @retval EFI_SUCCESS Get Control signals successfully
+**/
+EFI_STATUS
+EFIAPI
+PciSerialGetControl (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ OUT UINT32 *Control
+ )
+;
+
+/**
+ Write the specified number of bytes to serial device
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] BufferSize On input the size of Buffer, on output the amount of data actually written
+ @param[in] Buffer The buffer of data to write
+
+ @retval EFI_SUCCESS The data were written successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The write operation was stopped due to timeout
+**/
+EFI_STATUS
+EFIAPI
+PciSerialWrite (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+;
+
+/**
+ Read the specified number of bytes from serial device
+
+ @param[in] This Pointer to EFI_SERIAL_IO_PROTOCOL
+ @param[in] BufferSize On input the size of Buffer, on output the amount of data returned in buffer
+ @param[in] Buffer The buffer to return the data into
+
+ @retval EFI_SUCCESS The data were read successfully
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_TIMEOUT The read operation was stopped due to timeout
+**/
+EFI_STATUS
+EFIAPI
+PciSerialRead (
+ IN EFI_SERIAL_IO_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+;
+
+///
+/// Internal Functions
+///
+/**
+ Check serial port status.
+
+ @param[in] SerialDevice The serial device instance
+
+ @retval True It is present.
+ @retval False No present.
+**/
+BOOLEAN
+PciSerialPortPresent (
+ IN SERIAL_DEV *SerialDevice
+ )
+;
+
+/**
+ PCI I/O read for byte only
+
+ @param[in] PciIo Pointer of Pci IO protocol
+ @param[in] BarIndex Index of the BAR within PCI device
+ @param[in] Offset Offset of the BARIndex within PCI device
+
+ @retval Return value read
+**/
+UINT8
+PciSerialReadPort (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 BarIndex,
+ IN UINT16 Offset
+ )
+;
+
+/**
+ PCI I/O - write a byte
+
+ @param[in] PciIo Pointer of Pci IO protocol
+ @param[in] BarIndex Index of the BAR within PCI device
+ @param[in] Offset Offset of the BARIndex within PCI device
+ @param[in] Data Written value
+**/
+VOID
+PciSerialWritePort (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT16 BarIndex,
+ IN UINT16 Offset,
+ IN UINT8 Data
+ )
+;
+
+/**
+ Sol driver entry
+
+ @param[in] ImageHandle Handle for this drivers loaded image protocol.
+ @param[in] SystemTable EFI system table.
+
+ @retval EFI_SUCCESS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+PciSerialControllerDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+;
+#endif
diff --git a/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.inf b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.inf
new file mode 100644
index 0000000..a3b4e0b
--- /dev/null
+++ b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.inf
@@ -0,0 +1,87 @@
+## @file
+# Component description file for PciSerial module.
+#
+#@copyright
+# Copyright (c) 2004 - 2012 Intel Corporation. All rights reserved
+# This software and associated documentation (if any) is furnished
+# under a license and may only be used or copied in accordance
+# with the terms of the license. Except as permitted by such
+# license, no part of this software or documentation may be
+# reproduced, stored in a retrieval system, or transmitted in any
+# form or by any means without the express written consent of
+# Intel Corporation.
+#
+# This file contains a 'Sample Driver' and is licensed as such
+# under the terms of your license agreement with Intel or your
+# vendor. This file may be modified by the user, subject to
+# the additional terms of the license agreement
+#
+
+[defines]
+BASE_NAME = PciSerial
+FILE_GUID = FB142B99-DF57-46cb-BC69-0BF858A734F9
+COMPONENT_TYPE = BS_DRIVER
+
+[sources.common]
+ PciSerial.c
+ PciSerial.h
+ ComponentName.c
+
+#
+# Edk II Glue Driver Entry Point
+#
+ EdkIIGlueDxeDriverEntryPoint.c
+
+[includes.common]
+ $(EFI_SOURCE)/$(PROJECT_ME_ROOT)
+ $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Include
+ $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/AMT/Dxe
+ $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/AMT/Include
+ $(EFI_SOURCE)/$(PROJECT_ME_ROOT)/Library/MeKernel/Include
+ $(EFI_SOURCE)/$(PROJECT_PCH_ROOT)/Include
+
+#
+# EDK II Glue Library utilizes some standard headers from EDK
+#
+ $(EDK_SOURCE)/Foundation
+ $(EDK_SOURCE)/Foundation/Core/Dxe
+ $(EDK_SOURCE)/Foundation/Efi
+ $(EDK_SOURCE)/Foundation/Efi/Include
+ $(EDK_SOURCE)/Foundation/Framework
+ $(EDK_SOURCE)/Foundation/Framework/Include
+ $(EDK_SOURCE)/Foundation/Include
+ $(EDK_SOURCE)/Foundation/Include/IndustryStandard
+ $(EDK_SOURCE)/Foundation/Library/Dxe/Include
+ $(EDK_SOURCE)/Foundation/Library/EdkIIGlueLib/Include
+
+[libraries.common]
+ AmtLib
+ EdkProtocolLib
+ EdkIIGlueBaseLib
+ EdkIIGlueBaseMemoryLib
+ EdkIIGlueDxeReportStatusCodeLib
+ EdkIIGlueDxeDebugLibReportStatusCode
+ EdkIIGlueUefiBootServicesTableLib
+ EdkIIGlueUefiRuntimeServicesTableLib
+ EdkIIGlueUefiDevicePathLib
+ EdkIIGlueUefiLib
+ EdkIIGlueUefiDriverModelLib
+
+[nmake.common]
+ IMAGE_ENTRY_POINT = _ModuleEntryPoint
+
+#
+# Module Entry Point
+#
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_MODULE_ENTRY_POINT__=PciSerialControllerDriverEntryPoint \
+ -D __EDKII_GLUE_DRIVER_BINDING_PROTOCOL_INSTANCE__=mPciSerialControllerDriverBinding \
+ -D __EDKII_GLUE_COMPONENT_NAME_PROTOCOL_INSTANCE__=mPciSerialComponentName
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_BASE_LIB__ \
+ -D __EDKII_GLUE_BASE_MEMORY_LIB__ \
+ -D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ -D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ -D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_RUNTIME_SERVICES_TABLE_LIB__ \
+ -D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__
+ C_FLAGS = $(C_FLAGS) -D __EDKII_GLUE_UEFI_LIB__ \
+ -D __EDKII_GLUE_UEFI_DRIVER_MODEL_LIB__
diff --git a/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.mak b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.mak
new file mode 100644
index 0000000..a94fda5
--- /dev/null
+++ b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.mak
@@ -0,0 +1,55 @@
+# MAK file for the ModulePart:PciSerial
+
+all : PciSerial
+
+$(BUILD_DIR)\PciSerial.mak : $(PciSerial_DIR)\$(@B).cif $(PciSerial_DIR)\$(@B).mak $(BUILD_RULES)
+ $(CIF2MAK) $(PciSerial_DIR)\$(@B).cif $(CIF2MAK_DEFAULTS)
+
+PciSerial : $(BUILD_DIR)\PciSerial.mak PciSerialBin
+
+PciSerial_INCLUDES=\
+ $(EdkIIGlueLib_INCLUDES)\
+ $(ME_INCLUDES)\
+ $(INTEL_PCH_INCLUDES)
+
+PciSerial_LIBS=\
+ $(EDKPROTOCOLLIB)\
+ $(AmtLibDxe_LIB)\
+ $(EdkIIGlueBaseLib_LIB)\
+!IF "$(x64_BUILD)"=="1"
+ $(EdkIIGlueBaseLibX64_LIB)\
+!ELSE
+ $(EdkIIGlueBaseLibIA32_LIB)\
+!ENDIF
+ $(EdkIIGlueBaseMemoryLib_LIB)\
+ $(EdkIIGlueDxeReportStatusCodeLib_LIB)\
+ $(EdkIIGlueDxeDebugLibReportStatusCode_LIB)\
+ $(EdkIIGlueUefiBootServicesTableLib_LIB)\
+ $(EdkIIGlueUefiDevicePathLib_LIB)\
+ $(EdkIIGlueUefiLib_LIB)\
+ $(EdkIIGlueUefiDriverModelLib_LIB)\
+
+PciSerial_DEFINES=\
+ $(MY_DEFINES)\
+ /D"__EDKII_GLUE_MODULE_ENTRY_POINT__=PciSerialControllerDriverEntryPoint"\
+ /D"__EDKII_GLUE_DRIVER_BINDING_PROTOCOL_INSTANCE__=mPciSerialControllerDriverBinding"\
+ /D"__EDKII_GLUE_COMPONENT_NAME_PROTOCOL_INSTANCE__=mPciSerialComponentName"\
+ /D __EDKII_GLUE_BASE_LIB__\
+ /D __EDKII_GLUE_BASE_MEMORY_LIB__\
+ /D __EDKII_GLUE_DXE_REPORT_STATUS_CODE_LIB__ \
+ /D __EDKII_GLUE_DXE_DEBUG_LIB_REPORT_STATUS_CODE__ \
+ /D __EDKII_GLUE_UEFI_BOOT_SERVICES_TABLE_LIB__\
+ /D __EDKII_GLUE_UEFI_DEVICE_PATH_LIB__\
+ /D __EDKII_GLUE_UEFI_LIB__ \
+ /D __EDKII_GLUE_UEFI_DRIVER_MODEL_LIB__
+
+PciSerialBin : $(PciSerial_LIBS)
+ $(MAKE) /$(MAKEFLAGS) $(EDKIIGLUE_DEFAULTS)\
+ /f $(BUILD_DIR)\PciSerial.mak all \
+ "MY_INCLUDES=$(PciSerial_INCLUDES)"\
+ "MY_DEFINES=$(PciSerial_DEFINES)"\
+ GUID=FB142B99-DF57-46cb-BC69-0BF858A734F9 \
+ ENTRY_POINT=_ModuleEntryPoint \
+ TYPE=BS_DRIVER \
+ EDKIIModule=DXEDRIVER\
+ COMPRESS=1
diff --git a/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.sdl b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.sdl
new file mode 100644
index 0000000..b485486
--- /dev/null
+++ b/ReferenceCode/ME/ActiveManagement/Sol/Dxe/PciSerial.sdl
@@ -0,0 +1,24 @@
+TOKEN
+ Name = "PciSerial_SUPPORT"
+ Value = "1"
+ TokenType = Boolean
+ TargetEQU = Yes
+ TargetMAK = Yes
+ Master = Yes
+ Help = "Main switch to enable PciSerial support in Project"
+End
+MODULE
+ Help = "Includes PciSerial.mak to Project"
+ File = "PciSerial.mak"
+End
+
+PATH
+ Name = "PciSerial_DIR"
+ Help = "iAMT PciSerial file source directory"
+End
+
+ELINK
+ Name = "$(BUILD_DIR)\PciSerial.ffs"
+ Parent = "FV_MAIN"
+ InvokeOrder = AfterParent
+End \ No newline at end of file