diff options
-rw-r--r-- | src/arch/x86/acpi.c | 112 | ||||
-rw-r--r-- | src/arch/x86/include/arch/acpi.h | 44 |
2 files changed, 156 insertions, 0 deletions
diff --git a/src/arch/x86/acpi.c b/src/arch/x86/acpi.c index 02884c494c..56f64084e8 100644 --- a/src/arch/x86/acpi.c +++ b/src/arch/x86/acpi.c @@ -658,6 +658,118 @@ unsigned long acpi_write_hpet(device_t device, unsigned long 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) { memset((void *)facs, 0, sizeof(acpi_facs_t)); diff --git a/src/arch/x86/include/arch/acpi.h b/src/arch/x86/include/arch/acpi.h index 1b239912d7..5418420342 100644 --- a/src/arch/x86/include/arch/acpi.h +++ b/src/arch/x86/include/arch/acpi.h @@ -404,6 +404,43 @@ typedef struct acpi_madt_irqoverride { u16 flags; /* MPS INTI flags */ } __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) */ typedef struct acpi_fadt { 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_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, unsigned long (*acpi_fill_dmar)(unsigned long)); unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags, |