+ return;
+ }
+
+ InterfaceType = **InterfaceTypeParentPtr;
+
+ if (InterfaceType == EFI_ACPI_MPAM_INTERFACE_PCC) {
+ MmioSize = *((UINT32 *)Ptr);
+
+ if (MmioSize != 0) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: MMIO size should be 0 for PCC interface type. Size - %u\n",
+ MmioSize
+ );
+ }
+ }
+}
+
+/**
+ This function decodes and validates the link type for MPAM's interconnect
+ descriptor. Valid links are of NUMA and PROC type.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information. For this
+ function, context is ignored.
+ @param [in] Length Length of the field.
+**/
+STATIC
+VOID
+EFIAPI
+DecodeLinkType (
+ IN UINT8 *Ptr,
+ IN VOID *Context,
+ IN UINT32 Length
+ )
+{
+ UINT8 LinkType;
+
+ LinkType = *Ptr;
+
+ if (LinkType == EFI_ACPI_MPAM_LINK_TYPE_NUMA) {
+ Print (
+ L" (NUMA)"
+ );
+ } else if (LinkType == EFI_ACPI_MPAM_LINK_TYPE_PROC) {
+ Print (
+ L" (PROC)"
+ );
+ } else {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Invalid link type - %u\n",
+ (UINT32)LinkType
+ );
+ }
+}
+
+/**
+ This function decodes the hardware ID field present within MPAM ACPI table.
+ The specification states that the hardware ID has to be set to zero if not
+ being used.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information. For this
+ function, context is ignored.
+ @param [in] Length Length of the field.
+**/
+STATIC
+VOID
+EFIAPI
+DecodeHardwareId (
+ IN UINT8 *Ptr,
+ IN VOID *Context,
+ IN UINT32 Length
+ )
+{
+ UINT64 HardwareId;
+
+ HardwareId = *((UINT64 *)Ptr);
+
+ if (HardwareId != 0) {
+ Print (L" (");
+ Dump8Chars (NULL, Ptr, Length);
+ Print (L")");
+ }
+}
+
+/**
+ This function decodes and validates the interface type for MPAM. Valid
+ interfaces are of MMIO and PCC type.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information. For this
+ function, context is ignored.
+ @param [in] Length Length of the field.
+**/
+STATIC
+VOID
+EFIAPI
+DecodeInterfaceType (
+ IN UINT8 *Ptr,
+ IN VOID *Context,
+ IN UINT32 Length
+ )
+{
+ UINT8 InterfaceType;
+
+ InterfaceType = *Ptr;
+
+ if (InterfaceType == EFI_ACPI_MPAM_INTERFACE_MMIO) {
+ Print (L" (MMIO)");
+ } else if (InterfaceType == EFI_ACPI_MPAM_INTERFACE_PCC) {
+ Print (L" (PCC)");
+ } else {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Invalid interface type - %u\n",
+ (UINT32)InterfaceType
+ );
+ }
+}
+
+/**
+ This function decodes the interrupt mode flag for MPAM. Interrupt mode could
+ either be "edge triggered" or "level triggered".
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information. For this
+ function, context holds the parent/double pointer to a
+ variable holding the interrupt gsiv. Make sure to call
+ the function accordingly.
+ @param [in] Length Length of the field.
+**/
+STATIC
+VOID
+EFIAPI
+DecodeInterruptMode (
+ IN UINT8 *Ptr,
+ IN VOID *Context,
+ IN UINT32 Length
+ )
+{
+ UINT8 InterruptMode;
+
+ InterruptMode = *Ptr;
+
+ if (InterruptMode == EFI_ACPI_MPAM_INTERRUPT_LEVEL_TRIGGERED) {
+ Print (L" (Level triggered)");
+ } else {
+ Print (L" (Edge triggered)");
+ }
+}
+
+/**
+ This function decodes the interrupt type flag for MPAM. Interrupt type could
+ be "wired interrupt". Other values are reserved at this point.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information. For this
+ function, context holds the parent/double pointer to a
+ variable holding the interrupt gsiv. Make sure to call
+ the function accordingly.
+ @param [in] Length Length of the field.
+**/
+STATIC
+VOID
+EFIAPI
+DecodeInterruptType (
+ IN UINT8 *Ptr,
+ IN VOID *Context,
+ IN UINT32 Length
+ )
+{
+ UINT8 InterruptType;
+
+ InterruptType = *Ptr;
+
+ if (InterruptType == EFI_ACPI_MPAM_INTERRUPT_WIRED) {
+ Print (L" (Wired interrupt)");
+ } else {
+ IncrementWarningCount ();
+ Print (L" (Reserved value!)");
+ }
+}
+
+/**
+ This function decodes the interrupt affinity valid flag for MPAM. Interrupt
+ affinity could be either be valid or not.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information. For this
+ function, context holds the parent/double pointer to a
+ variable holding the interrupt gsiv. Make sure to call
+ the function accordingly.
+ @param [in] Length Length of the field.
+**/
+STATIC
+VOID
+EFIAPI
+DecodeInterruptAffinityValid (
+ IN UINT8 *Ptr,
+ IN VOID *Context,
+ IN UINT32 Length
+ )
+{
+ UINT8 InterruptAffinityValid;
+
+ InterruptAffinityValid = *Ptr;
+
+ if (InterruptAffinityValid != EFI_ACPI_MPAM_INTERRUPT_AFFINITY_VALID) {
+ Print (L" (Affinity not valid)");
+ } else {
+ Print (L" (Affinity valid)");
+ }
+}
+
+/**
+ This function decodes the interrupt affinity type flag for MPAM. Interrupt
+ affinity type could either be "Processor affinity" or "Processor container
+ affinity"
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information. For this
+ function, context holds the parent/double pointer to a
+ variable holding the interrupt gsiv. Make sure to call
+ the function accordingly.
+ @param [in] Length Length of the field.
+**/
+STATIC
+VOID
+EFIAPI
+DecodeInterruptAffinityType (
+ IN UINT8 *Ptr,
+ IN VOID *Context,
+ IN UINT32 Length
+ )
+{
+ UINT8 InterruptAffinityType;
+
+ InterruptAffinityType = *Ptr;
+
+ if (InterruptAffinityType == EFI_ACPI_MPAM_INTERRUPT_PROCESSOR_AFFINITY) {
+ Print (L" (Processor affinity)");
+ } else {
+ Print (L" (Processor container affinity)");
+ }
+}
+
+/**
+ This function decodes the locator type for a particular MPAM MSC resource.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information. For this
+ function, context holds the parent/double pointer to a
+ variable holding the interrupt gsiv. Make sure to call
+ the function accordingly.
+ @param [in] Length Length of the field.
+**/
+STATIC
+VOID
+EFIAPI
+DecodeLocatorType (
+ IN UINT8 *Ptr,
+ IN VOID *Context,
+ IN UINT32 Length
+ )
+{
+ UINT8 LocatorType;
+
+ LocatorType = *Ptr;
+
+ if (LocatorType <= EFI_ACPI_MPAM_LOCATION_INTERCONNECT) {
+ Print (L" (%s)", MpamMscLocatorTitles[LocatorType]);
+ } else if (LocatorType == EFI_ACPI_MPAM_LOCATION_UNKNOWN) {
+ Print (L" (Unknown)");
+ } else {
+ Print (L" (Reserved)");
+ }
+}
+
+/**
+ ACPI_PARSER array describing MPAM MSC interrupt flags.
+**/
+STATIC CONST ACPI_PARSER MpamMscInterruptFlagParser[] = {
+ { L"Interrupt Mode", 1, 0, L"%u", NULL, NULL,
+ DecodeInterruptMode, NULL },
+ { L"Interrupt Type", 2, 1, L"%u", NULL, NULL,
+ DecodeInterruptType, NULL },
+ { L"Affinity Type", 1, 3, L"%u", NULL, NULL,
+ DecodeInterruptAffinityType, NULL },
+ { L"Affinity Valid", 1, 4, L"%u", NULL, NULL,
+ DecodeInterruptAffinityValid, NULL },
+ { L"Reserved", 27, 5, NULL, DumpReservedBits, NULL,
+ ValidateReservedBits, NULL }
+};
+
+/**
+ This function traces MPAM MSC Interrupt Flags.
+ If no format string is specified the Format must be NULL.
+
+ @param [in] Format Optional format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the field.
+**/
+STATIC
+VOID
+EFIAPI
+DumpMpamMscInterruptFlags (
+ IN CONST CHAR16 *Format OPTIONAL,
+ IN UINT8 *Ptr,
+ IN UINT32 Length
+ )
+{
+ Print (L"%u\n", *(UINT32 *)Ptr);
+
+ ParseAcpiBitFields (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 4,
+ PARSER_PARAMS (MpamMscInterruptFlagParser)
+ );
+}
+
+/**
+ ACPI_PARSER array describing the MPAM MSC processor cache locator field.
+**/
+STATIC CONST ACPI_PARSER MpamMscProcessorCacheLocatorParser[] = {
+ { L"Cache reference", 8, 0, L"%lu", NULL, NULL, NULL, NULL },
+ { L"Reserved", 4, 8, NULL, DumpReserved, NULL,
+ ValidateReserved, NULL }
+};
+
+/**
+ ACPI_PARSER array describing the MPAM MSC memory locator field.
+**/
+STATIC CONST ACPI_PARSER MpamMscMemoryLocatorParser[] = {
+ { L"Proximity domain", 8, 0, L"%lu", NULL, NULL, NULL, NULL },
+ { L"Reserved", 4, 8, NULL, DumpReserved, NULL,
+ ValidateReserved, NULL }
+};
+
+/**
+ ACPI_PARSER array describing the MPAM MSC SMMU locator field.
+**/
+STATIC CONST ACPI_PARSER MpamMscSMMULocatorParser[] = {
+ { L"SMMU interface", 8, 0, L"%lu", NULL, NULL, NULL, NULL },
+ { L"Reserved", 4, 8, NULL, DumpReserved, NULL,
+ ValidateReserved, NULL }
+};
+
+/**
+ ACPI_PARSER array describing the MPAM MSC memory cache locator field.
+**/
+STATIC CONST ACPI_PARSER MpamMscMemoryCacheLocatorParser[] = {
+ { L"Reserved", 7, 0, NULL, DumpReserved, NULL,
+ ValidateReserved, NULL },
+ { L"Level", 1, 7, L"%u", NULL, NULL,NULL, NULL },
+ { L"Reference", 4, 8, L"%u", NULL, NULL,NULL, NULL }
+};
+
+/**
+ ACPI_PARSER array describing the MPAM MSC ACPI device locator field.
+**/
+STATIC CONST ACPI_PARSER MpamMscAcpiDeviceLocatorParser[] = {
+ { L"ACPI hardware ID", 8, 0, L"0x%lx", NULL, NULL,
+ DecodeHardwareId, NULL },
+ { L"ACPI unique ID", 4, 8, L"%u", NULL, NULL,NULL,NULL }
+};
+
+/**
+ ACPI_PARSER array describing the MPAM MSC interconnect locator field.
+**/
+STATIC CONST ACPI_PARSER MpamMscInterconnectLocatorParser[] = {
+ { L"Interconnect desc tbl offset", 8, 0, L"%lu", NULL,
+ (VOID **)&InterconnectTableOffset, NULL, NULL },
+ { L"Reserved", 4, 8, NULL, DumpReserved,
+ NULL, ValidateReserved, NULL }
+};
+
+/**
+ ACPI_PARSER array describing the MPAM MSC generic resource locator field.
+**/
+STATIC CONST ACPI_PARSER MpamMscGenericLocatorParser[] = {
+ { L"Descriptor1", 8, 0, L"%lu", NULL, NULL, NULL, NULL },
+ { L"Descriptor2", 4, 8, L"%u", NULL, NULL, NULL, NULL }
+};
+
+/**
+ This function parses the locator field within the resource node for ACPI MPAM
+ table. The parsing is based on the locator type field.
+
+ @param [in] Format Optional format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] Length Length of the field.
+**/
+STATIC
+VOID
+EFIAPI
+ParseLocator (
+ IN CONST CHAR16 *Format OPTIONAL,
+ IN UINT8 *Ptr,
+ IN UINT32 Length
+ )
+{
+ Print (L"\n");
+ switch (*ResourceLocatorType) {
+ case EFI_ACPI_MPAM_LOCATION_PROCESSOR_CACHE:
+ ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 12,
+ PARSER_PARAMS (MpamMscProcessorCacheLocatorParser)
+ );
+ break;
+ case EFI_ACPI_MPAM_LOCATION_MEMORY:
+ ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 12,
+ PARSER_PARAMS (MpamMscMemoryLocatorParser)
+ );
+ break;
+ case EFI_ACPI_MPAM_LOCATION_SMMU:
+ ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 12,
+ PARSER_PARAMS (MpamMscSMMULocatorParser)
+ );
+ break;
+ case EFI_ACPI_MPAM_LOCATION_MEMORY_CACHE:
+ ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 12,
+ PARSER_PARAMS (MpamMscMemoryCacheLocatorParser)
+ );
+ break;
+ case EFI_ACPI_MPAM_LOCATION_ACPI_DEVICE:
+ ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 12,
+ PARSER_PARAMS (MpamMscAcpiDeviceLocatorParser)
+ );
+ break;
+ case EFI_ACPI_MPAM_LOCATION_INTERCONNECT:
+ ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 12,
+ PARSER_PARAMS (MpamMscInterconnectLocatorParser)
+ );
+ break;
+ // For both UNKNOWN and RESERVED locator types, the locator is parsed using
+ // the generic locator parser as the spec does not define any format.
+ case EFI_ACPI_MPAM_LOCATION_UNKNOWN:
+ ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 12,
+ PARSER_PARAMS (MpamMscGenericLocatorParser)
+ );
+ break;
+ default:
+ Print (L"\nWARNING : Reserved locator type\n");
+ ParseAcpi (
+ TRUE,
+ 2,
+ NULL,
+ Ptr,
+ 12,
+ PARSER_PARAMS (MpamMscGenericLocatorParser)
+ );
+ IncrementWarningCount ();
+ break;
+ } // switch
+}
+
+/**
+ ACPI_PARSER array describing the Generic ACPI MPAM table header.
+**/
+STATIC CONST ACPI_PARSER MpamParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo)
+};
+
+/**
+ ACPI_PARSER array describing the MPAM MSC node object.
+**/
+STATIC CONST ACPI_PARSER MpamMscNodeParser[] = {
+ { L"Length", 2, 0, L"%u", NULL,
+ (VOID **)&MpamMscNodeLength, NULL, NULL },
+ // Once Interface type is decoded, the address of interface type field is
+ // captured into InterfaceType pointer so that it could be used to check if
+ // MMIO Size field is set as per the specification.
+ { L"Interface type", 1, 2, L"0x%x", NULL,
+ (VOID **)&MscInterfaceType, DecodeInterfaceType, NULL },
+ { L"Reserved", 1, 3, NULL, DumpReserved,
+ NULL, ValidateReserved, NULL },
+ { L"Identifier", 4, 4, L"%u", NULL,
+ NULL, NULL, NULL },
+ { L"Base address", 8, 8, L"0x%lx", NULL,
+ NULL, NULL, NULL },
+ { L"MMIO Size", 4, 16, L"0x%x", NULL,
+ NULL, ValidateMmioSize, (VOID **)&MscInterfaceType },
+ { L"Overflow interrupt", 4, 20, L"%u", NULL,
+ NULL, NULL, NULL },
+ { L"Overflow interrupt flags", 4, 24, NULL,
DumpMpamMscInterruptFlags,
+ NULL, NULL, NULL },
+ { L"Reserved1", 4, 28, NULL, DumpReserved,
+ NULL, ValidateReserved, NULL },
+ { L"Overflow interrupt affinity", 4, 32, L"0x%x", NULL,
+ NULL, NULL, NULL },
+ { L"Error interrupt", 4, 36, L"%u", NULL,
+ NULL, NULL, NULL },
+ { L"Error interrupt flags", 4, 40, NULL,
DumpMpamMscInterruptFlags,
+ NULL, NULL, NULL },
+ { L"Reserved2", 4, 44, NULL, DumpReserved,
+ NULL, ValidateReserved, NULL },
+ { L"Error interrupt affinity", 4, 48, L"0x%x", NULL,
+ NULL, NULL, NULL },
+ { L"MAX_NRDY_USEC", 4, 52, L"0x%x", NULL,
+ NULL, NULL, NULL },
+ { L"Hardware ID of linked device", 8, 56, L"0x%lx", NULL,
+ NULL, DecodeHardwareId, NULL },
+ { L"Instance ID of linked device", 4, 64, L"0x%x", NULL,
+ NULL, NULL, NULL },
+ { L"Number of resource nodes", 4, 68, L"%u", NULL,
+ (VOID **)&NumberOfMscResources, NULL, NULL }
+};
+
+/**
+ ACPI_PARSER array describing the MPAM MSC resource.
+**/
+STATIC CONST ACPI_PARSER MpamMscResourceParser[] = {
+ { L"Identifier", 4, 0, L"%u", NULL,
+ NULL, NULL, NULL },
+ { L"RIS index", 1, 4, L"%u", NULL,
+ NULL, NULL, NULL },
+ { L"Reserved1", 2, 5, NULL, DumpReserved,
+ NULL, ValidateReserved, NULL },
+ { L"Locator type", 1, 7, L"0x%x", NULL,
+ (VOID **)&ResourceLocatorType,
+ DecodeLocatorType, NULL },
+ { L"Locator", 12, 8, NULL, ParseLocator,
+ NULL, NULL, NULL },
+ { L"Number of func dependencies", 4, 20, L"%u", NULL,
+ (VOID **)&NumberOfFunctionalDependencies, NULL, NULL }
+};
+
+/**
+ ACPI_PARSER array describing the MPAM MSC resource's functional dependencies.
+**/
+STATIC CONST ACPI_PARSER MpamMscFunctionalDependencyParser[] = {
+ { L"Producer", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
+ { L"Reserved", 4, 4, NULL, DumpReserved,
+ NULL, ValidateReserved, NULL },
+};
+
+/**
+ ACPI_PARSER array describing the interconnect descriptor table associated
with
+ the interconnect locator type.
+**/
+STATIC CONST ACPI_PARSER MpamInterconnectDescriptorTableParser[] = {
+ { L"Signature", 16, 0,
+ L"%x%x%x%x-%x%x-%x%x-%x%x-%x%x%x%x%x%x", Dump16Chars, NULL, NULL, NULL },
+ { L"Number of Interconnect desc", 4, 16,L"0x%x", NULL,
+ (VOID **)&NumberOfInterconnectDescriptors, NULL, NULL }
+};
+
+/**
+ ACPI_PARSER array describing the interconnect descriptor associated with the
+ interconnect locator type.
+**/
+STATIC CONST ACPI_PARSER MpamInterconnectDescriptorParser[] = {
+ { L"Source ID", 4, 0, L"%u", NULL, NULL, NULL, NULL },
+ { L"Destination ID", 4, 4, L"%u", NULL, NULL, NULL, NULL },
+ { L"Link type", 1, 8, L"0x%x", NULL,
+ NULL, DecodeLinkType, NULL },
+ { L"Reserved", 3, 9, NULL, DumpReserved, NULL,
+ ValidateReserved, NULL }
+};
+
+/**
+ PrintBlockTitle could be used to print the title of blocks that
+ appear more than once in the MPAM ACPI table.
+
+ @param [in] Indent Number of spaces to add to the global table
+ indent. The global table indent is 0 by
+ default; however this value is updated on
+ entry to the ParseAcpi() by adding the indent
+ value provided to ParseAcpi() and restored
+ back on exit. Therefore the total indent in
+ the output is dependent on from where this
+ function is called.
+ @param [in] Title Title string to be used for the block.
+ @param [in] Index Index of the block.
+**/
+STATIC
+VOID
+EFIAPI
+PrintBlockTitle (
+ IN UINT32 Indent,
+ IN CONST CHAR16 *Title,
+ IN CONST UINT32 Index
+ )
+{
+ Print (L"\n");
+ PrintFieldName (Indent, Title);
+ Print (L"%u\n\n", Index);
+}
+
+/**
+ This function parses the interconnect descriptor(s) associated with
+ an interconnect type locator object.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in, out] Offset Pointer to current offset within Ptr.
+
+Returns:
+
+ Status
+
+ EFI_SUCCESS MPAM MSC nodes were parsed properly.
+ EFI_BAD_BUFFER_SIZE The buffer pointer provided as input is not
+ long enough to be parsed correctly.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ParseInterconnectDescriptors (
+ IN UINT8 *CONST Ptr,
+ IN CONST UINT32 AcpiTableLength,
+ IN OUT UINT32 *CONST Offset
+ )
+{
+ UINT32 InterconnectDescriptorIndex;
+
+ InterconnectDescriptorIndex = 0;
+
+ if (NumberOfInterconnectDescriptors == NULL) {
+ MpamLengthError (L"Number of interconnect descriptors not set!");
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ while (InterconnectDescriptorIndex < *NumberOfInterconnectDescriptors) {
+ PrintBlockTitle (
+ 6,
+ L"* Interconnect descriptor *",
+ InterconnectDescriptorIndex
+ );
+
+ // Parse interconnect descriptor
+ *Offset += ParseAcpi (
+ TRUE,
+ 4,
+ NULL,
+ Ptr + *Offset,
+ AcpiTableLength - *Offset,
+ PARSER_PARAMS (MpamInterconnectDescriptorParser)
+ );
+
+ InterconnectDescriptorIndex++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function parses the interconnect descriptor table associated with an
+ interconnect type locator object. It also performs necessary validation to
+ make sure the interconnect descriptor is at a valid location.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] Offset Pointer to current offset within Ptr.
+ @param [in] InterconnectOffset Offset to the interconnect descriptor table.
+
+Returns:
+
+ Status
+
+ EFI_SUCCESS MPAM MSC nodes were parsed properly.
+ EFI_BAD_BUFFER_SIZE The buffer pointer provided as input is not
+ long enough to be parsed correctly.
+ EFI_INVALID_PARAMETER The Offset parameter encoded within the Ptr
+ buffer is not valid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ParseInterconnectDescriptorTable (
+ IN UINT8 *CONST Ptr,
+ IN CONST UINT32 AcpiTableLength,
+ IN UINT32 Offset,
+ IN CONST UINT64 InterconnectOffset
+ )
+{
+ EFI_STATUS Status;
+
+ if (Offset > (MpamMscNodeStart + InterconnectOffset)) {
+ IncrementErrorCount ();
+ Print (L"\nERROR : Parsing Interconnect descriptor table failed!\n");
+ Print (
+ L"ERROR : Offset overlaps with other objects within the MSC. Offset
%u.\n",
+ InterconnectOffset
+ );
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (InterconnectOffset > (*MpamMscNodeLength)) {
+ IncrementErrorCount ();
+ Print (L"\nERROR : Parsing Interconnect descriptor table failed!\n");
+ Print (
+ L"ERROR : Offset falls outside MSC's space. Offset %u.\n",
+ InterconnectOffset
+ );
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // It is safe to cast InterconnectOffset to UINT32 as IntercconnectOffset can
+ // never exceed the MPAM table length which is at max 2 bytes.
+ Offset = MpamMscNodeStart + (UINT32)InterconnectOffset;
+
+ Print (L"\n");
+ PrintFieldName (6, L"* Interconnect desc table *");
+ Print (L"\n\n");
+
+ // Parse interconnect descriptor table
+ Offset += ParseAcpi (
+ TRUE,
+ 4,
+ NULL,
+ Ptr + Offset,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (MpamInterconnectDescriptorTableParser)
+ );
+
+ Status = ParseInterconnectDescriptors (
+ Ptr,
+ AcpiTableLength,
+ &Offset
+ );
+
+ ResourceDataSize += Offset - (MpamMscNodeStart + (UINT32)InterconnectOffset);
+ return Status;
+}
+
+/**
+ This function parses all the MPAM functional dependency nodes within a
+ single resource node.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in, out] Offset Pointer to current offset within Ptr.
+
+Returns:
+
+ Status
+
+ EFI_SUCCESS MPAM MSC nodes were parsed properly.
+ EFI_BAD_BUFFER_SIZE The buffer pointer provided as input is not
+ long enough to be parsed correctly.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ParseMpamMscFunctionalDependencies (
+ IN UINT8 *CONST Ptr,
+ IN CONST UINT32 AcpiTableLength,
+ IN OUT UINT32 *CONST Offset
+ )
+{
+ UINT32 FunctionalDependencyIndex;
+
+ FunctionalDependencyIndex = 0;
+
+ if (NumberOfFunctionalDependencies == NULL) {
+ MpamLengthError (L"Number of functional dependencies not set!");
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ while (FunctionalDependencyIndex < *NumberOfFunctionalDependencies) {
+ PrintBlockTitle (
+ 6,
+ L"* Functional dependency *",
+ FunctionalDependencyIndex
+ );
+
+ // Parse functional dependency
+ *Offset += ParseAcpi (
+ TRUE,
+ 4,
+ NULL,
+ Ptr + *Offset,
+ AcpiTableLength - *Offset,
+ PARSER_PARAMS (MpamMscFunctionalDependencyParser)
+ );
+
+ FunctionalDependencyIndex++;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function parses all the MPAM resource nodes within a single MSC
+ node within the MPAM ACPI table. It also invokes helper functions to
+ validate and parse locators and functional dependency descriptors.
+
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in, out] Offset Pointer to current offset within Ptr.
+
+Returns:
+
+ Status
+
+ EFI_SUCCESS MPAM MSC nodes were parsed properly.
+ EFI_BAD_BUFFER_SIZE The buffer pointer provided as input is not
+ long enough to be parsed correctly.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ParseMpamMscResources (
+ IN UINT8 *CONST Ptr,
+ IN CONST UINT32 AcpiTableLength,
+ IN OUT UINT32 *CONST Offset
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ResourceIndex;
+
+ ResourceIndex = 0;