4 Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 - Microsoft Serial Port Console Redirection Table
15 Specification - Version 1.03 - August 10, 2015.
19 #include <IndustryStandard/DebugPort2Table.h>
20 #include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
21 #include <Library/AcpiLib.h>
22 #include <Library/DebugLib.h>
23 #include <Protocol/AcpiTable.h>
25 // Module specific include files.
26 #include <AcpiTableGenerator.h>
27 #include <ConfigurationManagerObject.h>
28 #include <ConfigurationManagerHelper.h>
29 #include <Library/TableHelperLib.h>
30 #include <Protocol/ConfigurationManagerProtocol.h>
32 /** ARM standard SPCR Table Generator
34 Constructs the SPCR table for PL011 or SBSA UART peripherals.
37 The following Configuration Manager Object(s) are required by
39 - EArmObjSerialConsolePortInfo
41 NOTE: This implementation ignores the possibility that the Serial settings may
42 be modified from the UEFI Shell. A more complex handler would be needed
43 to (e.g.) recover serial port settings from the UART, or non-volatile
49 /** This macro defines the no flow control option.
51 #define SPCR_FLOW_CONTROL_NONE 0
53 /**A template for generating the SPCR Table.
55 Note: fields marked "{Template}" will be updated dynamically.
58 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr
= {
60 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
,
61 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE
,
62 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
64 0, // {Template}: Serial Port Subtype
66 EFI_ACPI_RESERVED_BYTE
,
67 EFI_ACPI_RESERVED_BYTE
,
68 EFI_ACPI_RESERVED_BYTE
70 ARM_GAS32 (0), // {Template}: Serial Port Base Address
71 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC
,
73 0, // {Template}: Serial Port Interrupt
74 0, // {Template}: Serial Port Baudrate
75 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY
,
76 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1
,
77 SPCR_FLOW_CONTROL_NONE
,
78 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI
,
79 EFI_ACPI_RESERVED_BYTE
,
87 EFI_ACPI_RESERVED_DWORD
92 /** This macro expands to a function that retrieves the Serial
93 Port Information from the Configuration Manager.
97 EArmObjSerialConsolePortInfo
,
98 CM_ARM_SERIAL_PORT_INFO
101 /** Construct the SPCR ACPI table.
103 This function invokes the Configuration Manager protocol interface
104 to get the required hardware information for generating the ACPI
107 If this function allocates any resources then they must be freed
108 in the FreeXXXXTableResources function.
110 @param [in] This Pointer to the table generator.
111 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
112 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
114 @param [out] Table Pointer to the constructed ACPI Table.
116 @retval EFI_SUCCESS Table generated successfully.
117 @retval EFI_INVALID_PARAMETER A parameter is invalid.
118 @retval EFI_NOT_FOUND The required object was not found.
119 @retval EFI_UNSUPPORTED An unsupported baudrate was specified by the
120 Configuration Manager.
121 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
122 Manager is less than the Object size for the
129 IN CONST ACPI_TABLE_GENERATOR
* CONST This
,
130 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
131 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
132 OUT EFI_ACPI_DESCRIPTION_HEADER
** CONST Table
136 CM_ARM_SERIAL_PORT_INFO
* SerialPortInfo
;
138 ASSERT (This
!= NULL
);
139 ASSERT (AcpiTableInfo
!= NULL
);
140 ASSERT (CfgMgrProtocol
!= NULL
);
141 ASSERT (Table
!= NULL
);
142 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
143 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
145 if ((AcpiTableInfo
->AcpiTableRevision
< This
->MinAcpiTableRevision
) ||
146 (AcpiTableInfo
->AcpiTableRevision
> This
->AcpiTableRevision
)) {
149 "ERROR: SPCR: Requested table revision = %d, is not supported."
150 "Supported table revision: Minimum = %d, Maximum = %d\n",
151 AcpiTableInfo
->AcpiTableRevision
,
152 This
->MinAcpiTableRevision
,
153 This
->AcpiTableRevision
155 return EFI_INVALID_PARAMETER
;
160 Status
= GetEArmObjSerialConsolePortInfo (
166 if (EFI_ERROR (Status
)) {
169 "ERROR: SPCR: Failed to get serial port information. Status = %r\n",
175 if (SerialPortInfo
->BaseAddress
== 0) {
176 Status
= EFI_INVALID_PARAMETER
;
179 "ERROR: SPCR: Uart port base address is invalid. BaseAddress = 0x%lx\n",
180 SerialPortInfo
->BaseAddress
185 if ((SerialPortInfo
->PortSubtype
!=
186 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART
) &&
187 (SerialPortInfo
->PortSubtype
!=
188 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X
) &&
189 (SerialPortInfo
->PortSubtype
!=
190 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART
) &&
191 (SerialPortInfo
->PortSubtype
!=
192 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550
) &&
193 (SerialPortInfo
->PortSubtype
!=
194 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC
)) {
195 Status
= EFI_INVALID_PARAMETER
;
198 "ERROR: SPCR: Uart port sybtype is invalid. PortSubtype = 0x%x\n",
199 SerialPortInfo
->PortSubtype
204 DEBUG ((DEBUG_INFO
, "SPCR UART Configuration:\n"));
205 DEBUG ((DEBUG_INFO
, " UART Base = 0x%lx\n", SerialPortInfo
->BaseAddress
));
206 DEBUG ((DEBUG_INFO
, " Clock = %d\n", SerialPortInfo
->Clock
));
207 DEBUG ((DEBUG_INFO
, " Baudrate = %ld\n", SerialPortInfo
->BaudRate
));
208 DEBUG ((DEBUG_INFO
, " Interrupt = %d\n", SerialPortInfo
->Interrupt
));
210 Status
= AddAcpiHeader (
213 (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiSpcr
,
214 AcpiTableInfo
->AcpiTableRevision
,
215 sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE
)
217 if (EFI_ERROR (Status
)) {
220 "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",
226 // Update the serial port subtype
227 AcpiSpcr
.InterfaceType
= SerialPortInfo
->PortSubtype
;
229 // Update the base address
230 AcpiSpcr
.BaseAddress
.Address
= SerialPortInfo
->BaseAddress
;
232 // Update the UART interrupt
233 AcpiSpcr
.GlobalSystemInterrupt
= SerialPortInfo
->Interrupt
;
235 switch (SerialPortInfo
->BaudRate
) {
238 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600
;
242 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200
;
246 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600
;
250 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200
;
253 Status
= EFI_UNSUPPORTED
;
256 "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
257 SerialPortInfo
->BaudRate
,
263 *Table
= (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiSpcr
;
269 /** This macro defines the SPCR Table Generator revision.
271 #define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
273 /** The interface for the SPCR Table Generator.
277 ACPI_TABLE_GENERATOR SpcrGenerator
= {
279 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr
),
280 // Generator Description
281 L
"ACPI.STD.SPCR.GENERATOR",
282 // ACPI Table Signature
283 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
,
284 // ACPI Table Revision supported by this Generator
285 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
,
286 // Minimum supported ACPI Table Revision
287 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
,
289 TABLE_GENERATOR_CREATOR_ID_ARM
,
291 SPCR_GENERATOR_REVISION
,
292 // Build Table function
294 // No additional resources are allocated by the generator.
295 // Hence the Free Resource function is not required.
297 // Extended build function not needed
299 // Extended build function not implemented by the generator.
300 // Hence extended free resource function is not required.
304 /** Register the Generator with the ACPI Table Factory.
306 @param [in] ImageHandle The handle to the image.
307 @param [in] SystemTable Pointer to the System Table.
309 @retval EFI_SUCCESS The Generator is registered.
310 @retval EFI_INVALID_PARAMETER A parameter is invalid.
311 @retval EFI_ALREADY_STARTED The Generator for the Table ID
312 is already registered.
316 AcpiSpcrLibConstructor (
317 IN CONST EFI_HANDLE ImageHandle
,
318 IN EFI_SYSTEM_TABLE
* CONST SystemTable
322 Status
= RegisterAcpiTableGenerator (&SpcrGenerator
);
323 DEBUG ((DEBUG_INFO
, "SPCR: Register Generator. Status = %r\n", Status
));
324 ASSERT_EFI_ERROR (Status
);
328 /** Deregister the Generator from the ACPI Table Factory.
330 @param [in] ImageHandle The handle to the image.
331 @param [in] SystemTable Pointer to the System Table.
333 @retval EFI_SUCCESS The Generator is deregistered.
334 @retval EFI_INVALID_PARAMETER A parameter is invalid.
335 @retval EFI_NOT_FOUND The Generator is not registered.
339 AcpiSpcrLibDestructor (
340 IN CONST EFI_HANDLE ImageHandle
,
341 IN EFI_SYSTEM_TABLE
* CONST SystemTable
345 Status
= DeregisterAcpiTableGenerator (&SpcrGenerator
);
346 DEBUG ((DEBUG_INFO
, "SPCR: Deregister Generator. Status = %r\n", Status
));
347 ASSERT_EFI_ERROR (Status
);