Patchwork [3/5] acpi: acpidump: dump out the DMAR table

login
register
mail settings
Submitter Colin King
Date June 29, 2012, 1:11 p.m.
Message ID <1340975467-23977-4-git-send-email-colin.king@canonical.com>
Download mbox | patch
Permalink /patch/168072/
State Rejected
Headers show

Comments

Colin King - June 29, 2012, 1:11 p.m.
From: Colin Ian King <colin.king@canonical.com>

The DMAR table is fairly well described so lets also dump
this one out in an annotated form too.

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 src/acpi/acpidump/acpidump.c |  117 ++++++++++++++++++++++++++++++++++++++++++
 src/lib/include/fwts_acpi.h  |   53 +++++++++++++++++++
 2 files changed, 170 insertions(+)
Alex Hung - July 2, 2012, 6:09 a.m.
Hi Colin,

I read DMA Remapping Table 
(http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf), 
and both Reserved Memory Definition and Root Port ATS capability 
reporting structure has a field "Device Scope []" that is only present 
in your DMA remapping hardware unit definition structure.

Is this intentional?

Best Regards,
Alex Hung

On 06/29/2012 09:11 PM, Colin King wrote:
> From: Colin Ian King <colin.king@canonical.com>
>
> The DMAR table is fairly well described so lets also dump
> this one out in an annotated form too.
>
> Signed-off-by: Colin Ian King <colin.king@canonical.com>
> ---
>   src/acpi/acpidump/acpidump.c |  117 ++++++++++++++++++++++++++++++++++++++++++
>   src/lib/include/fwts_acpi.h  |   53 +++++++++++++++++++
>   2 files changed, 170 insertions(+)
>
> diff --git a/src/acpi/acpidump/acpidump.c b/src/acpi/acpidump/acpidump.c
> index 3ff3e75..79d4c4d 100644
> --- a/src/acpi/acpidump/acpidump.c
> +++ b/src/acpi/acpidump/acpidump.c
> @@ -1202,6 +1202,122 @@ static void acpidump_asf(fwts_framework *fw, fwts_acpi_table_info *table)
>   	}
>   }
>
> +/*
> + *  acpidump_dmar()
> + *	dump out DMAR
> + *	http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf
> + */
> +static void acpidump_dmar(fwts_framework *fw, fwts_acpi_table_info *table)
> +{
> +	uint8_t *data = (uint8_t *)table->data;
> +	size_t length = table->length;
> +	uint8_t *ptr = data;
> +	size_t device_scope_length;
> +
> +	static fwts_acpidump_field dmar_fields[] = {
> +		FIELD_UINT("Host Address Width", 	fwts_acpi_table_dmar, host_addr_width),
> +		FIELD_UINT("Flags", 			fwts_acpi_table_dmar, flags),
> +		FIELD_UINT("Reserved", 			fwts_acpi_table_dmar, reserved),
> +		FIELD_END
> +	};
> +
> +	static fwts_acpidump_field dmar_header_fields[] = {
> +		FIELD_UINT("Type",			fwts_acpi_table_dmar_header, type),
> +		FIELD_UINT("Length",			fwts_acpi_table_dmar_header, length),
> +		FIELD_END
> +	};
> +
> +	static fwts_acpidump_field dmar_hardware_unit_fields[] = {
> +		FIELD_UINT("Flags",			fwts_acpi_table_dmar_hardware_unit, flags),
> +		FIELD_UINT("Reserved",			fwts_acpi_table_dmar_hardware_unit, reserved),
> +		FIELD_UINT("Segment Number",		fwts_acpi_table_dmar_hardware_unit, segment_number),
> +		FIELD_UINT("Register Base Address",	fwts_acpi_table_dmar_hardware_unit, register_base_addr),
> +		FIELD_UINT("Device Scope",		fwts_acpi_table_dmar_hardware_unit, device_scope),
> +		FIELD_END
> +	};
> +
> +	static fwts_acpidump_field dmar_reserved_memory_fields[] = {
> +		FIELD_UINT("Reserved",			fwts_acpi_table_dmar_reserved_memory, reserved),
> +		FIELD_UINT("Segment",			fwts_acpi_table_dmar_reserved_memory, segment),
> +		FIELD_UINT("Base Address",		fwts_acpi_table_dmar_reserved_memory, base_address),
> +		FIELD_UINT("End Address",		fwts_acpi_table_dmar_reserved_memory, end_address),
> +		
> +		FIELD_END
> +	};
> +
> +	static fwts_acpidump_field dmar_atsr_fields[] = {
> +		FIELD_UINT("Flags",			fwts_acpi_table_dmar_atsr, flags),
> +		FIELD_UINT("Reserved",			fwts_acpi_table_dmar_atsr, reserved),
> +		FIELD_UINT("Segment",			fwts_acpi_table_dmar_atsr, segment),
> +		FIELD_END
> +	};
> +	
> +	static fwts_acpidump_field dmar_device_scope_fields[] = {
> +		FIELD_UINT("Type",			fwts_acpi_table_dmar_device_scope, type),
> +		FIELD_UINT("Length",			fwts_acpi_table_dmar_device_scope, length),
> +		FIELD_UINT("Reserved",			fwts_acpi_table_dmar_device_scope, reserved),
> +		FIELD_UINT("Enumeration ID",		fwts_acpi_table_dmar_device_scope, enumeration_id),
> +		FIELD_UINT("Start Bus Number",		fwts_acpi_table_dmar_device_scope, start_bus_number),
> +		FIELD_END
> +	};
> +
> +	__acpi_dump_table_fields(fw, ptr, dmar_fields, ptr - data);
> +
> +	ptr += sizeof(fwts_acpi_table_dmar);
> +
> +	while (ptr < data + length) {
> +		uint8_t *tmpptr;
> +		fwts_acpi_table_dmar_header *header =
> +			(fwts_acpi_table_dmar_header *)ptr;
> +
> +		fwts_log_nl(fw);
> +
> +		switch (header->type) {
> +		case 0:
> +			fwts_log_info_verbatum(fw, "Hardware Unit Definition:");
> +			__acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr - data);
> +			__acpi_dump_table_fields(fw, ptr, dmar_hardware_unit_fields, ptr - data);
> +			device_scope_length = (size_t)header->length - sizeof(fwts_acpi_table_dmar_hardware_unit);
> +			tmpptr = ptr + sizeof(fwts_acpi_table_dmar_hardware_unit);
> +
> +			/* Parse through multiple device scopes */
> +			while (device_scope_length > 0) {
> +				int i;
> +
> +				fwts_acpi_table_dmar_device_scope *device_scope =
> +					(fwts_acpi_table_dmar_device_scope *)tmpptr;
> +				__acpi_dump_table_fields(fw, tmpptr, dmar_device_scope_fields, tmpptr - data);
> +				/*
> +				 *  The device scope has a variable length path,
> +				 *  so just dump this raw data out for now.
> +				 */
> +				for (i=0; i < device_scope->length - sizeof(fwts_acpi_table_dmar_device_scope); i++) {
> +					uint8_t val8 = device_scope->path[i];
> +					fwts_log_info_verbatum(fw, "%s 0x%2.2x [%d]", acpi_dump_field_info("Path", 1, (tmpptr - data) + sizeof(fwts_acpi_table_dmar_device_scope) + i), val8, i);
> +				}
> +				tmpptr += device_scope->length;
> +				device_scope_length -= device_scope->length;
> +			}
> +			break;
> +		case 1:
> +			fwts_log_info_verbatum(fw, "Reserved Memory Definition:");
> +			__acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr - data);
> +			__acpi_dump_table_fields(fw, ptr, dmar_reserved_memory_fields, ptr - data);
> +			break;
> +		case 2:
> +			fwts_log_info_verbatum(fw, "Root Port ATS Capability Reporting Structure:");
> +			__acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr - data);
> +			__acpi_dump_table_fields(fw, ptr, dmar_atsr_fields, ptr - data);
> +			break;
> +		default:
> +			/* and anything else */
> +			break;
> +		}
> +
> +		ptr += header->length;
> +	}
> +}
> +
>   typedef struct {
>   	char *name;
>   	void (*func)(fwts_framework *fw, fwts_acpi_table_info *table);
> @@ -1220,6 +1336,7 @@ static acpidump_table_vec table_vec[] = {
>   	{ "BOOT", 	acpidump_boot, 	1 },
>   	{ "CPEP", 	acpidump_cpep, 	1 },
>   	{ "DSDT", 	acpidump_amlcode, 1 },
> +	{ "DMAR", 	acpidump_dmar,	1 },
>   	{ "ECDT", 	acpidump_ecdt, 	1 },
>   	{ "EINJ", 	acpidump_einj, 	1 },
>   	{ "ERST", 	acpidump_erst, 	1 },
> diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h
> index 03f7c2e..ef25ef5 100644
> --- a/src/lib/include/fwts_acpi.h
> +++ b/src/lib/include/fwts_acpi.h
> @@ -504,6 +504,59 @@ typedef struct {
>   	uint8_t		fwts_acpi_table_asf_addr_element[0];
>   } __attribute__ ((packed)) fwts_acpi_table_asf_addr;
>
> +/*
> + *  DMAR
> + *  See http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf
> + */
> +typedef struct {
> +	fwts_acpi_table_header header;
> +	uint8_t		host_addr_width;
> +	uint8_t		flags;
> +	uint8_t		reserved[10];
> +} __attribute__ ((packed)) fwts_acpi_table_dmar;
> +
> +typedef struct {
> +	uint16_t	type;
> +	uint16_t	length;
> +} __attribute__ ((packed)) fwts_acpi_table_dmar_header;
> +
> +/* DMA remapping hardware unit definition structure */
> +typedef struct {
> +	fwts_acpi_table_dmar_header header;
> +	uint8_t		flags;
> +	uint8_t		reserved;
> +	uint16_t	segment_number;
> +	uint64_t	register_base_addr;
> +	uint8_t		device_scope[0];
> +} __attribute__ ((packed)) fwts_acpi_table_dmar_hardware_unit;
> +
> +/* Reserved Memory Defininition */
> +typedef struct {
> +	fwts_acpi_table_dmar_header header;
> +	uint16_t	reserved;
> +	uint16_t	segment;
> +	uint64_t	base_address;
> +	uint64_t	end_address;
> +} __attribute__ ((packed)) fwts_acpi_table_dmar_reserved_memory;
> +
> +/* Root Port ATS capability reporting structure */
> +typedef struct {
> +	fwts_acpi_table_dmar_header header;
> +	uint8_t		flags;
> +	uint8_t		reserved;
> +	uint16_t	segment;
> +} __attribute__ ((packed)) fwts_acpi_table_dmar_atsr;
> +
> +/* DMA remapping device scope entries */
> +typedef struct {
> +	uint8_t		type;
> +	uint8_t		length;
> +	uint8_t		reserved[2];
> +	uint8_t		enumeration_id;
> +	uint8_t		start_bus_number;
> +	uint8_t		path[0];
> +} __attribute__ ((packed)) fwts_acpi_table_dmar_device_scope;
> +
>   void fwts_acpi_table_get_header(fwts_acpi_table_header *hdr, uint8_t *data);
>
>   #endif
>
Colin King - July 2, 2012, 8:03 a.m.
On 02/07/12 07:09, Alex Hung wrote:
> Hi Colin,
>
> I read DMA Remapping Table
> (http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf),
> and both Reserved Memory Definition and Root Port ATS capability
> reporting structure has a field "Device Scope []" that is only present
> in your DMA remapping hardware unit definition structure.
>
> Is this intentional?

My mistake. Let me fix that up and send out the correct patch later. 
Thanks for spotting that!

Colin
>
> Best Regards,
> Alex Hung
>
> On 06/29/2012 09:11 PM, Colin King wrote:
>> From: Colin Ian King <colin.king@canonical.com>
>>
>> The DMAR table is fairly well described so lets also dump
>> this one out in an annotated form too.
>>
>> Signed-off-by: Colin Ian King <colin.king@canonical.com>
>> ---
>>   src/acpi/acpidump/acpidump.c |  117
>> ++++++++++++++++++++++++++++++++++++++++++
>>   src/lib/include/fwts_acpi.h  |   53 +++++++++++++++++++
>>   2 files changed, 170 insertions(+)
>>
>> diff --git a/src/acpi/acpidump/acpidump.c b/src/acpi/acpidump/acpidump.c
>> index 3ff3e75..79d4c4d 100644
>> --- a/src/acpi/acpidump/acpidump.c
>> +++ b/src/acpi/acpidump/acpidump.c
>> @@ -1202,6 +1202,122 @@ static void acpidump_asf(fwts_framework *fw,
>> fwts_acpi_table_info *table)
>>       }
>>   }
>>
>> +/*
>> + *  acpidump_dmar()
>> + *    dump out DMAR
>> + *
>> http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf
>>
>> + */
>> +static void acpidump_dmar(fwts_framework *fw, fwts_acpi_table_info
>> *table)
>> +{
>> +    uint8_t *data = (uint8_t *)table->data;
>> +    size_t length = table->length;
>> +    uint8_t *ptr = data;
>> +    size_t device_scope_length;
>> +
>> +    static fwts_acpidump_field dmar_fields[] = {
>> +        FIELD_UINT("Host Address Width",     fwts_acpi_table_dmar,
>> host_addr_width),
>> +        FIELD_UINT("Flags",             fwts_acpi_table_dmar, flags),
>> +        FIELD_UINT("Reserved",             fwts_acpi_table_dmar,
>> reserved),
>> +        FIELD_END
>> +    };
>> +
>> +    static fwts_acpidump_field dmar_header_fields[] = {
>> +        FIELD_UINT("Type",            fwts_acpi_table_dmar_header,
>> type),
>> +        FIELD_UINT("Length",            fwts_acpi_table_dmar_header,
>> length),
>> +        FIELD_END
>> +    };
>> +
>> +    static fwts_acpidump_field dmar_hardware_unit_fields[] = {
>> +        FIELD_UINT("Flags",
>> fwts_acpi_table_dmar_hardware_unit, flags),
>> +        FIELD_UINT("Reserved",
>> fwts_acpi_table_dmar_hardware_unit, reserved),
>> +        FIELD_UINT("Segment Number",
>> fwts_acpi_table_dmar_hardware_unit, segment_number),
>> +        FIELD_UINT("Register Base Address",
>> fwts_acpi_table_dmar_hardware_unit, register_base_addr),
>> +        FIELD_UINT("Device Scope",
>> fwts_acpi_table_dmar_hardware_unit, device_scope),
>> +        FIELD_END
>> +    };
>> +
>> +    static fwts_acpidump_field dmar_reserved_memory_fields[] = {
>> +        FIELD_UINT("Reserved",
>> fwts_acpi_table_dmar_reserved_memory, reserved),
>> +        FIELD_UINT("Segment",
>> fwts_acpi_table_dmar_reserved_memory, segment),
>> +        FIELD_UINT("Base Address",
>> fwts_acpi_table_dmar_reserved_memory, base_address),
>> +        FIELD_UINT("End Address",
>> fwts_acpi_table_dmar_reserved_memory, end_address),
>> +
>> +        FIELD_END
>> +    };
>> +
>> +    static fwts_acpidump_field dmar_atsr_fields[] = {
>> +        FIELD_UINT("Flags",            fwts_acpi_table_dmar_atsr,
>> flags),
>> +        FIELD_UINT("Reserved",            fwts_acpi_table_dmar_atsr,
>> reserved),
>> +        FIELD_UINT("Segment",            fwts_acpi_table_dmar_atsr,
>> segment),
>> +        FIELD_END
>> +    };
>> +
>> +    static fwts_acpidump_field dmar_device_scope_fields[] = {
>> +        FIELD_UINT("Type",
>> fwts_acpi_table_dmar_device_scope, type),
>> +        FIELD_UINT("Length",
>> fwts_acpi_table_dmar_device_scope, length),
>> +        FIELD_UINT("Reserved",
>> fwts_acpi_table_dmar_device_scope, reserved),
>> +        FIELD_UINT("Enumeration ID",
>> fwts_acpi_table_dmar_device_scope, enumeration_id),
>> +        FIELD_UINT("Start Bus Number",
>> fwts_acpi_table_dmar_device_scope, start_bus_number),
>> +        FIELD_END
>> +    };
>> +
>> +    __acpi_dump_table_fields(fw, ptr, dmar_fields, ptr - data);
>> +
>> +    ptr += sizeof(fwts_acpi_table_dmar);
>> +
>> +    while (ptr < data + length) {
>> +        uint8_t *tmpptr;
>> +        fwts_acpi_table_dmar_header *header =
>> +            (fwts_acpi_table_dmar_header *)ptr;
>> +
>> +        fwts_log_nl(fw);
>> +
>> +        switch (header->type) {
>> +        case 0:
>> +            fwts_log_info_verbatum(fw, "Hardware Unit Definition:");
>> +            __acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr
>> - data);
>> +            __acpi_dump_table_fields(fw, ptr,
>> dmar_hardware_unit_fields, ptr - data);
>> +            device_scope_length = (size_t)header->length -
>> sizeof(fwts_acpi_table_dmar_hardware_unit);
>> +            tmpptr = ptr + sizeof(fwts_acpi_table_dmar_hardware_unit);
>> +
>> +            /* Parse through multiple device scopes */
>> +            while (device_scope_length > 0) {
>> +                int i;
>> +
>> +                fwts_acpi_table_dmar_device_scope *device_scope =
>> +                    (fwts_acpi_table_dmar_device_scope *)tmpptr;
>> +                __acpi_dump_table_fields(fw, tmpptr,
>> dmar_device_scope_fields, tmpptr - data);
>> +                /*
>> +                 *  The device scope has a variable length path,
>> +                 *  so just dump this raw data out for now.
>> +                 */
>> +                for (i=0; i < device_scope->length -
>> sizeof(fwts_acpi_table_dmar_device_scope); i++) {
>> +                    uint8_t val8 = device_scope->path[i];
>> +                    fwts_log_info_verbatum(fw, "%s 0x%2.2x [%d]",
>> acpi_dump_field_info("Path", 1, (tmpptr - data) +
>> sizeof(fwts_acpi_table_dmar_device_scope) + i), val8, i);
>> +                }
>> +                tmpptr += device_scope->length;
>> +                device_scope_length -= device_scope->length;
>> +            }
>> +            break;
>> +        case 1:
>> +            fwts_log_info_verbatum(fw, "Reserved Memory Definition:");
>> +            __acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr
>> - data);
>> +            __acpi_dump_table_fields(fw, ptr,
>> dmar_reserved_memory_fields, ptr - data);
>> +            break;
>> +        case 2:
>> +            fwts_log_info_verbatum(fw, "Root Port ATS Capability
>> Reporting Structure:");
>> +            __acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr
>> - data);
>> +            __acpi_dump_table_fields(fw, ptr, dmar_atsr_fields, ptr -
>> data);
>> +            break;
>> +        default:
>> +            /* and anything else */
>> +            break;
>> +        }
>> +
>> +        ptr += header->length;
>> +    }
>> +}
>> +
>>   typedef struct {
>>       char *name;
>>       void (*func)(fwts_framework *fw, fwts_acpi_table_info *table);
>> @@ -1220,6 +1336,7 @@ static acpidump_table_vec table_vec[] = {
>>       { "BOOT",     acpidump_boot,     1 },
>>       { "CPEP",     acpidump_cpep,     1 },
>>       { "DSDT",     acpidump_amlcode, 1 },
>> +    { "DMAR",     acpidump_dmar,    1 },
>>       { "ECDT",     acpidump_ecdt,     1 },
>>       { "EINJ",     acpidump_einj,     1 },
>>       { "ERST",     acpidump_erst,     1 },
>> diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h
>> index 03f7c2e..ef25ef5 100644
>> --- a/src/lib/include/fwts_acpi.h
>> +++ b/src/lib/include/fwts_acpi.h
>> @@ -504,6 +504,59 @@ typedef struct {
>>       uint8_t        fwts_acpi_table_asf_addr_element[0];
>>   } __attribute__ ((packed)) fwts_acpi_table_asf_addr;
>>
>> +/*
>> + *  DMAR
>> + *  See
>> http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf
>>
>> + */
>> +typedef struct {
>> +    fwts_acpi_table_header header;
>> +    uint8_t        host_addr_width;
>> +    uint8_t        flags;
>> +    uint8_t        reserved[10];
>> +} __attribute__ ((packed)) fwts_acpi_table_dmar;
>> +
>> +typedef struct {
>> +    uint16_t    type;
>> +    uint16_t    length;
>> +} __attribute__ ((packed)) fwts_acpi_table_dmar_header;
>> +
>> +/* DMA remapping hardware unit definition structure */
>> +typedef struct {
>> +    fwts_acpi_table_dmar_header header;
>> +    uint8_t        flags;
>> +    uint8_t        reserved;
>> +    uint16_t    segment_number;
>> +    uint64_t    register_base_addr;
>> +    uint8_t        device_scope[0];
>> +} __attribute__ ((packed)) fwts_acpi_table_dmar_hardware_unit;
>> +
>> +/* Reserved Memory Defininition */
>> +typedef struct {
>> +    fwts_acpi_table_dmar_header header;
>> +    uint16_t    reserved;
>> +    uint16_t    segment;
>> +    uint64_t    base_address;
>> +    uint64_t    end_address;
>> +} __attribute__ ((packed)) fwts_acpi_table_dmar_reserved_memory;
>> +
>> +/* Root Port ATS capability reporting structure */
>> +typedef struct {
>> +    fwts_acpi_table_dmar_header header;
>> +    uint8_t        flags;
>> +    uint8_t        reserved;
>> +    uint16_t    segment;
>> +} __attribute__ ((packed)) fwts_acpi_table_dmar_atsr;
>> +
>> +/* DMA remapping device scope entries */
>> +typedef struct {
>> +    uint8_t        type;
>> +    uint8_t        length;
>> +    uint8_t        reserved[2];
>> +    uint8_t        enumeration_id;
>> +    uint8_t        start_bus_number;
>> +    uint8_t        path[0];
>> +} __attribute__ ((packed)) fwts_acpi_table_dmar_device_scope;
>> +
>>   void fwts_acpi_table_get_header(fwts_acpi_table_header *hdr, uint8_t
>> *data);
>>
>>   #endif
>>
>
>
>

Patch

diff --git a/src/acpi/acpidump/acpidump.c b/src/acpi/acpidump/acpidump.c
index 3ff3e75..79d4c4d 100644
--- a/src/acpi/acpidump/acpidump.c
+++ b/src/acpi/acpidump/acpidump.c
@@ -1202,6 +1202,122 @@  static void acpidump_asf(fwts_framework *fw, fwts_acpi_table_info *table)
 	}
 }
 
+/*
+ *  acpidump_dmar()
+ *	dump out DMAR
+ *	http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf
+ */
+static void acpidump_dmar(fwts_framework *fw, fwts_acpi_table_info *table)
+{
+	uint8_t *data = (uint8_t *)table->data;
+	size_t length = table->length;
+	uint8_t *ptr = data;
+	size_t device_scope_length;
+
+	static fwts_acpidump_field dmar_fields[] = {
+		FIELD_UINT("Host Address Width", 	fwts_acpi_table_dmar, host_addr_width),
+		FIELD_UINT("Flags", 			fwts_acpi_table_dmar, flags),
+		FIELD_UINT("Reserved", 			fwts_acpi_table_dmar, reserved),
+		FIELD_END
+	};
+
+	static fwts_acpidump_field dmar_header_fields[] = {
+		FIELD_UINT("Type",			fwts_acpi_table_dmar_header, type),
+		FIELD_UINT("Length",			fwts_acpi_table_dmar_header, length),
+		FIELD_END
+	};
+
+	static fwts_acpidump_field dmar_hardware_unit_fields[] = {
+		FIELD_UINT("Flags",			fwts_acpi_table_dmar_hardware_unit, flags),
+		FIELD_UINT("Reserved",			fwts_acpi_table_dmar_hardware_unit, reserved),
+		FIELD_UINT("Segment Number",		fwts_acpi_table_dmar_hardware_unit, segment_number),
+		FIELD_UINT("Register Base Address",	fwts_acpi_table_dmar_hardware_unit, register_base_addr),
+		FIELD_UINT("Device Scope",		fwts_acpi_table_dmar_hardware_unit, device_scope),
+		FIELD_END
+	};
+
+	static fwts_acpidump_field dmar_reserved_memory_fields[] = {
+		FIELD_UINT("Reserved",			fwts_acpi_table_dmar_reserved_memory, reserved),
+		FIELD_UINT("Segment",			fwts_acpi_table_dmar_reserved_memory, segment),
+		FIELD_UINT("Base Address",		fwts_acpi_table_dmar_reserved_memory, base_address),
+		FIELD_UINT("End Address",		fwts_acpi_table_dmar_reserved_memory, end_address),
+		
+		FIELD_END
+	};
+
+	static fwts_acpidump_field dmar_atsr_fields[] = {
+		FIELD_UINT("Flags",			fwts_acpi_table_dmar_atsr, flags),
+		FIELD_UINT("Reserved",			fwts_acpi_table_dmar_atsr, reserved),
+		FIELD_UINT("Segment",			fwts_acpi_table_dmar_atsr, segment),
+		FIELD_END
+	};
+	
+	static fwts_acpidump_field dmar_device_scope_fields[] = {
+		FIELD_UINT("Type",			fwts_acpi_table_dmar_device_scope, type),
+		FIELD_UINT("Length",			fwts_acpi_table_dmar_device_scope, length),
+		FIELD_UINT("Reserved",			fwts_acpi_table_dmar_device_scope, reserved),
+		FIELD_UINT("Enumeration ID",		fwts_acpi_table_dmar_device_scope, enumeration_id),
+		FIELD_UINT("Start Bus Number",		fwts_acpi_table_dmar_device_scope, start_bus_number),
+		FIELD_END
+	};
+
+	__acpi_dump_table_fields(fw, ptr, dmar_fields, ptr - data);
+
+	ptr += sizeof(fwts_acpi_table_dmar);
+
+	while (ptr < data + length) {
+		uint8_t *tmpptr;
+		fwts_acpi_table_dmar_header *header =
+			(fwts_acpi_table_dmar_header *)ptr;
+
+		fwts_log_nl(fw);
+
+		switch (header->type) {
+		case 0:
+			fwts_log_info_verbatum(fw, "Hardware Unit Definition:");
+			__acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr - data);
+			__acpi_dump_table_fields(fw, ptr, dmar_hardware_unit_fields, ptr - data);
+			device_scope_length = (size_t)header->length - sizeof(fwts_acpi_table_dmar_hardware_unit);
+			tmpptr = ptr + sizeof(fwts_acpi_table_dmar_hardware_unit);
+
+			/* Parse through multiple device scopes */
+			while (device_scope_length > 0) {
+				int i;
+
+				fwts_acpi_table_dmar_device_scope *device_scope =
+					(fwts_acpi_table_dmar_device_scope *)tmpptr;
+				__acpi_dump_table_fields(fw, tmpptr, dmar_device_scope_fields, tmpptr - data);
+				/*
+				 *  The device scope has a variable length path,
+				 *  so just dump this raw data out for now.
+				 */
+				for (i=0; i < device_scope->length - sizeof(fwts_acpi_table_dmar_device_scope); i++) {
+					uint8_t val8 = device_scope->path[i];
+					fwts_log_info_verbatum(fw, "%s 0x%2.2x [%d]", acpi_dump_field_info("Path", 1, (tmpptr - data) + sizeof(fwts_acpi_table_dmar_device_scope) + i), val8, i);
+				}
+				tmpptr += device_scope->length;
+				device_scope_length -= device_scope->length;
+			}
+			break;
+		case 1:
+			fwts_log_info_verbatum(fw, "Reserved Memory Definition:");
+			__acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr - data);
+			__acpi_dump_table_fields(fw, ptr, dmar_reserved_memory_fields, ptr - data);
+			break;
+		case 2:
+			fwts_log_info_verbatum(fw, "Root Port ATS Capability Reporting Structure:");
+			__acpi_dump_table_fields(fw, ptr, dmar_header_fields, ptr - data);
+			__acpi_dump_table_fields(fw, ptr, dmar_atsr_fields, ptr - data);
+			break;
+		default:
+			/* and anything else */
+			break;
+		}
+
+		ptr += header->length;
+	}
+}
+
 typedef struct {
 	char *name;
 	void (*func)(fwts_framework *fw, fwts_acpi_table_info *table);
@@ -1220,6 +1336,7 @@  static acpidump_table_vec table_vec[] = {
 	{ "BOOT", 	acpidump_boot, 	1 },
 	{ "CPEP", 	acpidump_cpep, 	1 },
 	{ "DSDT", 	acpidump_amlcode, 1 },
+	{ "DMAR", 	acpidump_dmar,	1 },
 	{ "ECDT", 	acpidump_ecdt, 	1 },
 	{ "EINJ", 	acpidump_einj, 	1 },
 	{ "ERST", 	acpidump_erst, 	1 },
diff --git a/src/lib/include/fwts_acpi.h b/src/lib/include/fwts_acpi.h
index 03f7c2e..ef25ef5 100644
--- a/src/lib/include/fwts_acpi.h
+++ b/src/lib/include/fwts_acpi.h
@@ -504,6 +504,59 @@  typedef struct {
 	uint8_t		fwts_acpi_table_asf_addr_element[0];
 } __attribute__ ((packed)) fwts_acpi_table_asf_addr;
 
+/*
+ *  DMAR
+ *  See http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf
+ */
+typedef struct {
+	fwts_acpi_table_header header;
+	uint8_t		host_addr_width;
+	uint8_t		flags;
+	uint8_t		reserved[10];
+} __attribute__ ((packed)) fwts_acpi_table_dmar;
+
+typedef struct {
+	uint16_t	type;
+	uint16_t	length;
+} __attribute__ ((packed)) fwts_acpi_table_dmar_header;
+
+/* DMA remapping hardware unit definition structure */
+typedef struct {
+	fwts_acpi_table_dmar_header header;
+	uint8_t		flags;
+	uint8_t		reserved;
+	uint16_t	segment_number;
+	uint64_t	register_base_addr;
+	uint8_t		device_scope[0];
+} __attribute__ ((packed)) fwts_acpi_table_dmar_hardware_unit;
+
+/* Reserved Memory Defininition */
+typedef struct {
+	fwts_acpi_table_dmar_header header;
+	uint16_t	reserved;
+	uint16_t	segment;
+	uint64_t	base_address;
+	uint64_t	end_address;
+} __attribute__ ((packed)) fwts_acpi_table_dmar_reserved_memory;
+
+/* Root Port ATS capability reporting structure */
+typedef struct {
+	fwts_acpi_table_dmar_header header;
+	uint8_t		flags;
+	uint8_t		reserved;
+	uint16_t	segment;
+} __attribute__ ((packed)) fwts_acpi_table_dmar_atsr;
+
+/* DMA remapping device scope entries */
+typedef struct {
+	uint8_t		type;
+	uint8_t		length;
+	uint8_t		reserved[2];
+	uint8_t		enumeration_id;
+	uint8_t		start_bus_number;
+	uint8_t		path[0];
+} __attribute__ ((packed)) fwts_acpi_table_dmar_device_scope;
+
 void fwts_acpi_table_get_header(fwts_acpi_table_header *hdr, uint8_t *data);
 
 #endif