arch/x86/acpi: Add support for writing ACPI DBG2 table

Add a function to create an ACPI DBG2 table, which is a Microsoft
ACPI extension for providing a description of the available debug
interface on a board.

A convenience function is provided for creating a DBG2 table with
a 16550 UART based on a PCI device.

This is tested by generating a device and verifying it with iasl:

[000h 0000   4]                    Signature : "DBG2"
[004h 0004   4]                 Table Length : 00000061
[008h 0008   1]                     Revision : 00
[009h 0009   1]                     Checksum : 3B
[00Ah 0010   6]                       Oem ID : "CORE  "
[010h 0016   8]                 Oem Table ID : "COREBOOT"
[018h 0024   4]                 Oem Revision : 00000000
[01Ch 0028   4]              Asl Compiler ID : "CORE"
[020h 0032   4]        Asl Compiler Revision : 00000000

[024h 0036   4]                  Info Offset : 0000002C
[028h 0040   4]                   Info Count : 00000001

[02Ch 0044   1]                     Revision : 00
[02Dh 0045   2]                       Length : 0035
[02Fh 0047   1]               Register Count : 01
[030h 0048   2]              Namepath Length : 000F
[032h 0050   2]              Namepath Offset : 0026
[034h 0052   2]              OEM Data Length : 0000
[036h 0054   2]              OEM Data Offset : 0000
[038h 0056   2]                    Port Type : 8000
[03Ah 0058   2]                 Port Subtype : 0000
[03Ch 0060   2]                     Reserved : 0000
[03Eh 0062   2]          Base Address Offset : 0016
[040h 0064   2]          Address Size Offset : 0022

[042h 0066  12]        Base Address Register : [Generic Address Structure]
[042h 0066   1]                     Space ID : 00 [SystemMemory]
[043h 0067   1]                    Bit Width : 00
[044h 0068   1]                   Bit Offset : 00
[045h 0069   1]         Encoded Access Width : 03 [DWord Access:32]
[046h 0070   8]                      Address : 00000000FE034000

[04Eh 0078   4]                 Address Size : 00001000

[052h 0082  15]                     Namepath : "\_SB.PCI0.UAR2"

Raw Table Data: Length 97 (0x61)

  0000: 44 42 47 32 61 00 00 00 00 3B 43 4F 52 45 20 20  // DBG2a....;CORE
  0010: 43 4F 52 45 42 4F 4F 54 00 00 00 00 43 4F 52 45  // COREBOOT....CORE
  0020: 00 00 00 00 2C 00 00 00 01 00 00 00 00 35 00 01  // ....,........5..
  0030: 0F 00 26 00 00 00 00 00 00 80 00 00 00 00 16 00  // ..&.............
  0040: 22 00 00 00 00 03 00 40 03 FE 00 00 00 00 00 10  // "......@........
  0050: 00 00 5C 5F 53 42 2E 50 43 49 30 2E 55 41 52 32  // ..\_SB.PCI0.UAR2
  0060: 00                                               // .

Change-Id: I55aa3f24776b2f8aa38d7da117f422d8b8ec5479
Signed-off-by: Duncan Laurie <dlaurie@google.com>
Reviewed-on: https://review.coreboot.org/22452
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
Duncan Laurie 2017-11-11 19:33:25 -08:00 committed by Duncan Laurie
parent 8f20044c77
commit e4a36c7b52
2 changed files with 156 additions and 0 deletions

View file

@ -658,6 +658,118 @@ unsigned long acpi_write_hpet(device_t device, unsigned long current,
return current; return current;
} }
void acpi_create_dbg2(acpi_dbg2_header_t *dbg2,
int port_type, int port_subtype,
acpi_addr_t *address, uint32_t address_size,
const char *device_path)
{
uintptr_t current;
acpi_dbg2_device_t *device;
uint32_t *dbg2_addr_size;
acpi_header_t *header;
size_t path_len;
const char *path;
char *namespace;
/* Fill out header fields. */
current = (uintptr_t)dbg2;
memset(dbg2, 0, sizeof(acpi_dbg2_header_t));
header = &(dbg2->header);
header->revision = 0;
memcpy(header->signature, "DBG2", 4);
memcpy(header->oem_id, OEM_ID, 6);
memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
memcpy(header->asl_compiler_id, ASLC, 4);
/* One debug device defined */
dbg2->devices_offset = sizeof(acpi_dbg2_header_t);
dbg2->devices_count = 1;
current += sizeof(acpi_dbg2_header_t);
/* Device comes after the header */
device = (acpi_dbg2_device_t *)current;
memset(device, 0, sizeof(acpi_dbg2_device_t));
current += sizeof(acpi_dbg2_device_t);
device->revision = 0;
device->address_count = 1;
device->port_type = port_type;
device->port_subtype = port_subtype;
/* Base Address comes after device structure */
memcpy((void *)current, address, sizeof(acpi_addr_t));
device->base_address_offset = current - (uintptr_t)device;
current += sizeof(acpi_addr_t);
/* Address Size comes after address structure */
dbg2_addr_size = (uint32_t *)current;
device->address_size_offset = current - (uintptr_t)device;
*dbg2_addr_size = address_size;
current += sizeof(uint32_t);
/* Namespace string comes last, use '.' if not provided */
path = device_path ? : ".";
/* Namespace string length includes NULL terminator */
path_len = strlen(path) + 1;
namespace = (char *)current;
device->namespace_string_length = path_len;
device->namespace_string_offset = current - (uintptr_t)device;
strncpy(namespace, path, path_len);
current += path_len;
/* Update structure lengths and checksum */
device->length = current - (uintptr_t)device;
header->length = current - (uintptr_t)dbg2;
header->checksum = acpi_checksum((uint8_t *)dbg2, header->length);
}
unsigned long acpi_write_dbg2_pci_uart(acpi_rsdp_t *rsdp, unsigned long current,
struct device *dev, uint8_t access_size)
{
acpi_dbg2_header_t *dbg2 = (acpi_dbg2_header_t *)current;
struct resource *res;
acpi_addr_t address;
if (!dev) {
printk(BIOS_ERR, "%s: Device not found\n", __func__);
return current;
}
res = find_resource(dev, PCI_BASE_ADDRESS_0);
if (!res) {
printk(BIOS_ERR, "%s: Unable to find resource for %s\n",
__func__, dev_path(dev));
return current;
}
memset(&address, 0, sizeof(address));
if (res->flags & IORESOURCE_IO)
address.space_id = ACPI_ADDRESS_SPACE_IO;
else if (res->flags & IORESOURCE_MEM)
address.space_id = ACPI_ADDRESS_SPACE_MEMORY;
else {
printk(BIOS_ERR, "%s: Unknown address space type\n", __func__);
return current;
}
address.addrl = (uint32_t)res->base;
address.addrh = (uint32_t)((res->base >> 32) & 0xffffffff);
address.access_size = access_size;
acpi_create_dbg2(dbg2,
ACPI_DBG2_PORT_SERIAL,
ACPI_DBG2_PORT_SERIAL_16550,
&address, res->size,
acpi_device_path(dev));
if (dbg2->header.length) {
current += dbg2->header.length;
current = acpi_align_current(current);
acpi_add_table(rsdp, dbg2);
}
return current;
}
void acpi_create_facs(acpi_facs_t *facs) void acpi_create_facs(acpi_facs_t *facs)
{ {
memset((void *)facs, 0, sizeof(acpi_facs_t)); memset((void *)facs, 0, sizeof(acpi_facs_t));

View file

@ -404,6 +404,43 @@ typedef struct acpi_madt_irqoverride {
u16 flags; /* MPS INTI flags */ u16 flags; /* MPS INTI flags */
} __packed acpi_madt_irqoverride_t; } __packed acpi_madt_irqoverride_t;
#define ACPI_DBG2_PORT_SERIAL 0x8000
#define ACPI_DBG2_PORT_SERIAL_16550 0x0000
#define ACPI_DBG2_PORT_SERIAL_16550_DBGP 0x0001
#define ACPI_DBG2_PORT_SERIAL_ARM_PL011 0x0003
#define ACPI_DBG2_PORT_SERIAL_ARM_SBSA 0x000e
#define ACPI_DBG2_PORT_SERIAL_ARM_DDC 0x000f
#define ACPI_DBG2_PORT_SERIAL_BCM2835 0x0010
#define ACPI_DBG2_PORT_IEEE1394 0x8001
#define ACPI_DBG2_PORT_IEEE1394_STANDARD 0x0000
#define ACPI_DBG2_PORT_USB 0x8002
#define ACPI_DBG2_PORT_USB_XHCI 0x0000
#define ACPI_DBG2_PORT_USB_EHCI 0x0001
#define ACPI_DBG2_PORT_NET 0x8003
/* DBG2: Microsoft Debug Port Table 2 header */
typedef struct acpi_dbg2_header {
struct acpi_table_header header;
uint32_t devices_offset;
uint32_t devices_count;
} __attribute__ ((packed)) acpi_dbg2_header_t;
/* DBG2: Microsoft Debug Port Table 2 device entry */
typedef struct acpi_dbg2_device {
uint8_t revision;
uint16_t length;
uint8_t address_count;
uint16_t namespace_string_length;
uint16_t namespace_string_offset;
uint16_t oem_data_length;
uint16_t oem_data_offset;
uint16_t port_type;
uint16_t port_subtype;
uint8_t reserved[2];
uint16_t base_address_offset;
uint16_t address_size_offset;
} __attribute__ ((packed)) acpi_dbg2_device_t;
/* FADT (Fixed ACPI Description Table) */ /* FADT (Fixed ACPI Description Table) */
typedef struct acpi_fadt { typedef struct acpi_fadt {
struct acpi_table_header header; struct acpi_table_header header;
@ -667,6 +704,13 @@ void acpi_create_mcfg(acpi_mcfg_t *mcfg);
void acpi_create_facs(acpi_facs_t *facs); void acpi_create_facs(acpi_facs_t *facs);
void acpi_create_dbg2(acpi_dbg2_header_t *dbg2_header,
int port_type, int port_subtype,
acpi_addr_t *address, uint32_t address_size,
const char *device_path);
unsigned long acpi_write_dbg2_pci_uart(acpi_rsdp_t *rsdp, unsigned long current,
struct device *dev, uint8_t access_size);
void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags, void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags,
unsigned long (*acpi_fill_dmar)(unsigned long)); unsigned long (*acpi_fill_dmar)(unsigned long));
unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags, unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,