]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
DynamicTablesPkg: Apply uncrustify changes
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiDbg2LibArm / Dbg2Generator.c
1 /** @file
2 DBG2 Table Generator
3
4 Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 @par Reference(s):
9 - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015.
10
11 **/
12
13 #include <IndustryStandard/DebugPort2Table.h>
14 #include <Library/AcpiLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/PL011UartLib.h>
18 #include <Protocol/AcpiTable.h>
19 #include <Protocol/SerialIo.h>
20
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>
28
29 /** ARM standard DBG2 Table Generator
30
31 Constructs the DBG2 table for PL011 or SBSA UART peripherals.
32
33 Requirements:
34 The following Configuration Manager Object(s) are required by
35 this Generator:
36 - EArmObjSerialDebugPortInfo
37 */
38
39 #pragma pack(1)
40
41 /** The number of debug ports represented by the Table.
42 */
43 #define DBG2_NUM_DEBUG_PORTS 1
44
45 /** The number of Generic Address Registers
46 presented in the debug device information.
47 */
48 #define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS 1
49
50 /** The index for the debug port 0 in the Debug port information list.
51 */
52 #define INDEX_DBG_PORT0 0
53
54 /** A string representing the name of the debug port 0.
55 */
56 #define NAME_STR_DBG_PORT0 "COM0"
57
58 /** An UID representing the debug port 0.
59 */
60 #define UID_DBG_PORT0 0
61
62 /** The length of the namespace string.
63 */
64 #define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAME_STR_DBG_PORT0)
65
66 /** The PL011 UART address range length.
67 */
68 #define PL011_UART_LENGTH 0x1000
69
70 /** A structure that provides the OS with the required information
71 for initializing a debugger connection.
72 */
73 typedef struct {
74 /// The debug device information for the platform
75 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device;
76
77 /// The base address register for the serial port
78 EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
79
80 /// The address size
81 UINT32 AddressSize;
82
83 /// The debug port name string
84 UINT8 NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE];
85 } DBG2_DEBUG_DEVICE_INFORMATION;
86
87 /** A structure representing the information about the debug port(s)
88 available on the platform.
89 */
90 typedef struct {
91 /// The DBG2 table header
92 EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description;
93
94 /// Debug port information list
95 DBG2_DEBUG_DEVICE_INFORMATION Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS];
96 } DBG2_TABLE;
97
98 /** A helper macro used for initializing the debug port device
99 information structure.
100
101 @param [in] SubType The DBG Port SubType.
102 @param [in] UartBase The UART port base address.
103 @param [in] UartAddrLen The UART port address range length.
104 @param [in] UartNameStr The UART port name string.
105 **/
106 #define DBG2_DEBUG_PORT_DDI( \
107 SubType, \
108 UartBase, \
109 UartAddrLen, \
110 UartNameStr \
111 ) {\
112 { \
113 /* UINT8 Revision */ \
114 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, \
115 /* UINT16 Length */ \
116 sizeof (DBG2_DEBUG_DEVICE_INFORMATION), \
117 /* UINT8 NumberofGenericAddressRegisters */ \
118 DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS, \
119 /* UINT16 NameSpaceStringLength */ \
120 DBG2_NAMESPACESTRING_FIELD_SIZE, \
121 /* UINT16 NameSpaceStringOffset */ \
122 OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString), \
123 /* UINT16 OemDataLength */ \
124 0, \
125 /* UINT16 OemDataOffset */ \
126 0, \
127 /* UINT16 Port Type */ \
128 EFI_ACPI_DBG2_PORT_TYPE_SERIAL, \
129 /* UINT16 Port Subtype */ \
130 SubType, \
131 /* UINT8 Reserved[2] */ \
132 {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE}, \
133 /* UINT16 BaseAddressRegister Offset */ \
134 OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, BaseAddressRegister), \
135 /* UINT16 AddressSize Offset */ \
136 OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize) \
137 }, \
138 /* EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */ \
139 ARM_GAS32 (UartBase), \
140 /* UINT32 AddressSize */ \
141 UartAddrLen, \
142 /* UINT8 NameSpaceString[MAX_DBG2_NAME_LEN] */ \
143 UartNameStr \
144 }
145
146 /** The DBG2 Table template definition.
147
148 Note: fields marked with "{Template}" will be set dynamically
149 */
150 STATIC
151 DBG2_TABLE AcpiDbg2 = {
152 {
153 ACPI_HEADER (
154 EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE,
155 DBG2_TABLE,
156 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
157 ),
158 OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo),
159 DBG2_NUM_DEBUG_PORTS
160 },
161 {
162 /*
163 * Debug port 1
164 */
165 DBG2_DEBUG_PORT_DDI (
166 0, // {Template}: Serial Port Subtype
167 0, // {Template}: Serial Port Base Address
168 PL011_UART_LENGTH,
169 NAME_STR_DBG_PORT0
170 )
171 }
172 };
173
174 #pragma pack()
175
176 /** This macro expands to a function that retrieves the Serial
177 debug port information from the Configuration Manager
178 */
179 GET_OBJECT_LIST (
180 EObjNameSpaceArm,
181 EArmObjSerialDebugPortInfo,
182 CM_ARM_SERIAL_PORT_INFO
183 );
184
185 /** Initialize the PL011/SBSA UART with the parameters obtained from
186 the Configuration Manager.
187
188 @param [in] SerialPortInfo Pointer to the Serial Port Information.
189
190 @retval EFI_SUCCESS Success.
191 @retval EFI_INVALID_PARAMETER The parameters for serial port initialization
192 are invalid.
193 **/
194 STATIC
195 EFI_STATUS
196 SetupDebugUart (
197 IN CONST CM_ARM_SERIAL_PORT_INFO *CONST SerialPortInfo
198 )
199 {
200 EFI_STATUS Status;
201 UINT64 BaudRate;
202 UINT32 ReceiveFifoDepth;
203 EFI_PARITY_TYPE Parity;
204 UINT8 DataBits;
205 EFI_STOP_BITS_TYPE StopBits;
206
207 ASSERT (SerialPortInfo != NULL);
208
209 // Initialize the Serial Debug UART
210 DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n"));
211 ReceiveFifoDepth = 0; // Use the default value for FIFO depth
212 Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
213 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
214 StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
215
216 BaudRate = SerialPortInfo->BaudRate;
217 Status = PL011UartInitializePort (
218 (UINTN)SerialPortInfo->BaseAddress,
219 SerialPortInfo->Clock,
220 &BaudRate,
221 &ReceiveFifoDepth,
222 &Parity,
223 &DataBits,
224 &StopBits
225 );
226
227 ASSERT_EFI_ERROR (Status);
228 return Status;
229 }
230
231 /** Free any resources allocated for constructing the tables.
232
233 @param [in] This Pointer to the ACPI table generator.
234 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
235 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
236 Protocol Interface.
237 @param [in, out] Table Pointer to an array of pointers
238 to ACPI Table(s).
239 @param [in] TableCount Number of ACPI table(s).
240
241 @retval EFI_SUCCESS The resources were freed successfully.
242 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
243 **/
244 STATIC
245 EFI_STATUS
246 EFIAPI
247 FreeDbg2TableEx (
248 IN CONST ACPI_TABLE_GENERATOR *CONST This,
249 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
250 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
251 IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table,
252 IN CONST UINTN TableCount
253 )
254 {
255 EFI_STATUS Status;
256 EFI_ACPI_DESCRIPTION_HEADER **TableList;
257
258 ASSERT (This != NULL);
259 ASSERT (AcpiTableInfo != NULL);
260 ASSERT (CfgMgrProtocol != NULL);
261 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
262 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
263
264 if ((Table == NULL) ||
265 (*Table == NULL) ||
266 (TableCount != 2))
267 {
268 DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid Table Pointer\n"));
269 return EFI_INVALID_PARAMETER;
270 }
271
272 TableList = *Table;
273
274 if ((TableList[1] == NULL) ||
275 (TableList[1]->Signature !=
276 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE))
277 {
278 DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid SSDT table pointer.\n"));
279 return EFI_INVALID_PARAMETER;
280 }
281
282 // Only need to free the SSDT table at index 1. The DBG2 table is static.
283 Status = FreeSsdtSerialPortTable (TableList[1]);
284 ASSERT_EFI_ERROR (Status);
285
286 // Free the table list.
287 FreePool (*Table);
288
289 return Status;
290 }
291
292 /** Construct the DBG2 ACPI table and its associated SSDT table.
293
294 This function invokes the Configuration Manager protocol interface
295 to get the required hardware information for generating the ACPI
296 table.
297
298 If this function allocates any resources then they must be freed
299 in the FreeXXXXTableResourcesEx function.
300
301 @param [in] This Pointer to the ACPI table generator.
302 @param [in] AcpiTableInfo Pointer to the ACPI table information.
303 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
304 Protocol interface.
305 @param [out] Table Pointer to a list of generated ACPI table(s).
306 @param [out] TableCount Number of generated ACPI table(s).
307
308 @retval EFI_SUCCESS Table generated successfully.
309 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
310 Manager is less than the Object size for
311 the requested object.
312 @retval EFI_INVALID_PARAMETER A parameter is invalid.
313 @retval EFI_NOT_FOUND Could not find information.
314 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
315 @retval EFI_UNSUPPORTED Unsupported configuration.
316 **/
317 STATIC
318 EFI_STATUS
319 EFIAPI
320 BuildDbg2TableEx (
321 IN CONST ACPI_TABLE_GENERATOR *This,
322 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
323 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
324 OUT EFI_ACPI_DESCRIPTION_HEADER ***Table,
325 OUT UINTN *CONST TableCount
326 )
327 {
328 EFI_STATUS Status;
329 CM_ARM_SERIAL_PORT_INFO *SerialPortInfo;
330 UINT32 SerialPortCount;
331 EFI_ACPI_DESCRIPTION_HEADER **TableList;
332
333 ASSERT (This != NULL);
334 ASSERT (AcpiTableInfo != NULL);
335 ASSERT (CfgMgrProtocol != NULL);
336 ASSERT (Table != NULL);
337 ASSERT (TableCount != NULL);
338 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
339 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
340
341 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
342 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
343 {
344 DEBUG ((
345 DEBUG_ERROR,
346 "ERROR: DBG2: Requested table revision = %d, is not supported."
347 "Supported table revision: Minimum = %d, Maximum = %d\n",
348 AcpiTableInfo->AcpiTableRevision,
349 This->MinAcpiTableRevision,
350 This->AcpiTableRevision
351 ));
352 return EFI_INVALID_PARAMETER;
353 }
354
355 *Table = NULL;
356
357 Status = GetEArmObjSerialDebugPortInfo (
358 CfgMgrProtocol,
359 CM_NULL_TOKEN,
360 &SerialPortInfo,
361 &SerialPortCount
362 );
363 if (EFI_ERROR (Status)) {
364 DEBUG ((
365 DEBUG_ERROR,
366 "ERROR: DBG2: Failed to get serial port information. Status = %r\n",
367 Status
368 ));
369 return Status;
370 }
371
372 if (SerialPortCount == 0) {
373 DEBUG ((
374 DEBUG_ERROR,
375 "ERROR: DBG2: Serial port information not found. Status = %r\n",
376 EFI_NOT_FOUND
377 ));
378 return EFI_NOT_FOUND;
379 }
380
381 // Only use the first DBG2 port information.
382 Status = ValidateSerialPortInfo (SerialPortInfo, 1);
383 if (EFI_ERROR (Status)) {
384 DEBUG ((
385 DEBUG_ERROR,
386 "ERROR: DBG2: Invalid serial port information. Status = %r\n",
387 Status
388 ));
389 return Status;
390 }
391
392 // Allocate a table to store pointers to the DBG2 and SSDT tables.
393 TableList = (EFI_ACPI_DESCRIPTION_HEADER **)
394 AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * 2);
395 if (TableList == NULL) {
396 Status = EFI_OUT_OF_RESOURCES;
397 DEBUG ((
398 DEBUG_ERROR,
399 "ERROR: DBG2: Failed to allocate memory for Table List," \
400 " Status = %r\n",
401 Status
402 ));
403 return Status;
404 }
405
406 Status = AddAcpiHeader (
407 CfgMgrProtocol,
408 This,
409 (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiDbg2,
410 AcpiTableInfo,
411 sizeof (DBG2_TABLE)
412 );
413 if (EFI_ERROR (Status)) {
414 DEBUG ((
415 DEBUG_ERROR,
416 "ERROR: DBG2: Failed to add ACPI header. Status = %r\n",
417 Status
418 ));
419 goto error_handler;
420 }
421
422 // Update the base address
423 AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.Address =
424 SerialPortInfo->BaseAddress;
425
426 // Set the access size
427 if (SerialPortInfo->AccessSize >= EFI_ACPI_6_3_QWORD) {
428 Status = EFI_INVALID_PARAMETER;
429 DEBUG ((
430 DEBUG_ERROR,
431 "ERROR: DBG2: Access size must be <= 3 (DWORD). Status = %r\n",
432 Status
433 ));
434 goto error_handler;
435 } else if (SerialPortInfo->AccessSize == EFI_ACPI_6_3_UNDEFINED) {
436 // 0 Undefined (legacy reasons)
437 // Default to DWORD access size as the access
438 // size field was introduced at a later date
439 // and some ConfigurationManager implementations
440 // may not be providing this field data
441 AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.AccessSize =
442 EFI_ACPI_6_3_DWORD;
443 } else {
444 AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.AccessSize =
445 SerialPortInfo->AccessSize;
446 }
447
448 // Update the serial port subtype
449 AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].Dbg2Device.PortSubtype =
450 SerialPortInfo->PortSubtype;
451
452 if ((SerialPortInfo->PortSubtype ==
453 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) ||
454 (SerialPortInfo->PortSubtype ==
455 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) ||
456 (SerialPortInfo->PortSubtype ==
457 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART))
458 {
459 // Initialize the serial port
460 Status = SetupDebugUart (SerialPortInfo);
461 if (EFI_ERROR (Status)) {
462 DEBUG ((
463 DEBUG_ERROR,
464 "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n",
465 Status
466 ));
467 goto error_handler;
468 }
469 }
470
471 TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiDbg2;
472
473 // Build a SSDT table describing the serial port.
474 Status = BuildSsdtSerialPortTable (
475 AcpiTableInfo,
476 SerialPortInfo,
477 NAME_STR_DBG_PORT0,
478 UID_DBG_PORT0,
479 &TableList[1]
480 );
481 if (EFI_ERROR (Status)) {
482 DEBUG ((
483 DEBUG_ERROR,
484 "ERROR: DBG2: Failed to build associated SSDT table. Status = %r\n",
485 Status
486 ));
487 goto error_handler;
488 }
489
490 *TableCount = 2;
491 *Table = TableList;
492
493 return Status;
494
495 error_handler:
496 if (TableList != NULL) {
497 FreePool (TableList);
498 }
499
500 return Status;
501 }
502
503 /** This macro defines the DBG2 Table Generator revision.
504 */
505 #define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0)
506
507 /** The interface for the DBG2 Table Generator.
508 */
509 STATIC
510 CONST
511 ACPI_TABLE_GENERATOR Dbg2Generator = {
512 // Generator ID
513 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2),
514 // Generator Description
515 L"ACPI.STD.DBG2.GENERATOR",
516 // ACPI Table Signature
517 EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE,
518 // ACPI Table Revision supported by this Generator
519 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
520 // Minimum supported ACPI Table Revision
521 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
522 // Creator ID
523 TABLE_GENERATOR_CREATOR_ID_ARM,
524 // Creator Revision
525 DBG2_GENERATOR_REVISION,
526 // Build table function. Use the extended version instead.
527 NULL,
528 // Free table function. Use the extended version instead.
529 NULL,
530 // Extended Build table function.
531 BuildDbg2TableEx,
532 // Extended free function.
533 FreeDbg2TableEx
534 };
535
536 /** Register the Generator with the ACPI Table Factory.
537
538 @param [in] ImageHandle The handle to the image.
539 @param [in] SystemTable Pointer to the System Table.
540
541 @retval EFI_SUCCESS The Generator is registered.
542 @retval EFI_INVALID_PARAMETER A parameter is invalid.
543 @retval EFI_ALREADY_STARTED The Generator for the Table ID
544 is already registered.
545 **/
546 EFI_STATUS
547 EFIAPI
548 AcpiDbg2LibConstructor (
549 IN EFI_HANDLE ImageHandle,
550 IN EFI_SYSTEM_TABLE *SystemTable
551 )
552 {
553 EFI_STATUS Status;
554
555 Status = RegisterAcpiTableGenerator (&Dbg2Generator);
556 DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status));
557 ASSERT_EFI_ERROR (Status);
558 return Status;
559 }
560
561 /** Deregister the Generator from the ACPI Table Factory.
562
563 @param [in] ImageHandle The handle to the image.
564 @param [in] SystemTable Pointer to the System Table.
565
566 @retval EFI_SUCCESS The Generator is deregistered.
567 @retval EFI_INVALID_PARAMETER A parameter is invalid.
568 @retval EFI_NOT_FOUND The Generator is not registered.
569 **/
570 EFI_STATUS
571 EFIAPI
572 AcpiDbg2LibDestructor (
573 IN EFI_HANDLE ImageHandle,
574 IN EFI_SYSTEM_TABLE *SystemTable
575 )
576 {
577 EFI_STATUS Status;
578
579 Status = DeregisterAcpiTableGenerator (&Dbg2Generator);
580 DEBUG ((DEBUG_INFO, "DBG2: Deregister Generator. Status = %r\n", Status));
581 ASSERT_EFI_ERROR (Status);
582 return Status;
583 }