Attention is currently required from: Martin L Roth.
Jakub Czapiga has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/70110 )
Change subject: [WIP][DO NOT MERGE] ssdtgen: ACPI SSDT generator ......................................................................
[WIP][DO NOT MERGE] ssdtgen: ACPI SSDT generator
Work in progress. TODO: - Documentation - Better help - Dynamic/config-based mocks - Modular devicetree (multi-override in sconfig?) - Cleanup
Signed-off-by: Jakub Czapiga jacz@semihalf.com Change-Id: I78766cd1f47e24b2cd7f9b5cf1cca066441ead06 --- M Makefile A ssdtgen/Makefile.inc A ssdtgen/devicetree.cb A ssdtgen/fw_config.c A ssdtgen/mock/fsp/util.h A ssdtgen/mock/gpio.c A ssdtgen/mock/soc/gpio.h A ssdtgen/mock/soc/nvs.h A ssdtgen/ssdtgen.h A ssdtgen/ssdtgen_main.c A ssdtgen/ssdtgen_sys.c 11 files changed, 442 insertions(+), 4 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/10/70110/1
diff --git a/Makefile b/Makefile index 58cd85b..a83d273 100644 --- a/Makefile +++ b/Makefile @@ -115,20 +115,29 @@ ifneq ($(filter %clean lint% help% what-jenkins-does,$(MAKECMDGOALS)),) NOMKDIR:=1 UNIT_TEST:=1 +SSDTGEN:=1 endif endif
-ifneq ($(filter help%, $(MAKECMDGOALS)), ) +ifneq ($(filter help%,$(MAKECMDGOALS)),) NOCOMPILE:=1 UNIT_TEST:=1 +SSDTGEN:=1 else -ifneq ($(filter %-test %-tests %coverage-report, $(MAKECMDGOALS)),) -ifneq ($(filter-out %-test %-tests %coverage-report, $(MAKECMDGOALS)),) +ifneq ($(filter %-test %-tests %coverage-report,$(MAKECMDGOALS)),) +ifneq ($(filter-out %-test %-tests %coverage-report,$(MAKECMDGOALS)),) $(error Cannot mix unit-tests targets with other targets) endif UNIT_TEST:=1 NOCOMPILE:= endif +ifneq ($(filter %ssdtgen,$(MAKECMDGOALS)),) +ifneq ($(filter-out %ssdtgen,$(MAKECMDGOALS)),) +$(error Cannot mix ssdtgen targets with other targets) +endif +SSDTGEN:=1 +NOCOMPILE:= +endif endif
$(xcompile): util/xcompile/xcompile @@ -148,6 +157,7 @@ include $(TOPLEVEL)/util/testing/Makefile.inc -include $(TOPLEVEL)/site-local/Makefile.inc include $(TOPLEVEL)/tests/Makefile.inc +include $(TOPLEVEL)/ssdtgen/Makefile.inc real-all: @echo "Error: Trying to build, but NOCOMPILE is set." >&2 @echo " Please file a bug with the following information:" @@ -158,8 +168,10 @@ else
ifneq ($(UNIT_TEST),1) +ifneq ($(SSDTGEN),1) include $(DOTCONFIG) endif +endif
# The toolchain requires xcompile to determine the ARCH_SUPPORTED, so we can't # wait for make to generate the file. @@ -191,8 +203,10 @@ endif
ifneq ($(UNIT_TEST),1) +ifneq ($(SSDTGEN),1) include toolchain.inc endif +endif
strip_quotes = $(strip $(subst ",,$(subst ",,$(1)))) # fix makefile syntax highlighting after strip macro " ")) @@ -294,10 +308,14 @@ subdirs:=$(TOPLEVEL) postinclude-hooks :=
-# Don't iterate through Makefile.incs under src/ when building tests +# Don't iterate through Makefile.incs under src/ when building tests or ssdtgen ifneq ($(UNIT_TEST),1) +ifneq ($(SSDTGEN),1) $(eval $(call evaluate_subdirs)) else +include $(TOPLEVEL)/ssdtgen/Makefile.inc +endif +else include $(TOPLEVEL)/tests/Makefile.inc endif
diff --git a/ssdtgen/Makefile.inc b/ssdtgen/Makefile.inc new file mode 100644 index 0000000..601497f --- /dev/null +++ b/ssdtgen/Makefile.inc @@ -0,0 +1,144 @@ +# SPDX-License-Identifier: GPL-2.0-only + +# Import SCONFIG utility required by this file +subdirs := $(top)/util/sconfig +$(call evaluate_subdirs) + +testobj := $(obj)/ssdtgen +ssdtgenobj := $(testobj)/ssdtgen + +ifeq ($(SSDT_CONFIG),) +$(error SSDT_CONFIG= not provided) +endif +TEST_DEFAULT_CONFIG := $(SSDT_CONFIG) +include $(TEST_DEFAULT_CONFIG) + +# Build info file. To satisfy sources +build_h := $(ssdtgenobj)/build.h + +$(build_h): $$(shell $$(build_h_check)) + @printf " GEN build.h\n" + mkdir -p $(dir $@) + $(top)/util/genbuild_h/genbuild_h.sh /dev/null >$@ 2>/dev/null; + + +# Devicetree configuration +# User should provide path to devicetree and optionaly to chipset and override devicetree +# in DEVICETREE, CHIPSET_DEVICETREE and OVERRIDE_DEVICETREE +ifeq ($(DEVICETREE),) +$(error DEVICETREE= unset, but required) +endif +SCONFIG_OPTIONS := --mainboard_devtree=$(DEVICETREE) + +ifneq ($(OVERRIDE_DEVICETREE),) +SCONFIG_OPTIONS += --override_devtree=$(OVERRIDE_DEVICETREE) +endif + +ifneq ($(CHIPSET_DEVICETREE),) +SCONFIG_OPTIONS += --chipset_devtree=$(CHIPSET_DEVICETREE) +endif + +DEVICETREE_STATIC_C := $(ssdtgenobj)/static.c +SCONFIG_OPTIONS += --output_c=$(DEVICETREE_STATIC_C) + +DEVICETREE_STATIC_H := $(ssdtgenobj)/static.h +SCONFIG_OPTIONS += --output_h=$(DEVICETREE_STATIC_H) + +DEVICETREE_DEVICENAMES_H := $(ssdtgenobj)/static_devices.h +SCONFIG_OPTIONS += --output_d=$(DEVICETREE_DEVICENAMES_H) + +DEVICETREE_FWCONFIG_H := $(ssdtgenobj)/static_fw_config.h +SCONFIG_OPTIONS += --output_f=$(DEVICETREE_FWCONFIG_H) + +$(DEVICETREE_STATIC_C): $(DEVICETREE) $(OVERRIDE_DEVICETREE) $(CHIPSET_DEVICETREE) $(objutil)/sconfig/sconfig $(build_h) + @printf " SCONFIG $(subst $(src)/,,$(<))\n" + mkdir -p $(dir $(DEVICETREE_STATIC_C)) + $(objutil)/sconfig/sconfig $(SCONFIG_OPTIONS) + +# Get all chips to load appropriate files +chips := $(shell cat $(DEVICETREE) $(OVERRIDE_DEVICETREE) $(CHIPSET_DEVICETREE) \ + | perl -lne '/^\s*chip\s+((\w+/?)+)\s*$$/ && print $1' | sort | uniq) + + +# Get ramstage sources +$(call add-class,ramstage) + +subdirs-y := src/lib src/device src/acpi +subdirs-y += $(addprefix src/,$(chips)) +subdirs-$(CONFIG_HAVE_SMI_HANDLER) += src/cpu/x86/smm + +subdirs := $(addprefix $(top)/,$(subdirs-y)) +$(call evaluate_subdirs) + +# Use testing framework +include $(top)/tests/Makefile.common + + +# Test framework is not needed +ssdtgen-no_test_framework := yes + +# ACPI tables are generated in ramstage +ssdtgen-stage := ramstage + +# Main generator code +ssdtgen-srcs += ssdtgen/ssdtgen_main.c +ssdtgen-syssrcs += ssdtgen/ssdtgen_sys.c + +# Mocks +ssdtgen-srcs += ssdtgen/fw_config.c + +# SoC ACPI GPIO +ssdtgen-srcs += $(if $(CONFIG_SOC_INTEL_COMMON_BLOCK_ACPI), src/soc/intel/common/block/acpi/gpio.c) +ssdtgen-srcs += $(if $(CONFIG_SOC_AMD_COMMON_BLOCK_ACPI_GPIO), src/soc/amd/common/block/acpi/gpio.c) + +# Include configurad sources, exclude conflicting files +files-to-exclude := src/lib/hardwaremain.c \ + src/lib/fmap.c \ + src/lib/malloc.c + +ssdtgen-srcs += $(filter-out $(files-to-exclude), \ + $(filter %.c,$(ramstage-srcs))) + +ssdtgen-mocks += fw_config_get fw_config_probe +ssdtgen-cflags += -Issdtgen/mock +ssdtgen-srcs += ssdtgen/mock/gpio.c + +# Provide include path to generated devicetree files +ssdtgen-cflags += -I$(ssdtgenobj) + +ssdtgen-cflags += -Os + +# Generated source file lives in build directory, +# so object file has to match pattern and thus has double nested object path +ssdtgen-objs += $(ssdtgenobj)/$(ssdtgenobj)/static.o + +ssdtgen-srcobjs += $(addprefix $(ssdtgenobj)/, \ + $(patsubst %.c,%.o,$(filter src/%,$(ssdtgen-srcs)))) +ssdtgen-objs += $(addprefix $(ssdtgenobj)/, \ + $(patsubst %.c,%.o,$(ssdtgen-srcs))) +ssdtgen-syslibcobjs += $(addprefix $(ssdtgenobj)/, \ + $(patsubst %.c,%.o,$(ssdtgen-syssrcs))) + +ssdtgen-bin := $(ssdtgenobj)/ssdtgenerator + +$(eval $(call TEST_CC_template,ssdtgen)) + +DEPENDENCIES += $(addsuffix .d,$(basename $(ssdtgen-objs) $(ssdtgen-syslibcobjs))) +-include $(DEPENDENCIES) + +.PHONY: ssdtgen clean-ssdtgen ssdtgen-help + +ssdtgen: $(ssdtgen-bin) + @mkdir -p $(testobj)/output/ + $(ssdtgen-bin) -o $(testobj)/output/ssdt.bin + @echo 'SSDT generated' + +clean-sstdgen: + rm -rf $(testobj) + +help-ssdtgen help:: + @echo '*** coreboot ACPI SSDT generator targets ***' + @echo ' ssdtgen - Build and run ACPI SSDT Generator' # TODO + @echo ' clean-ssdt - Remove all SSDT Generator artifacts' + @echo + diff --git a/ssdtgen/devicetree.cb b/ssdtgen/devicetree.cb new file mode 100644 index 0000000..8673761 --- /dev/null +++ b/ssdtgen/devicetree.cb @@ -0,0 +1,24 @@ + chip drivers/i2c/generic + register "hid" = ""10EC5682"" + register "name" = ""RT58"" + register "desc" = ""Realtek RT5682"" + register "irq_gpio" = "ACPI_GPIO_IRQ_EDGE_BOTH(31)" + register "property_count" = "1" + # Set the jd_src to RT5668_JD1 for jack detection + register "property_list[0].type" = "ACPI_DP_TYPE_INTEGER" + register "property_list[0].name" = ""realtek,jd-src"" + register "property_list[0].integer" = "1" + device i2c 1a on end + end + chip drivers/i2c/generic + register "hid" = ""1234KZ"" + register "name" = ""KZM22"" + register "desc" = ""MyOwnDevice Co."" + register "irq_gpio" = "ACPI_GPIO_IRQ_EDGE_BOTH(32)" + register "property_count" = "1" + # Set the jd_src to RT5668_JD1 for jack detection + register "property_list[0].type" = "ACPI_DP_TYPE_INTEGER" + register "property_list[0].name" = ""kzm, test dev"" + register "property_list[0].integer" = "1" + device i2c 1b on end + end diff --git a/ssdtgen/fw_config.c b/ssdtgen/fw_config.c new file mode 100644 index 0000000..ca6bd9c --- /dev/null +++ b/ssdtgen/fw_config.c @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <fw_config.h> + + +#if !defined(FW_CONFIG_VALUE) +# define FW_CONFIG_VALUE UNDEFINED_FW_CONFIG +#endif + +static uint64_t fw_config_value = FW_CONFIG_VALUE; + +uint64_t fw_config_get(void) +{ + return fw_config_value; +} + +#if CONFIG(FW_CONFIG) + +bool fw_config_probe(const struct fw_config *match) +{ + /* If fw_config is not provisioned, then there is nothing to match. */ + if (!fw_config_is_provisioned()) + return false; + + /* Compare to system value. */ + return (fw_config_get() & match->mask) == match->value; +} + +#endif diff --git a/ssdtgen/mock/fsp/util.h b/ssdtgen/mock/fsp/util.h new file mode 100644 index 0000000..92d6d69 --- /dev/null +++ b/ssdtgen/mock/fsp/util.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SSDTGEN_MOCK_FSP_UTIL_H_ +#define SSDTGEN_MOCK_FSP_UTIL_H_ + +static inline void lb_string_platform_blob_version(struct lb_header *header) +{ + +} + +#endif /* SSDTGEN_MOCK_FSP_UTIL_H_ */ diff --git a/ssdtgen/mock/gpio.c b/ssdtgen/mock/gpio.c new file mode 100644 index 0000000..30c6226 --- /dev/null +++ b/ssdtgen/mock/gpio.c @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <soc/gpio.h> + +int gpio_get(gpio_t gpio) +{ + return 0; +} diff --git a/ssdtgen/mock/soc/gpio.h b/ssdtgen/mock/soc/gpio.h new file mode 100644 index 0000000..6a53afe --- /dev/null +++ b/ssdtgen/mock/soc/gpio.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SSDTGEN_MOCK_SOC_GPIO_H_ +#define SSDTGEN_MOCK_SOC_GPIO_H_ + +#include <inttypes.h> + +typedef uint32_t gpio_t; + +#endif /* SSDTGEN_MOCK_SOC_GPIO_H_ */ diff --git a/ssdtgen/mock/soc/nvs.h b/ssdtgen/mock/soc/nvs.h new file mode 100644 index 0000000..b6fdfdc --- /dev/null +++ b/ssdtgen/mock/soc/nvs.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SSDTGEN_MOCK_SOC_NVS_H +#define SSDTGEN_MOCK_SOC_NVS_H + +#include <stdint.h> + +struct __packed global_nvs { + /* Miscellaneous */ + u16 unused_was_osys; /* 0x00 - 0x01 Operating System */ + u8 smif; /* 0x02 - SMI function call ("TRAP") */ + u8 unused_was_pcnt; /* 0x03 - Processor Count */ + u8 ppcm; /* 0x04 - Max PPC State */ + u8 tlvl; /* 0x05 - Throttle Level Limit */ + u8 lids; /* 0x06 - LID State */ + u8 unused_was_pwrs; /* 0x07 - AC Power State */ + u32 cbmc; /* 0x08 - 0xb coreboot Memory Console */ + u64 pm1i; /* 0x0c - 0x13 PM1 wake status bit */ + u64 gpei; /* 0x14 - 0x1b GPE wake status bit */ + u8 dpte; /* 0x1c - Enable DPTF */ + u64 nhla; /* 0x1d - 0x24 NHLT Address */ + u32 nhll; /* 0x25 - 0x28 NHLT Length */ + u16 unused_was_cid1; /* 0x29 - 0x2a Wifi Country Identifier */ + u16 u2we; /* 0x2b - 0x2c USB2 Wake Enable Bitmap */ + u16 u3we; /* 0x2d - 0x2e USB3 Wake Enable Bitmap */ + u8 uior; /* 0x2f - UART debug controller init on S3 resume */ + u64 hest_log_addr; /* 0x30 - 0x37 err log addr (used in SMM, not ASL code) */ +}; + +#endif diff --git a/ssdtgen/ssdtgen.h b/ssdtgen/ssdtgen.h new file mode 100644 index 0000000..507ab3b --- /dev/null +++ b/ssdtgen/ssdtgen.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <inttypes.h> + +int ssdtgen_parse_args(int argc, char **argv); + +int ssdtgen_save(uint8_t *buf, size_t size); diff --git a/ssdtgen/ssdtgen_main.c b/ssdtgen/ssdtgen_main.c new file mode 100644 index 0000000..91174eb --- /dev/null +++ b/ssdtgen/ssdtgen_main.c @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <acpi/acpigen.h> +#include <console/console.h> +#include <device/device.h> +#include <timer.h> + +#include "ssdtgen.h" + + +/* Temporary mocks TODO: Move to appropriate files */ + +int printk(int msg_level, const char *fmt, ...) +{ + return 0; +} + +int vprintk(int msg_level, const char *fmt, va_list args) +{ + return 0; +} + +void mock_assert(const int result, const char *expression, const char *const file, + const int line) +{ +} + +void smm_region(uintptr_t *start, size_t *size) +{ + *size = 0; + *start = 0; +} + +void do_board_reset(void) +{ + // TODO: Might need implementation +} + +void cmos_post_path(const struct device *dev) +{ + +} + +void timer_monotonic_get(struct mono_time *mt) +{ + mt->microseconds = 0; +} + +/* End of temporary mocks */ + +/* Pre-allocated buffer for generated AML */ +static uint8_t acpigen_data_buf[16 * MiB]; + +int main(int argc, char **argv) +{ + all_devices = &dev_root; + + /* Enable all devices */ + struct device *dev; + for (dev = all_devices; dev; dev = dev->next) { + if (dev && dev->chip_ops && dev->chip_ops->enable_dev) { + dev->chip_ops->enable_dev(dev); + } + } + + const int result = ssdtgen_parse_args(argc, argv); + if (result) + return result; + + acpi_header_t *ssdt_table = (acpi_header_t *)&acpigen_data_buf; + acpi_create_ssdt_generator(ssdt_table, ACPI_TABLE_CREATOR); + + return ssdtgen_save(acpigen_data_buf, ssdt_table->length); +} diff --git a/ssdtgen/ssdtgen_sys.c b/ssdtgen/ssdtgen_sys.c new file mode 100644 index 0000000..493921b --- /dev/null +++ b/ssdtgen/ssdtgen_sys.c @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <errno.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +char *output_file = NULL; + +static void print_usage(const char *name, int exit_code) +{ + printf("usage: %s [OPTIONS]\n", name); + printf("Options:\n" + " -o <path> SSDT table output file path\n" + " -h print this help\n" + "\n"); + exit(exit_code); +} + +int ssdtgen_parse_args(int argc, char **argv) +{ + int c = 0; + opterr = 0; + + while ((c = getopt(argc, argv, "ho:")) != -1) { + switch (c) { + case 'o': + output_file = optarg; + break; + case 'h': + print_usage(argv[0], 0); + break; + case '?': + default: + print_usage(argv[0], 1); + break; + } + } + + if (!output_file) + print_usage(argv[0], 1); + + return 0; +} + +int ssdtgen_save(uint8_t *buf, size_t size) +{ + FILE *f = fopen(output_file, "wb"); + + if (!f) { + perror("Failed to open output file"); + return 1; + } + + if (fwrite(buf, sizeof(uint8_t), size, f) != size) { + perror("Failed to write full contents to file"); + return 1; + } + + fclose(f); + return 0; +} +