/** @file Implementation of FspSerialIoUartDebugHelperLib. @copyright INTEL CONFIDENTIAL Copyright 2019 - 2020 Intel Corporation. The source code contained or described herein and all documents related to the source code ("Material") are owned by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or its suppliers and licensors. The Material may contain trade secrets and proprietary and confidential information of Intel Corporation and its suppliers and licensors, and is protected by worldwide copyright and trade secret laws and treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted, transmitted, distributed, or disclosed in any way without Intel's prior express written permission. No license under any patent, copyright, trade secret or other intellectual property right is granted to or conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement, estoppel or otherwise. Any license under such intellectual property rights must be express and approved by Intel in writing. Unless otherwise agreed by Intel in writing, you may not remove or alter this notice or any other notice embedded in Materials by Intel or Intel's suppliers or licensors in any way. 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. @par Specification Reference: **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /** Configures Serial IO Controller @param[in] UartNumber UART Number @param[in] UartDeviceConfig SerialIo UART Config @param[in] PsfDisable Applies only for SerialIoUartDisabled devices. TRUE - Device will be disabled in PSF, and will no longer enumerate on PCI. FALSE - PSF configuration is left unmodified. **/ VOID SerialIoUartConfiguration ( IN UINT8 UartNumber, IN SERIAL_IO_UART_CONFIG *UartDeviceConfig, IN BOOLEAN PsfDisable ); /** Return FSPT UPD Location Ppi **/ FSPT_UPD * EFIAPI FspSerialIoUartDebugGetFsptUpdLocPpi ( VOID ) { CONST EFI_PEI_SERVICES **PeiServices; IA32_DESCRIPTOR Idtr; EFI_STATUS Status; FSPT_UPD *FsptUpdLocationPpi; Status = EFI_SUCCESS; PeiServices = NULL; FsptUpdLocationPpi = NULL; if (PcdGetBool (PcdFspValidatePeiServiceTablePointer)) { // New PCD to control do PeiServiceTablepointer check or not. For SEC, this PCD is configured as FALSE. Its default value is TRUE AsmReadIdtr (&Idtr); PeiServices = (CONST EFI_PEI_SERVICES **) (*(UINTN*)(Idtr.Base - sizeof (UINTN))); } if (PeiServices != NULL) { Status = (*PeiServices)->LocatePpi ( PeiServices, &gFsptUpdLocationPpiGuid, 0, NULL, (VOID **) &FsptUpdLocationPpi ); if (EFI_ERROR (Status)) { FsptUpdLocationPpi = NULL; } } return FsptUpdLocationPpi; } /** Get FSPT Config @param[in] FsptConfig FSPT Config @retval TRUE if FSPT exists @retval FALSE unable to locate FSP **/ BOOLEAN STATIC GetFsptConfig ( OUT FSP_T_CONFIG **Fspt ) { FSPT_UPD *FsptUpd; FsptUpd = FspSerialIoUartDebugGetFsptUpdLocPpi (); if (FsptUpd != NULL) { *Fspt = &FsptUpd->FsptConfig; return TRUE; } return FALSE; } /** Get FSPM Config @param[out] Fspm FSPM Config @retval TRUE if FSPM exists @retval FALSE unable to locate FSP **/ BOOLEAN STATIC GetFspmConfig ( OUT FSP_M_CONFIG **Fspm ) { FSP_GLOBAL_DATA *FspData; FSPM_UPD *FspmUpd; FspData = GetFspGlobalDataPointer (); if (((UINTN)FspData == 0x00 || (UINTN)FspData == 0xFFFFFFFF) || (FspData->Signature != FSP_GLOBAL_DATA_SIGNATURE)) { return FALSE; } else if ((FspData->FspMode == FSP_IN_API_MODE) && (FspData->MemoryInitUpdPtr != NULL)) { FspmUpd = FspData->MemoryInitUpdPtr; *Fspm = &FspmUpd->FspmConfig; return TRUE; } return FALSE; } /** Returns UART attributes @param[out] UartDeviceConfig A pointer to the SERIAL_IO_UART_CONFIG. @param[out] SerialIoUartNumber The Number of Serial Io Uart. **/ VOID STATIC FspSerialIoUartDebugGetDeviceConfig ( OUT SERIAL_IO_UART_CONFIG *UartDeviceConfig, OUT UINT8 *UartNumber ) { FSP_M_CONFIG *FspmConfig; FSP_T_CONFIG *FsptConfig; FspmConfig = NULL; FsptConfig = NULL; if (GetFsptConfig (&FsptConfig)) { UartDeviceConfig->Attributes.BaudRate = FsptConfig->PcdSerialIoUartBaudRate; UartDeviceConfig->Attributes.Parity = FsptConfig->PcdSerialIoUartParity; UartDeviceConfig->Attributes.DataBits = FsptConfig->PcdSerialIoUartDataBits; UartDeviceConfig->Attributes.StopBits = FsptConfig->PcdSerialIoUartStopBits; UartDeviceConfig->Attributes.AutoFlow = FsptConfig->PcdSerialIoUartAutoFlow; UartDeviceConfig->Mode = FsptConfig->PcdSerialIoUartMode; UartDeviceConfig->PinMux.Rx = FsptConfig->PcdSerialIoUartRxPinMux; UartDeviceConfig->PinMux.Tx = FsptConfig->PcdSerialIoUartTxPinMux; UartDeviceConfig->PinMux.Rts = FsptConfig->PcdSerialIoUartRtsPinMux; UartDeviceConfig->PinMux.Cts = FsptConfig->PcdSerialIoUartCtsPinMux; *UartNumber = FsptConfig->PcdSerialIoUartNumber; } else if (GetFspmConfig (&FspmConfig)) { UartDeviceConfig->Attributes.BaudRate = FspmConfig->SerialIoUartDebugBaudRate; UartDeviceConfig->Attributes.Parity = FspmConfig->SerialIoUartDebugParity; UartDeviceConfig->Attributes.DataBits = FspmConfig->SerialIoUartDebugDataBits; UartDeviceConfig->Attributes.StopBits = FspmConfig->SerialIoUartDebugStopBits; UartDeviceConfig->Attributes.AutoFlow = FspmConfig->SerialIoUartDebugAutoFlow; UartDeviceConfig->Mode = FspmConfig->SerialIoUartDebugMode; UartDeviceConfig->PinMux.Rx = FspmConfig->SerialIoUartDebugRxPinMux; UartDeviceConfig->PinMux.Tx = FspmConfig->SerialIoUartDebugTxPinMux; UartDeviceConfig->PinMux.Rts = FspmConfig->SerialIoUartDebugRtsPinMux; UartDeviceConfig->PinMux.Cts = FspmConfig->SerialIoUartDebugCtsPinMux; *UartNumber = FspmConfig->SerialIoUartDebugControllerNumber; } else { SerialIoUartDebugPcdGetDeviceConfig (UartDeviceConfig, UartNumber); } return; } /** Returns Serial Io UART Controller Number used in Debug mode @retval ControllerNumber UART Controller Number **/ UINT8 STATIC FspSerialIoUartDebugGetControllerNumber ( VOID ) { FSP_M_CONFIG *FspmConfig; FSP_T_CONFIG *FsptConfig; FspmConfig = NULL; FsptConfig = NULL; if (GetFsptConfig (&FsptConfig)) { return FsptConfig->PcdSerialIoUartNumber; } else if (GetFspmConfig (&FspmConfig)) { return FspmConfig->SerialIoUartDebugControllerNumber; } else { return SerialIoUartDebugPcdGetControllerNumber (); } } /** Returns Serial Io UART MMIO Base Address in Debug mode @retval MMIO Base Address by default in PCI Mode **/ UINT32 STATIC FspSerialIoUartDebugGetPciDefaultMmioBase ( VOID ) { FSP_M_CONFIG *FspmConfig; FSP_T_CONFIG *FsptConfig; UINT32 MmioBase; FspmConfig = NULL; FsptConfig = NULL; if (GetFsptConfig (&FsptConfig)) { MmioBase = FsptConfig->PcdSerialIoUartDebugMmioBase; } else if (GetFspmConfig (&FspmConfig)) { MmioBase = FspmConfig->SerialIoUartDebugMmioBase; } else { return SerialIoUartDebugPcdGetPciDefaultMmioBase (); } return MmioBase; } /** Initialize SerialIo UART for debug. **/ VOID EFIAPI SerialIoUartDebugInit ( VOID ) { UINT64 PciCfgBase; UINT64 Bar0; UINT8 UartNumber; EFI_STATUS Status; SERIAL_IO_UART_CONFIG UartDeviceConfig; FspSerialIoUartDebugGetDeviceConfig (&UartDeviceConfig, &UartNumber); if (UartDeviceConfig.Mode == SerialIoUartSkipInit) { return; } PciCfgBase = GetSerialIoUartPciCfg (UartNumber); Bar0 = GetSerialIoBar (PciCfgBase); UartDeviceConfig.DBG2 = FALSE; UartDeviceConfig.DmaEnable = FALSE; SerialIoUartConfiguration (UartNumber, &UartDeviceConfig, TRUE); // // Assign MMIO for HS-UART used in PCI Mode. // if (!IsSerialIoUartInPciMode (UartNumber)) { return; } Bar0 = FspSerialIoUartDebugGetPciDefaultMmioBase (); Status = SerialIoUartSetMmioInPciMode (UartNumber, Bar0); if (Status == EFI_UNSUPPORTED) { return; } // // UART Reset // SerialIoUartGetOutOfReset (Bar0); // // Initialize UART Attributes // SerialIoUartSetAttributes ( UartNumber, UartDeviceConfig.Attributes.BaudRate, UartDeviceConfig.Attributes.Parity, UartDeviceConfig.Attributes.DataBits, UartDeviceConfig.Attributes.StopBits, UartDeviceConfig.Attributes.AutoFlow ); } /** Write data to serial device. If the buffer is NULL, then return 0; if NumberOfBytes is zero, then return 0. @param[in] Buffer Data pointer @param[in] NumberOfBytes Number of output bytes which are cached in Buffer. @retval Actual number of bytes written to serial device. **/ UINTN EFIAPI SerialIoUartDebugWrite ( IN UINT8 *Buffer, IN UINTN NumberOfBytes ) { return SerialIoUartWrite (FspSerialIoUartDebugGetControllerNumber (), Buffer, NumberOfBytes); }