4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
8 - Microsoft Serial Port Console Redirection Table
9 Specification - Version 1.03 - August 10, 2015.
13 #include <IndustryStandard/DebugPort2Table.h>
14 #include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
15 #include <Library/AcpiLib.h>
16 #include <Library/DebugLib.h>
17 #include <Protocol/AcpiTable.h>
19 // Module specific include files.
20 #include <AcpiTableGenerator.h>
21 #include <ConfigurationManagerObject.h>
22 #include <ConfigurationManagerHelper.h>
23 #include <Library/TableHelperLib.h>
24 #include <Protocol/ConfigurationManagerProtocol.h>
26 /** ARM standard SPCR Table Generator
28 Constructs the SPCR table for PL011 or SBSA UART peripherals.
31 The following Configuration Manager Object(s) are required by
33 - EArmObjSerialConsolePortInfo
35 NOTE: This implementation ignores the possibility that the Serial settings may
36 be modified from the UEFI Shell. A more complex handler would be needed
37 to (e.g.) recover serial port settings from the UART, or non-volatile
43 /** This macro defines the no flow control option.
45 #define SPCR_FLOW_CONTROL_NONE 0
47 /**A template for generating the SPCR Table.
49 Note: fields marked "{Template}" will be updated dynamically.
52 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr
= {
54 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
,
55 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE
,
56 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
58 0, // {Template}: Serial Port Subtype
60 EFI_ACPI_RESERVED_BYTE
,
61 EFI_ACPI_RESERVED_BYTE
,
62 EFI_ACPI_RESERVED_BYTE
64 ARM_GAS32 (0), // {Template}: Serial Port Base Address
65 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC
,
67 0, // {Template}: Serial Port Interrupt
68 0, // {Template}: Serial Port Baudrate
69 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY
,
70 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1
,
71 SPCR_FLOW_CONTROL_NONE
,
72 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI
,
73 EFI_ACPI_RESERVED_BYTE
,
81 EFI_ACPI_RESERVED_DWORD
86 /** This macro expands to a function that retrieves the Serial
87 Port Information from the Configuration Manager.
91 EArmObjSerialConsolePortInfo
,
92 CM_ARM_SERIAL_PORT_INFO
95 /** Construct the SPCR ACPI table.
97 This function invokes the Configuration Manager protocol interface
98 to get the required hardware information for generating the ACPI
101 If this function allocates any resources then they must be freed
102 in the FreeXXXXTableResources function.
104 @param [in] This Pointer to the table generator.
105 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
106 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
108 @param [out] Table Pointer to the constructed ACPI Table.
110 @retval EFI_SUCCESS Table generated successfully.
111 @retval EFI_INVALID_PARAMETER A parameter is invalid.
112 @retval EFI_NOT_FOUND The required object was not found.
113 @retval EFI_UNSUPPORTED An unsupported baudrate was specified by the
114 Configuration Manager.
115 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
116 Manager is less than the Object size for the
123 IN CONST ACPI_TABLE_GENERATOR
* CONST This
,
124 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
125 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
126 OUT EFI_ACPI_DESCRIPTION_HEADER
** CONST Table
130 CM_ARM_SERIAL_PORT_INFO
* SerialPortInfo
;
132 ASSERT (This
!= NULL
);
133 ASSERT (AcpiTableInfo
!= NULL
);
134 ASSERT (CfgMgrProtocol
!= NULL
);
135 ASSERT (Table
!= NULL
);
136 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
137 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
139 if ((AcpiTableInfo
->AcpiTableRevision
< This
->MinAcpiTableRevision
) ||
140 (AcpiTableInfo
->AcpiTableRevision
> This
->AcpiTableRevision
)) {
143 "ERROR: SPCR: Requested table revision = %d, is not supported."
144 "Supported table revision: Minimum = %d, Maximum = %d\n",
145 AcpiTableInfo
->AcpiTableRevision
,
146 This
->MinAcpiTableRevision
,
147 This
->AcpiTableRevision
149 return EFI_INVALID_PARAMETER
;
154 Status
= GetEArmObjSerialConsolePortInfo (
160 if (EFI_ERROR (Status
)) {
163 "ERROR: SPCR: Failed to get serial port information. Status = %r\n",
169 if (SerialPortInfo
->BaseAddress
== 0) {
170 Status
= EFI_INVALID_PARAMETER
;
173 "ERROR: SPCR: Uart port base address is invalid. BaseAddress = 0x%lx\n",
174 SerialPortInfo
->BaseAddress
179 if ((SerialPortInfo
->PortSubtype
!=
180 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART
) &&
181 (SerialPortInfo
->PortSubtype
!=
182 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X
) &&
183 (SerialPortInfo
->PortSubtype
!=
184 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART
) &&
185 (SerialPortInfo
->PortSubtype
!=
186 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550
) &&
187 (SerialPortInfo
->PortSubtype
!=
188 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC
)) {
189 Status
= EFI_INVALID_PARAMETER
;
192 "ERROR: SPCR: Uart port sybtype is invalid. PortSubtype = 0x%x\n",
193 SerialPortInfo
->PortSubtype
198 DEBUG ((DEBUG_INFO
, "SPCR UART Configuration:\n"));
199 DEBUG ((DEBUG_INFO
, " UART Base = 0x%lx\n", SerialPortInfo
->BaseAddress
));
200 DEBUG ((DEBUG_INFO
, " Clock = %d\n", SerialPortInfo
->Clock
));
201 DEBUG ((DEBUG_INFO
, " Baudrate = %ld\n", SerialPortInfo
->BaudRate
));
202 DEBUG ((DEBUG_INFO
, " Interrupt = %d\n", SerialPortInfo
->Interrupt
));
204 Status
= AddAcpiHeader (
207 (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiSpcr
,
209 sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE
)
211 if (EFI_ERROR (Status
)) {
214 "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",
220 // Update the serial port subtype
221 AcpiSpcr
.InterfaceType
= SerialPortInfo
->PortSubtype
;
223 // Update the base address
224 AcpiSpcr
.BaseAddress
.Address
= SerialPortInfo
->BaseAddress
;
226 // Update the UART interrupt
227 AcpiSpcr
.GlobalSystemInterrupt
= SerialPortInfo
->Interrupt
;
229 switch (SerialPortInfo
->BaudRate
) {
232 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600
;
236 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200
;
240 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600
;
244 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200
;
247 Status
= EFI_UNSUPPORTED
;
250 "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
251 SerialPortInfo
->BaudRate
,
257 *Table
= (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiSpcr
;
263 /** This macro defines the SPCR Table Generator revision.
265 #define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
267 /** The interface for the SPCR Table Generator.
271 ACPI_TABLE_GENERATOR SpcrGenerator
= {
273 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr
),
274 // Generator Description
275 L
"ACPI.STD.SPCR.GENERATOR",
276 // ACPI Table Signature
277 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
,
278 // ACPI Table Revision supported by this Generator
279 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
,
280 // Minimum supported ACPI Table Revision
281 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
,
283 TABLE_GENERATOR_CREATOR_ID_ARM
,
285 SPCR_GENERATOR_REVISION
,
286 // Build Table function
288 // No additional resources are allocated by the generator.
289 // Hence the Free Resource function is not required.
291 // Extended build function not needed
293 // Extended build function not implemented by the generator.
294 // Hence extended free resource function is not required.
298 /** Register the Generator with the ACPI Table Factory.
300 @param [in] ImageHandle The handle to the image.
301 @param [in] SystemTable Pointer to the System Table.
303 @retval EFI_SUCCESS The Generator is registered.
304 @retval EFI_INVALID_PARAMETER A parameter is invalid.
305 @retval EFI_ALREADY_STARTED The Generator for the Table ID
306 is already registered.
310 AcpiSpcrLibConstructor (
311 IN CONST EFI_HANDLE ImageHandle
,
312 IN EFI_SYSTEM_TABLE
* CONST SystemTable
316 Status
= RegisterAcpiTableGenerator (&SpcrGenerator
);
317 DEBUG ((DEBUG_INFO
, "SPCR: Register Generator. Status = %r\n", Status
));
318 ASSERT_EFI_ERROR (Status
);
322 /** Deregister the Generator from the ACPI Table Factory.
324 @param [in] ImageHandle The handle to the image.
325 @param [in] SystemTable Pointer to the System Table.
327 @retval EFI_SUCCESS The Generator is deregistered.
328 @retval EFI_INVALID_PARAMETER A parameter is invalid.
329 @retval EFI_NOT_FOUND The Generator is not registered.
333 AcpiSpcrLibDestructor (
334 IN CONST EFI_HANDLE ImageHandle
,
335 IN EFI_SYSTEM_TABLE
* CONST SystemTable
339 Status
= DeregisterAcpiTableGenerator (&SpcrGenerator
);
340 DEBUG ((DEBUG_INFO
, "SPCR: Deregister Generator. Status = %r\n", Status
));
341 ASSERT_EFI_ERROR (Status
);