TianoCore EDK2 master
Loading...
Searching...
No Matches
PcctParser.c
Go to the documentation of this file.
1
12#include <Library/PrintLib.h>
13#include <Library/UefiLib.h>
14#include "AcpiParser.h"
15#include "AcpiView.h"
16#include "AcpiViewConfig.h"
17#include "PcctParser.h"
18
19// Local variables
21
22STATIC UINT32 *PccGlobalFlags;
23STATIC UINT8 *PccSubspaceLength;
24STATIC UINT8 *PccSubspaceType;
25STATIC UINT8 *ExtendedPccSubspaceInterruptFlags;
26
36VOID
37EFIAPI
39 IN UINT8 *Ptr,
40 IN UINT32 Length,
41 IN VOID *Context
42 )
43{
44 if (*(UINT32 *)Ptr < MIN_EXT_PCC_SUBSPACE_MEM_RANGE_LEN) {
46 Print (
47 L"\nError: Shared memory range length is too short.\n"
48 L"Length is %u when it should be greater than or equal to %u",
49 *(UINT32 *)Ptr,
51 );
52 }
53}
54
64VOID
65EFIAPI
67 IN UINT8 *Ptr,
68 IN UINT32 Length,
69 IN VOID *Context
70 )
71{
72 if (*(UINT64 *)Ptr <= MIN_MEMORY_RANGE_LENGTH) {
74 Print (
75 L"\nError: Shared memory range length is too short.\n"
76 L"Length is %u when it should be greater than %u",
77 *(UINT64 *)Ptr,
79 );
80 }
81}
82
92VOID
93EFIAPI
95 IN UINT8 *Ptr,
96 IN UINT32 Length,
97 IN VOID *Context
98 )
99{
100 switch (*(UINT8 *)Ptr) {
101 #if !(defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
102 case EFI_ACPI_6_4_SYSTEM_IO:
103 #endif //if not (defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
104 case EFI_ACPI_6_4_SYSTEM_MEMORY:
105 return;
106 default:
108 Print (L"\nError: Invalid address space");
109 }
110}
111
120STATIC
121VOID
122EFIAPI
124 IN UINT8 *Ptr,
125 IN UINT32 Length,
126 IN VOID *Context
127 )
128{
129 switch (*(UINT8 *)Ptr) {
130 #if !(defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
131 case EFI_ACPI_6_4_SYSTEM_IO:
132 #endif //if not (defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
133 case EFI_ACPI_6_4_FUNCTIONAL_FIXED_HARDWARE:
134 case EFI_ACPI_6_4_SYSTEM_MEMORY:
135 return;
136 default:
138 Print (L"\nError: Invalid address space");
139 }
140}
141
150STATIC
151VOID
152EFIAPI
154 IN UINT8 *Ptr,
155 IN UINT32 Length,
156 IN VOID *Context
157 )
158{
159 // For responder subspaces this field is optional, if not present the field
160 // should just contain zeros.
161 if (*PccSubspaceType == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {
162 if (IsZeroBuffer (
163 Ptr,
165 ))
166 {
167 return;
168 }
169 }
170
171 ValidatePccGas (Ptr, Length, Context);
172}
173
183STATIC
184VOID
185EFIAPI
187 IN UINT8 *Ptr,
188 IN UINT32 Length,
189 IN VOID *Context
190 )
191{
192 // If the subspace does not support interrupts or the interrupt is
193 // edge driven the register may be omitted. A value of 0x0 on all
194 // 12 bytes of the GAS structure indicates the register is not
195 // present.
196 if (((*PccGlobalFlags & EFI_ACPI_6_4_PCCT_FLAGS_PLATFORM_INTERRUPT) !=
198 ((*ExtendedPccSubspaceInterruptFlags &
199 EFI_ACPI_6_4_PCCT_SUBSPACE_PLATFORM_INTERRUPT_FLAGS_MODE) ==
200 EFI_ACPI_6_4_PCCT_SUBSPACE_PLATFORM_INTERRUPT_FLAGS_MODE))
201 {
202 if (IsZeroBuffer (
203 Ptr,
205 ))
206 {
207 return;
208 }
209 }
210
211 ValidatePccGas (Ptr, Length, Context);
212}
213
222STATIC
223VOID
224EFIAPI
226 IN UINT8 *Ptr,
227 IN UINT32 Length,
228 IN VOID *Context
229 )
230{
231 // This field is ignored by the OSPM on responder channels.
232 if (*PccSubspaceType == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {
233 return;
234 }
235
236 ValidatePccGas (Ptr, Length, Context);
237}
238
247STATIC
248VOID
249EFIAPI
251 IN UINT8 *Ptr,
252 IN UINT32 Length,
253 IN VOID *Context
254 )
255{
256 // If a responder subspace is present in the PCCT, then the global Platform
257 // Interrupt flag must be set to 1.
258 if ((*PccSubspaceType == EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) &&
259 ((*PccGlobalFlags & EFI_ACPI_6_4_PCCT_FLAGS_PLATFORM_INTERRUPT) !=
261 {
263 Print (
264 L"\nError: Global Platform interrupt flag must be set to 1" \
265 L" if a PCC type 4 structure is present in PCCT."
266 );
267 }
268}
269
274 PARSE_ACPI_HEADER (&AcpiHdrInfo),
275 { L"Flags", 4, 36, NULL, NULL, (VOID **)&PccGlobalFlags, NULL, NULL },
276 { L"Reserved", 8, 40, NULL, NULL, NULL, NULL, NULL }
277};
278
285 // ... Type Specific Fields ...
286};
287
293 { L"Reserved", 6, 2, L"%x %x %x %x %x %x", Dump6Chars, NULL, NULL, NULL },
294 { L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
295 { L"Memory Range Length",8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,
296 NULL },
297 { L"Doorbell Register",12, 24, NULL, DumpGas, NULL, ValidatePccMemoryIoGas,
298 NULL },
299 { L"Doorbell Preserve",8, 36, L"0x%lx", NULL, NULL, NULL, NULL },
300 { L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL },
301 { L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL },
302 { L"Maximum Periodic Access Rate",4, 56, L"%u", NULL, NULL, NULL, NULL },
303 { L"Minimum Request Turnaround Time",2, 60, L"%u", NULL, NULL, NULL, NULL }
304};
305
312 { L"Platform Interrupt",4, 2, L"0x%x", NULL, NULL, NULL, NULL },
313 { L"Platform Interrupt Flags",1, 6, L"0x%x", NULL, NULL, NULL, NULL },
314 { L"Reserved", 1, 7, L"0x%x", NULL, NULL, NULL, NULL },
315 { L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
316 { L"Memory Range Length",8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,
317 NULL },
318 { L"Doorbell Register",12, 24, NULL, DumpGas, NULL,
320 { L"Doorbell Preserve",8, 36, L"0x%lx", NULL, NULL, NULL, NULL },
321 { L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL },
322 { L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL },
323 { L"Maximum Periodic Access Rate",4, 56, L"%u", NULL, NULL, NULL, NULL },
324 { L"Minimum Request Turnaround Time",2, 60, L"%u", NULL, NULL, NULL, NULL }
325};
326
333 { L"Platform Interrupt",4, 2, L"0x%x", NULL, NULL, NULL, NULL },
334 { L"Platform Interrupt Flags",1, 6, L"0x%x", NULL, NULL, NULL, NULL },
335 { L"Reserved", 1, 7, L"0x%x", NULL, NULL, NULL, NULL },
336 { L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL },
337 { L"Memory Range Length",8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,
338 NULL },
339 { L"Doorbell Register",12, 24, NULL, DumpGas, NULL,
341 { L"Doorbell Preserve",8, 36, L"0x%lx", NULL, NULL, NULL, NULL },
342 { L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL },
343 { L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL },
344 { L"Maximum Periodic Access Rate",4, 56, L"%u", NULL, NULL, NULL, NULL },
345 { L"Minimum Request Turnaround Time",2, 60, L"%u", NULL, NULL, NULL, NULL },
346 { L"Platform Interrupt Ack Register",12, 62, NULL, DumpGas, NULL,
348 { L"Platform Interrupt Ack Preserve",8, 74, L"0x%lx", NULL, NULL, NULL, NULL },
349 { L"Platform Interrupt Ack Write",8, 82, L"0x%lx", NULL, NULL,
350 NULL, NULL },
351};
352
358 { L"Platform Interrupt", 4, 2, L"0x%x", NULL, NULL,
360 { L"Platform Interrupt Flags", 1, 6, L"0x%x", NULL,
361 (VOID **)&ExtendedPccSubspaceInterruptFlags,NULL, NULL },
362 { L"Reserved", 1, 7, L"0x%x", NULL, NULL,NULL, NULL },
363 { L"Base Address", 8, 8, L"0x%lx", NULL, NULL,NULL, NULL },
364 { L"Memory Range Length", 4, 16, L"0x%x", NULL, NULL,ValidateRangeLength4,
365 NULL },
366 { L"Doorbell Register", 12, 20, NULL, DumpGas, NULL,
368 { L"Doorbell Preserve", 8, 32, L"0x%lx", NULL, NULL,NULL, NULL },
369 { L"Doorbell Write", 8, 40, L"0x%lx", NULL, NULL,NULL, NULL },
370 { L"Nominal Latency", 4, 48, L"%u", NULL, NULL,NULL, NULL },
371 { L"Maximum Periodic Access Rate", 4, 52, L"%u", NULL, NULL,NULL, NULL },
372 { L"Minimum Request Turnaround Time", 4, 56, L"%u", NULL, NULL,NULL, NULL },
373 { L"Platform Interrupt Ack Register", 12, 60, NULL, DumpGas, NULL,
375 { L"Platform Interrupt Ack Preserve", 8, 72, L"0x%lx", NULL, NULL,NULL, NULL },
376 { L"Platform Interrupt Ack Set", 8, 80, L"0x%lx", NULL, NULL,NULL, NULL },
377 { L"Reserved", 8, 88, L"0x%lx", NULL, NULL,NULL, NULL },
378 { L"Cmd Complete Check Reg Addr", 12, 96, NULL, DumpGas, NULL,
380 { L"Cmd Complete Check Mask", 8, 108, L"0x%lx", NULL, NULL,NULL, NULL },
381 { L"Cmd Update Reg Addr", 12, 116, NULL, DumpGas, NULL,
383 { L"Cmd Update Preserve mask", 8, 128, L"0x%lx", NULL, NULL,NULL, NULL },
384 { L"Cmd Update Set mask", 8, 136, L"0x%lx", NULL, NULL,NULL, NULL },
385 { L"Error Status Register", 12, 144, NULL, DumpGas, NULL,
387 { L"Error Status Mask", 8, 156, L"0x%lx", NULL, NULL,NULL, NULL },
388};
389
396 { L"Version", 2, 2, L"0x%x", NULL, NULL, NULL, NULL },
397 { L"Base Address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL },
398 { L"Shared Memory Range Length",8, 12, L"0x%lx", NULL, NULL, NULL, NULL },
399 { L"Doorbell Register", 12, 20, NULL, DumpGas, NULL,
401 { L"Doorbell Preserve", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL },
402 { L"Doorbell Write", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL },
403 { L"Command Complete Check Register",12, 48, NULL, DumpGas, NULL,
405 { L"Command Complete Check Mask",8, 60, L"0x%lx", NULL, NULL, NULL, NULL },
406 { L"Error Status Register",12, 68, NULL, DumpGas, NULL,
408 { L"Error Status Mask", 8, 80, L"0x%lx", NULL, NULL, NULL, NULL },
409 { L"Nominal Latency", 4, 88, L"0x%x", NULL, NULL, NULL, NULL },
410 { L"Minimum Request Turnaround Time",4, 92, L"0x%x", NULL, NULL, NULL, NULL }
411};
412
419STATIC
420VOID
422 IN UINT8 *Ptr,
423 IN UINT8 Length
424 )
425{
426 ParseAcpi (
427 TRUE,
428 2,
429 "Subspace Type 0",
430 Ptr,
431 Length,
433 );
434}
435
442STATIC
443VOID
445 IN UINT8 *Ptr,
446 IN UINT8 Length
447 )
448{
449 ParseAcpi (
450 TRUE,
451 2,
452 "Subspace Type 1",
453 Ptr,
454 Length,
456 );
457}
458
465STATIC
466VOID
468 IN UINT8 *Ptr,
469 IN UINT8 Length
470 )
471{
472 ParseAcpi (
473 TRUE,
474 2,
475 "Subspace Type 2",
476 Ptr,
477 Length,
479 );
480}
481
488STATIC
489VOID
491 IN UINT8 *Ptr,
492 IN UINT8 Length
493 )
494{
495 ParseAcpi (
496 TRUE,
497 2,
498 "Subspace Type 3",
499 Ptr,
500 Length,
502 );
503}
504
511STATIC
512VOID
514 IN UINT8 *Ptr,
515 IN UINT8 Length
516 )
517{
518 ParseAcpi (
519 TRUE,
520 2,
521 "Subspace Type 4",
522 Ptr,
523 Length,
525 );
526}
527
534STATIC
535VOID
537 IN UINT8 *Ptr,
538 IN UINT8 Length
539 )
540{
541 ParseAcpi (
542 TRUE,
543 2,
544 "Subspace Type 5",
545 Ptr,
546 Length,
548 );
549}
550
564VOID
565EFIAPI
567 IN BOOLEAN Trace,
568 IN UINT8 *Ptr,
569 IN UINT32 AcpiTableLength,
570 IN UINT8 AcpiTableRevision
571 )
572{
573 UINT32 Offset;
574 UINT8 *PccSubspacePtr;
575 UINTN SubspaceCount;
576
577 if (!Trace) {
578 return;
579 }
580
581 Offset = ParseAcpi (
582 TRUE,
583 0,
584 "PCCT",
585 Ptr,
586 AcpiTableLength,
588 );
589
590 PccSubspacePtr = Ptr + Offset;
591
592 SubspaceCount = 0;
593 while (Offset < AcpiTableLength) {
594 // Parse common structure header to obtain Type and Length.
595 ParseAcpi (
596 FALSE,
597 0,
598 NULL,
599 PccSubspacePtr,
600 AcpiTableLength - Offset,
602 );
603
604 // Check if the values used to control the parsing logic have been
605 // successfully read.
606 if ((PccSubspaceType == NULL) ||
607 (PccSubspaceLength == NULL))
608 {
610 Print (
611 L"ERROR: Insufficient remaining table buffer length to read the " \
612 L"structure header. Length = %u.\n",
613 AcpiTableLength - Offset
614 );
615 return;
616 }
617
618 // Validate Structure length
619 if ((*PccSubspaceLength == 0) ||
620 ((Offset + (*PccSubspaceLength)) > AcpiTableLength))
621 {
623 Print (
624 L"ERROR: Invalid Structure length. " \
625 L"Length = %u. Offset = %u. AcpiTableLength = %u.\n",
626 *PccSubspaceLength,
627 Offset,
628 AcpiTableLength
629 );
630 return;
631 }
632
633 switch (*PccSubspaceType) {
634 case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_GENERIC:
636 PccSubspacePtr,
637 *PccSubspaceLength
638 );
639 break;
640 case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS:
642 PccSubspacePtr,
643 *PccSubspaceLength
644 );
645 break;
646 case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS:
648 PccSubspacePtr,
649 *PccSubspaceLength
650 );
651 break;
652 case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC:
654 PccSubspacePtr,
655 *PccSubspaceLength
656 );
657 break;
658 case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC:
660 PccSubspacePtr,
661 *PccSubspaceLength
662 );
663 break;
664 case EFI_ACPI_6_4_PCCT_SUBSPACE_TYPE_5_HW_REGISTERS_COMMUNICATIONS:
666 PccSubspacePtr,
667 *PccSubspaceLength
668 );
669 break;
670 default:
672 Print (
673 L"ERROR: Unknown PCC subspace structure:"
674 L" Type = %u, Length = %u\n",
675 PccSubspaceType,
676 *PccSubspaceLength
677 );
678 }
679
680 PccSubspacePtr += *PccSubspaceLength;
681 Offset += *PccSubspaceLength;
682 SubspaceCount++;
683 } // while
684
685 if (SubspaceCount > MAX_PCC_SUBSPACES) {
687 Print (L"ERROR: Too many PCC subspaces.");
688 }
689}
UINT64 UINTN
#define EFI_ACPI_6_4_PCCT_FLAGS_PLATFORM_INTERRUPT
Definition: Acpi64.h:2419
VOID EFIAPI DumpGas(IN CONST CHAR16 *Format OPTIONAL, IN UINT8 *Ptr, IN UINT32 Length)
Definition: AcpiParser.c:867
VOID EFIAPI IncrementErrorCount(VOID)
Definition: AcpiParser.c:83
UINT32 EFIAPI ParseAcpi(IN BOOLEAN Trace, IN UINT32 Indent, IN CONST CHAR8 *AsciiName OPTIONAL, IN UINT8 *Ptr, IN UINT32 Length, IN CONST ACPI_PARSER *Parser, IN UINT32 ParserItems)
Definition: AcpiParser.c:683
VOID EFIAPI Dump6Chars(IN CONST CHAR16 *Format OPTIONAL, IN UINT8 *Ptr, IN UINT32 Length)
Definition: AcpiParser.c:379
#define PARSER_PARAMS(Parser)
Definition: AcpiParser.h:494
#define PARSE_ACPI_HEADER(Info)
Definition: AcpiParser.h:501
BOOLEAN EFIAPI IsZeroBuffer(IN CONST VOID *Buffer, IN UINTN Length)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
STATIC VOID DumpPccSubspaceType1(IN UINT8 *Ptr, IN UINT8 Length)
Definition: PcctParser.c:444
VOID EFIAPI ParseAcpiPcct(IN BOOLEAN Trace, IN UINT8 *Ptr, IN UINT32 AcpiTableLength, IN UINT8 AcpiTableRevision)
Definition: PcctParser.c:566
STATIC CONST ACPI_PARSER PcctParser[]
Definition: PcctParser.c:273
STATIC VOID EFIAPI ValidatePccMemoryIoGas(IN UINT8 *Ptr, IN UINT32 Length, IN VOID *Context)
Definition: PcctParser.c:94
STATIC CONST ACPI_PARSER PccSubspaceHeaderParser[]
Definition: PcctParser.c:283
STATIC CONST ACPI_PARSER PccSubspaceType0Parser[]
Definition: PcctParser.c:291
STATIC VOID DumpPccSubspaceType0(IN UINT8 *Ptr, IN UINT8 Length)
Definition: PcctParser.c:421
STATIC VOID DumpPccSubspaceType3(IN UINT8 *Ptr, IN UINT8 Length)
Definition: PcctParser.c:490
STATIC VOID EFIAPI ValidatePccErrStatusGas(IN UINT8 *Ptr, IN UINT32 Length, IN VOID *Context)
Definition: PcctParser.c:225
STATIC VOID EFIAPI ValidatePccGas(IN UINT8 *Ptr, IN UINT32 Length, IN VOID *Context)
Definition: PcctParser.c:123
STATIC VOID EFIAPI ValidatePccIntAckGas(IN UINT8 *Ptr, IN UINT32 Length, IN VOID *Context)
Definition: PcctParser.c:186
STATIC VOID DumpPccSubspaceType5(IN UINT8 *Ptr, IN UINT8 Length)
Definition: PcctParser.c:536
STATIC CONST ACPI_PARSER PccSubspaceType2Parser[]
Definition: PcctParser.c:331
STATIC VOID EFIAPI ValidateRangeLength8(IN UINT8 *Ptr, IN UINT32 Length, IN VOID *Context)
Definition: PcctParser.c:66
STATIC VOID DumpPccSubspaceType4(IN UINT8 *Ptr, IN UINT8 Length)
Definition: PcctParser.c:513
STATIC CONST ACPI_PARSER PccSubspaceType1Parser[]
Definition: PcctParser.c:310
STATIC VOID EFIAPI ValidatePlatInterrupt(IN UINT8 *Ptr, IN UINT32 Length, IN VOID *Context)
Definition: PcctParser.c:250
STATIC CONST ACPI_PARSER PccSubspaceType5Parser[]
Definition: PcctParser.c:394
STATIC VOID EFIAPI ValidateRangeLength4(IN UINT8 *Ptr, IN UINT32 Length, IN VOID *Context)
Definition: PcctParser.c:38
STATIC VOID DumpPccSubspaceType2(IN UINT8 *Ptr, IN UINT8 Length)
Definition: PcctParser.c:467
STATIC VOID EFIAPI ValidatePccDoorbellGas(IN UINT8 *Ptr, IN UINT32 Length, IN VOID *Context)
Definition: PcctParser.c:153
STATIC CONST ACPI_PARSER PccSubspaceType3Parser[]
Definition: PcctParser.c:356
#define PCC_SUBSPACE_HEADER()
Definition: PcctParser.h:29
#define MAX_PCC_SUBSPACES
Definition: PcctParser.h:24
#define MIN_EXT_PCC_SUBSPACE_MEM_RANGE_LEN
Definition: PcctParser.h:19
#define MIN_MEMORY_RANGE_LENGTH
Definition: PcctParser.h:14
UINTN EFIAPI Print(IN CONST CHAR16 *Format,...)
Definition: UefiLibPrint.c:113