/** @file Serial I/O Port library functions with base address discovered from FDT Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.
Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.
Copyright (c) 2014, Linaro Ltd. All rights reserved.
Copyright (c) 2014, Red Hat, Inc.
Copyright (c) 2015, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include STATIC UINTN mSerialBaseAddress; STATIC RETURN_STATUS mPermanentStatus = RETURN_SUCCESS; /** Program hardware of Serial port @retval RETURN_SUCCESS If the serial port was initialized successfully by this call, or an earlier call, to SerialPortInitialize(). @retval RETURN_NOT_FOUND If no PL011 base address could be found. @return Error codes forwarded from PL011UartInitializePort(). **/ RETURN_STATUS EFIAPI SerialPortInitialize ( VOID ) { VOID *Hob; RETURN_STATUS Status; CONST EARLY_PL011_BASE_ADDRESS *UartBase; UINTN SerialBaseAddress; UINT64 BaudRate; UINT32 ReceiveFifoDepth; EFI_PARITY_TYPE Parity; UINT8 DataBits; EFI_STOP_BITS_TYPE StopBits; if (mSerialBaseAddress != 0) { return RETURN_SUCCESS; } if (RETURN_ERROR (mPermanentStatus)) { return mPermanentStatus; } Hob = GetFirstGuidHob (&gEarlyPL011BaseAddressGuid); if ((Hob == NULL) || (GET_GUID_HOB_DATA_SIZE (Hob) != sizeof *UartBase)) { Status = RETURN_NOT_FOUND; goto Failed; } UartBase = GET_GUID_HOB_DATA (Hob); SerialBaseAddress = (UINTN)UartBase->ConsoleAddress; if (SerialBaseAddress == 0) { Status = RETURN_NOT_FOUND; goto Failed; } BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate); ReceiveFifoDepth = 0; // Use the default value for Fifo depth Parity = (EFI_PARITY_TYPE)PcdGet8 (PcdUartDefaultParity); DataBits = PcdGet8 (PcdUartDefaultDataBits); StopBits = (EFI_STOP_BITS_TYPE)PcdGet8 (PcdUartDefaultStopBits); Status = PL011UartInitializePort ( SerialBaseAddress, FixedPcdGet32 (PL011UartClkInHz), &BaudRate, &ReceiveFifoDepth, &Parity, &DataBits, &StopBits ); if (RETURN_ERROR (Status)) { goto Failed; } mSerialBaseAddress = SerialBaseAddress; return RETURN_SUCCESS; Failed: mPermanentStatus = Status; return Status; } /** Write data to serial device. @param Buffer Point of data buffer which need to be written. @param NumberOfBytes Number of output bytes which are cached in Buffer. @retval 0 Write data failed. @retval !0 Actual number of bytes written to serial device. **/ UINTN EFIAPI SerialPortWrite ( IN UINT8 *Buffer, IN UINTN NumberOfBytes ) { if (!RETURN_ERROR (SerialPortInitialize ())) { return PL011UartWrite (mSerialBaseAddress, Buffer, NumberOfBytes); } return 0; } /** Read data from serial device and save the data in buffer. @param Buffer Point of data buffer which need to be written. @param NumberOfBytes Number of output bytes which are cached in Buffer. @retval 0 Read data failed. @retval !0 Actual number of bytes read from serial device. **/ UINTN EFIAPI SerialPortRead ( OUT UINT8 *Buffer, IN UINTN NumberOfBytes ) { if (!RETURN_ERROR (SerialPortInitialize ())) { return PL011UartRead (mSerialBaseAddress, Buffer, NumberOfBytes); } return 0; } /** Check to see if any data is available to be read from the debug device. @retval TRUE At least one byte of data is available to be read @retval FALSE No data is available to be read **/ BOOLEAN EFIAPI SerialPortPoll ( VOID ) { if (!RETURN_ERROR (SerialPortInitialize ())) { return PL011UartPoll (mSerialBaseAddress); } return FALSE; } /** Sets the baud rate, receive FIFO depth, transmit/receive time out, parity, data bits, and stop bits on a serial device. @param BaudRate The requested baud rate. A BaudRate value of 0 will use the device's default interface speed. On output, the value actually set. @param ReceiveFifoDepth The requested depth of the FIFO on the receive side of the serial interface. A ReceiveFifoDepth value of 0 will use the device's default FIFO depth. On output, the value actually set. @param Timeout The requested time out for a single character in microseconds. This timeout applies to both the transmit and receive side of the interface. A Timeout value of 0 will use the device's default time out value. On output, the value actually set. @param Parity The type of parity to use on this serial device. A Parity value of DefaultParity will use the device's default parity value. On output, the value actually set. @param DataBits The number of data bits to use on the serial device. A DataBits value of 0 will use the device's default data bit setting. On output, the value actually set. @param StopBits The number of stop bits to use on this serial device. A StopBits value of DefaultStopBits will use the device's default number of stop bits. On output, the value actually set. @retval RETURN_SUCCESS The new attributes were set on the serial device. @retval RETURN_UNSUPPORTED The serial device does not support this operation. @retval RETURN_INVALID_PARAMETER One or more of the attributes has an unsupported value. @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. **/ RETURN_STATUS EFIAPI SerialPortSetAttributes ( IN OUT UINT64 *BaudRate, IN OUT UINT32 *ReceiveFifoDepth, IN OUT UINT32 *Timeout, IN OUT EFI_PARITY_TYPE *Parity, IN OUT UINT8 *DataBits, IN OUT EFI_STOP_BITS_TYPE *StopBits ) { RETURN_STATUS Status; if (RETURN_ERROR (SerialPortInitialize ())) { Status = RETURN_UNSUPPORTED; } else { Status = PL011UartInitializePort ( mSerialBaseAddress, FixedPcdGet32 (PL011UartClkInHz), BaudRate, ReceiveFifoDepth, Parity, DataBits, StopBits ); } return Status; } /** Sets the control bits on a serial device. @param Control Sets the bits of Control that are settable. @retval RETURN_SUCCESS The new control bits were set on the serial device. @retval RETURN_UNSUPPORTED The serial device does not support this operation. @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. **/ RETURN_STATUS EFIAPI SerialPortSetControl ( IN UINT32 Control ) { RETURN_STATUS Status; if (RETURN_ERROR (SerialPortInitialize ())) { Status = RETURN_UNSUPPORTED; } else { Status = PL011UartSetControl (mSerialBaseAddress, Control); } return Status; } /** Retrieve the status of the control bits on a serial device. @param Control A pointer to return the current control signals from the serial device. @retval RETURN_SUCCESS The control bits were read from the serial device. @retval RETURN_UNSUPPORTED The serial device does not support this operation. @retval RETURN_DEVICE_ERROR The serial device is not functioning correctly. **/ RETURN_STATUS EFIAPI SerialPortGetControl ( OUT UINT32 *Control ) { RETURN_STATUS Status; if (RETURN_ERROR (SerialPortInitialize ())) { Status = RETURN_UNSUPPORTED; } else { Status = PL011UartGetControl (mSerialBaseAddress, Control); } return Status; }