Patchwork [3/3] acpi: acpidump: add DBG2 table (LP: #1260356)

login
register
mail settings
Submitter Colin King
Date Dec. 12, 2013, 2:57 p.m.
Message ID <1386860225-1666-3-git-send-email-colin.king@canonical.com>
Download mbox | patch
Permalink /patch/300678/
State Accepted
Headers show

Comments

Colin King - Dec. 12, 2013, 2:57 p.m.
From: Colin Ian King <colin.king@canonical.com>

Add support for the Debug Port Table 2.  We need to add a zero terminated
string dump helper acpi_dump_strz and fix acpi_dump_gas to include the GAS
offset rather than assuming it is zero.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 src/acpi/acpidump/acpidump.c | 127 ++++++++++++++++++++++++++++++++++++++++++-
 src/lib/include/fwts_acpi.h  |  21 +++++++
 2 files changed, 146 insertions(+), 2 deletions(-)
Ivan Hu - Dec. 16, 2013, 3:13 a.m.
On 12/12/2013 10:57 PM, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> Add support for the Debug Port Table 2.  We need to add a zero terminated
> string dump helper acpi_dump_strz and fix acpi_dump_gas to include the GAS
> offset rather than assuming it is zero.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
>   src/acpi/acpidump/acpidump.c | 127 ++++++++++++++++++++++++++++++++++++++++++-
>   src/lib/include/fwts_acpi.h  |  21 +++++++
>   2 files changed, 146 insertions(+), 2 deletions(-)
>
> diff --git a/src/acpi/acpidump/acpidump.c b/src/acpi/acpidump/acpidump.c
> index 9163a1b..c89690d 100644
> --- a/src/acpi/acpidump/acpidump.c
> +++ b/src/acpi/acpidump/acpidump.c
> @@ -66,6 +66,9 @@ typedef struct fwts_acpidump_field {
>   #define FIELD_STR(text, type, field)			\
>   	FIELD(text, type, field, acpi_dump_str, 0, 0, NULL, 0, NULL)
>
> +#define FIELD_STRZ(text, type, field)			\
> +	FIELD(text, type, field, acpi_dump_strz, 0, 0, NULL, 0, NULL)
> +
>   #define FIELD_STRS(text, type, field, strings, strings_len)			\
>   	FIELD(text, type, field, acpi_dump_strings, 0, 0, strings, strings_len, NULL)
>
> @@ -107,6 +110,17 @@ static void acpi_dump_str(
>   		info->size, info->size, (char *)data);
>   }
>
> +static void acpi_dump_strz(
> +	fwts_framework *fw,
> +	const fwts_acpidump_field *info,
> +	const void *data,
> +	const int offset)
> +{
> +	fwts_log_info_verbatum(fw, "%s %s",
> +		acpi_dump_field_info(info->label, strlen(data) + 1, info->offset + offset),
> +		(char *)data);
> +}
> +
>   static uint64_t apci_dump_get_uint64_t(
>   	const fwts_acpidump_field *info,
>   	const void *data)
> @@ -354,9 +368,9 @@ static void acpi_dump_gas(
>
>   	fwts_log_nl(fw);
>   	fwts_log_info_verbatum(fw, "%s (Generic Address Structure)",
> -		acpi_dump_field_info(info->label, info->size, info->offset));
> +		acpi_dump_field_info(info->label, info->size, offset + info->offset));
>   	
> -	__acpi_dump_table_fields(fw, data, fields, info->offset);
> +	__acpi_dump_table_fields(fw, data, fields, offset + info->offset);
>   }
>
>   static void acpidump_hdr(
> @@ -1728,6 +1742,114 @@ static void acpidump_dbgp(fwts_framework *fw, const fwts_acpi_table_info *table)
>   	acpi_dump_table_fields(fw, table->data, dbgp_fields, 0, table->length);
>   }
>
> +/*
> + *  acpidump_dbg2()
> + *	dump dbg2, debug port table
> + */
> +static void acpidump_dbg2(fwts_framework *fw, const fwts_acpi_table_info *table)
> +{
> +	fwts_acpi_table_dbg2 *dbg2 = (fwts_acpi_table_dbg2 *)table->data;
> +	uint32_t i;
> +	size_t offset;
> +
> +	typedef struct {
> +		fwts_acpi_gas	addr;
> +	} gas_addr;
> +
> +	typedef struct {
> +		uint32_t	size;
> +	} addr_size;
> +
> +	typedef struct {
> +		char		*path;
> +	} namespace;
> +
> +	static const fwts_acpidump_field dbg2_fields[] = {
> +		FIELD_UINT("Info Offset", 		fwts_acpi_table_dbg2, info_offset),
> +		FIELD_UINT("Info Count", 		fwts_acpi_table_dbg2, info_count),
> +		FIELD_END
> +	};
> +
> +	static const fwts_acpidump_field dbg2_info_fields[] = {
> +		FIELD_UINT("Revision", 			fwts_acpi_table_dbg2_info, revision),
> +		FIELD_UINT("Length", 			fwts_acpi_table_dbg2_info, length),
> +		FIELD_UINT("Register Count",		fwts_acpi_table_dbg2_info, number_of_regs),
> +		FIELD_UINT("Namespace Length", 		fwts_acpi_table_dbg2_info, namespace_length),
> +		FIELD_UINT("Namespace Offset",		fwts_acpi_table_dbg2_info, namespace_offset),
> +		FIELD_UINT("OEM Data Length", 		fwts_acpi_table_dbg2_info, oem_data_length),
> +		FIELD_UINT("OEM Data Offset",		fwts_acpi_table_dbg2_info, oem_data_offset),
> +		FIELD_UINT("Port Type", 		fwts_acpi_table_dbg2_info, port_type),
> +		FIELD_UINT("Port Subtype",		fwts_acpi_table_dbg2_info, port_subtype),
> +		FIELD_UINT("Reserved",			fwts_acpi_table_dbg2_info, reserved),
> +		FIELD_UINT("Base Address Offset",	fwts_acpi_table_dbg2_info, base_address_offset),
> +		FIELD_UINT("Address Size Offset", 	fwts_acpi_table_dbg2_info, address_size_offset),
> +		FIELD_END
> +	};
> +
> +	static const fwts_acpidump_field dbg2_gas_fields[] = {
> +		FIELD_GAS ("Base Address Register",	gas_addr, addr),
> +		FIELD_END
> +	};
> +
> +	static const fwts_acpidump_field dbg2_addr_fields[] = {
> +		FIELD_UINT("Address Size", 		addr_size, size),
> +		FIELD_END
> +	};
> +
> +	static const fwts_acpidump_field dbg2_namespace_fields[] = {
> +		FIELD_STRZ("Namepath", 			namespace, path),
> +		FIELD_END
> +	};
> +
> +	acpi_dump_table_fields(fw, table->data, dbg2_fields, 0, table->length);
> +	fwts_log_nl(fw);
> +
> +	offset = dbg2->info_offset;
> +
> +	/* Dump out info_count number of instances */
> +	for (i = 0; i < dbg2->info_count; i++) {
> +		uint32_t j;
> +		fwts_acpi_table_dbg2_info *dbg2_info = (fwts_acpi_table_dbg2_info *)(table->data + offset);
> +		uint8_t *base_addr_regs = (uint8_t *)dbg2_info + dbg2_info->base_address_offset;
> +		uint8_t *address_size   = (uint8_t *)dbg2_info + dbg2_info->address_size_offset;
> +		uint8_t *namespace_str  = (uint8_t *)dbg2_info + dbg2_info->namespace_offset;
> +		uint8_t *oem_data       = (uint8_t *)dbg2_info + dbg2_info->oem_data_offset;
> +
> +		__acpi_dump_table_fields(fw, table->data + offset, dbg2_info_fields, offset);
> +
> +		if (dbg2_info->number_of_regs) {
> +			/* Dump out the register GAS and sizes */
> +			for (j = 0; j < dbg2_info->number_of_regs; j++) {
> +				__acpi_dump_table_fields(fw, &base_addr_regs[j], dbg2_gas_fields,
> +					(void*)&base_addr_regs[j] - table->data);
> +			}
> +			fwts_log_nl(fw);
> +
> +			for (j = 0; j < dbg2_info->number_of_regs; j++)
> +				acpi_dump_uint(fw, dbg2_addr_fields, &address_size[j],
> +					(void *)&address_size[j] - table->data);
> +			fwts_log_nl(fw);
> +
> +		}
> +		/* Do we have a namespace to dump? */
> +		if (dbg2_info->namespace_offset)
> +			acpi_dump_strz(fw, dbg2_namespace_fields, namespace_str,
> +				(void *)namespace_str - table->data);
> +
> +		/* And dump any OEM specific data */
> +		if (dbg2_info->oem_data_length) {
> +			fwts_log_nl(fw);
> +			fwts_log_info_verbatum(fw, "OEM Data:");
> +			acpi_dump_raw_data(fw, oem_data, dbg2_info->oem_data_length,
> +				(void *)oem_data - table->data);
> +		}
> +
> +		offset += dbg2_info->length;
> +		if (offset > table->length)
> +			break;
> +	}
> +}
> +
>   typedef struct {
>   	const char *name;
>   	void (*func)(fwts_framework *fw, const fwts_acpi_table_info *table);
> @@ -1747,6 +1869,7 @@ static const acpidump_table_vec table_vec[] = {
>   	{ "BGRT", 	acpidump_bgrt, 	1 },
>   	{ "BOOT", 	acpidump_boot, 	1 },
>   	{ "CPEP", 	acpidump_cpep, 	1 },
> +	{ "DBG2", 	acpidump_dbg2,	1 },
>   	{ "DBGP", 	acpidump_dbgp,	1 },
>   	{ "DSDT", 	acpidump_amlcode, 1 },
>   	{ "DMAR", 	acpidump_dmar,	1 },
> diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h
> index 009e5ac..34619bd 100644
> --- a/src/lib/include/fwts_acpi.h
> +++ b/src/lib/include/fwts_acpi.h
> @@ -712,6 +712,27 @@ typedef struct {
>   	fwts_acpi_gas	base_address;
>   } __attribute__ ((packed)) fwts_acpi_table_dbgp;
>
> +typedef struct {
> +	fwts_acpi_table_header	header;
> +	uint32_t	info_offset;
> +	uint32_t	info_count;
> +} __attribute__ ((packed)) fwts_acpi_table_dbg2;
> +
> +typedef struct {
> +	uint8_t		revision;
> +	uint16_t	length;
> +	uint8_t		number_of_regs;
> +	uint16_t	namespace_length;
> +	uint16_t	namespace_offset;
> +	uint16_t	oem_data_length;
> +	uint16_t	oem_data_offset;
> +	uint16_t	port_type;
> +	uint16_t	port_subtype;
> +	uint16_t	reserved;
> +	uint16_t	base_address_offset;
> +	uint16_t	address_size_offset;
> +} __attribute__ ((packed)) fwts_acpi_table_dbg2_info;
> +
>   void fwts_acpi_table_get_header(fwts_acpi_table_header *hdr, uint8_t *data);
>
>   #endif
>

Acked-by: Ivan Hu <ivan.hu@canonical.com>
Keng-Yu Lin - Dec. 20, 2013, 9:12 a.m.
On Mon, Dec 16, 2013 at 11:13 AM, IvanHu <ivan.hu@canonical.com> wrote:
> On 12/12/2013 10:57 PM, Colin King wrote:
>>
>> From: Colin Ian King <colin.king@canonical.com>
>>
>> Add support for the Debug Port Table 2.  We need to add a zero terminated
>> string dump helper acpi_dump_strz and fix acpi_dump_gas to include the GAS
>> offset rather than assuming it is zero.
>>
>> Signed-off-by: Colin Ian King <colin.king@canonical.com>
>> ---
>>   src/acpi/acpidump/acpidump.c | 127
>> ++++++++++++++++++++++++++++++++++++++++++-
>>   src/lib/include/fwts_acpi.h  |  21 +++++++
>>   2 files changed, 146 insertions(+), 2 deletions(-)
>>
>> diff --git a/src/acpi/acpidump/acpidump.c b/src/acpi/acpidump/acpidump.c
>> index 9163a1b..c89690d 100644
>> --- a/src/acpi/acpidump/acpidump.c
>> +++ b/src/acpi/acpidump/acpidump.c
>> @@ -66,6 +66,9 @@ typedef struct fwts_acpidump_field {
>>   #define FIELD_STR(text, type, field)                  \
>>         FIELD(text, type, field, acpi_dump_str, 0, 0, NULL, 0, NULL)
>>
>> +#define FIELD_STRZ(text, type, field)                  \
>> +       FIELD(text, type, field, acpi_dump_strz, 0, 0, NULL, 0, NULL)
>> +
>>   #define FIELD_STRS(text, type, field, strings, strings_len)
>> \
>>         FIELD(text, type, field, acpi_dump_strings, 0, 0, strings,
>> strings_len, NULL)
>>
>> @@ -107,6 +110,17 @@ static void acpi_dump_str(
>>                 info->size, info->size, (char *)data);
>>   }
>>
>> +static void acpi_dump_strz(
>> +       fwts_framework *fw,
>> +       const fwts_acpidump_field *info,
>> +       const void *data,
>> +       const int offset)
>> +{
>> +       fwts_log_info_verbatum(fw, "%s %s",
>> +               acpi_dump_field_info(info->label, strlen(data) + 1,
>> info->offset + offset),
>> +               (char *)data);
>> +}
>> +
>>   static uint64_t apci_dump_get_uint64_t(
>>         const fwts_acpidump_field *info,
>>         const void *data)
>> @@ -354,9 +368,9 @@ static void acpi_dump_gas(
>>
>>         fwts_log_nl(fw);
>>         fwts_log_info_verbatum(fw, "%s (Generic Address Structure)",
>> -               acpi_dump_field_info(info->label, info->size,
>> info->offset));
>> +               acpi_dump_field_info(info->label, info->size, offset +
>> info->offset));
>>
>> -       __acpi_dump_table_fields(fw, data, fields, info->offset);
>> +       __acpi_dump_table_fields(fw, data, fields, offset + info->offset);
>>   }
>>
>>   static void acpidump_hdr(
>> @@ -1728,6 +1742,114 @@ static void acpidump_dbgp(fwts_framework *fw,
>> const fwts_acpi_table_info *table)
>>         acpi_dump_table_fields(fw, table->data, dbgp_fields, 0,
>> table->length);
>>   }
>>
>> +/*
>> + *  acpidump_dbg2()
>> + *     dump dbg2, debug port table
>> + */
>> +static void acpidump_dbg2(fwts_framework *fw, const fwts_acpi_table_info
>> *table)
>> +{
>> +       fwts_acpi_table_dbg2 *dbg2 = (fwts_acpi_table_dbg2 *)table->data;
>> +       uint32_t i;
>> +       size_t offset;
>> +
>> +       typedef struct {
>> +               fwts_acpi_gas   addr;
>> +       } gas_addr;
>> +
>> +       typedef struct {
>> +               uint32_t        size;
>> +       } addr_size;
>> +
>> +       typedef struct {
>> +               char            *path;
>> +       } namespace;
>> +
>> +       static const fwts_acpidump_field dbg2_fields[] = {
>> +               FIELD_UINT("Info Offset",
>> fwts_acpi_table_dbg2, info_offset),
>> +               FIELD_UINT("Info Count",
>> fwts_acpi_table_dbg2, info_count),
>> +               FIELD_END
>> +       };
>> +
>> +       static const fwts_acpidump_field dbg2_info_fields[] = {
>> +               FIELD_UINT("Revision",
>> fwts_acpi_table_dbg2_info, revision),
>> +               FIELD_UINT("Length",
>> fwts_acpi_table_dbg2_info, length),
>> +               FIELD_UINT("Register Count",
>> fwts_acpi_table_dbg2_info, number_of_regs),
>> +               FIELD_UINT("Namespace Length",
>> fwts_acpi_table_dbg2_info, namespace_length),
>> +               FIELD_UINT("Namespace Offset",
>> fwts_acpi_table_dbg2_info, namespace_offset),
>> +               FIELD_UINT("OEM Data Length",
>> fwts_acpi_table_dbg2_info, oem_data_length),
>> +               FIELD_UINT("OEM Data Offset",
>> fwts_acpi_table_dbg2_info, oem_data_offset),
>> +               FIELD_UINT("Port Type",
>> fwts_acpi_table_dbg2_info, port_type),
>> +               FIELD_UINT("Port Subtype",
>> fwts_acpi_table_dbg2_info, port_subtype),
>> +               FIELD_UINT("Reserved",
>> fwts_acpi_table_dbg2_info, reserved),
>> +               FIELD_UINT("Base Address Offset",
>> fwts_acpi_table_dbg2_info, base_address_offset),
>> +               FIELD_UINT("Address Size Offset",
>> fwts_acpi_table_dbg2_info, address_size_offset),
>> +               FIELD_END
>> +       };
>> +
>> +       static const fwts_acpidump_field dbg2_gas_fields[] = {
>> +               FIELD_GAS ("Base Address Register",     gas_addr, addr),
>> +               FIELD_END
>> +       };
>> +
>> +       static const fwts_acpidump_field dbg2_addr_fields[] = {
>> +               FIELD_UINT("Address Size",              addr_size, size),
>> +               FIELD_END
>> +       };
>> +
>> +       static const fwts_acpidump_field dbg2_namespace_fields[] = {
>> +               FIELD_STRZ("Namepath",                  namespace, path),
>> +               FIELD_END
>> +       };
>> +
>> +       acpi_dump_table_fields(fw, table->data, dbg2_fields, 0,
>> table->length);
>> +       fwts_log_nl(fw);
>> +
>> +       offset = dbg2->info_offset;
>> +
>> +       /* Dump out info_count number of instances */
>> +       for (i = 0; i < dbg2->info_count; i++) {
>> +               uint32_t j;
>> +               fwts_acpi_table_dbg2_info *dbg2_info =
>> (fwts_acpi_table_dbg2_info *)(table->data + offset);
>> +               uint8_t *base_addr_regs = (uint8_t *)dbg2_info +
>> dbg2_info->base_address_offset;
>> +               uint8_t *address_size   = (uint8_t *)dbg2_info +
>> dbg2_info->address_size_offset;
>> +               uint8_t *namespace_str  = (uint8_t *)dbg2_info +
>> dbg2_info->namespace_offset;
>> +               uint8_t *oem_data       = (uint8_t *)dbg2_info +
>> dbg2_info->oem_data_offset;
>> +
>> +               __acpi_dump_table_fields(fw, table->data + offset,
>> dbg2_info_fields, offset);
>> +
>> +               if (dbg2_info->number_of_regs) {
>> +                       /* Dump out the register GAS and sizes */
>> +                       for (j = 0; j < dbg2_info->number_of_regs; j++) {
>> +                               __acpi_dump_table_fields(fw,
>> &base_addr_regs[j], dbg2_gas_fields,
>> +                                       (void*)&base_addr_regs[j] -
>> table->data);
>> +                       }
>> +                       fwts_log_nl(fw);
>> +
>> +                       for (j = 0; j < dbg2_info->number_of_regs; j++)
>> +                               acpi_dump_uint(fw, dbg2_addr_fields,
>> &address_size[j],
>> +                                       (void *)&address_size[j] -
>> table->data);
>> +                       fwts_log_nl(fw);
>> +
>> +               }
>> +               /* Do we have a namespace to dump? */
>> +               if (dbg2_info->namespace_offset)
>> +                       acpi_dump_strz(fw, dbg2_namespace_fields,
>> namespace_str,
>> +                               (void *)namespace_str - table->data);
>> +
>> +               /* And dump any OEM specific data */
>> +               if (dbg2_info->oem_data_length) {
>> +                       fwts_log_nl(fw);
>> +                       fwts_log_info_verbatum(fw, "OEM Data:");
>> +                       acpi_dump_raw_data(fw, oem_data,
>> dbg2_info->oem_data_length,
>> +                               (void *)oem_data - table->data);
>> +               }
>> +
>> +               offset += dbg2_info->length;
>> +               if (offset > table->length)
>> +                       break;
>> +       }
>> +}
>> +
>>   typedef struct {
>>         const char *name;
>>         void (*func)(fwts_framework *fw, const fwts_acpi_table_info
>> *table);
>> @@ -1747,6 +1869,7 @@ static const acpidump_table_vec table_vec[] = {
>>         { "BGRT",       acpidump_bgrt,  1 },
>>         { "BOOT",       acpidump_boot,  1 },
>>         { "CPEP",       acpidump_cpep,  1 },
>> +       { "DBG2",       acpidump_dbg2,  1 },
>>         { "DBGP",       acpidump_dbgp,  1 },
>>         { "DSDT",       acpidump_amlcode, 1 },
>>         { "DMAR",       acpidump_dmar,  1 },
>> diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h
>> index 009e5ac..34619bd 100644
>> --- a/src/lib/include/fwts_acpi.h
>> +++ b/src/lib/include/fwts_acpi.h
>> @@ -712,6 +712,27 @@ typedef struct {
>>         fwts_acpi_gas   base_address;
>>   } __attribute__ ((packed)) fwts_acpi_table_dbgp;
>>
>> +typedef struct {
>> +       fwts_acpi_table_header  header;
>> +       uint32_t        info_offset;
>> +       uint32_t        info_count;
>> +} __attribute__ ((packed)) fwts_acpi_table_dbg2;
>> +
>> +typedef struct {
>> +       uint8_t         revision;
>> +       uint16_t        length;
>> +       uint8_t         number_of_regs;
>> +       uint16_t        namespace_length;
>> +       uint16_t        namespace_offset;
>> +       uint16_t        oem_data_length;
>> +       uint16_t        oem_data_offset;
>> +       uint16_t        port_type;
>> +       uint16_t        port_subtype;
>> +       uint16_t        reserved;
>> +       uint16_t        base_address_offset;
>> +       uint16_t        address_size_offset;
>> +} __attribute__ ((packed)) fwts_acpi_table_dbg2_info;
>> +
>>   void fwts_acpi_table_get_header(fwts_acpi_table_header *hdr, uint8_t
>> *data);
>>
>>   #endif
>>
>
> Acked-by: Ivan Hu <ivan.hu@canonical.com>
>

Acked-by: Keng-Yu Lin <kengyu@canonical.com>

Patch

diff --git a/src/acpi/acpidump/acpidump.c b/src/acpi/acpidump/acpidump.c
index 9163a1b..c89690d 100644
--- a/src/acpi/acpidump/acpidump.c
+++ b/src/acpi/acpidump/acpidump.c
@@ -66,6 +66,9 @@  typedef struct fwts_acpidump_field {
 #define FIELD_STR(text, type, field)			\
 	FIELD(text, type, field, acpi_dump_str, 0, 0, NULL, 0, NULL)
 
+#define FIELD_STRZ(text, type, field)			\
+	FIELD(text, type, field, acpi_dump_strz, 0, 0, NULL, 0, NULL)
+
 #define FIELD_STRS(text, type, field, strings, strings_len)			\
 	FIELD(text, type, field, acpi_dump_strings, 0, 0, strings, strings_len, NULL)
 
@@ -107,6 +110,17 @@  static void acpi_dump_str(
 		info->size, info->size, (char *)data);
 }
 
+static void acpi_dump_strz(
+	fwts_framework *fw,
+	const fwts_acpidump_field *info,
+	const void *data,
+	const int offset)
+{
+	fwts_log_info_verbatum(fw, "%s %s",
+		acpi_dump_field_info(info->label, strlen(data) + 1, info->offset + offset),
+		(char *)data);
+}
+
 static uint64_t apci_dump_get_uint64_t(
 	const fwts_acpidump_field *info,
 	const void *data)
@@ -354,9 +368,9 @@  static void acpi_dump_gas(
 
 	fwts_log_nl(fw);
 	fwts_log_info_verbatum(fw, "%s (Generic Address Structure)",
-		acpi_dump_field_info(info->label, info->size, info->offset));
+		acpi_dump_field_info(info->label, info->size, offset + info->offset));
 	
-	__acpi_dump_table_fields(fw, data, fields, info->offset);
+	__acpi_dump_table_fields(fw, data, fields, offset + info->offset);
 }
 
 static void acpidump_hdr(
@@ -1728,6 +1742,114 @@  static void acpidump_dbgp(fwts_framework *fw, const fwts_acpi_table_info *table)
 	acpi_dump_table_fields(fw, table->data, dbgp_fields, 0, table->length);
 }
 
+/*
+ *  acpidump_dbg2()
+ *	dump dbg2, debug port table
+ */
+static void acpidump_dbg2(fwts_framework *fw, const fwts_acpi_table_info *table)
+{
+	fwts_acpi_table_dbg2 *dbg2 = (fwts_acpi_table_dbg2 *)table->data;
+	uint32_t i;
+	size_t offset;
+
+	typedef struct {
+		fwts_acpi_gas	addr;
+	} gas_addr;
+
+	typedef struct {
+		uint32_t	size;
+	} addr_size;
+
+	typedef struct {
+		char		*path;
+	} namespace;
+
+	static const fwts_acpidump_field dbg2_fields[] = {
+		FIELD_UINT("Info Offset", 		fwts_acpi_table_dbg2, info_offset),
+		FIELD_UINT("Info Count", 		fwts_acpi_table_dbg2, info_count),
+		FIELD_END
+	};
+
+	static const fwts_acpidump_field dbg2_info_fields[] = {
+		FIELD_UINT("Revision", 			fwts_acpi_table_dbg2_info, revision),
+		FIELD_UINT("Length", 			fwts_acpi_table_dbg2_info, length),
+		FIELD_UINT("Register Count",		fwts_acpi_table_dbg2_info, number_of_regs),
+		FIELD_UINT("Namespace Length", 		fwts_acpi_table_dbg2_info, namespace_length),
+		FIELD_UINT("Namespace Offset",		fwts_acpi_table_dbg2_info, namespace_offset),
+		FIELD_UINT("OEM Data Length", 		fwts_acpi_table_dbg2_info, oem_data_length),
+		FIELD_UINT("OEM Data Offset",		fwts_acpi_table_dbg2_info, oem_data_offset),
+		FIELD_UINT("Port Type", 		fwts_acpi_table_dbg2_info, port_type),
+		FIELD_UINT("Port Subtype",		fwts_acpi_table_dbg2_info, port_subtype),
+		FIELD_UINT("Reserved",			fwts_acpi_table_dbg2_info, reserved),
+		FIELD_UINT("Base Address Offset",	fwts_acpi_table_dbg2_info, base_address_offset),
+		FIELD_UINT("Address Size Offset", 	fwts_acpi_table_dbg2_info, address_size_offset),
+		FIELD_END
+	};
+
+	static const fwts_acpidump_field dbg2_gas_fields[] = {
+		FIELD_GAS ("Base Address Register",	gas_addr, addr),
+		FIELD_END
+	};
+
+	static const fwts_acpidump_field dbg2_addr_fields[] = {
+		FIELD_UINT("Address Size", 		addr_size, size),
+		FIELD_END
+	};
+
+	static const fwts_acpidump_field dbg2_namespace_fields[] = {
+		FIELD_STRZ("Namepath", 			namespace, path),
+		FIELD_END
+	};
+
+	acpi_dump_table_fields(fw, table->data, dbg2_fields, 0, table->length);
+	fwts_log_nl(fw);
+
+	offset = dbg2->info_offset;
+
+	/* Dump out info_count number of instances */
+	for (i = 0; i < dbg2->info_count; i++) {
+		uint32_t j;
+		fwts_acpi_table_dbg2_info *dbg2_info = (fwts_acpi_table_dbg2_info *)(table->data + offset);
+		uint8_t *base_addr_regs = (uint8_t *)dbg2_info + dbg2_info->base_address_offset;
+		uint8_t *address_size   = (uint8_t *)dbg2_info + dbg2_info->address_size_offset;
+		uint8_t *namespace_str  = (uint8_t *)dbg2_info + dbg2_info->namespace_offset;
+		uint8_t *oem_data       = (uint8_t *)dbg2_info + dbg2_info->oem_data_offset;
+
+		__acpi_dump_table_fields(fw, table->data + offset, dbg2_info_fields, offset);
+
+		if (dbg2_info->number_of_regs) {
+			/* Dump out the register GAS and sizes */
+			for (j = 0; j < dbg2_info->number_of_regs; j++) {
+				__acpi_dump_table_fields(fw, &base_addr_regs[j], dbg2_gas_fields,
+					(void*)&base_addr_regs[j] - table->data);
+			}
+			fwts_log_nl(fw);
+
+			for (j = 0; j < dbg2_info->number_of_regs; j++)
+				acpi_dump_uint(fw, dbg2_addr_fields, &address_size[j],
+					(void *)&address_size[j] - table->data);
+			fwts_log_nl(fw);
+
+		}
+		/* Do we have a namespace to dump? */
+		if (dbg2_info->namespace_offset)
+			acpi_dump_strz(fw, dbg2_namespace_fields, namespace_str,
+				(void *)namespace_str - table->data);
+
+		/* And dump any OEM specific data */
+		if (dbg2_info->oem_data_length) {
+			fwts_log_nl(fw);
+			fwts_log_info_verbatum(fw, "OEM Data:");
+			acpi_dump_raw_data(fw, oem_data, dbg2_info->oem_data_length,
+				(void *)oem_data - table->data);
+		}
+
+		offset += dbg2_info->length;
+		if (offset > table->length)
+			break;
+	}
+}
+
 typedef struct {
 	const char *name;
 	void (*func)(fwts_framework *fw, const fwts_acpi_table_info *table);
@@ -1747,6 +1869,7 @@  static const acpidump_table_vec table_vec[] = {
 	{ "BGRT", 	acpidump_bgrt, 	1 },
 	{ "BOOT", 	acpidump_boot, 	1 },
 	{ "CPEP", 	acpidump_cpep, 	1 },
+	{ "DBG2", 	acpidump_dbg2,	1 },
 	{ "DBGP", 	acpidump_dbgp,	1 },
 	{ "DSDT", 	acpidump_amlcode, 1 },
 	{ "DMAR", 	acpidump_dmar,	1 },
diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h
index 009e5ac..34619bd 100644
--- a/src/lib/include/fwts_acpi.h
+++ b/src/lib/include/fwts_acpi.h
@@ -712,6 +712,27 @@  typedef struct {
 	fwts_acpi_gas	base_address;
 } __attribute__ ((packed)) fwts_acpi_table_dbgp;
 
+typedef struct {
+	fwts_acpi_table_header	header;
+	uint32_t	info_offset;
+	uint32_t	info_count;
+} __attribute__ ((packed)) fwts_acpi_table_dbg2;
+
+typedef struct {
+	uint8_t		revision;
+	uint16_t	length;
+	uint8_t		number_of_regs;
+	uint16_t	namespace_length;
+	uint16_t	namespace_offset;
+	uint16_t	oem_data_length;
+	uint16_t	oem_data_offset;
+	uint16_t	port_type;
+	uint16_t	port_subtype;
+	uint16_t	reserved;
+	uint16_t	base_address_offset;
+	uint16_t	address_size_offset;
+} __attribute__ ((packed)) fwts_acpi_table_dbg2_info;
+
 void fwts_acpi_table_get_header(fwts_acpi_table_header *hdr, uint8_t *data);
 
 #endif