From 4d08e9803fe68d2b1f26e310fd7aa479affddc48 Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Sat, 18 Feb 2023 21:48:51 +0100 Subject: [PATCH] add devicetree support on x86 Since linux kernel has dropped support for simple firmware interface (SFI), the only way of boot newer versions on intel MID platform is using devicetree --- kexec/arch/i386/include/arch/options.h | 4 +++- kexec/arch/i386/kexec-beoboot-x86.c | 2 +- kexec/arch/i386/kexec-bzImage.c | 21 ++++++++++++++++++++- kexec/arch/i386/kexec-x86.h | 1 + kexec/arch/i386/x86-linux-setup.c | 15 +++++++++++++++ kexec/arch/i386/x86-linux-setup.h | 2 ++ kexec/arch/x86_64/kexec-bzImage64.c | 2 +- 7 files changed, 43 insertions(+), 4 deletions(-) diff --git a/kexec/arch/i386/include/arch/options.h b/kexec/arch/i386/include/arch/options.h index 0e57951..89e0a95 100644 --- a/kexec/arch/i386/include/arch/options.h +++ b/kexec/arch/i386/include/arch/options.h @@ -33,6 +33,7 @@ #define OPT_PASS_MEMMAP_CMDLINE (OPT_ARCH_MAX+11) #define OPT_NOEFI (OPT_ARCH_MAX+12) #define OPT_REUSE_VIDEO_TYPE (OPT_ARCH_MAX+13) +#define OPT_DTB (OPT_ARCH_MAX+14) /* Options relevant to the architecture (excluding loader-specific ones): */ #define KEXEC_ARCH_OPTIONS \ @@ -76,7 +77,8 @@ { "args-none", 0, NULL, OPT_ARGS_NONE }, \ { "module", 1, 0, OPT_MOD }, \ { "real-mode", 0, NULL, OPT_REAL_MODE }, \ - { "entry-32bit", 0, NULL, OPT_ENTRY_32BIT }, + { "entry-32bit", 0, NULL, OPT_ENTRY_32BIT }, \ + { "dtb", 1, NULL, OPT_DTB }, #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR diff --git a/kexec/arch/i386/kexec-beoboot-x86.c b/kexec/arch/i386/kexec-beoboot-x86.c index b121834..d949ab8 100644 --- a/kexec/arch/i386/kexec-beoboot-x86.c +++ b/kexec/arch/i386/kexec-beoboot-x86.c @@ -125,7 +125,7 @@ int beoboot_load(int argc, char **argv, const char *buf, off_t UNUSED(len), kernel, bb_header.kernel_size, command_line, bb_header.cmdline_size, initrd, bb_header.initrd_size, - real_mode_entry); + 0, 0, real_mode_entry); return result; } diff --git a/kexec/arch/i386/kexec-bzImage.c b/kexec/arch/i386/kexec-bzImage.c index df8985d..1b8f20c 100644 --- a/kexec/arch/i386/kexec-bzImage.c +++ b/kexec/arch/i386/kexec-bzImage.c @@ -95,6 +95,7 @@ void bzImage_usage(void) " --reuse-cmdline Use kernel command line from running system.\n" " --initrd=FILE Use FILE as the kernel's initial ramdisk.\n" " --ramdisk=FILE Use FILE as the kernel's initial ramdisk.\n" + " --dtb=FILE Use FILE as devicetree.\n" ); } @@ -103,6 +104,7 @@ int do_bzImage_load(struct kexec_info *info, const char *kernel, off_t kernel_len, const char *command_line, off_t command_line_len, const char *initrd, off_t initrd_len, + const char *dtb, off_t dtb_len, int real_mode_entry) { struct x86_linux_header setup_header; @@ -373,6 +375,10 @@ int do_bzImage_load(struct kexec_info *info, setup_linux_system_parameters(info, real_mode); } + if (dtb) { + setup_linux_dtb(info, real_mode, dtb, dtb_len); + } + return 0; } @@ -381,13 +387,15 @@ int bzImage_load(int argc, char **argv, const char *buf, off_t len, { char *command_line = NULL; char *tmp_cmdline = NULL; - const char *ramdisk, *append = NULL; + const char *ramdisk, *append = NULL, *dtb; char *ramdisk_buf; off_t ramdisk_length; int command_line_len; int real_mode_entry; int opt; int result; + char *dtb_buf; + off_t dtb_length; /* See options.h -- add any more there, too. */ static const struct option options[] = { @@ -398,6 +406,7 @@ int bzImage_load(int argc, char **argv, const char *buf, off_t len, { "initrd", 1, 0, OPT_RAMDISK }, { "ramdisk", 1, 0, OPT_RAMDISK }, { "real-mode", 0, 0, OPT_REAL_MODE }, + { "dtb", 1, 0, OPT_DTB }, { 0, 0, 0, 0 }, }; static const char short_options[] = KEXEC_ARCH_OPT_STR "d"; @@ -405,6 +414,8 @@ int bzImage_load(int argc, char **argv, const char *buf, off_t len, real_mode_entry = 0; ramdisk = 0; ramdisk_length = 0; + dtb = 0; + dtb_length = 0; while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { switch(opt) { default: @@ -424,6 +435,9 @@ int bzImage_load(int argc, char **argv, const char *buf, off_t len, case OPT_REAL_MODE: real_mode_entry = 1; break; + case OPT_DTB: + dtb = optarg; + break; } } command_line = concat_cmdline(tmp_cmdline, append); @@ -441,10 +455,15 @@ int bzImage_load(int argc, char **argv, const char *buf, off_t len, if (ramdisk) { ramdisk_buf = slurp_file(ramdisk, &ramdisk_length); } + dtb_buf = 0; + if (dtb) { + dtb_buf = slurp_file(dtb, &dtb_length); + } result = do_bzImage_load(info, buf, len, command_line, command_line_len, ramdisk_buf, ramdisk_length, + dtb_buf, dtb_length, real_mode_entry); free(command_line); diff --git a/kexec/arch/i386/kexec-x86.h b/kexec/arch/i386/kexec-x86.h index 71e4329..46e2898 100644 --- a/kexec/arch/i386/kexec-x86.h +++ b/kexec/arch/i386/kexec-x86.h @@ -79,6 +79,7 @@ int do_bzImage_load(struct kexec_info *info, const char *kernel, off_t kernel_len, const char *command_line, off_t command_line_len, const char *initrd, off_t initrd_len, + const char *dtb, off_t dtb_len, int real_mode_entry); int beoboot_probe(const char *buf, off_t len); diff --git a/kexec/arch/i386/x86-linux-setup.c b/kexec/arch/i386/x86-linux-setup.c index 14263b0..9a281dc 100644 --- a/kexec/arch/i386/x86-linux-setup.c +++ b/kexec/arch/i386/x86-linux-setup.c @@ -954,3 +954,18 @@ void setup_linux_system_parameters(struct kexec_info *info, /* Always try to fill acpi_rsdp_addr */ real_mode->acpi_rsdp_addr = get_acpi_rsdp(); } + +void setup_linux_dtb(struct kexec_info *info, struct x86_linux_param_header *real_mode, + const char *dtb_buf, int dtb_len) +{ + struct setup_data *sd; + + sd = xmalloc(sizeof(struct setup_data) + dtb_len); + sd->next = 0; + sd->len = dtb_len; + sd->type = SETUP_DTB; + memcpy(sd->data, dtb_buf, dtb_len); + + + add_setup_data(info, real_mode, sd); +} diff --git a/kexec/arch/i386/x86-linux-setup.h b/kexec/arch/i386/x86-linux-setup.h index 0c651e5..b5e1ad5 100644 --- a/kexec/arch/i386/x86-linux-setup.h +++ b/kexec/arch/i386/x86-linux-setup.h @@ -21,6 +21,8 @@ static inline void setup_linux_bootloader_parameters( } void setup_linux_system_parameters(struct kexec_info *info, struct x86_linux_param_header *real_mode); +void setup_linux_dtb(struct kexec_info *info, struct x86_linux_param_header *real_mode, + const char *dtb_buf, int dtb_len); int get_bootparam(void *buf, off_t offset, size_t size); diff --git a/kexec/arch/x86_64/kexec-bzImage64.c b/kexec/arch/x86_64/kexec-bzImage64.c index ba8dc48..aba4e3b 100644 --- a/kexec/arch/x86_64/kexec-bzImage64.c +++ b/kexec/arch/x86_64/kexec-bzImage64.c @@ -386,7 +386,7 @@ int bzImage64_load(int argc, char **argv, const char *buf, off_t len, if (entry_16bit || entry_32bit) result = do_bzImage_load(info, buf, len, command_line, command_line_len, ramdisk_buf, - ramdisk_length, entry_16bit); + ramdisk_length, 0, 0, entry_16bit); else result = do_bzImage64_load(info, buf, len, command_line, command_line_len, ramdisk_buf, -- 2.39.1