]> git.proxmox.com Git - mirror_edk2.git/blob - DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / DynamicTablesPkg / Library / Acpi / Arm / AcpiDbg2LibArm / Dbg2Generator.c
1 /** @file
2 DBG2 Table Generator
3
4 Copyright (c) 2017 - 2022, 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 /** A string representing the full path name of the debug port 0.
59 */
60 #define NAMESPACE_STR_DBG_PORT0 "\\_SB_.COM0"
61
62 /** An UID representing the debug port 0.
63 */
64 #define UID_DBG_PORT0 0
65
66 /** The length of the namespace string.
67 */
68 #define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAMESPACE_STR_DBG_PORT0)
69
70 /** The PL011 UART address range length.
71 */
72 #define PL011_UART_LENGTH 0x1000
73
74 /** A structure that provides the OS with the required information
75 for initializing a debugger connection.
76 */
77 typedef struct {
78 /// The debug device information for the platform
79 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT Dbg2Device;
80
81 /// The base address register for the serial port
82 EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister;
83
84 /// The address size
85 UINT32 AddressSize;
86
87 /// The debug port name string
88 UINT8 NameSpaceString[DBG2_NAMESPACESTRING_FIELD_SIZE];
89 } DBG2_DEBUG_DEVICE_INFORMATION;
90
91 /** A structure representing the information about the debug port(s)
92 available on the platform.
93 */
94 typedef struct {
95 /// The DBG2 table header
96 EFI_ACPI_DEBUG_PORT_2_DESCRIPTION_TABLE Description;
97
98 /// Debug port information list
99 DBG2_DEBUG_DEVICE_INFORMATION Dbg2DeviceInfo[DBG2_NUM_DEBUG_PORTS];
100 } DBG2_TABLE;
101
102 /** A helper macro used for initializing the debug port device
103 information structure.
104
105 @param [in] SubType The DBG Port SubType.
106 @param [in] UartBase The UART port base address.
107 @param [in] UartAddrLen The UART port address range length.
108 @param [in] UartNameStr The UART port name string.
109 **/
110 #define DBG2_DEBUG_PORT_DDI( \
111 SubType, \
112 UartBase, \
113 UartAddrLen, \
114 UartNameStr \
115 ) {\
116 { \
117 /* UINT8 Revision */ \
118 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION, \
119 /* UINT16 Length */ \
120 sizeof (DBG2_DEBUG_DEVICE_INFORMATION), \
121 /* UINT8 NumberofGenericAddressRegisters */ \
122 DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS, \
123 /* UINT16 NameSpaceStringLength */ \
124 DBG2_NAMESPACESTRING_FIELD_SIZE, \
125 /* UINT16 NameSpaceStringOffset */ \
126 OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, NameSpaceString), \
127 /* UINT16 OemDataLength */ \
128 0, \
129 /* UINT16 OemDataOffset */ \
130 0, \
131 /* UINT16 Port Type */ \
132 EFI_ACPI_DBG2_PORT_TYPE_SERIAL, \
133 /* UINT16 Port Subtype */ \
134 SubType, \
135 /* UINT8 Reserved[2] */ \
136 {EFI_ACPI_RESERVED_BYTE, EFI_ACPI_RESERVED_BYTE}, \
137 /* UINT16 BaseAddressRegister Offset */ \
138 OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, BaseAddressRegister), \
139 /* UINT16 AddressSize Offset */ \
140 OFFSET_OF (DBG2_DEBUG_DEVICE_INFORMATION, AddressSize) \
141 }, \
142 /* EFI_ACPI_6_2_GENERIC_ADDRESS_STRUCTURE BaseAddressRegister */ \
143 ARM_GAS32 (UartBase), \
144 /* UINT32 AddressSize */ \
145 UartAddrLen, \
146 /* UINT8 NameSpaceString[MAX_DBG2_NAME_LEN] */ \
147 UartNameStr \
148 }
149
150 /** The DBG2 Table template definition.
151
152 Note: fields marked with "{Template}" will be set dynamically
153 */
154 STATIC
155 DBG2_TABLE AcpiDbg2 = {
156 {
157 ACPI_HEADER (
158 EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE,
159 DBG2_TABLE,
160 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION
161 ),
162 OFFSET_OF (DBG2_TABLE, Dbg2DeviceInfo),
163 DBG2_NUM_DEBUG_PORTS
164 },
165 {
166 /*
167 * Debug port 1
168 */
169 DBG2_DEBUG_PORT_DDI (
170 0, // {Template}: Serial Port Subtype
171 0, // {Template}: Serial Port Base Address
172 PL011_UART_LENGTH,
173 NAMESPACE_STR_DBG_PORT0
174 )
175 }
176 };
177
178 #pragma pack()
179
180 /** This macro expands to a function that retrieves the Serial
181 debug port information from the Configuration Manager
182 */
183 GET_OBJECT_LIST (
184 EObjNameSpaceArm,
185 EArmObjSerialDebugPortInfo,
186 CM_ARM_SERIAL_PORT_INFO
187 );
188
189 /** Initialize the PL011/SBSA UART with the parameters obtained from
190 the Configuration Manager.
191
192 @param [in] SerialPortInfo Pointer to the Serial Port Information.
193
194 @retval EFI_SUCCESS Success.
195 @retval EFI_INVALID_PARAMETER The parameters for serial port initialization
196 are invalid.
197 **/
198 STATIC
199 EFI_STATUS
200 SetupDebugUart (
201 IN CONST CM_ARM_SERIAL_PORT_INFO *CONST SerialPortInfo
202 )
203 {
204 EFI_STATUS Status;
205 UINT64 BaudRate;
206 UINT32 ReceiveFifoDepth;
207 EFI_PARITY_TYPE Parity;
208 UINT8 DataBits;
209 EFI_STOP_BITS_TYPE StopBits;
210
211 ASSERT (SerialPortInfo != NULL);
212
213 // Initialize the Serial Debug UART
214 DEBUG ((DEBUG_INFO, "Initializing Serial Debug UART...\n"));
215 ReceiveFifoDepth = 0; // Use the default value for FIFO depth
216 Parity = (EFI_PARITY_TYPE)FixedPcdGet8 (PcdUartDefaultParity);
217 DataBits = FixedPcdGet8 (PcdUartDefaultDataBits);
218 StopBits = (EFI_STOP_BITS_TYPE)FixedPcdGet8 (PcdUartDefaultStopBits);
219
220 BaudRate = SerialPortInfo->BaudRate;
221 Status = PL011UartInitializePort (
222 (UINTN)SerialPortInfo->BaseAddress,
223 SerialPortInfo->Clock,
224 &BaudRate,
225 &ReceiveFifoDepth,
226 &Parity,
227 &DataBits,
228 &StopBits
229 );
230
231 ASSERT_EFI_ERROR (Status);
232 return Status;
233 }
234
235 /** Free any resources allocated for constructing the tables.
236
237 @param [in] This Pointer to the ACPI table generator.
238 @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
239 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
240 Protocol Interface.
241 @param [in, out] Table Pointer to an array of pointers
242 to ACPI Table(s).
243 @param [in] TableCount Number of ACPI table(s).
244
245 @retval EFI_SUCCESS The resources were freed successfully.
246 @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
247 **/
248 STATIC
249 EFI_STATUS
250 EFIAPI
251 FreeDbg2TableEx (
252 IN CONST ACPI_TABLE_GENERATOR *CONST This,
253 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
254 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
255 IN OUT EFI_ACPI_DESCRIPTION_HEADER ***CONST Table,
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 !=
280 EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_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
296 /** Construct the DBG2 ACPI table and its associated SSDT table.
297
298 This function invokes the Configuration Manager protocol interface
299 to get the required hardware information for generating the ACPI
300 table.
301
302 If this function allocates any resources then they must be freed
303 in the FreeXXXXTableResourcesEx function.
304
305 @param [in] This Pointer to the ACPI table generator.
306 @param [in] AcpiTableInfo Pointer to the ACPI table information.
307 @param [in] CfgMgrProtocol Pointer to the Configuration Manager
308 Protocol interface.
309 @param [out] Table Pointer to a list of generated ACPI table(s).
310 @param [out] TableCount Number of generated ACPI table(s).
311
312 @retval EFI_SUCCESS Table generated successfully.
313 @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
314 Manager is less than the Object size for
315 the requested object.
316 @retval EFI_INVALID_PARAMETER A parameter is invalid.
317 @retval EFI_NOT_FOUND Could not find information.
318 @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
319 @retval EFI_UNSUPPORTED Unsupported configuration.
320 **/
321 STATIC
322 EFI_STATUS
323 EFIAPI
324 BuildDbg2TableEx (
325 IN CONST ACPI_TABLE_GENERATOR *This,
326 IN CONST CM_STD_OBJ_ACPI_TABLE_INFO *CONST AcpiTableInfo,
327 IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL *CONST CfgMgrProtocol,
328 OUT EFI_ACPI_DESCRIPTION_HEADER ***Table,
329 OUT UINTN *CONST TableCount
330 )
331 {
332 EFI_STATUS Status;
333 CM_ARM_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 = GetEArmObjSerialDebugPortInfo (
362 CfgMgrProtocol,
363 CM_NULL_TOKEN,
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 **)
398 AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER *) * 2);
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,
413 (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiDbg2,
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
427 AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.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
445 AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.AccessSize =
446 EFI_ACPI_6_3_DWORD;
447 } else {
448 AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.AccessSize =
449 SerialPortInfo->AccessSize;
450 }
451
452 // Update the serial port subtype
453 AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].Dbg2Device.PortSubtype =
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 // Initialize the serial port
464 Status = SetupDebugUart (SerialPortInfo);
465 if (EFI_ERROR (Status)) {
466 DEBUG ((
467 DEBUG_ERROR,
468 "ERROR: DBG2: Failed to configure debug serial port. Status = %r\n",
469 Status
470 ));
471 goto error_handler;
472 }
473 }
474
475 TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER *)&AcpiDbg2;
476
477 // Build a SSDT table describing the serial port.
478 Status = BuildSsdtSerialPortTable (
479 AcpiTableInfo,
480 SerialPortInfo,
481 NAME_STR_DBG_PORT0,
482 UID_DBG_PORT0,
483 &TableList[1]
484 );
485 if (EFI_ERROR (Status)) {
486 DEBUG ((
487 DEBUG_ERROR,
488 "ERROR: DBG2: Failed to build associated SSDT table. Status = %r\n",
489 Status
490 ));
491 goto error_handler;
492 }
493
494 *TableCount = 2;
495 *Table = TableList;
496
497 return Status;
498
499 error_handler:
500 if (TableList != NULL) {
501 FreePool (TableList);
502 }
503
504 return Status;
505 }
506
507 /** This macro defines the DBG2 Table Generator revision.
508 */
509 #define DBG2_GENERATOR_REVISION CREATE_REVISION (1, 0)
510
511 /** The interface for the DBG2 Table Generator.
512 */
513 STATIC
514 CONST
515 ACPI_TABLE_GENERATOR Dbg2Generator = {
516 // Generator ID
517 CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdDbg2),
518 // Generator Description
519 L"ACPI.STD.DBG2.GENERATOR",
520 // ACPI Table Signature
521 EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE,
522 // ACPI Table Revision supported by this Generator
523 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
524 // Minimum supported ACPI Table Revision
525 EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
526 // Creator ID
527 TABLE_GENERATOR_CREATOR_ID_ARM,
528 // Creator Revision
529 DBG2_GENERATOR_REVISION,
530 // Build table function. Use the extended version instead.
531 NULL,
532 // Free table function. Use the extended version instead.
533 NULL,
534 // Extended Build table function.
535 BuildDbg2TableEx,
536 // Extended free function.
537 FreeDbg2TableEx
538 };
539
540 /** Register the Generator with the ACPI Table Factory.
541
542 @param [in] ImageHandle The handle to the image.
543 @param [in] SystemTable Pointer to the System Table.
544
545 @retval EFI_SUCCESS The Generator is registered.
546 @retval EFI_INVALID_PARAMETER A parameter is invalid.
547 @retval EFI_ALREADY_STARTED The Generator for the Table ID
548 is already registered.
549 **/
550 EFI_STATUS
551 EFIAPI
552 AcpiDbg2LibConstructor (
553 IN EFI_HANDLE ImageHandle,
554 IN EFI_SYSTEM_TABLE *SystemTable
555 )
556 {
557 EFI_STATUS Status;
558
559 Status = RegisterAcpiTableGenerator (&Dbg2Generator);
560 DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status));
561 ASSERT_EFI_ERROR (Status);
562 return Status;
563 }
564
565 /** Deregister the Generator from the ACPI Table Factory.
566
567 @param [in] ImageHandle The handle to the image.
568 @param [in] SystemTable Pointer to the System Table.
569
570 @retval EFI_SUCCESS The Generator is deregistered.
571 @retval EFI_INVALID_PARAMETER A parameter is invalid.
572 @retval EFI_NOT_FOUND The Generator is not registered.
573 **/
574 EFI_STATUS
575 EFIAPI
576 AcpiDbg2LibDestructor (
577 IN EFI_HANDLE ImageHandle,
578 IN EFI_SYSTEM_TABLE *SystemTable
579 )
580 {
581 EFI_STATUS Status;
582
583 Status = DeregisterAcpiTableGenerator (&Dbg2Generator);
584 DEBUG ((DEBUG_INFO, "DBG2: Deregister Generator. Status = %r\n", Status));
585 ASSERT_EFI_ERROR (Status);
586 return Status;
587 }