4 Copyright (c) 2017 - 2020, 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 subtype 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 // The SPCR InterfaceType uses the same encoding as that of the
221 // DBG2 table Port Subtype field. However InterfaceType is 8-bit
222 // while the Port Subtype field in the DBG2 table is 16-bit.
223 if ((SerialPortInfo
->PortSubtype
& 0xFF00) != 0) {
224 Status
= EFI_INVALID_PARAMETER
;
227 "ERROR: SPCR: Invalid Port subtype (must be < 256). Status = %r\n",
233 // Update the serial port subtype
234 AcpiSpcr
.InterfaceType
= (UINT8
)SerialPortInfo
->PortSubtype
;
236 // Update the base address
237 AcpiSpcr
.BaseAddress
.Address
= SerialPortInfo
->BaseAddress
;
239 // Update the UART interrupt
240 AcpiSpcr
.GlobalSystemInterrupt
= SerialPortInfo
->Interrupt
;
242 switch (SerialPortInfo
->BaudRate
) {
245 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600
;
249 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200
;
253 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600
;
257 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200
;
260 Status
= EFI_UNSUPPORTED
;
263 "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
264 SerialPortInfo
->BaudRate
,
270 *Table
= (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiSpcr
;
276 /** This macro defines the SPCR Table Generator revision.
278 #define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
280 /** The interface for the SPCR Table Generator.
284 ACPI_TABLE_GENERATOR SpcrGenerator
= {
286 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr
),
287 // Generator Description
288 L
"ACPI.STD.SPCR.GENERATOR",
289 // ACPI Table Signature
290 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
,
291 // ACPI Table Revision supported by this Generator
292 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
,
293 // Minimum supported ACPI Table Revision
294 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
,
296 TABLE_GENERATOR_CREATOR_ID_ARM
,
298 SPCR_GENERATOR_REVISION
,
299 // Build Table function
301 // No additional resources are allocated by the generator.
302 // Hence the Free Resource function is not required.
304 // Extended build function not needed
306 // Extended build function not implemented by the generator.
307 // Hence extended free resource function is not required.
311 /** Register the Generator with the ACPI Table Factory.
313 @param [in] ImageHandle The handle to the image.
314 @param [in] SystemTable Pointer to the System Table.
316 @retval EFI_SUCCESS The Generator is registered.
317 @retval EFI_INVALID_PARAMETER A parameter is invalid.
318 @retval EFI_ALREADY_STARTED The Generator for the Table ID
319 is already registered.
323 AcpiSpcrLibConstructor (
324 IN EFI_HANDLE ImageHandle
,
325 IN EFI_SYSTEM_TABLE
* SystemTable
329 Status
= RegisterAcpiTableGenerator (&SpcrGenerator
);
330 DEBUG ((DEBUG_INFO
, "SPCR: Register Generator. Status = %r\n", Status
));
331 ASSERT_EFI_ERROR (Status
);
335 /** Deregister the Generator from the ACPI Table Factory.
337 @param [in] ImageHandle The handle to the image.
338 @param [in] SystemTable Pointer to the System Table.
340 @retval EFI_SUCCESS The Generator is deregistered.
341 @retval EFI_INVALID_PARAMETER A parameter is invalid.
342 @retval EFI_NOT_FOUND The Generator is not registered.
346 AcpiSpcrLibDestructor (
347 IN EFI_HANDLE ImageHandle
,
348 IN EFI_SYSTEM_TABLE
* SystemTable
352 Status
= DeregisterAcpiTableGenerator (&SpcrGenerator
);
353 DEBUG ((DEBUG_INFO
, "SPCR: Deregister Generator. Status = %r\n", Status
));
354 ASSERT_EFI_ERROR (Status
);