TianoCore EDK2 master
Loading...
Searching...
No Matches
Dbg2Generator.c
Go to the documentation of this file.
1
14#include <Library/AcpiLib.h>
15#include <Library/DebugLib.h>
17#include <Protocol/AcpiTable.h>
18#include <Protocol/SerialIo.h>
19
20// Module specific include files.
21#include <AcpiTableGenerator.h>
27
28#include "Dbg2Generator.h"
29
40#pragma pack(1)
41
44#define DBG2_NUM_DEBUG_PORTS 1
45
49#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS 1
50
53#define INDEX_DBG_PORT0 0
54
57#define NAME_STR_DBG_PORT0 "COM0"
58
61#define NAMESPACE_STR_DBG_PORT0 "\\_SB_.COM0"
62
65#define UID_DBG_PORT0 0
66
69#define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAMESPACE_STR_DBG_PORT0)
70
73#define PL011_UART_LENGTH 0x1000
74
78typedef struct {
81
84
87
89 UINT8 NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE];
91
95typedef struct {
98
101} DBG2_TABLE;
102
111#define DBG2_DEBUG_PORT_DDI( \
112 SubType, \
113 UartBase, \
114 UartAddrLen, \
115 UartNameStr \
116 ) {\
117 { \
118 /* UINT8 Revision */ \
119 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, \
120 /* UINT16 Length */ \
121 sizeof (DBG2_DEBUG_DEVICE_INFORMATION), \
122 /* UINT8 NumberofGenericAddressRegisters */ \
123 DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS, \
124 /* UINT16 NameSpaceStringLength */ \
125 DBG2_NAMESPACESTRING_FIELD_SIZE, \
126 /* UINT16 NameSpaceStringOffset */ \
127 OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString), \
128 /* UINT16 OemDataLength */ \
129 0, \
130 /* UINT16 OemDataOffset */ \
131 0, \
132 /* UINT16 Port Type */ \
133 EFI_ACPI_DBG2_PORT_TYPE_SERIAL, \
134 /* UINT16 Port Subtype */ \
135 SubType, \
136 /* UINT8 Reserved[2] */ \
137 {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE}, \
138 /* UINT16 BaseAddressRegister Offset */ \
139 OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, BaseAddressRegister), \
140 /* UINT16 AddressSize Offset */ \
141 OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize) \
142 }, \
143 /* EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */ \
144 ARM_GAS32 (UartBase), \
145 /* UINT32 AddressSize */ \
146 UartAddrLen, \
147 /* UINT8 NameSpaceString[MAX_DBG2_NAME_LEN] */ \
148 UartNameStr \
149 }
150
155STATIC
157 {
161 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
162 ),
163 OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo),
165 },
166 {
167 /*
168 * Debug port 1
169 */
171 0, // {Template}: Serial Port Subtype
172 0, // {Template}: Serial Port Base Address
173 0, // {Template}: Serial Port Base Address Size
175 )
176 }
177};
178
179#pragma pack()
180
188 );
189
199STATIC
203 )
204{
205 EFI_STATUS Status;
206 UINT64 BaudRate;
207 UINT32 ReceiveFifoDepth;
208 EFI_PARITY_TYPE Parity;
209 UINT8 DataBits;
210 EFI_STOP_BITS_TYPE StopBits;
211
212 ASSERT (SerialPortInfo != NULL);
213
214 // Initialize the Serial Debug UART
215 DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n"));
216 ReceiveFifoDepth = 0; // Use the default value for FIFO depth
217 Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
218 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
219 StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
220
221 BaudRate = SerialPortInfo->BaudRate;
222 Status = Dbg2InitializePort (
223 SerialPortInfo,
224 &BaudRate,
225 &ReceiveFifoDepth,
226 &Parity,
227 &DataBits,
228 &StopBits
229 );
230
231 ASSERT_EFI_ERROR (Status);
232 return Status;
233}
234
248STATIC
250EFIAPI
256 IN CONST UINTN TableCount
257 )
258{
259 EFI_STATUS Status;
260 EFI_ACPI_DESCRIPTION_HEADER **TableList;
261
262 ASSERT (This != NULL);
263 ASSERT (AcpiTableInfo != NULL);
264 ASSERT (CfgMgrProtocol != NULL);
265 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
266 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
267
268 if ((Table == NULL) ||
269 (*Table == NULL) ||
270 (TableCount != 2))
271 {
272 DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid Table Pointer\n"));
273 return EFI_INVALID_PARAMETER;
274 }
275
276 TableList = *Table;
277
278 if ((TableList[1] == NULL) ||
279 (TableList[1]->Signature !=
281 {
282 DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid SSDT table pointer.\n"));
283 return EFI_INVALID_PARAMETER;
284 }
285
286 // Only need to free the SSDT table at index 1. The DBG2 table is static.
287 Status = FreeSsdtSerialPortTable (TableList[1]);
288 ASSERT_EFI_ERROR (Status);
289
290 // Free the table list.
291 FreePool (*Table);
292
293 return Status;
294}
295
321STATIC
323EFIAPI
329 OUT UINTN *CONST TableCount
330 )
331{
332 EFI_STATUS Status;
333 CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo;
334 UINT32 SerialPortCount;
335 EFI_ACPI_DESCRIPTION_HEADER **TableList;
336
337 ASSERT (This != NULL);
338 ASSERT (AcpiTableInfo != NULL);
339 ASSERT (CfgMgrProtocol != NULL);
340 ASSERT (Table != NULL);
341 ASSERT (TableCount != NULL);
342 ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
343 ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
344
345 if ((AcpiTableInfo->AcpiTableRevision < This->MinAcpiTableRevision) ||
346 (AcpiTableInfo->AcpiTableRevision > This->AcpiTableRevision))
347 {
348 DEBUG ((
349 DEBUG_ERROR,
350 "ERROR: DBG2: Requested table revision = %d, is not supported."
351 "Supported table revision: Minimum = %d, Maximum = %d\n",
352 AcpiTableInfo->AcpiTableRevision,
353 This->MinAcpiTableRevision,
354 This->AcpiTableRevision
355 ));
356 return EFI_INVALID_PARAMETER;
357 }
358
359 *Table = NULL;
360
361 Status = GetEArchCommonObjSerialDebugPortInfo (
362 CfgMgrProtocol,
364 &SerialPortInfo,
365 &SerialPortCount
366 );
367 if (EFI_ERROR (Status)) {
368 DEBUG ((
369 DEBUG_ERROR,
370 "ERROR: DBG2: Failed to get serial port information. Status = %r\n",
371 Status
372 ));
373 return Status;
374 }
375
376 if (SerialPortCount == 0) {
377 DEBUG ((
378 DEBUG_ERROR,
379 "ERROR: DBG2: Serial port information not found. Status = %r\n",
380 EFI_NOT_FOUND
381 ));
382 return EFI_NOT_FOUND;
383 }
384
385 // Only use the first DBG2 port information.
386 Status = ValidateSerialPortInfo (SerialPortInfo, 1);
387 if (EFI_ERROR (Status)) {
388 DEBUG ((
389 DEBUG_ERROR,
390 "ERROR: DBG2: Invalid serial port information. Status = %r\n",
391 Status
392 ));
393 return Status;
394 }
395
396 // Allocate a table to store pointers to the DBG2 and SSDT tables.
397 TableList = (EFI_ACPI_DESCRIPTION_HEADER **)
399 if (TableList == NULL) {
400 Status = EFI_OUT_OF_RESOURCES;
401 DEBUG ((
402 DEBUG_ERROR,
403 "ERROR: DBG2: Failed to allocate memory for Table List," \
404 " Status = %r\n",
405 Status
406 ));
407 return Status;
408 }
409
410 Status = AddAcpiHeader (
411 CfgMgrProtocol,
412 This,
414 AcpiTableInfo,
415 sizeof (DBG2_TABLE)
416 );
417 if (EFI_ERROR (Status)) {
418 DEBUG ((
419 DEBUG_ERROR,
420 "ERROR: DBG2: Failed to add ACPI header. Status = %r\n",
421 Status
422 ));
423 goto error_handler;
424 }
425
426 // Update the base address
428 SerialPortInfo->BaseAddress;
429
430 // Set the access size
431 if (SerialPortInfo->AccessSize >= EFI_ACPI_6_3_QWORD) {
432 Status = EFI_INVALID_PARAMETER;
433 DEBUG ((
434 DEBUG_ERROR,
435 "ERROR: DBG2: Access size must be <= 3 (DWORD). Status = %r\n",
436 Status
437 ));
438 goto error_handler;
439 } else if (SerialPortInfo->AccessSize == EFI_ACPI_6_3_UNDEFINED) {
440 // 0 Undefined (legacy reasons)
441 // Default to DWORD access size as the access
442 // size field was introduced at a later date
443 // and some ConfigurationManager implementations
444 // may not be providing this field data
446 EFI_ACPI_6_3_DWORD;
447 } else {
449 SerialPortInfo->AccessSize;
450 }
451
452 // Update the serial port subtype
454 SerialPortInfo->PortSubtype;
455
456 if ((SerialPortInfo->PortSubtype ==
457 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) ||
458 (SerialPortInfo->PortSubtype ==
459 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) ||
460 (SerialPortInfo->PortSubtype ==
461 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART))
462 {
463 // Setup the PL011 length.
465
466 // Initialize the serial port
467 Status = SetupDebugUart (SerialPortInfo);
468 if (EFI_ERROR (Status)) {
469 DEBUG ((
470 DEBUG_ERROR,
471 "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n",
472 Status
473 ));
474 goto error_handler;
475 }
476 } else if ((SerialPortInfo->PortSubtype ==
477 EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_16550_WITH_GAS))
478 {
480 } else {
481 // Try to catch other serial ports, but don't return an error.
482 ASSERT (0);
483 }
484
485 TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiDbg2;
486
487 // Build a SSDT table describing the serial port.
488 Status = BuildSsdtSerialPortTable (
489 AcpiTableInfo,
490 SerialPortInfo,
493 &TableList[1]
494 );
495 if (EFI_ERROR (Status)) {
496 DEBUG ((
497 DEBUG_ERROR,
498 "ERROR: DBG2: Failed to build associated SSDT table. Status = %r\n",
499 Status
500 ));
501 goto error_handler;
502 }
503
504 *TableCount = 2;
505 *Table = TableList;
506
507 return Status;
508
509error_handler:
510 if (TableList != NULL) {
511 FreePool (TableList);
512 }
513
514 return Status;
515}
516
519#define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0)
520
523STATIC
524CONST
526 // Generator ID
528 // Generator Description
529 L"ACPI.STD.DBG2.GENERATOR",
530 // ACPI Table Signature
532 // ACPI Table Revision supported by this Generator
533 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
534 // Minimum supported ACPI Table Revision
535 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
536 // Creator ID
538 // Creator Revision
540 // Build table function. Use the extended version instead.
541 NULL,
542 // Free table function. Use the extended version instead.
543 NULL,
544 // Extended Build table function.
546 // Extended free function.
548};
549
561EFIAPI
563 IN EFI_HANDLE ImageHandle,
564 IN EFI_SYSTEM_TABLE *SystemTable
565 )
566{
567 EFI_STATUS Status;
568
570 DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status));
571 ASSERT_EFI_ERROR (Status);
572 return Status;
573}
574
585EFIAPI
587 IN EFI_HANDLE ImageHandle,
588 IN EFI_SYSTEM_TABLE *SystemTable
589 )
590{
591 EFI_STATUS Status;
592
594 DEBUG ((DEBUG_INFO, "DBG2: Deregister Generator. Status = %r\n", Status));
595 ASSERT_EFI_ERROR (Status);
596 return Status;
597}
UINT64 UINTN
#define EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE
Definition: Acpi62.h:2851
#define EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE
Definition: Acpi63.h:2831
#define EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE
Definition: Acpi63.h:2851
EFI_STATUS EFIAPI RegisterAcpiTableGenerator(IN CONST ACPI_TABLE_GENERATOR *CONST Generator)
EFI_STATUS EFIAPI DeregisterAcpiTableGenerator(IN CONST ACPI_TABLE_GENERATOR *CONST Generator)
#define CREATE_STD_ACPI_TABLE_GEN_ID(TableId)
#define TABLE_GENERATOR_CREATOR_ID
@ EStdAcpiTableIdDbg2
DBG2 Generator.
#define ACPI_HEADER(Signature, Type, Revision)
@ EArchCommonObjSerialDebugPortInfo
4 - Serial Debug Port Info
RETURN_STATUS EFIAPI Dbg2InitializePort(IN CONST CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo, IN OUT UINT64 *BaudRate, IN OUT UINT32 *ReceiveFifoDepth, IN OUT EFI_PARITY_TYPE *Parity, IN OUT UINT8 *DataBits, IN OUT EFI_STOP_BITS_TYPE *StopBits)
#define GET_OBJECT_LIST(CmObjectNameSpace, CmObjectId, Type)
@ EObjNameSpaceArchCommon
Arch Common Objects Namespace.
EFI_STATUS EFIAPI AcpiDbg2LibDestructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
#define NAME_STR_DBG_PORT0
Definition: Dbg2Generator.c:57
STATIC EFI_STATUS EFIAPI BuildDbg2TableEx(IN CONST ACPI_TABLE_GENERATOR *This, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, OUT EFI_ACPI_DESCRIPTION_HEADER ***Table, OUT UINTN *CONST TableCount)
EFI_STATUS EFIAPI AcpiDbg2LibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
#define NAMESPACE_STR_DBG_PORT0
Definition: Dbg2Generator.c:61
STATIC EFI_STATUS SetupDebugUart(IN CONST CM_ARCH_COMMON_SERIAL_PORT_INFO *CONST SerialPortInfo)
#define DBG2_DEBUG_PORT_DDI( SubType, UartBase, UartAddrLen, UartNameStr)
STATIC CONST ACPI_TABLE_GENERATOR Dbg2Generator
#define DBG2_GENERATOR_REVISION
#define DBG2_NUM_DEBUG_PORTS
Definition: Dbg2Generator.c:44
STATIC EFI_STATUS EFIAPI FreeDbg2TableEx(IN CONST ACPI_TABLE_GENERATOR *CONST This, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table, IN CONST UINTN TableCount)
#define DBG2_NAMESPACESTRING_FIELD_SIZE
Definition: Dbg2Generator.c:69
STATIC DBG2_TABLE AcpiDbg2
#define INDEX_DBG_PORT0
Definition: Dbg2Generator.c:53
#define PL011_UART_LENGTH
Definition: Dbg2Generator.c:73
#define UID_DBG_PORT0
Definition: Dbg2Generator.c:65
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define FixedPcdGet8(TokenName)
Definition: PcdLib.h:64
EFI_STOP_BITS_TYPE
Definition: SerialIo.h:53
EFI_PARITY_TYPE
Definition: SerialIo.h:41
EFI_STATUS EFIAPI ValidateSerialPortInfo(IN CONST CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfoTable, IN UINT32 SerialPortCount)
EFI_STATUS EFIAPI FreeSsdtSerialPortTable(IN EFI_ACPI_DESCRIPTION_HEADER *Table)
EFI_STATUS EFIAPI BuildSsdtSerialPortTable(IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *AcpiTableInfo, IN CONST CM_ARCH_COMMON_SERIAL_PORT_INFO *SerialPortInfo, IN CONST CHAR8 *Name, IN CONST UINT64 Uid, OUT EFI_ACPI_DESCRIPTION_HEADER **Table)
#define CM_NULL_TOKEN
EFI_STATUS EFIAPI AddAcpiHeader(IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol, IN CONST ACPI_TABLE_GENERATOR *CONST Generator, IN OUT EFI_ACPI_DESCRIPTION_HEADER *CONST AcpiHeader, IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo, IN CONST UINT32 Length)
Definition: TableHelper.c:114
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister
The base address register for the serial port.
Definition: Dbg2Generator.c:83
EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device
The debug device information for the platform.
Definition: Dbg2Generator.c:80
UINT32 AddressSize
The address size.
Definition: Dbg2Generator.c:86
EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description
The DBG2 table header.
Definition: Dbg2Generator.c:97
DBG2_DEBUG_DEVICE_INFORMATION Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS]
Debug port information list.
UINT16 PortSubtype
Serial Port subtype.
UINT64 BaseAddress
The physical base address for the serial port.