Message ID | 20200126220508.84.I8f7a76fcf50225b3e105c3230c1c5cd66e76967b@changeid |
---|---|
State | New |
Headers | show |
Series | RFC: dm: Add programatic generation of ACPI tables | expand |
Hi Simon, A portion of this set is very much not x86-specific. (more below) On Sun, Jan 26, 2020 at 22:06:31 -0700, Simon Glass wrote: > Add an implementation of the DBG2 (Debug Port Table 2) ACPI table. > Adjust one of the header includes to be in the correct order, before > adding more. > > Signed-off-by: Simon Glass <sjg at chromium.org> > --- > > arch/x86/lib/acpi_table.c | 112 +++++++++++++++++++++++++++++++++++++- > include/acpi_table.h | 31 +++++++++++ > 2 files changed, 142 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c > index a810b12cfe..f12344de50 100644 > --- a/arch/x86/lib/acpi_table.c > +++ b/arch/x86/lib/acpi_table.c > @@ -8,6 +8,8 @@ > > #include <common.h> > #include <acpigen.h> > +#include <acpi_device.h> > +#include <acpi_table.h> > #include <cpu.h> > #include <dm.h> > #include <dm/uclass-internal.h> > @@ -15,7 +17,6 @@ > #include <serial.h> > #include <version.h> > #include <asm/acpi/global_nvs.h> > -#include <acpi_table.h> > #include <asm/ioapic.h> > #include <asm/lapic.h> > #include <asm/mpspec.h> > @@ -52,6 +53,50 @@ int acpi_write_hpet(struct acpi_ctx *ctx, const struct udevice *dev) > return 0; > } > > +int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev, > + uint access_size) > +{ So, this one could possibly be argued either way (it is certainly not fully generic). > + struct acpi_dbg2_header *dbg2 = ctx->current; > + char path[ACPI_PATH_MAX]; > + struct acpi_gen_regaddr address; > + phys_addr_t addr; > + int ret; > + > + if (!dev) { > + log_err("Device not found\n"); > + return -ENODEV; > + } > + if (!device_active(dev)) { > + log_info("Device not enabled\n"); > + return -EACCES; > + } > + /* > + * PCI devices don't remember their resource allocation information in > + * U-Boot at present. We assume that MMIO is used for the UART and that > + * the address space is 32 bytes: ns16550 uses 8 registers of up to > + * 32-bits each. This is only for debugging so it is not a big deal. > + */ > + addr = dm_pci_read_bar32(dev, 0); > + printf("UART addr %lx\n", (ulong)addr); > + > + memset(&address, '\0', sizeof(address)); > + address.space_id = ACPI_ADDRESS_SPACE_MEMORY; > + address.addrl = (uint32_t)addr; > + address.addrh = (uint32_t)((addr >> 32) & 0xffffffff); > + address.access_size = access_size; > + > + ret = acpi_device_path(dev, path, sizeof(path)); > + if (ret) > + return log_msg_ret("path", ret); > + acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT, > + ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path); > + > + acpi_inc_align(ctx, dbg2->header.length); > + acpi_add_table(ctx, dbg2); > + > + return 0; > +} > + > static void acpi_create_facs(struct acpi_facs *facs) > { > memset((void *)facs, 0, sizeof(struct acpi_facs)); > @@ -439,6 +484,71 @@ int acpi_create_hpet(struct acpi_hpet *hpet) > return 0; > } > > +void acpi_create_dbg2(struct acpi_dbg2_header *dbg2, > + int port_type, int port_subtype, > + struct acpi_gen_regaddr *address, u32 address_size, > + const char *device_path) But this one would be usable by any of the architectures supported by ACPI. Could the acpi_create_* functions be moved somewhere non-arch-specific, like a new lib/acpi? / Leif > +{ > + uintptr_t current; > + struct acpi_dbg2_device *device; > + u32 *dbg2_addr_size; > + struct acpi_table_header *header; > + size_t path_len; > + const char *path; > + char *namespace; > + > + /* Fill out header fields. */ > + current = (uintptr_t)dbg2; > + memset(dbg2, '\0', sizeof(struct acpi_dbg2_header)); > + header = &dbg2->header; > + > + header->revision = acpi_get_table_revision(ACPITAB_DBG2); > + acpi_fill_header(header, "DBG2"); > + header->aslc_revision = ASL_REVISION; > + > + /* One debug device defined */ > + dbg2->devices_offset = sizeof(struct acpi_dbg2_header); > + dbg2->devices_count = 1; > + current += sizeof(struct acpi_dbg2_header); > + > + /* Device comes after the header */ > + device = (struct acpi_dbg2_device *)current; > + memset(device, 0, sizeof(struct acpi_dbg2_device)); > + current += sizeof(struct acpi_dbg2_device); > + > + 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(struct acpi_gen_regaddr)); > + device->base_address_offset = current - (uintptr_t)device; > + current += sizeof(struct acpi_gen_regaddr); > + > + /* 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 = table_compute_checksum((uint8_t *)dbg2, > + header->length); > +} > + > /* > * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c > */ > diff --git a/include/acpi_table.h b/include/acpi_table.h > index 1d78665abe..6d91ae85e2 100644 > --- a/include/acpi_table.h > +++ b/include/acpi_table.h > @@ -489,6 +489,29 @@ struct acpi_dmar { > > #define ACPI_DBG2_UNKNOWN 0x00FF > > +/* DBG2: Microsoft Debug Port Table 2 header */ > +struct __packed acpi_dbg2_header { > + struct acpi_table_header header; > + u32 devices_offset; > + u32 devices_count; > +}; > + > +/* DBG2: Microsoft Debug Port Table 2 device entry */ > +struct __packed acpi_dbg2_device { > + u8 revision; > + u16 length; > + u8 address_count; > + u16 namespace_string_length; > + u16 namespace_string_offset; > + u16 oem_data_length; > + u16 oem_data_offset; > + u16 port_type; > + u16 port_subtype; > + u8 reserved[2]; > + u16 base_address_offset; > + u16 address_size_offset; > +}; > + > /* SPCR (Serial Port Console Redirection table) */ > struct __packed acpi_spcr { > struct acpi_table_header header; > @@ -564,6 +587,11 @@ int acpi_get_table_revision(enum acpi_tables table); > */ > int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags); > > +void acpi_create_dbg2(struct acpi_dbg2_header *dbg2, > + int port_type, int port_subtype, > + struct acpi_gen_regaddr *address, uint32_t address_size, > + const char *device_path); > + > /** > * acpi_fill_header() - Set up a new table header > * > @@ -631,6 +659,9 @@ int acpi_write_hpet(struct acpi_ctx *ctx, const struct udevice *dev); > > int acpi_create_hpet(struct acpi_hpet *hpet); > > +int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev, > + uint access_size); > + > #endif /* !__ACPI__*/ > > #include <asm/acpi_table.h> > -- > 2.25.0.341.g760bfbb309-goog >
Hi Leif, On Mon, 27 Jan 2020 at 05:34, Leif Lindholm <leif at nuviainc.com> wrote: > > Hi Simon, > > A portion of this set is very much not x86-specific. (more below) > > On Sun, Jan 26, 2020 at 22:06:31 -0700, Simon Glass wrote: > > Add an implementation of the DBG2 (Debug Port Table 2) ACPI table. > > Adjust one of the header includes to be in the correct order, before > > adding more. > > > > Signed-off-by: Simon Glass <sjg at chromium.org> > > --- > > > > arch/x86/lib/acpi_table.c | 112 +++++++++++++++++++++++++++++++++++++- > > include/acpi_table.h | 31 +++++++++++ > > 2 files changed, 142 insertions(+), 1 deletion(-) > > [..] > > +void acpi_create_dbg2(struct acpi_dbg2_header *dbg2, > > + int port_type, int port_subtype, > > + struct acpi_gen_regaddr *address, u32 address_size, > > + const char *device_path) > > But this one would be usable by any of the architectures supported by > ACPI. Could the acpi_create_* functions be moved somewhere > non-arch-specific, like a new lib/acpi? > > / > Leif OK I'll move this one. In general I don't know which ones are generic and I'd rather keep them x86-specific unless we know. Regards, Simon
diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index a810b12cfe..f12344de50 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -8,6 +8,8 @@ #include <common.h> #include <acpigen.h> +#include <acpi_device.h> +#include <acpi_table.h> #include <cpu.h> #include <dm.h> #include <dm/uclass-internal.h> @@ -15,7 +17,6 @@ #include <serial.h> #include <version.h> #include <asm/acpi/global_nvs.h> -#include <acpi_table.h> #include <asm/ioapic.h> #include <asm/lapic.h> #include <asm/mpspec.h> @@ -52,6 +53,50 @@ int acpi_write_hpet(struct acpi_ctx *ctx, const struct udevice *dev) return 0; } +int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev, + uint access_size) +{ + struct acpi_dbg2_header *dbg2 = ctx->current; + char path[ACPI_PATH_MAX]; + struct acpi_gen_regaddr address; + phys_addr_t addr; + int ret; + + if (!dev) { + log_err("Device not found\n"); + return -ENODEV; + } + if (!device_active(dev)) { + log_info("Device not enabled\n"); + return -EACCES; + } + /* + * PCI devices don't remember their resource allocation information in + * U-Boot at present. We assume that MMIO is used for the UART and that + * the address space is 32 bytes: ns16550 uses 8 registers of up to + * 32-bits each. This is only for debugging so it is not a big deal. + */ + addr = dm_pci_read_bar32(dev, 0); + printf("UART addr %lx\n", (ulong)addr); + + memset(&address, '\0', sizeof(address)); + address.space_id = ACPI_ADDRESS_SPACE_MEMORY; + address.addrl = (uint32_t)addr; + address.addrh = (uint32_t)((addr >> 32) & 0xffffffff); + address.access_size = access_size; + + ret = acpi_device_path(dev, path, sizeof(path)); + if (ret) + return log_msg_ret("path", ret); + acpi_create_dbg2(dbg2, ACPI_DBG2_SERIAL_PORT, + ACPI_DBG2_16550_COMPATIBLE, &address, 0x1000, path); + + acpi_inc_align(ctx, dbg2->header.length); + acpi_add_table(ctx, dbg2); + + return 0; +} + static void acpi_create_facs(struct acpi_facs *facs) { memset((void *)facs, 0, sizeof(struct acpi_facs)); @@ -439,6 +484,71 @@ int acpi_create_hpet(struct acpi_hpet *hpet) return 0; } +void acpi_create_dbg2(struct acpi_dbg2_header *dbg2, + int port_type, int port_subtype, + struct acpi_gen_regaddr *address, u32 address_size, + const char *device_path) +{ + uintptr_t current; + struct acpi_dbg2_device *device; + u32 *dbg2_addr_size; + struct acpi_table_header *header; + size_t path_len; + const char *path; + char *namespace; + + /* Fill out header fields. */ + current = (uintptr_t)dbg2; + memset(dbg2, '\0', sizeof(struct acpi_dbg2_header)); + header = &dbg2->header; + + header->revision = acpi_get_table_revision(ACPITAB_DBG2); + acpi_fill_header(header, "DBG2"); + header->aslc_revision = ASL_REVISION; + + /* One debug device defined */ + dbg2->devices_offset = sizeof(struct acpi_dbg2_header); + dbg2->devices_count = 1; + current += sizeof(struct acpi_dbg2_header); + + /* Device comes after the header */ + device = (struct acpi_dbg2_device *)current; + memset(device, 0, sizeof(struct acpi_dbg2_device)); + current += sizeof(struct acpi_dbg2_device); + + 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(struct acpi_gen_regaddr)); + device->base_address_offset = current - (uintptr_t)device; + current += sizeof(struct acpi_gen_regaddr); + + /* 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 = table_compute_checksum((uint8_t *)dbg2, + header->length); +} + /* * QEMU's version of write_acpi_tables is defined in drivers/misc/qfw.c */ diff --git a/include/acpi_table.h b/include/acpi_table.h index 1d78665abe..6d91ae85e2 100644 --- a/include/acpi_table.h +++ b/include/acpi_table.h @@ -489,6 +489,29 @@ struct acpi_dmar { #define ACPI_DBG2_UNKNOWN 0x00FF +/* DBG2: Microsoft Debug Port Table 2 header */ +struct __packed acpi_dbg2_header { + struct acpi_table_header header; + u32 devices_offset; + u32 devices_count; +}; + +/* DBG2: Microsoft Debug Port Table 2 device entry */ +struct __packed acpi_dbg2_device { + u8 revision; + u16 length; + u8 address_count; + u16 namespace_string_length; + u16 namespace_string_offset; + u16 oem_data_length; + u16 oem_data_offset; + u16 port_type; + u16 port_subtype; + u8 reserved[2]; + u16 base_address_offset; + u16 address_size_offset; +}; + /* SPCR (Serial Port Console Redirection table) */ struct __packed acpi_spcr { struct acpi_table_header header; @@ -564,6 +587,11 @@ int acpi_get_table_revision(enum acpi_tables table); */ int acpi_create_dmar(struct acpi_dmar *dmar, enum dmar_flags flags); +void acpi_create_dbg2(struct acpi_dbg2_header *dbg2, + int port_type, int port_subtype, + struct acpi_gen_regaddr *address, uint32_t address_size, + const char *device_path); + /** * acpi_fill_header() - Set up a new table header * @@ -631,6 +659,9 @@ int acpi_write_hpet(struct acpi_ctx *ctx, const struct udevice *dev); int acpi_create_hpet(struct acpi_hpet *hpet); +int acpi_write_dbg2_pci_uart(struct acpi_ctx *ctx, struct udevice *dev, + uint access_size); + #endif /* !__ACPI__*/ #include <asm/acpi_table.h>
Add an implementation of the DBG2 (Debug Port Table 2) ACPI table. Adjust one of the header includes to be in the correct order, before adding more. Signed-off-by: Simon Glass <sjg at chromium.org> --- arch/x86/lib/acpi_table.c | 112 +++++++++++++++++++++++++++++++++++++- include/acpi_table.h | 31 +++++++++++ 2 files changed, 142 insertions(+), 1 deletion(-)