4 Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
9 - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015.
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>
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 DBG2 Table Generator
31 Constructs the DBG2 table for PL011 or SBSA UART peripherals.
34 The following Configuration Manager Object(s) are required by
36 - EArmObjSerialDebugPortInfo
41 /** The number of debug ports represented by the Table.
43 #define DBG2_NUM_DEBUG_PORTS 1
45 /** The number of Generic Address Registers
46 presented in the debug device information.
48 #define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS 1
50 /** The index for the debug port 0 in the Debug port information list.
52 #define INDEX_DBG_PORT0 0
54 /** A string representing the name of the debug port 0.
56 #define NAME_STR_DBG_PORT0 "COM0"
58 /** An UID representing the debug port 0.
60 #define UID_DBG_PORT0 0
62 /** The length of the namespace string.
64 #define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAME_STR_DBG_PORT0)
66 /** The PL011 UART address range length.
68 #define PL011_UART_LENGTH 0x1000
70 /** A structure that provides the OS with the required information
71 for initializing a debugger connection.
74 /// The debug device information for the platform
75 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device
;
77 /// The base address register for the serial port
78 EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister
;
83 /// The debug port name string
84 UINT8 NameSpaceString
[DBG2_NAMESPACESTRING_FIELD_SIZE
];
85 } DBG2_DEBUG_DEVICE_INFORMATION
;
87 /** A structure representing the information about the debug port(s)
88 available on the platform.
91 /// The DBG2 table header
92 EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description
;
94 /// Debug port information list
95 DBG2_DEBUG_DEVICE_INFORMATION Dbg2DeviceInfo
[DBG2_NUM_DEBUG_PORTS
];
98 /** A helper macro used for initializing the debug port device
99 information structure.
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.
106 #define DBG2_DEBUG_PORT_DDI( \
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 */ \
125 /* UINT16 OemDataOffset */ \
127 /* UINT16 Port Type */ \
128 EFI_ACPI_DBG2_PORT_TYPE_SERIAL, \
129 /* UINT16 Port 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) \
138 /* EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */ \
139 ARM_GAS32 (UartBase), \
140 /* UINT32 AddressSize */ \
142 /* UINT8 NameSpaceString[MAX_DBG2_NAME_LEN] */ \
146 /** The DBG2 Table template definition.
148 Note: fields marked with "{Template}" will be set dynamically
151 DBG2_TABLE AcpiDbg2
= {
154 EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE
,
156 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
158 OFFSET_OF (DBG2_TABLE
, Dbg2DeviceInfo
),
165 DBG2_DEBUG_PORT_DDI (
166 0, // {Template}: Serial Port Subtype
167 0, // {Template}: Serial Port Base Address
176 /** This macro expands to a function that retrieves the Serial
177 debug port information from the Configuration Manager
181 EArmObjSerialDebugPortInfo
,
182 CM_ARM_SERIAL_PORT_INFO
185 /** Initialize the PL011/SBSA UART with the parameters obtained from
186 the Configuration Manager.
188 @param [in] SerialPortInfo Pointer to the Serial Port Information.
190 @retval EFI_SUCCESS Success.
191 @retval EFI_INVALID_PARAMETER The parameters for serial port initialization
197 IN CONST CM_ARM_SERIAL_PORT_INFO
* CONST SerialPortInfo
202 UINT32 ReceiveFifoDepth
;
203 EFI_PARITY_TYPE Parity
;
205 EFI_STOP_BITS_TYPE StopBits
;
207 ASSERT (SerialPortInfo
!= NULL
);
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
);
216 BaudRate
= SerialPortInfo
->BaudRate
;
217 Status
= PL011UartInitializePort (
218 (UINTN
)SerialPortInfo
->BaseAddress
,
219 SerialPortInfo
->Clock
,
227 ASSERT_EFI_ERROR (Status
);
231 /** Free any resources allocated for constructing the tables.
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
237 @param [in, out] Table Pointer to an array of pointers
239 @param [in] TableCount Number of ACPI table(s).
241 @retval EFI_SUCCESS The resources were freed successfully.
242 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
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
256 EFI_ACPI_DESCRIPTION_HEADER
** TableList
;
258 ASSERT (This
!= NULL
);
259 ASSERT (AcpiTableInfo
!= NULL
);
260 ASSERT (CfgMgrProtocol
!= NULL
);
261 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
262 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
264 if ((Table
== NULL
) ||
267 DEBUG ((DEBUG_ERROR
, "ERROR: DBG2: Invalid Table Pointer\n"));
268 return EFI_INVALID_PARAMETER
;
273 if ((TableList
[1] == NULL
) ||
274 (TableList
[1]->Signature
!=
275 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
)) {
276 DEBUG ((DEBUG_ERROR
, "ERROR: DBG2: Invalid SSDT table pointer.\n"));
277 return EFI_INVALID_PARAMETER
;
280 // Only need to free the SSDT table at index 1. The DBG2 table is static.
281 Status
= FreeSsdtSerialPortTable (TableList
[1]);
282 ASSERT_EFI_ERROR (Status
);
284 // Free the table list.
290 /** Construct the DBG2 ACPI table and its associated SSDT table.
292 This function invokes the Configuration Manager protocol interface
293 to get the required hardware information for generating the ACPI
296 If this function allocates any resources then they must be freed
297 in the FreeXXXXTableResourcesEx function.
299 @param [in] This Pointer to the ACPI table generator.
300 @param [in] AcpiTableInfo Pointer to the ACPI table information.
301 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
303 @param [out] Table Pointer to a list of generated ACPI table(s).
304 @param [out] TableCount Number of generated ACPI table(s).
306 @retval EFI_SUCCESS Table generated successfully.
307 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
308 Manager is less than the Object size for
309 the requested object.
310 @retval EFI_INVALID_PARAMETER A parameter is invalid.
311 @retval EFI_NOT_FOUND Could not find information.
312 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
313 @retval EFI_UNSUPPORTED Unsupported configuration.
319 IN CONST ACPI_TABLE_GENERATOR
* This
,
320 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO
* CONST AcpiTableInfo
,
321 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL
* CONST CfgMgrProtocol
,
322 OUT EFI_ACPI_DESCRIPTION_HEADER
*** Table
,
323 OUT UINTN
* CONST TableCount
327 CM_ARM_SERIAL_PORT_INFO
* SerialPortInfo
;
328 UINT32 SerialPortCount
;
329 EFI_ACPI_DESCRIPTION_HEADER
** TableList
;
331 ASSERT (This
!= NULL
);
332 ASSERT (AcpiTableInfo
!= NULL
);
333 ASSERT (CfgMgrProtocol
!= NULL
);
334 ASSERT (Table
!= NULL
);
335 ASSERT (TableCount
!= NULL
);
336 ASSERT (AcpiTableInfo
->TableGeneratorId
== This
->GeneratorID
);
337 ASSERT (AcpiTableInfo
->AcpiTableSignature
== This
->AcpiTableSignature
);
339 if ((AcpiTableInfo
->AcpiTableRevision
< This
->MinAcpiTableRevision
) ||
340 (AcpiTableInfo
->AcpiTableRevision
> This
->AcpiTableRevision
)) {
343 "ERROR: DBG2: Requested table revision = %d, is not supported."
344 "Supported table revision: Minimum = %d, Maximum = %d\n",
345 AcpiTableInfo
->AcpiTableRevision
,
346 This
->MinAcpiTableRevision
,
347 This
->AcpiTableRevision
349 return EFI_INVALID_PARAMETER
;
354 Status
= GetEArmObjSerialDebugPortInfo (
360 if (EFI_ERROR (Status
)) {
363 "ERROR: DBG2: Failed to get serial port information. Status = %r\n",
369 if (SerialPortCount
== 0) {
372 "ERROR: DBG2: Serial port information not found. Status = %r\n",
375 return EFI_NOT_FOUND
;
378 // Only use the first DBG2 port information.
379 Status
= ValidateSerialPortInfo (SerialPortInfo
, 1);
380 if (EFI_ERROR (Status
)) {
383 "ERROR: DBG2: Invalid serial port information. Status = %r\n",
389 // Allocate a table to store pointers to the DBG2 and SSDT tables.
390 TableList
= (EFI_ACPI_DESCRIPTION_HEADER
**)
391 AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER
*) * 2);
392 if (TableList
== NULL
) {
393 Status
= EFI_OUT_OF_RESOURCES
;
396 "ERROR: DBG2: Failed to allocate memory for Table List," \
403 Status
= AddAcpiHeader (
406 (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiDbg2
,
410 if (EFI_ERROR (Status
)) {
413 "ERROR: DBG2: Failed to add ACPI header. Status = %r\n",
419 // Update the base address
420 AcpiDbg2
.Dbg2DeviceInfo
[INDEX_DBG_PORT0
].BaseAddressRegister
.Address
=
421 SerialPortInfo
->BaseAddress
;
423 // Set the access size
424 if (SerialPortInfo
->AccessSize
>= EFI_ACPI_6_3_QWORD
) {
425 Status
= EFI_INVALID_PARAMETER
;
428 "ERROR: DBG2: Access size must be <= 3 (DWORD). Status = %r\n",
432 } else if (SerialPortInfo
->AccessSize
== EFI_ACPI_6_3_UNDEFINED
) {
433 // 0 Undefined (legacy reasons)
434 // Default to DWORD access size as the access
435 // size field was introduced at a later date
436 // and some ConfigurationManager implementations
437 // may not be providing this field data
438 AcpiDbg2
.Dbg2DeviceInfo
[INDEX_DBG_PORT0
].BaseAddressRegister
.AccessSize
=
441 AcpiDbg2
.Dbg2DeviceInfo
[INDEX_DBG_PORT0
].BaseAddressRegister
.AccessSize
=
442 SerialPortInfo
->AccessSize
;
445 // Update the serial port subtype
446 AcpiDbg2
.Dbg2DeviceInfo
[INDEX_DBG_PORT0
].Dbg2Device
.PortSubtype
=
447 SerialPortInfo
->PortSubtype
;
449 if ((SerialPortInfo
->PortSubtype
==
450 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART
) ||
451 (SerialPortInfo
->PortSubtype
==
452 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X
) ||
453 (SerialPortInfo
->PortSubtype
==
454 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART
)) {
455 // Initialize the serial port
456 Status
= SetupDebugUart (SerialPortInfo
);
457 if (EFI_ERROR (Status
)) {
460 "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n",
467 TableList
[0] = (EFI_ACPI_DESCRIPTION_HEADER
*)&AcpiDbg2
;
469 // Build a SSDT table describing the serial port.
470 Status
= BuildSsdtSerialPortTable (
477 if (EFI_ERROR (Status
)) {
480 "ERROR: DBG2: Failed to build associated SSDT table. Status = %r\n",
492 if (TableList
!= NULL
) {
493 FreePool (TableList
);
499 /** This macro defines the DBG2 Table Generator revision.
501 #define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0)
503 /** The interface for the DBG2 Table Generator.
507 ACPI_TABLE_GENERATOR Dbg2Generator
= {
509 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2
),
510 // Generator Description
511 L
"ACPI.STD.DBG2.GENERATOR",
512 // ACPI Table Signature
513 EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE
,
514 // ACPI Table Revision supported by this Generator
515 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
,
516 // Minimum supported ACPI Table Revision
517 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
,
519 TABLE_GENERATOR_CREATOR_ID_ARM
,
521 DBG2_GENERATOR_REVISION
,
522 // Build table function. Use the extended version instead.
524 // Free table function. Use the extended version instead.
526 // Extended Build table function.
528 // Extended free function.
532 /** Register the Generator with the ACPI Table Factory.
534 @param [in] ImageHandle The handle to the image.
535 @param [in] SystemTable Pointer to the System Table.
537 @retval EFI_SUCCESS The Generator is registered.
538 @retval EFI_INVALID_PARAMETER A parameter is invalid.
539 @retval EFI_ALREADY_STARTED The Generator for the Table ID
540 is already registered.
544 AcpiDbg2LibConstructor (
545 IN EFI_HANDLE ImageHandle
,
546 IN EFI_SYSTEM_TABLE
* SystemTable
550 Status
= RegisterAcpiTableGenerator (&Dbg2Generator
);
551 DEBUG ((DEBUG_INFO
, "DBG2: Register Generator. Status = %r\n", Status
));
552 ASSERT_EFI_ERROR (Status
);
556 /** Deregister the Generator from the ACPI Table Factory.
558 @param [in] ImageHandle The handle to the image.
559 @param [in] SystemTable Pointer to the System Table.
561 @retval EFI_SUCCESS The Generator is deregistered.
562 @retval EFI_INVALID_PARAMETER A parameter is invalid.
563 @retval EFI_NOT_FOUND The Generator is not registered.
567 AcpiDbg2LibDestructor (
568 IN EFI_HANDLE ImageHandle
,
569 IN EFI_SYSTEM_TABLE
* SystemTable
573 Status
= DeregisterAcpiTableGenerator (&Dbg2Generator
);
574 DEBUG ((DEBUG_INFO
, "DBG2: Deregister Generator. Status = %r\n", Status
));
575 ASSERT_EFI_ERROR (Status
);