]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
DynamicTablesPkg: Fix issues reported by EDKII CI
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiSpcrLibArm / SpcrGenerator.c
CommitLineData
9123b687
SM
1/** @file\r
2 SPCR Table Generator\r
3\r
e3f8605a 4 Copyright (c) 2017 - 2020, ARM Limited. All rights reserved.\r
9cd9bdc6 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9123b687
SM
6\r
7 @par Reference(s):\r
8 - Microsoft Serial Port Console Redirection Table\r
9 Specification - Version 1.03 - August 10, 2015.\r
10\r
11**/\r
12\r
13#include <IndustryStandard/DebugPort2Table.h>\r
14#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>\r
15#include <Library/AcpiLib.h>\r
16#include <Library/DebugLib.h>\r
17#include <Protocol/AcpiTable.h>\r
18\r
19// Module specific include files.\r
20#include <AcpiTableGenerator.h>\r
21#include <ConfigurationManagerObject.h>\r
22#include <ConfigurationManagerHelper.h>\r
23#include <Library/TableHelperLib.h>\r
24#include <Protocol/ConfigurationManagerProtocol.h>\r
25\r
26/** ARM standard SPCR Table Generator\r
27\r
28 Constructs the SPCR table for PL011 or SBSA UART peripherals.\r
29\r
30Requirements:\r
31 The following Configuration Manager Object(s) are required by\r
32 this Generator:\r
33 - EArmObjSerialConsolePortInfo\r
34\r
35NOTE: This implementation ignores the possibility that the Serial settings may\r
36 be modified from the UEFI Shell. A more complex handler would be needed\r
37 to (e.g.) recover serial port settings from the UART, or non-volatile\r
38 storage.\r
39*/\r
40\r
41#pragma pack(1)\r
42\r
43/** This macro defines the no flow control option.\r
44*/\r
45#define SPCR_FLOW_CONTROL_NONE 0\r
46\r
47/**A template for generating the SPCR Table.\r
48\r
49 Note: fields marked "{Template}" will be updated dynamically.\r
50*/\r
51STATIC\r
52EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = {\r
53 ACPI_HEADER (\r
54 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,\r
55 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE,\r
56 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION\r
57 ),\r
58 0, // {Template}: Serial Port Subtype\r
59 {\r
60 EFI_ACPI_RESERVED_BYTE,\r
61 EFI_ACPI_RESERVED_BYTE,\r
62 EFI_ACPI_RESERVED_BYTE\r
63 },\r
64 ARM_GAS32 (0), // {Template}: Serial Port Base Address\r
65 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC,\r
66 0, // Not used on ARM\r
67 0, // {Template}: Serial Port Interrupt\r
68 0, // {Template}: Serial Port Baudrate\r
69 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,\r
70 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,\r
71 SPCR_FLOW_CONTROL_NONE,\r
72 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI,\r
73 EFI_ACPI_RESERVED_BYTE,\r
74 0xFFFF,\r
75 0xFFFF,\r
76 0x00,\r
77 0x00,\r
78 0x00,\r
79 0x00000000,\r
80 0x00,\r
81 EFI_ACPI_RESERVED_DWORD\r
82};\r
83\r
84#pragma pack()\r
85\r
86/** This macro expands to a function that retrieves the Serial\r
87 Port Information from the Configuration Manager.\r
88*/\r
89GET_OBJECT_LIST (\r
90 EObjNameSpaceArm,\r
91 EArmObjSerialConsolePortInfo,\r
92 CM_ARM_SERIAL_PORT_INFO\r
93 )\r
94\r
95/** Construct the SPCR ACPI table.\r
96\r
97 This function invokes the Configuration Manager protocol interface\r
98 to get the required hardware information for generating the ACPI\r
99 table.\r
100\r
101 If this function allocates any resources then they must be freed\r
102 in the FreeXXXXTableResources function.\r
103\r
104 @param [in] This Pointer to the table generator.\r
105 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
106 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
107 Protocol Interface.\r
108 @param [out] Table Pointer to the constructed ACPI Table.\r
109\r
110 @retval EFI_SUCCESS Table generated successfully.\r
111 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
112 @retval EFI_NOT_FOUND The required object was not found.\r
113 @retval EFI_UNSUPPORTED An unsupported baudrate was specified by the\r
114 Configuration Manager.\r
115 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
116 Manager is less than the Object size for the\r
117 requested object.\r
118**/\r
119STATIC\r
120EFI_STATUS\r
121EFIAPI\r
122BuildSpcrTable (\r
123 IN CONST ACPI_TABLE_GENERATOR * CONST This,\r
124 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,\r
125 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,\r
126 OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table\r
127 )\r
128{\r
129 EFI_STATUS Status;\r
130 CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;\r
131\r
132 ASSERT (This != NULL);\r
133 ASSERT (AcpiTableInfo != NULL);\r
134 ASSERT (CfgMgrProtocol != NULL);\r
135 ASSERT (Table != NULL);\r
136 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
137 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
138\r
139 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
140 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision)) {\r
141 DEBUG ((\r
142 DEBUG_ERROR,\r
143 "ERROR: SPCR: Requested table revision = %d, is not supported."\r
144 "Supported table revision: Minimum = %d, Maximum = %d\n",\r
145 AcpiTableInfo->AcpiTableRevision,\r
146 This->MinAcpiTableRevision,\r
147 This->AcpiTableRevision\r
148 ));\r
149 return EFI_INVALID_PARAMETER;\r
150 }\r
151\r
152 *Table = NULL;\r
153\r
154 Status = GetEArmObjSerialConsolePortInfo (\r
155 CfgMgrProtocol,\r
156 CM_NULL_TOKEN,\r
157 &SerialPortInfo,\r
158 NULL\r
159 );\r
160 if (EFI_ERROR (Status)) {\r
161 DEBUG ((\r
162 DEBUG_ERROR,\r
163 "ERROR: SPCR: Failed to get serial port information. Status = %r\n",\r
164 Status\r
165 ));\r
166 goto error_handler;\r
167 }\r
168\r
169 if (SerialPortInfo->BaseAddress == 0) {\r
170 Status = EFI_INVALID_PARAMETER;\r
171 DEBUG ((\r
172 DEBUG_ERROR,\r
173 "ERROR: SPCR: Uart port base address is invalid. BaseAddress = 0x%lx\n",\r
174 SerialPortInfo->BaseAddress\r
175 ));\r
176 goto error_handler;\r
177 }\r
178\r
179 if ((SerialPortInfo->PortSubtype !=\r
180 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) &&\r
181 (SerialPortInfo->PortSubtype !=\r
182 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) &&\r
183 (SerialPortInfo->PortSubtype !=\r
184 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) &&\r
185 (SerialPortInfo->PortSubtype !=\r
0692ef87
AS
186 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550) &&\r
187 (SerialPortInfo->PortSubtype !=\r
9123b687
SM
188 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) {\r
189 Status = EFI_INVALID_PARAMETER;\r
190 DEBUG ((\r
191 DEBUG_ERROR,\r
e3f8605a 192 "ERROR: SPCR: Uart port subtype is invalid. PortSubtype = 0x%x\n",\r
9123b687
SM
193 SerialPortInfo->PortSubtype\r
194 ));\r
195 goto error_handler;\r
196 }\r
197\r
198 DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n"));\r
199 DEBUG ((DEBUG_INFO, " UART Base = 0x%lx\n", SerialPortInfo->BaseAddress));\r
200 DEBUG ((DEBUG_INFO, " Clock = %d\n", SerialPortInfo->Clock));\r
201 DEBUG ((DEBUG_INFO, " Baudrate = %ld\n", SerialPortInfo->BaudRate));\r
202 DEBUG ((DEBUG_INFO, " Interrupt = %d\n", SerialPortInfo->Interrupt));\r
203\r
204 Status = AddAcpiHeader (\r
205 CfgMgrProtocol,\r
206 This,\r
207 (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr,\r
e12bdeb1 208 AcpiTableInfo,\r
9123b687
SM
209 sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE)\r
210 );\r
211 if (EFI_ERROR (Status)) {\r
212 DEBUG ((\r
213 DEBUG_ERROR,\r
214 "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",\r
215 Status\r
216 ));\r
217 goto error_handler;\r
218 }\r
219\r
869f2341
SM
220 // The SPCR InterfaceType uses the same encoding as that of the\r
221 // DBG2 table Port Subtype field. However InterfaceType is 8-bit\r
222 // while the Port Subtype field in the DBG2 table is 16-bit.\r
223 if ((SerialPortInfo->PortSubtype & 0xFF00) != 0) {\r
224 Status = EFI_INVALID_PARAMETER;\r
225 DEBUG ((\r
226 DEBUG_ERROR,\r
e3f8605a 227 "ERROR: SPCR: Invalid Port subtype (must be < 256). Status = %r\n",\r
869f2341
SM
228 Status\r
229 ));\r
230 goto error_handler;\r
231 }\r
232\r
9123b687 233 // Update the serial port subtype\r
869f2341 234 AcpiSpcr.InterfaceType = (UINT8)SerialPortInfo->PortSubtype;\r
9123b687
SM
235\r
236 // Update the base address\r
237 AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;\r
238\r
239 // Update the UART interrupt\r
240 AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;\r
241\r
242 switch (SerialPortInfo->BaudRate) {\r
243 case 9600:\r
244 AcpiSpcr.BaudRate =\r
245 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600;\r
246 break;\r
247 case 19200:\r
248 AcpiSpcr.BaudRate =\r
249 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200;\r
250 break;\r
251 case 57600:\r
252 AcpiSpcr.BaudRate =\r
253 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600;\r
254 break;\r
255 case 115200:\r
256 AcpiSpcr.BaudRate =\r
257 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200;\r
258 break;\r
259 default:\r
260 Status = EFI_UNSUPPORTED;\r
261 DEBUG ((\r
262 DEBUG_ERROR,\r
263 "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",\r
264 SerialPortInfo->BaudRate,\r
265 Status\r
266 ));\r
267 goto error_handler;\r
268 } // switch\r
269\r
270 *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;\r
271\r
272error_handler:\r
273 return Status;\r
274}\r
275\r
276/** This macro defines the SPCR Table Generator revision.\r
277*/\r
278#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
279\r
280/** The interface for the SPCR Table Generator.\r
281*/\r
282STATIC\r
283CONST\r
284ACPI_TABLE_GENERATOR SpcrGenerator = {\r
285 // Generator ID\r
286 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr),\r
287 // Generator Description\r
288 L"ACPI.STD.SPCR.GENERATOR",\r
289 // ACPI Table Signature\r
290 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,\r
291 // ACPI Table Revision supported by this Generator\r
292 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,\r
293 // Minimum supported ACPI Table Revision\r
294 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,\r
295 // Creator ID\r
296 TABLE_GENERATOR_CREATOR_ID_ARM,\r
297 // Creator Revision\r
298 SPCR_GENERATOR_REVISION,\r
299 // Build Table function\r
300 BuildSpcrTable,\r
301 // No additional resources are allocated by the generator.\r
302 // Hence the Free Resource function is not required.\r
303 NULL,\r
304 // Extended build function not needed\r
305 NULL,\r
306 // Extended build function not implemented by the generator.\r
307 // Hence extended free resource function is not required.\r
308 NULL\r
309};\r
310\r
311/** Register the Generator with the ACPI Table Factory.\r
312\r
313 @param [in] ImageHandle The handle to the image.\r
314 @param [in] SystemTable Pointer to the System Table.\r
315\r
316 @retval EFI_SUCCESS The Generator is registered.\r
317 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
318 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
319 is already registered.\r
320**/\r
321EFI_STATUS\r
322EFIAPI\r
323AcpiSpcrLibConstructor (\r
43a0e08d
SM
324 IN EFI_HANDLE ImageHandle,\r
325 IN EFI_SYSTEM_TABLE * SystemTable\r
9123b687
SM
326 )\r
327{\r
328 EFI_STATUS Status;\r
329 Status = RegisterAcpiTableGenerator (&SpcrGenerator);\r
330 DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status));\r
331 ASSERT_EFI_ERROR (Status);\r
332 return Status;\r
333}\r
334\r
335/** Deregister the Generator from the ACPI Table Factory.\r
336\r
337 @param [in] ImageHandle The handle to the image.\r
338 @param [in] SystemTable Pointer to the System Table.\r
339\r
340 @retval EFI_SUCCESS The Generator is deregistered.\r
341 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
342 @retval EFI_NOT_FOUND The Generator is not registered.\r
343**/\r
344EFI_STATUS\r
345EFIAPI\r
346AcpiSpcrLibDestructor (\r
43a0e08d
SM
347 IN EFI_HANDLE ImageHandle,\r
348 IN EFI_SYSTEM_TABLE * SystemTable\r
9123b687
SM
349 )\r
350{\r
351 EFI_STATUS Status;\r
352 Status = DeregisterAcpiTableGenerator (&SpcrGenerator);\r
353 DEBUG ((DEBUG_INFO, "SPCR: Deregister Generator. Status = %r\n", Status));\r
354 ASSERT_EFI_ERROR (Status);\r
355 return Status;\r
356}\r