4 Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 - Microsoft Serial Port Console Redirection Table
10 Specification - Version 1.03 - August 10, 2015.
14 #include <IndustryStandard/DebugPort2Table.h>
15 #include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
16 #include <Library/AcpiLib.h>
17 #include <Library/DebugLib.h>
18 #include <Library/MemoryAllocationLib.h>
19 #include <Protocol/AcpiTable.h>
21 // Module specific include files.
22 #include <AcpiTableGenerator.h>
23 #include <ConfigurationManagerObject.h>
24 #include <ConfigurationManagerHelper.h>
25 #include <Library/SsdtSerialPortFixupLib.h>
26 #include <Library/TableHelperLib.h>
27 #include <Protocol/ConfigurationManagerProtocol.h>
29 /** ARM standard SPCR Table Generator
31 Constructs the SPCR table for PL011 or SBSA UART peripherals.
34 The following Configuration Manager Object(s) are required by
36 - EArmObjSerialConsolePortInfo
38 NOTE: This implementation ignores the possibility that the Serial settings may
39 be modified from the UEFI Shell. A more complex handler would be needed
40 to (e.g.) recover serial port settings from the UART, or non-volatile
46 /** A string representing the name of the SPCR port.
48 #define NAME_STR_SPCR_PORT "COM1"
50 /** An UID representing the SPCR port.
52 #define UID_SPCR_PORT 1
54 /** This macro defines the no flow control option.
56 #define SPCR_FLOW_CONTROL_NONE 0
58 /**A template for generating the SPCR Table.
60 Note: fields marked "{Template}" will be updated dynamically.
63 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr
= {
65 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
,
66 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE
,
67 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
69 0, // {Template}: Serial Port Subtype
71 EFI_ACPI_RESERVED_BYTE
,
72 EFI_ACPI_RESERVED_BYTE
,
73 EFI_ACPI_RESERVED_BYTE
75 ARM_GAS32 (0), // {Template}: Serial Port Base Address
76 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC
,
78 0, // {Template}: Serial Port Interrupt
79 0, // {Template}: Serial Port Baudrate
80 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY
,
81 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1
,
82 SPCR_FLOW_CONTROL_NONE
,
83 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI
,
84 EFI_ACPI_RESERVED_BYTE
,
92 EFI_ACPI_RESERVED_DWORD
97 /** This macro expands to a function that retrieves the Serial
98 Port Information from the Configuration Manager.
102 EArmObjSerialConsolePortInfo
,
103 CM_ARM_SERIAL_PORT_INFO
106 /** Free any resources allocated for constructing the tables.
108 @param [in] This Pointer to the ACPI table generator.
109 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
110 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
112 @param [in, out] Table Pointer to an array of pointers
114 @param [in] TableCount Number of ACPI table(s).
116 @retval EFI_SUCCESS The resources were freed successfully.
117 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
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 IN OUT EFI_ACPI_DESCRIPTION_HEADER
*** CONST Table
,
127 IN CONST UINTN TableCount
131 EFI_ACPI_DESCRIPTION_HEADER
** TableList
;
133 ASSERT (This
!= NULL
);
134 ASSERT (AcpiTableInfo
!= NULL
);
135 ASSERT (CfgMgrProtocol
!= NULL
);
136 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
137 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
139 if ((Table
== NULL
) ||
142 DEBUG ((DEBUG_ERROR
, "ERROR: SPCR: Invalid Table Pointer\n"));
143 return EFI_INVALID_PARAMETER
;
148 if ((TableList
[1] == NULL
) ||
149 (TableList
[1]->Signature
!=
150 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
)) {
151 DEBUG ((DEBUG_ERROR
, "ERROR: SPCR: Invalid SSDT table pointer.\n"));
152 return EFI_INVALID_PARAMETER
;
155 // Only need to free the SSDT table at index 1. The SPCR table is static.
156 Status
= FreeSsdtSerialPortTable (TableList
[1]);
157 ASSERT_EFI_ERROR (Status
);
159 // Free the table list.
165 /** Construct the SPCR ACPI table and its associated SSDT table.
167 This function invokes the Configuration Manager protocol interface
168 to get the required hardware information for generating the ACPI
171 If this function allocates any resources then they must be freed
172 in the FreeXXXXTableResourcesEx function.
174 @param [in] This Pointer to the ACPI table generator.
175 @param [in] AcpiTableInfo Pointer to the ACPI table information.
176 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
178 @param [out] Table Pointer to a list of generated ACPI table(s).
179 @param [out] TableCount Number of generated ACPI table(s).
181 @retval EFI_SUCCESS Table generated successfully.
182 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
183 Manager is less than the Object size for
184 the requested object.
185 @retval EFI_INVALID_PARAMETER A parameter is invalid.
186 @retval EFI_NOT_FOUND Could not find information.
187 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
188 @retval EFI_UNSUPPORTED Unsupported configuration.
194 IN CONST ACPI_TABLE_GENERATOR
* This
,
195 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
196 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
197 OUT EFI_ACPI_DESCRIPTION_HEADER
*** Table
,
198 OUT UINTN
* CONST TableCount
202 CM_ARM_SERIAL_PORT_INFO
* SerialPortInfo
;
203 UINT32 SerialPortCount
;
204 EFI_ACPI_DESCRIPTION_HEADER
** TableList
;
206 ASSERT (This
!= NULL
);
207 ASSERT (AcpiTableInfo
!= NULL
);
208 ASSERT (CfgMgrProtocol
!= NULL
);
209 ASSERT (Table
!= NULL
);
210 ASSERT (TableCount
!= NULL
);
211 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
212 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
214 if ((AcpiTableInfo
->AcpiTableRevision
< This
->MinAcpiTableRevision
) ||
215 (AcpiTableInfo
->AcpiTableRevision
> This
->AcpiTableRevision
)) {
218 "ERROR: SPCR: Requested table revision = %d, is not supported."
219 "Supported table revision: Minimum = %d, Maximum = %d\n",
220 AcpiTableInfo
->AcpiTableRevision
,
221 This
->MinAcpiTableRevision
,
222 This
->AcpiTableRevision
224 return EFI_INVALID_PARAMETER
;
229 Status
= GetEArmObjSerialConsolePortInfo (
235 if (EFI_ERROR (Status
)) {
238 "ERROR: SPCR: Failed to get serial port information. Status = %r\n",
244 if (SerialPortCount
== 0) {
247 "ERROR: SPCR: Serial port information not found. Status = %r\n",
250 return EFI_NOT_FOUND
;
253 // Validate the SerialPort info. Only one SPCR port can be described.
254 // If platform provides description for multiple SPCR ports, use the
255 // first SPCR port information.
256 Status
= ValidateSerialPortInfo (SerialPortInfo
, 1);
257 if (EFI_ERROR (Status
)) {
260 "ERROR: SPCR: Invalid serial port information. Status = %r\n",
266 // Allocate a table to store pointers to the SPCR and SSDT tables.
267 TableList
= (EFI_ACPI_DESCRIPTION_HEADER
**)
268 AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER
*) * 2);
269 if (TableList
== NULL
) {
270 Status
= EFI_OUT_OF_RESOURCES
;
273 "ERROR: SPCR: Failed to allocate memory for Table List," \
281 Status
= AddAcpiHeader (
284 (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiSpcr
,
286 sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE
)
288 if (EFI_ERROR (Status
)) {
291 "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",
297 // The SPCR InterfaceType uses the same encoding as that of the
298 // DBG2 table Port Subtype field. However InterfaceType is 8-bit
299 // while the Port Subtype field in the DBG2 table is 16-bit.
300 if ((SerialPortInfo
->PortSubtype
& 0xFF00) != 0) {
301 Status
= EFI_INVALID_PARAMETER
;
304 "ERROR: SPCR: Invalid Port subtype (must be < 256). Status = %r\n",
310 // Update the serial port subtype
311 AcpiSpcr
.InterfaceType
= (UINT8
)SerialPortInfo
->PortSubtype
;
313 // Update the base address
314 AcpiSpcr
.BaseAddress
.Address
= SerialPortInfo
->BaseAddress
;
316 // Update the UART interrupt
317 AcpiSpcr
.GlobalSystemInterrupt
= SerialPortInfo
->Interrupt
;
319 switch (SerialPortInfo
->BaudRate
) {
322 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600
;
326 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200
;
330 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600
;
334 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200
;
337 Status
= EFI_UNSUPPORTED
;
340 "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",
341 SerialPortInfo
->BaudRate
,
347 TableList
[0] = (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiSpcr
;
349 // Build a SSDT table describing the serial port.
350 Status
= BuildSsdtSerialPortTable (
357 if (EFI_ERROR (Status
)) {
360 "ERROR: SPCR: Failed to build associated SSDT table. Status = %r\n",
372 if (TableList
!= NULL
) {
373 FreePool (TableList
);
379 /** This macro defines the SPCR Table Generator revision.
381 #define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)
383 /** The interface for the SPCR Table Generator.
387 ACPI_TABLE_GENERATOR SpcrGenerator
= {
389 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr
),
390 // Generator Description
391 L
"ACPI.STD.SPCR.GENERATOR",
392 // ACPI Table Signature
393 EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE
,
394 // ACPI Table Revision supported by this Generator
395 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
,
396 // Minimum supported ACPI Table Revision
397 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION
,
399 TABLE_GENERATOR_CREATOR_ID_ARM
,
401 SPCR_GENERATOR_REVISION
,
402 // Build table function. Use the extended version instead.
404 // Free table function. Use the extended version instead.
406 // Extended Build table function.
408 // Extended free function.
412 /** Register the Generator with the ACPI Table Factory.
414 @param [in] ImageHandle The handle to the image.
415 @param [in] SystemTable Pointer to the System Table.
417 @retval EFI_SUCCESS The Generator is registered.
418 @retval EFI_INVALID_PARAMETER A parameter is invalid.
419 @retval EFI_ALREADY_STARTED The Generator for the Table ID
420 is already registered.
424 AcpiSpcrLibConstructor (
425 IN EFI_HANDLE ImageHandle
,
426 IN EFI_SYSTEM_TABLE
* SystemTable
430 Status
= RegisterAcpiTableGenerator (&SpcrGenerator
);
431 DEBUG ((DEBUG_INFO
, "SPCR: Register Generator. Status = %r\n", Status
));
432 ASSERT_EFI_ERROR (Status
);
436 /** Deregister the Generator from the ACPI Table Factory.
438 @param [in] ImageHandle The handle to the image.
439 @param [in] SystemTable Pointer to the System Table.
441 @retval EFI_SUCCESS The Generator is deregistered.
442 @retval EFI_INVALID_PARAMETER A parameter is invalid.
443 @retval EFI_NOT_FOUND The Generator is not registered.
447 AcpiSpcrLibDestructor (
448 IN EFI_HANDLE ImageHandle
,
449 IN EFI_SYSTEM_TABLE
* SystemTable
453 Status
= DeregisterAcpiTableGenerator (&SpcrGenerator
);
454 DEBUG ((DEBUG_INFO
, "SPCR: Deregister Generator. Status = %r\n", Status
));
455 ASSERT_EFI_ERROR (Status
);