mirror of https://github.com/acidanthera/audk.git
312 lines
9.0 KiB
C
312 lines
9.0 KiB
C
/** @file
|
|
DBG2 table parser
|
|
|
|
Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
@par Reference(s):
|
|
- Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015.
|
|
**/
|
|
|
|
#include <IndustryStandard/DebugPort2Table.h>
|
|
#include <Library/UefiLib.h>
|
|
#include "AcpiParser.h"
|
|
#include "AcpiTableParser.h"
|
|
|
|
// Local variables pointing to the table fields
|
|
STATIC CONST UINT32 *OffsetDbgDeviceInfo;
|
|
STATIC CONST UINT32 *NumberDbgDeviceInfo;
|
|
STATIC CONST UINT16 *DbgDevInfoLen;
|
|
STATIC CONST UINT8 *GasCount;
|
|
STATIC CONST UINT16 *NameSpaceStringLength;
|
|
STATIC CONST UINT16 *NameSpaceStringOffset;
|
|
STATIC CONST UINT16 *OEMDataLength;
|
|
STATIC CONST UINT16 *OEMDataOffset;
|
|
STATIC CONST UINT16 *BaseAddrRegOffset;
|
|
STATIC CONST UINT16 *AddrSizeOffset;
|
|
STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
|
|
|
|
/**
|
|
This function validates the NameSpace string length.
|
|
|
|
@param [in] Ptr Pointer to the start of the buffer.
|
|
@param [in] Context Pointer to context specific information e.g. this
|
|
could be a pointer to the ACPI table header.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
EFIAPI
|
|
ValidateNameSpaceStrLen (
|
|
IN UINT8 *Ptr,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
UINT16 NameSpaceStrLen;
|
|
|
|
NameSpaceStrLen = *(UINT16 *)Ptr;
|
|
|
|
if (NameSpaceStrLen < 2) {
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"\nERROR: NamespaceString Length = %d. If no Namespace device exists, " \
|
|
L"NamespaceString[] must contain a period '.'",
|
|
NameSpaceStrLen
|
|
);
|
|
}
|
|
}
|
|
|
|
/// An ACPI_PARSER array describing the ACPI DBG2 table.
|
|
STATIC CONST ACPI_PARSER Dbg2Parser[] = {
|
|
PARSE_ACPI_HEADER (&AcpiHdrInfo),
|
|
{ L"OffsetDbgDeviceInfo", 4, 36, L"0x%x", NULL,
|
|
(VOID **)&OffsetDbgDeviceInfo, NULL, NULL },
|
|
{ L"NumberDbgDeviceInfo", 4, 40, L"%d", NULL,
|
|
(VOID **)&NumberDbgDeviceInfo, NULL, NULL }
|
|
};
|
|
|
|
/// An ACPI_PARSER array describing the debug device information structure
|
|
/// header.
|
|
STATIC CONST ACPI_PARSER DbgDevInfoHeaderParser[] = {
|
|
{ L"Revision", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
|
|
{ L"Length", 2, 1, L"%d", NULL, (VOID **)&DbgDevInfoLen, NULL, NULL }
|
|
};
|
|
|
|
/// An ACPI_PARSER array describing the debug device information.
|
|
STATIC CONST ACPI_PARSER DbgDevInfoParser[] = {
|
|
{ L"Revision", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
|
|
{ L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL },
|
|
|
|
{ L"Generic Address Registers Count", 1, 3, L"0x%x", NULL,
|
|
(VOID **)&GasCount, NULL, NULL },
|
|
{ L"NameSpace String Length", 2, 4, L"%d", NULL,
|
|
(VOID **)&NameSpaceStringLength, ValidateNameSpaceStrLen, NULL },
|
|
{ L"NameSpace String Offset", 2, 6, L"0x%x", NULL,
|
|
(VOID **)&NameSpaceStringOffset, NULL, NULL },
|
|
{ L"OEM Data Length", 2, 8, L"%d", NULL, (VOID **)&OEMDataLength,
|
|
NULL, NULL },
|
|
{ L"OEM Data Offset", 2, 10, L"0x%x", NULL, (VOID **)&OEMDataOffset,
|
|
NULL, NULL },
|
|
|
|
{ L"Port Type", 2, 12, L"0x%x", NULL, NULL, NULL, NULL },
|
|
{ L"Port SubType", 2, 14, L"0x%x", NULL, NULL, NULL, NULL },
|
|
{ L"Reserved", 2, 16, L"%x", NULL, NULL, NULL, NULL },
|
|
|
|
{ L"Base Address Register Offset", 2, 18, L"0x%x", NULL,
|
|
(VOID **)&BaseAddrRegOffset, NULL, NULL },
|
|
{ L"Address Size Offset", 2, 20, L"0x%x", NULL,
|
|
(VOID **)&AddrSizeOffset, NULL, NULL }
|
|
};
|
|
|
|
/**
|
|
This function parses the debug device information structure.
|
|
|
|
@param [in] Ptr Pointer to the start of the buffer.
|
|
@param [in] Length Length of the debug device information structure.
|
|
**/
|
|
STATIC
|
|
VOID
|
|
EFIAPI
|
|
DumpDbgDeviceInfo (
|
|
IN UINT8 *Ptr,
|
|
IN UINT16 Length
|
|
)
|
|
{
|
|
UINT16 Index;
|
|
UINT16 Offset;
|
|
|
|
ParseAcpi (
|
|
TRUE,
|
|
2,
|
|
"Debug Device Info",
|
|
Ptr,
|
|
Length,
|
|
PARSER_PARAMS (DbgDevInfoParser)
|
|
);
|
|
|
|
// Check if the values used to control the parsing logic have been
|
|
// successfully read.
|
|
if ((GasCount == NULL) ||
|
|
(NameSpaceStringLength == NULL) ||
|
|
(NameSpaceStringOffset == NULL) ||
|
|
(OEMDataLength == NULL) ||
|
|
(OEMDataOffset == NULL) ||
|
|
(BaseAddrRegOffset == NULL) ||
|
|
(AddrSizeOffset == NULL))
|
|
{
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"ERROR: Insufficient Debug Device Information Structure length. " \
|
|
L"Length = %d.\n",
|
|
Length
|
|
);
|
|
return;
|
|
}
|
|
|
|
// GAS
|
|
Index = 0;
|
|
Offset = *BaseAddrRegOffset;
|
|
while ((Index++ < *GasCount) &&
|
|
(Offset < Length))
|
|
{
|
|
PrintFieldName (4, L"BaseAddressRegister");
|
|
Offset += (UINT16)DumpGasStruct (
|
|
Ptr + Offset,
|
|
4,
|
|
Length - Offset
|
|
);
|
|
}
|
|
|
|
// Make sure the array of address sizes corresponding to each GAS fit in the
|
|
// Debug Device Information structure
|
|
if ((*AddrSizeOffset + (*GasCount * sizeof (UINT32))) > Length) {
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"ERROR: Invalid GAS count. GasCount = %d. RemainingBufferLength = %d. " \
|
|
L"Parsing of the Debug Device Information structure aborted.\n",
|
|
*GasCount,
|
|
Length - *AddrSizeOffset
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Address Size
|
|
Index = 0;
|
|
Offset = *AddrSizeOffset;
|
|
while ((Index++ < *GasCount) &&
|
|
(Offset < Length))
|
|
{
|
|
PrintFieldName (4, L"Address Size");
|
|
Print (L"0x%x\n", *((UINT32 *)(Ptr + Offset)));
|
|
Offset += sizeof (UINT32);
|
|
}
|
|
|
|
// NameSpace String
|
|
Index = 0;
|
|
Offset = *NameSpaceStringOffset;
|
|
PrintFieldName (4, L"NameSpace String");
|
|
while ((Index++ < *NameSpaceStringLength) &&
|
|
(Offset < Length))
|
|
{
|
|
Print (L"%c", *(Ptr + Offset));
|
|
Offset++;
|
|
}
|
|
|
|
Print (L"\n");
|
|
|
|
// OEM Data
|
|
if (*OEMDataOffset != 0) {
|
|
Index = 0;
|
|
Offset = *OEMDataOffset;
|
|
PrintFieldName (4, L"OEM Data");
|
|
while ((Index++ < *OEMDataLength) &&
|
|
(Offset < Length))
|
|
{
|
|
Print (L"%x ", *(Ptr + Offset));
|
|
if ((Index & 7) == 0) {
|
|
Print (L"\n%-*s ", OUTPUT_FIELD_COLUMN_WIDTH, L"");
|
|
}
|
|
|
|
Offset++;
|
|
}
|
|
|
|
Print (L"\n");
|
|
}
|
|
}
|
|
|
|
/**
|
|
This function parses the ACPI DBG2 table.
|
|
When trace is enabled this function parses the DBG2 table and
|
|
traces the ACPI table fields.
|
|
|
|
This function also performs validation of the ACPI table fields.
|
|
|
|
@param [in] Trace If TRUE, trace the ACPI fields.
|
|
@param [in] Ptr Pointer to the start of the buffer.
|
|
@param [in] AcpiTableLength Length of the ACPI table.
|
|
@param [in] AcpiTableRevision Revision of the ACPI table.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
ParseAcpiDbg2 (
|
|
IN BOOLEAN Trace,
|
|
IN UINT8 *Ptr,
|
|
IN UINT32 AcpiTableLength,
|
|
IN UINT8 AcpiTableRevision
|
|
)
|
|
{
|
|
UINT32 Offset;
|
|
UINT32 Index;
|
|
|
|
if (!Trace) {
|
|
return;
|
|
}
|
|
|
|
Offset = ParseAcpi (
|
|
TRUE,
|
|
0,
|
|
"DBG2",
|
|
Ptr,
|
|
AcpiTableLength,
|
|
PARSER_PARAMS (Dbg2Parser)
|
|
);
|
|
|
|
// Check if the values used to control the parsing logic have been
|
|
// successfully read.
|
|
if ((OffsetDbgDeviceInfo == NULL) ||
|
|
(NumberDbgDeviceInfo == NULL))
|
|
{
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"ERROR: Insufficient table length. AcpiTableLength = %d\n",
|
|
AcpiTableLength
|
|
);
|
|
return;
|
|
}
|
|
|
|
Offset = *OffsetDbgDeviceInfo;
|
|
Index = 0;
|
|
|
|
while (Index++ < *NumberDbgDeviceInfo) {
|
|
// Parse the Debug Device Information Structure header to obtain Length
|
|
ParseAcpi (
|
|
FALSE,
|
|
0,
|
|
NULL,
|
|
Ptr + Offset,
|
|
AcpiTableLength - Offset,
|
|
PARSER_PARAMS (DbgDevInfoHeaderParser)
|
|
);
|
|
|
|
// Check if the values used to control the parsing logic have been
|
|
// successfully read.
|
|
if (DbgDevInfoLen == NULL) {
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"ERROR: Insufficient remaining table buffer length to read the " \
|
|
L"Debug Device Information structure's 'Length' field. " \
|
|
L"RemainingTableBufferLength = %d.\n",
|
|
AcpiTableLength - Offset
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Validate Debug Device Information Structure length
|
|
if ((*DbgDevInfoLen == 0) ||
|
|
((Offset + (*DbgDevInfoLen)) > AcpiTableLength))
|
|
{
|
|
IncrementErrorCount ();
|
|
Print (
|
|
L"ERROR: Invalid Debug Device Information Structure length. " \
|
|
L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
|
|
*DbgDevInfoLen,
|
|
Offset,
|
|
AcpiTableLength
|
|
);
|
|
return;
|
|
}
|
|
|
|
DumpDbgDeviceInfo (Ptr + Offset, (*DbgDevInfoLen));
|
|
Offset += (*DbgDevInfoLen);
|
|
}
|
|
}
|