1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
/** @file
Early Platform Hook Library instance for 16550 Uart.
Copyright (c) 2020, 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 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);
}
|