On Fri, Oct 16, 2020 at 01:40:57PM +0200, Matthias Brugger wrote: > Hi, > > On 02/10/2020 20:34, Bhupesh Sharma wrote: > > Hello Matthias, > > > > Thanks for the updated revision. > > > > On Fri, Oct 2, 2020 at 7:13 PM <matthias.bgg@xxxxxxxxxx> wrote: > > > > > > From: Matthias Brugger <mbrugger@xxxxxxxx> > > > > > > Add option to allow purgatory printing on arm64 hardware > > > by passing the console name which should be used. > > > Based on a patch by Geoff Levand. > > > > > > Cc: Geoff Levand <geoff@xxxxxxxxxxxxx> > > > Signed-off-by: Matthias Brugger <mbrugger@xxxxxxxx> > > > > > > --- > > > > > > Changes in v4: > > > - fix snprintf error handling > > > > > > Changes in v3: > > > - check return value of snprintf > > > > > > Changes in v2: > > > - use sizeof(buffer) > > > - user serial command option instead of console > > > - reduce buffer to size 10 > > > - use snprintf > > > - fix error handling for wrong serial console parameter > > > - Update help information > > > > > > kexec/arch/arm64/include/arch/options.h | 6 ++- > > > kexec/arch/arm64/kexec-arm64.c | 71 +++++++++++++++++++++++++ > > > purgatory/arch/arm64/purgatory-arm64.c | 17 +++++- > > > 3 files changed, 92 insertions(+), 2 deletions(-) > > > > > > diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h > > > index a17d933..8c695f3 100644 > > > --- a/kexec/arch/arm64/include/arch/options.h > > > +++ b/kexec/arch/arm64/include/arch/options.h > > > @@ -5,7 +5,8 @@ > > > #define OPT_DTB ((OPT_MAX)+1) > > > #define OPT_INITRD ((OPT_MAX)+2) > > > #define OPT_REUSE_CMDLINE ((OPT_MAX)+3) > > > -#define OPT_ARCH_MAX ((OPT_MAX)+4) > > > +#define OPT_SERIAL ((OPT_MAX)+4) > > > +#define OPT_ARCH_MAX ((OPT_MAX)+5) > > > > > > #define KEXEC_ARCH_OPTIONS \ > > > KEXEC_OPTIONS \ > > > @@ -13,6 +14,7 @@ > > > { "command-line", 1, NULL, OPT_APPEND }, \ > > > { "dtb", 1, NULL, OPT_DTB }, \ > > > { "initrd", 1, NULL, OPT_INITRD }, \ > > > + { "serial", 1, NULL, OPT_SERIAL }, \ > > > { "ramdisk", 1, NULL, OPT_INITRD }, \ > > > { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \ > > > > > > @@ -25,6 +27,7 @@ static const char arm64_opts_usage[] __attribute__ ((unused)) = > > > " --command-line=STRING Set the kernel command line to STRING.\n" > > > " --dtb=FILE Use FILE as the device tree blob.\n" > > > " --initrd=FILE Use FILE as the kernel initial ramdisk.\n" > > > +" --serial=STRING Name of console used for purgatory printing. (e.g. ttyAMA0)\n" > > > " --ramdisk=FILE Use FILE as the kernel initial ramdisk.\n" > > > " --reuse-cmdline Use kernel command line from running system.\n"; > > > > > > @@ -32,6 +35,7 @@ struct arm64_opts { > > > const char *command_line; > > > const char *dtb; > > > const char *initrd; > > > + const char *console; > > > }; > > > > > > extern struct arm64_opts arm64_opts; > > > diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c > > > index 45ebc54..6f572ed 100644 > > > --- a/kexec/arch/arm64/kexec-arm64.c > > > +++ b/kexec/arch/arm64/kexec-arm64.c > > > @@ -165,6 +165,8 @@ int arch_process_options(int argc, char **argv) > > > break; > > > case OPT_KEXEC_FILE_SYSCALL: > > > do_kexec_file_syscall = 1; > > > + case OPT_SERIAL: > > > + arm64_opts.console = optarg; > > > break; > > > default: > > > break; /* Ignore core and unknown options. */ > > > @@ -180,12 +182,72 @@ int arch_process_options(int argc, char **argv) > > > dbgprintf("%s:%d: dtb: %s\n", __func__, __LINE__, > > > (do_kexec_file_syscall && arm64_opts.dtb ? "(ignored)" : > > > arm64_opts.dtb)); > > > + dbgprintf("%s:%d: console: %s\n", __func__, __LINE__, > > > + arm64_opts.console); > > > + > > > if (do_kexec_file_syscall) > > > arm64_opts.dtb = NULL; > > > > > > return 0; > > > } > > > > > > +/** > > > + * find_purgatory_sink - Find a sink for purgatory output. > > > + */ > > > + > > > +static uint64_t find_purgatory_sink(const char *console) > > > +{ > > > + int fd, ret; > > > + char device[255], mem[255]; > > > + struct stat sb; > > > + char buffer[10]; > > > + uint64_t iomem = 0x0; > > > + > > > + if (!console) > > > + return 0; > > > + > > > + ret = snprintf(device, sizeof(device), "/sys/class/tty/%s", console); > > > + if (ret < 0 || ret >= sizeof(device)) { > > > + fprintf(stderr, "snprintf failed: %s\n", strerror(errno)); > > > + return 0; > > > + } > > > + > > > + if (stat(device, &sb) || !S_ISDIR(sb.st_mode)) { > > > + fprintf(stderr, "kexec: %s: No valid console found for %s\n", > > > + __func__, device); > > > + return 0; > > > + } > > > + > > > + ret = snprintf(mem, sizeof(mem), "%s%s", device, "/iomem_base"); > > > + if (ret < 0 || ret >= sizeof(mem)) { > > > + fprintf(stderr, "snprintf failed: %s\n", strerror(errno)); > > > + return 0; > > > + } > > > + > > > + printf("console memory read from %s\n", mem); > > > + > > > + fd = open(mem, O_RDONLY); > > > + if (fd < 0) { > > > + fprintf(stderr, "kexec: %s: No able to open %s\n", > > > + __func__, mem); > > > + return 0; > > > + } > > > + > > > + memset(buffer, '\0', sizeof(buffer)); > > > + ret = read(fd, buffer, sizeof(buffer)); > > > + if (ret < 0) { > > > + fprintf(stderr, "kexec: %s: not able to read fd\n", __func__); > > > + close(fd); > > > + return 0; > > > + } > > > + > > > + sscanf(buffer, "%lx", &iomem); > > > + printf("console memory is at %#lx\n", iomem); > > > + > > > + close(fd); > > > + return iomem; > > > +} > > > + > > > /** > > > * struct dtb - Info about a binary device tree. > > > * > > > @@ -637,6 +699,7 @@ int arm64_load_other_segments(struct kexec_info *info, > > > unsigned long hole_min; > > > unsigned long hole_max; > > > unsigned long initrd_end; > > > + uint64_t purgatory_sink; > > > char *initrd_buf = NULL; > > > struct dtb dtb; > > > char command_line[COMMAND_LINE_SIZE] = ""; > > > @@ -654,6 +717,11 @@ int arm64_load_other_segments(struct kexec_info *info, > > > command_line[sizeof(command_line) - 1] = 0; > > > } > > > > > > + purgatory_sink = find_purgatory_sink(arm64_opts.console); > > > + > > > + dbgprintf("%s:%d: purgatory sink: 0x%" PRIx64 "\n", __func__, __LINE__, > > > + purgatory_sink); > > > + > > > if (arm64_opts.dtb) { > > > dtb.name = "dtb_user"; > > > dtb.buf = slurp_file(arm64_opts.dtb, &dtb.size); > > > @@ -742,6 +810,9 @@ int arm64_load_other_segments(struct kexec_info *info, > > > > > > info->entry = (void *)elf_rel_get_addr(&info->rhdr, "purgatory_start"); > > > > > > + elf_rel_set_symbol(&info->rhdr, "arm64_sink", &purgatory_sink, > > > + sizeof(purgatory_sink)); > > > + > > > elf_rel_set_symbol(&info->rhdr, "arm64_kernel_entry", &image_base, > > > sizeof(image_base)); > > > > > > diff --git a/purgatory/arch/arm64/purgatory-arm64.c b/purgatory/arch/arm64/purgatory-arm64.c > > > index fe50fcf..b4d8578 100644 > > > --- a/purgatory/arch/arm64/purgatory-arm64.c > > > +++ b/purgatory/arch/arm64/purgatory-arm64.c > > > @@ -5,15 +5,30 @@ > > > #include <stdint.h> > > > #include <purgatory.h> > > > > > > +/* Symbols set by kexec. */ > > > + > > > +uint8_t *arm64_sink __attribute__ ((section ("data"))); > > > +extern void (*arm64_kernel_entry)(uint64_t, uint64_t, uint64_t, uint64_t); > > > +extern uint64_t arm64_dtb_addr; > > > + > > > void putchar(int ch) > > > { > > > - /* Nothing for now */ > > > + if (!arm64_sink) > > > + return; > > > + > > > + *arm64_sink = ch; > > > + > > > + if (ch == '\n') > > > + *arm64_sink = '\r'; > > > } > > > > > > void post_verification_setup_arch(void) > > > { > > > + printf("purgatory: booting kernel now\n"); > > > } > > > > > > void setup_arch(void) > > > { > > > + printf("purgatory: entry=%lx\n", (unsigned long)arm64_kernel_entry); > > > + printf("purgatory: dtb=%lx\n", arm64_dtb_addr); > > > } > > > -- > > > 2.28.0 > > > > Looks good to me, so: > > Acked-by: Bhupesh Sharma <bhsharma@xxxxxxxxxx> > > > > Simon: friendly reminder of this patch. Please let me know if you have any > concerns regarding the patch. > > Best regards, > Matthias > Sorry for the extended delay, I've applied and pushed this change. _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec