When scanning for the Serial Port in the device tree, the length and value parameters to ScanMem8() are not in the right order. This results in the serial port not being detected if the chosen node in the device tree has additional elements. Therefore, pass the parameters to ScanMem8() in the correct order to fix this issue. Reviewed-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Pierre Gondois <pierre.gondois@arm.com> Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
139 lines
3.8 KiB
C
139 lines
3.8 KiB
C
/** @file
|
|
Early Platform Hook Library instance for 16550 Uart.
|
|
|
|
Copyright (c) 2020 - 2023, Arm Ltd. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <Base.h>
|
|
#include <Uefi.h>
|
|
|
|
#include <Pi/PiBootMode.h>
|
|
#include <Pi/PiHob.h>
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/PlatformHookLib.h>
|
|
#include <libfdt.h>
|
|
|
|
/** Get the UART base address of the console serial-port from the DT.
|
|
|
|
This function fetches the node referenced in the "stdout-path"
|
|
property of the "chosen" node and returns the base address of
|
|
the console UART.
|
|
|
|
@param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
|
|
@param [out] SerialConsoleAddress If success, contains the base address
|
|
of the console serial-port.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully.
|
|
@retval EFI_NOT_FOUND Console serial-port info not found in DT.
|
|
@retval EFI_INVALID_PARAMETER Invalid parameter.
|
|
**/
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
GetSerialConsolePortAddress (
|
|
IN CONST VOID *Fdt,
|
|
OUT UINT64 *SerialConsoleAddress
|
|
)
|
|
{
|
|
CONST CHAR8 *Prop;
|
|
INT32 PropSize;
|
|
CONST CHAR8 *Path;
|
|
INT32 PathLen;
|
|
INT32 ChosenNode;
|
|
INT32 SerialConsoleNode;
|
|
INT32 Len;
|
|
CONST CHAR8 *NodeStatus;
|
|
CONST UINT64 *RegProperty;
|
|
|
|
if ((Fdt == NULL) || (fdt_check_header (Fdt) != 0)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
// The "chosen" node resides at the root of the DT. Fetch it.
|
|
ChosenNode = fdt_path_offset (Fdt, "/chosen");
|
|
if (ChosenNode < 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Prop = fdt_getprop (Fdt, ChosenNode, "stdout-path", &PropSize);
|
|
if (PropSize < 0) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
// Determine the actual path length, as a colon terminates the path.
|
|
Path = ScanMem8 (Prop, PropSize, ':');
|
|
if (Path == NULL) {
|
|
PathLen = AsciiStrLen (Prop);
|
|
} else {
|
|
PathLen = Path - Prop;
|
|
}
|
|
|
|
// Aliases cannot start with a '/', so it must be the actual path.
|
|
if (Prop[0] == '/') {
|
|
SerialConsoleNode = fdt_path_offset_namelen (Fdt, Prop, PathLen);
|
|
} else {
|
|
// Lookup the alias, as this contains the actual path.
|
|
Path = fdt_get_alias_namelen (Fdt, Prop, PathLen);
|
|
if (Path == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
SerialConsoleNode = fdt_path_offset (Fdt, Path);
|
|
}
|
|
|
|
NodeStatus = fdt_getprop (Fdt, SerialConsoleNode, "status", &Len);
|
|
if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
RegProperty = fdt_getprop (Fdt, SerialConsoleNode, "reg", &Len);
|
|
if (Len != 16) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
*SerialConsoleAddress = fdt64_to_cpu (ReadUnaligned64 (RegProperty));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/** Platform hook to retrieve the 16550 UART base address from the platform
|
|
Device tree and store it in PcdSerialRegisterBase.
|
|
|
|
@retval RETURN_SUCCESS Success.
|
|
@retval RETURN_INVALID_PARAMETER A parameter was invalid.
|
|
@retval RETURN_NOT_FOUND Serial port information not found.
|
|
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
PlatformHookSerialPortInitialize (
|
|
VOID
|
|
)
|
|
{
|
|
RETURN_STATUS Status;
|
|
VOID *DeviceTreeBase;
|
|
UINT64 SerialConsoleAddress;
|
|
|
|
if (PcdGet64 (PcdSerialRegisterBase) != 0) {
|
|
return RETURN_SUCCESS;
|
|
}
|
|
|
|
DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
|
|
if (DeviceTreeBase == NULL) {
|
|
return RETURN_NOT_FOUND;
|
|
}
|
|
|
|
Status = GetSerialConsolePortAddress (DeviceTreeBase, &SerialConsoleAddress);
|
|
if (RETURN_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return (EFI_STATUS)PcdSet64S (PcdSerialRegisterBase, SerialConsoleAddress);
|
|
}
|