2 SSDT Serial Port Table Generator.
4 Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include <IndustryStandard/DebugPort2Table.h>
10 #include <Library/AcpiLib.h>
11 #include <Library/BaseLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/MemoryAllocationLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Protocol/AcpiTable.h>
18 // Module specific include files.
19 #include <AcpiTableGenerator.h>
20 #include <ConfigurationManagerObject.h>
21 #include <ConfigurationManagerHelper.h>
22 #include <Library/SsdtSerialPortFixupLib.h>
23 #include <Library/TableHelperLib.h>
24 #include <Protocol/ConfigurationManagerProtocol.h>
26 /** ARM standard SSDT Serial Port Table Generator
28 Constructs SSDT tables describing serial ports (other than the serial ports
29 used by the SPCR or DBG2 tables).
32 The following Configuration Manager Object(s) are required by
34 - EArmObjSerialPortInfo
37 /** This macro expands to a function that retrieves the Serial-port
38 information from the Configuration Manager.
42 EArmObjSerialPortInfo
,
43 CM_ARM_SERIAL_PORT_INFO
46 /** Starting value for the UID to represent the serial ports.
47 Note: The UID 0 and 1 are reserved for use by DBG2 port and SPCR
48 respectively. So, the UIDs for serial ports for general use
51 #define SERIAL_PORT_START_UID 2
53 /** Maximum serial ports supported by this generator.
54 This generator supports a maximum of 14 (16 - 2) serial ports.
55 The -2 here reflects the reservation for serial ports for the DBG2
56 and SPCR ports regardless of whether the DBG2 or SPCR port is enabled.
57 Note: This is not a hard limitation and can be extended if needed.
58 Corresponding changes would be needed to support the Name and
59 UID fields describing the serial port.
62 #define MAX_SERIAL_PORTS_SUPPORTED 14
64 /** Free any resources allocated for constructing the tables.
66 @param [in] This Pointer to the ACPI table generator.
67 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
68 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
70 @param [in, out] Table Pointer to an array of pointers
72 @param [in] TableCount Number of ACPI table(s).
74 @retval EFI_SUCCESS The resources were freed successfully.
75 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
80 FreeSsdtSerialPortTableEx (
81 IN CONST ACPI_TABLE_GENERATOR
* CONST This
,
82 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
83 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
84 IN OUT EFI_ACPI_DESCRIPTION_HEADER
*** CONST Table
,
85 IN CONST UINTN TableCount
89 EFI_ACPI_DESCRIPTION_HEADER
** TableList
;
92 ASSERT (This
!= NULL
);
93 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
94 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
95 ASSERT (CfgMgrProtocol
!= NULL
);
96 ASSERT (AcpiTableInfo
!= NULL
);
98 if ((Table
== NULL
) ||
101 DEBUG ((DEBUG_ERROR
, "ERROR: SSDT-SERIAL-PORT: Invalid Table Pointer\n"));
102 return EFI_INVALID_PARAMETER
;
107 for (Index
= 0; Index
< TableCount
; Index
++) {
108 if ((TableList
[Index
] != NULL
) &&
109 (TableList
[Index
]->Signature
==
110 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
)) {
111 Status
= FreeSsdtSerialPortTable (TableList
[Index
]);
113 Status
= EFI_INVALID_PARAMETER
;
116 if (EFI_ERROR (Status
)) {
119 "ERROR: SSDT-SERIAL-PORT: Could not free SSDT table at index %d."
128 // Free the table list.
134 /** Construct SSDT tables describing serial-ports.
136 This function invokes the Configuration Manager protocol interface
137 to get the required hardware information for generating the ACPI
140 If this function allocates any resources then they must be freed
141 in the FreeXXXXTableResourcesEx function.
143 @param [in] This Pointer to the ACPI table generator.
144 @param [in] AcpiTableInfo Pointer to the ACPI table information.
145 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
147 @param [out] Table Pointer to a list of generated ACPI table(s).
148 @param [out] TableCount Number of generated ACPI table(s).
150 @retval EFI_SUCCESS Table generated successfully.
151 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
152 Manager is less than the Object size for
153 the requested object.
154 @retval EFI_INVALID_PARAMETER A parameter is invalid.
155 @retval EFI_NOT_FOUND Could not find information.
156 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
157 @retval EFI_UNSUPPORTED Unsupported configuration.
162 BuildSsdtSerialPortTableEx (
163 IN CONST ACPI_TABLE_GENERATOR
* This
,
164 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
165 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
166 OUT EFI_ACPI_DESCRIPTION_HEADER
*** Table
,
167 OUT UINTN
* CONST TableCount
171 CM_ARM_SERIAL_PORT_INFO
* SerialPortInfo
;
172 UINT32 SerialPortCount
;
174 CHAR8 NewName
[] = "COMx";
176 EFI_ACPI_DESCRIPTION_HEADER
** TableList
;
178 ASSERT (This
!= NULL
);
179 ASSERT (AcpiTableInfo
!= NULL
);
180 ASSERT (CfgMgrProtocol
!= NULL
);
181 ASSERT (Table
!= NULL
);
182 ASSERT (TableCount
!= NULL
);
183 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
184 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
188 Status
= GetEArmObjSerialPortInfo (
194 if (EFI_ERROR (Status
)) {
197 "ERROR: SSDT-SERIAL-PORT: Failed to get serial port information."
204 if (SerialPortCount
> MAX_SERIAL_PORTS_SUPPORTED
) {
207 "ERROR: SSDT-SERIAL-PORT: Too many serial ports: %d."
208 " Maximum serial ports supported = %d.\n",
210 MAX_SERIAL_PORTS_SUPPORTED
212 return EFI_INVALID_PARAMETER
;
215 // Validate the SerialPort info.
216 Status
= ValidateSerialPortInfo (SerialPortInfo
, SerialPortCount
);
217 if (EFI_ERROR (Status
)) {
220 "ERROR: SSDT-SERIAL-PORT: Invalid serial port information. Status = %r\n",
226 // Allocate a table to store pointers to the SSDT tables.
227 TableList
= (EFI_ACPI_DESCRIPTION_HEADER
**)
229 (sizeof (EFI_ACPI_DESCRIPTION_HEADER
*) * SerialPortCount
)
231 if (TableList
== NULL
) {
232 Status
= EFI_OUT_OF_RESOURCES
;
235 "ERROR: SSDT-SERIAL-PORT: Failed to allocate memory for Table List."
242 // Setup the table list early so that that appropriate cleanup
243 // can be done in case of failure.
246 for (Index
= 0; Index
< SerialPortCount
; Index
++) {
247 Uid
= SERIAL_PORT_START_UID
+ Index
;
248 NewName
[3] = AsciiFromHex ((UINT8
)(Uid
));
250 // Build a SSDT table describing the serial port.
251 Status
= BuildSsdtSerialPortTable (
253 &SerialPortInfo
[Index
],
258 if (EFI_ERROR (Status
)) {
261 "ERROR: SSDT-SERIAL-PORT: Failed to build associated SSDT table."
268 // Increment the table count here so that appropriate cleanup
269 // can be done in case of failure.
274 // Note: Table list and Serial port count has been setup. The
275 // error handler does nothing here as the framework will invoke
276 // FreeSsdtSerialPortTableEx() even on failure.
280 /** This macro defines the SSDT Serial Port Table Generator revision.
282 #define SSDT_SERIAL_GENERATOR_REVISION CREATE_REVISION (1, 0)
284 /** The interface for the SSDT Serial Port Table Generator.
288 ACPI_TABLE_GENERATOR SsdtSerialPortGenerator
= {
290 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtSerialPort
),
291 // Generator Description
292 L
"ACPI.STD.SSDT.SERIAL.PORT.GENERATOR",
293 // ACPI Table Signature
294 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
,
295 // ACPI Table Revision - Unused
297 // Minimum ACPI Table Revision - Unused
300 TABLE_GENERATOR_CREATOR_ID_ARM
,
302 SSDT_SERIAL_GENERATOR_REVISION
,
303 // Build table function. Use the extended version instead.
305 // Free table function. Use the extended version instead.
307 // Extended Build table function.
308 BuildSsdtSerialPortTableEx
,
309 // Extended free function.
310 FreeSsdtSerialPortTableEx
313 /** Register the Generator with the ACPI Table Factory.
315 @param [in] ImageHandle The handle to the image.
316 @param [in] SystemTable Pointer to the System Table.
318 @retval EFI_SUCCESS The Generator is registered.
319 @retval EFI_INVALID_PARAMETER A parameter is invalid.
320 @retval EFI_ALREADY_STARTED The Generator for the Table ID
321 is already registered.
325 AcpiSsdtSerialPortLibConstructor (
326 IN EFI_HANDLE ImageHandle
,
327 IN EFI_SYSTEM_TABLE
* SystemTable
331 Status
= RegisterAcpiTableGenerator (&SsdtSerialPortGenerator
);
334 "SSDT-SERIAL-PORT: Register Generator. Status = %r\n",
337 ASSERT_EFI_ERROR (Status
);
342 /** Deregister the Generator from the ACPI Table Factory.
344 @param [in] ImageHandle The handle to the image.
345 @param [in] SystemTable Pointer to the System Table.
347 @retval EFI_SUCCESS The Generator is deregistered.
348 @retval EFI_INVALID_PARAMETER A parameter is invalid.
349 @retval EFI_NOT_FOUND The Generator is not registered.
353 AcpiSsdtSerialPortLibDestructor (
354 IN EFI_HANDLE ImageHandle
,
355 IN EFI_SYSTEM_TABLE
* SystemTable
359 Status
= DeregisterAcpiTableGenerator (&SsdtSerialPortGenerator
);
362 "SSDT-SERIAL-PORT: Deregister Generator. Status = %r\n",
365 ASSERT_EFI_ERROR (Status
);