]> git.proxmox.com Git - mirror_edk2.git/blame - DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiSpcrLibArm / SpcrGenerator.c
CommitLineData
9123b687
SM
1/** @file\r
2 SPCR Table Generator\r
3\r
a300f2a3 4 Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>\r
c76028a6 5\r
9cd9bdc6 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
9123b687
SM
7\r
8 @par Reference(s):\r
9 - Microsoft Serial Port Console Redirection Table\r
10 Specification - Version 1.03 - August 10, 2015.\r
11\r
12**/\r
13\r
14#include <IndustryStandard/DebugPort2Table.h>\r
15#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>\r
16#include <Library/AcpiLib.h>\r
17#include <Library/DebugLib.h>\r
c76028a6 18#include <Library/MemoryAllocationLib.h>\r
9123b687
SM
19#include <Protocol/AcpiTable.h>\r
20\r
21// Module specific include files.\r
22#include <AcpiTableGenerator.h>\r
23#include <ConfigurationManagerObject.h>\r
24#include <ConfigurationManagerHelper.h>\r
c76028a6 25#include <Library/SsdtSerialPortFixupLib.h>\r
9123b687
SM
26#include <Library/TableHelperLib.h>\r
27#include <Protocol/ConfigurationManagerProtocol.h>\r
28\r
29/** ARM standard SPCR Table Generator\r
30\r
31 Constructs the SPCR table for PL011 or SBSA UART peripherals.\r
32\r
33Requirements:\r
34 The following Configuration Manager Object(s) are required by\r
35 this Generator:\r
36 - EArmObjSerialConsolePortInfo\r
37\r
38NOTE: This implementation ignores the possibility that the Serial settings may\r
39 be modified from the UEFI Shell. A more complex handler would be needed\r
40 to (e.g.) recover serial port settings from the UART, or non-volatile\r
41 storage.\r
42*/\r
43\r
44#pragma pack(1)\r
45\r
c76028a6
PG
46/** A string representing the name of the SPCR port.\r
47*/\r
731c67e1 48#define NAME_STR_SPCR_PORT "COM1"\r
c76028a6
PG
49\r
50/** An UID representing the SPCR port.\r
51*/\r
731c67e1 52#define UID_SPCR_PORT 1\r
c76028a6 53\r
9123b687
SM
54/** This macro defines the no flow control option.\r
55*/\r
731c67e1 56#define SPCR_FLOW_CONTROL_NONE 0\r
9123b687
SM
57\r
58/**A template for generating the SPCR Table.\r
59\r
60 Note: fields marked "{Template}" will be updated dynamically.\r
61*/\r
62STATIC\r
731c67e1 63EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE AcpiSpcr = {\r
9123b687
SM
64 ACPI_HEADER (\r
65 EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,\r
66 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE,\r
67 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION\r
68 ),\r
69 0, // {Template}: Serial Port Subtype\r
70 {\r
71 EFI_ACPI_RESERVED_BYTE,\r
72 EFI_ACPI_RESERVED_BYTE,\r
73 EFI_ACPI_RESERVED_BYTE\r
74 },\r
75 ARM_GAS32 (0), // {Template}: Serial Port Base Address\r
76 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_GIC,\r
77 0, // Not used on ARM\r
78 0, // {Template}: Serial Port Interrupt\r
79 0, // {Template}: Serial Port Baudrate\r
80 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,\r
81 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,\r
82 SPCR_FLOW_CONTROL_NONE,\r
83 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_ANSI,\r
84 EFI_ACPI_RESERVED_BYTE,\r
85 0xFFFF,\r
86 0xFFFF,\r
87 0x00,\r
88 0x00,\r
89 0x00,\r
90 0x00000000,\r
91 0x00,\r
92 EFI_ACPI_RESERVED_DWORD\r
93};\r
94\r
95#pragma pack()\r
96\r
97/** This macro expands to a function that retrieves the Serial\r
98 Port Information from the Configuration Manager.\r
99*/\r
100GET_OBJECT_LIST (\r
101 EObjNameSpaceArm,\r
102 EArmObjSerialConsolePortInfo,\r
103 CM_ARM_SERIAL_PORT_INFO\r
104 )\r
105\r
c76028a6
PG
106/** Free any resources allocated for constructing the tables.\r
107\r
108 @param [in] This Pointer to the ACPI table generator.\r
109 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.\r
110 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
111 Protocol Interface.\r
112 @param [in, out] Table Pointer to an array of pointers\r
113 to ACPI Table(s).\r
114 @param [in] TableCount Number of ACPI table(s).\r
115\r
116 @retval EFI_SUCCESS The resources were freed successfully.\r
117 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.\r
118**/\r
119STATIC\r
120EFI_STATUS\r
121EFIAPI\r
122FreeSpcrTableEx (\r
731c67e1
MK
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 IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table,\r
c76028a6
PG
127 IN CONST UINTN TableCount\r
128 )\r
129{\r
731c67e1
MK
130 EFI_STATUS Status;\r
131 EFI_ACPI_DESCRIPTION_HEADER **TableList;\r
c76028a6
PG
132\r
133 ASSERT (This != NULL);\r
134 ASSERT (AcpiTableInfo != NULL);\r
135 ASSERT (CfgMgrProtocol != NULL);\r
136 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
137 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
138\r
139 if ((Table == NULL) ||\r
140 (*Table == NULL) ||\r
731c67e1
MK
141 (TableCount != 2))\r
142 {\r
c76028a6
PG
143 DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid Table Pointer\n"));\r
144 return EFI_INVALID_PARAMETER;\r
145 }\r
146\r
147 TableList = *Table;\r
148\r
149 if ((TableList[1] == NULL) ||\r
150 (TableList[1]->Signature !=\r
731c67e1
MK
151 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE))\r
152 {\r
c76028a6
PG
153 DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid SSDT table pointer.\n"));\r
154 return EFI_INVALID_PARAMETER;\r
155 }\r
156\r
157 // Only need to free the SSDT table at index 1. The SPCR table is static.\r
158 Status = FreeSsdtSerialPortTable (TableList[1]);\r
159 ASSERT_EFI_ERROR (Status);\r
160\r
161 // Free the table list.\r
162 FreePool (*Table);\r
163\r
164 return Status;\r
165}\r
166\r
167/** Construct the SPCR ACPI table and its associated SSDT table.\r
9123b687
SM
168\r
169 This function invokes the Configuration Manager protocol interface\r
170 to get the required hardware information for generating the ACPI\r
171 table.\r
172\r
173 If this function allocates any resources then they must be freed\r
c76028a6
PG
174 in the FreeXXXXTableResourcesEx function.\r
175\r
176 @param [in] This Pointer to the ACPI table generator.\r
177 @param [in] AcpiTableInfo Pointer to the ACPI table information.\r
178 @param [in] CfgMgrProtocol Pointer to the Configuration Manager\r
179 Protocol interface.\r
180 @param [out] Table Pointer to a list of generated ACPI table(s).\r
181 @param [out] TableCount Number of generated ACPI table(s).\r
182\r
183 @retval EFI_SUCCESS Table generated successfully.\r
184 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration\r
185 Manager is less than the Object size for\r
186 the requested object.\r
187 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
188 @retval EFI_NOT_FOUND Could not find information.\r
189 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.\r
190 @retval EFI_UNSUPPORTED Unsupported configuration.\r
9123b687
SM
191**/\r
192STATIC\r
193EFI_STATUS\r
194EFIAPI\r
c76028a6 195BuildSpcrTableEx (\r
731c67e1
MK
196 IN CONST ACPI_TABLE_GENERATOR *This,\r
197 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,\r
198 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,\r
199 OUT EFI_ACPI_DESCRIPTION_HEADER ***Table,\r
200 OUT UINTN *CONST TableCount\r
9123b687
SM
201 )\r
202{\r
731c67e1
MK
203 EFI_STATUS Status;\r
204 CM_ARM_SERIAL_PORT_INFO *SerialPortInfo;\r
205 UINT32 SerialPortCount;\r
206 EFI_ACPI_DESCRIPTION_HEADER **TableList;\r
9123b687
SM
207\r
208 ASSERT (This != NULL);\r
209 ASSERT (AcpiTableInfo != NULL);\r
210 ASSERT (CfgMgrProtocol != NULL);\r
211 ASSERT (Table != NULL);\r
c76028a6 212 ASSERT (TableCount != NULL);\r
9123b687
SM
213 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);\r
214 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);\r
215\r
216 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||\r
731c67e1
MK
217 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))\r
218 {\r
9123b687
SM
219 DEBUG ((\r
220 DEBUG_ERROR,\r
221 "ERROR: SPCR: Requested table revision = %d, is not supported."\r
222 "Supported table revision: Minimum = %d, Maximum = %d\n",\r
223 AcpiTableInfo->AcpiTableRevision,\r
224 This->MinAcpiTableRevision,\r
225 This->AcpiTableRevision\r
226 ));\r
227 return EFI_INVALID_PARAMETER;\r
228 }\r
229\r
230 *Table = NULL;\r
231\r
232 Status = GetEArmObjSerialConsolePortInfo (\r
233 CfgMgrProtocol,\r
234 CM_NULL_TOKEN,\r
235 &SerialPortInfo,\r
c76028a6 236 &SerialPortCount\r
9123b687
SM
237 );\r
238 if (EFI_ERROR (Status)) {\r
239 DEBUG ((\r
240 DEBUG_ERROR,\r
241 "ERROR: SPCR: Failed to get serial port information. Status = %r\n",\r
242 Status\r
243 ));\r
c76028a6 244 return Status;\r
9123b687
SM
245 }\r
246\r
c76028a6 247 if (SerialPortCount == 0) {\r
9123b687
SM
248 DEBUG ((\r
249 DEBUG_ERROR,\r
c76028a6
PG
250 "ERROR: SPCR: Serial port information not found. Status = %r\n",\r
251 EFI_NOT_FOUND\r
9123b687 252 ));\r
c76028a6 253 return EFI_NOT_FOUND;\r
9123b687
SM
254 }\r
255\r
c76028a6
PG
256 // Validate the SerialPort info. Only one SPCR port can be described.\r
257 // If platform provides description for multiple SPCR ports, use the\r
258 // first SPCR port information.\r
259 Status = ValidateSerialPortInfo (SerialPortInfo, 1);\r
260 if (EFI_ERROR (Status)) {\r
9123b687
SM
261 DEBUG ((\r
262 DEBUG_ERROR,\r
c76028a6
PG
263 "ERROR: SPCR: Invalid serial port information. Status = %r\n",\r
264 Status\r
9123b687 265 ));\r
c76028a6 266 return Status;\r
9123b687
SM
267 }\r
268\r
c76028a6 269 // Allocate a table to store pointers to the SPCR and SSDT tables.\r
731c67e1
MK
270 TableList = (EFI_ACPI_DESCRIPTION_HEADER **)\r
271 AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * 2);\r
c76028a6
PG
272 if (TableList == NULL) {\r
273 Status = EFI_OUT_OF_RESOURCES;\r
274 DEBUG ((\r
275 DEBUG_ERROR,\r
276 "ERROR: SPCR: Failed to allocate memory for Table List," \\r
277 " Status = %r\n",\r
278 Status\r
279 ));\r
280 return Status;\r
281 }\r
9123b687 282\r
c76028a6 283 // Build SPCR table.\r
9123b687
SM
284 Status = AddAcpiHeader (\r
285 CfgMgrProtocol,\r
286 This,\r
731c67e1 287 (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiSpcr,\r
e12bdeb1 288 AcpiTableInfo,\r
9123b687
SM
289 sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE)\r
290 );\r
291 if (EFI_ERROR (Status)) {\r
292 DEBUG ((\r
293 DEBUG_ERROR,\r
294 "ERROR: SPCR: Failed to add ACPI header. Status = %r\n",\r
295 Status\r
296 ));\r
297 goto error_handler;\r
298 }\r
299\r
869f2341
SM
300 // The SPCR InterfaceType uses the same encoding as that of the\r
301 // DBG2 table Port Subtype field. However InterfaceType is 8-bit\r
302 // while the Port Subtype field in the DBG2 table is 16-bit.\r
303 if ((SerialPortInfo->PortSubtype & 0xFF00) != 0) {\r
304 Status = EFI_INVALID_PARAMETER;\r
305 DEBUG ((\r
306 DEBUG_ERROR,\r
e3f8605a 307 "ERROR: SPCR: Invalid Port subtype (must be < 256). Status = %r\n",\r
869f2341
SM
308 Status\r
309 ));\r
310 goto error_handler;\r
311 }\r
312\r
9123b687 313 // Update the serial port subtype\r
869f2341 314 AcpiSpcr.InterfaceType = (UINT8)SerialPortInfo->PortSubtype;\r
9123b687
SM
315\r
316 // Update the base address\r
317 AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;\r
318\r
a300f2a3
JG
319 // Set the access size\r
320 if (SerialPortInfo->AccessSize >= EFI_ACPI_6_3_QWORD) {\r
321 Status = EFI_INVALID_PARAMETER;\r
322 DEBUG ((\r
323 DEBUG_ERROR,\r
324 "ERROR: SPCR: Access size must be <= 3 (DWORD). Status = %r\n",\r
325 Status\r
326 ));\r
327 goto error_handler;\r
328 } else if (SerialPortInfo->AccessSize == EFI_ACPI_6_3_UNDEFINED) {\r
329 // 0 Undefined (legacy reasons)\r
330 // Default to DWORD access size as the access\r
331 // size field was introduced at a later date\r
332 // and some ConfigurationManager implementations\r
333 // may not be providing this field data\r
334 AcpiSpcr.BaseAddress.AccessSize = EFI_ACPI_6_3_DWORD;\r
335 } else {\r
336 AcpiSpcr.BaseAddress.AccessSize = SerialPortInfo->AccessSize;\r
337 }\r
338\r
9123b687
SM
339 // Update the UART interrupt\r
340 AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;\r
341\r
342 switch (SerialPortInfo->BaudRate) {\r
343 case 9600:\r
344 AcpiSpcr.BaudRate =\r
345 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_9600;\r
346 break;\r
347 case 19200:\r
348 AcpiSpcr.BaudRate =\r
349 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_19200;\r
350 break;\r
351 case 57600:\r
352 AcpiSpcr.BaudRate =\r
353 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_57600;\r
354 break;\r
355 case 115200:\r
356 AcpiSpcr.BaudRate =\r
357 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200;\r
358 break;\r
359 default:\r
360 Status = EFI_UNSUPPORTED;\r
361 DEBUG ((\r
362 DEBUG_ERROR,\r
363 "ERROR: SPCR: Invalid Baud Rate %ld, Status = %r\n",\r
364 SerialPortInfo->BaudRate,\r
365 Status\r
366 ));\r
367 goto error_handler;\r
368 } // switch\r
369\r
731c67e1 370 TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiSpcr;\r
c76028a6
PG
371\r
372 // Build a SSDT table describing the serial port.\r
373 Status = BuildSsdtSerialPortTable (\r
374 AcpiTableInfo,\r
375 SerialPortInfo,\r
376 NAME_STR_SPCR_PORT,\r
377 UID_SPCR_PORT,\r
378 &TableList[1]\r
379 );\r
380 if (EFI_ERROR (Status)) {\r
381 DEBUG ((\r
382 DEBUG_ERROR,\r
383 "ERROR: SPCR: Failed to build associated SSDT table. Status = %r\n",\r
384 Status\r
385 ));\r
386 goto error_handler;\r
387 }\r
388\r
389 *TableCount = 2;\r
731c67e1 390 *Table = TableList;\r
c76028a6
PG
391\r
392 return Status;\r
9123b687
SM
393\r
394error_handler:\r
c76028a6
PG
395 if (TableList != NULL) {\r
396 FreePool (TableList);\r
397 }\r
398\r
9123b687
SM
399 return Status;\r
400}\r
401\r
402/** This macro defines the SPCR Table Generator revision.\r
403*/\r
731c67e1 404#define SPCR_GENERATOR_REVISION CREATE_REVISION (1, 0)\r
9123b687
SM
405\r
406/** The interface for the SPCR Table Generator.\r
407*/\r
408STATIC\r
409CONST\r
731c67e1 410ACPI_TABLE_GENERATOR SpcrGenerator = {\r
9123b687
SM
411 // Generator ID\r
412 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSpcr),\r
413 // Generator Description\r
414 L"ACPI.STD.SPCR.GENERATOR",\r
415 // ACPI Table Signature\r
c76028a6 416 EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,\r
9123b687
SM
417 // ACPI Table Revision supported by this Generator\r
418 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,\r
419 // Minimum supported ACPI Table Revision\r
420 EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,\r
421 // Creator ID\r
422 TABLE_GENERATOR_CREATOR_ID_ARM,\r
423 // Creator Revision\r
424 SPCR_GENERATOR_REVISION,\r
c76028a6 425 // Build table function. Use the extended version instead.\r
9123b687 426 NULL,\r
c76028a6 427 // Free table function. Use the extended version instead.\r
9123b687 428 NULL,\r
c76028a6
PG
429 // Extended Build table function.\r
430 BuildSpcrTableEx,\r
431 // Extended free function.\r
432 FreeSpcrTableEx\r
9123b687
SM
433};\r
434\r
435/** Register the Generator with the ACPI Table Factory.\r
436\r
437 @param [in] ImageHandle The handle to the image.\r
438 @param [in] SystemTable Pointer to the System Table.\r
439\r
440 @retval EFI_SUCCESS The Generator is registered.\r
441 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
442 @retval EFI_ALREADY_STARTED The Generator for the Table ID\r
443 is already registered.\r
444**/\r
445EFI_STATUS\r
446EFIAPI\r
447AcpiSpcrLibConstructor (\r
731c67e1
MK
448 IN EFI_HANDLE ImageHandle,\r
449 IN EFI_SYSTEM_TABLE *SystemTable\r
9123b687
SM
450 )\r
451{\r
452 EFI_STATUS Status;\r
731c67e1 453\r
9123b687
SM
454 Status = RegisterAcpiTableGenerator (&SpcrGenerator);\r
455 DEBUG ((DEBUG_INFO, "SPCR: Register Generator. Status = %r\n", Status));\r
456 ASSERT_EFI_ERROR (Status);\r
457 return Status;\r
458}\r
459\r
460/** Deregister the Generator from the ACPI Table Factory.\r
461\r
462 @param [in] ImageHandle The handle to the image.\r
463 @param [in] SystemTable Pointer to the System Table.\r
464\r
465 @retval EFI_SUCCESS The Generator is deregistered.\r
466 @retval EFI_INVALID_PARAMETER A parameter is invalid.\r
467 @retval EFI_NOT_FOUND The Generator is not registered.\r
468**/\r
469EFI_STATUS\r
470EFIAPI\r
471AcpiSpcrLibDestructor (\r
731c67e1
MK
472 IN EFI_HANDLE ImageHandle,\r
473 IN EFI_SYSTEM_TABLE *SystemTable\r
9123b687
SM
474 )\r
475{\r
476 EFI_STATUS Status;\r
731c67e1 477\r
9123b687
SM
478 Status = DeregisterAcpiTableGenerator (&SpcrGenerator);\r
479 DEBUG ((DEBUG_INFO, "SPCR: Deregister Generator. Status = %r\n", Status));\r
480 ASSERT_EFI_ERROR (Status);\r
481 return Status;\r
482}\r