Hi, thank you for your information. On our website you can find email addresses of companies and people. https://www.skymem.info In short, it’s like Google for emails. Best regards, Robert, Skymem team On Wed, Sep 28, 2022 at 4:31 AM Youling Tang <tangyouling@xxxxxxxxxxx> wrote: > > The LoongArch kernel will mainly use the vmlinux.efi image in PE format, > so add it support. > > I tested this on LoongArch 3A5000 machine and works as expected, > > kexec: > $ sudo kexec -l /boot/vmlinux.efi --reuse-cmdline > $ sudo kexec -e > > kdump: > $ sudo kexec -p /boot/vmlinux-kdump.efi --reuse-cmdline --append="nr_cpus=1" > # echo c > /proc/sysrq_trigger > > Signed-off-by: Youling Tang <tangyouling@xxxxxxxxxxx> > --- > kexec/arch/loongarch/Makefile | 2 + > kexec/arch/loongarch/image-header.h | 79 ++++++++++++++ > kexec/arch/loongarch/kexec-elf-loongarch.c | 3 + > kexec/arch/loongarch/kexec-loongarch.c | 19 ++++ > kexec/arch/loongarch/kexec-loongarch.h | 9 ++ > kexec/arch/loongarch/kexec-pei-loongarch.c | 117 +++++++++++++++++++++ > 6 files changed, 229 insertions(+) > create mode 100644 kexec/arch/loongarch/image-header.h > create mode 100644 kexec/arch/loongarch/kexec-pei-loongarch.c > > diff --git a/kexec/arch/loongarch/Makefile b/kexec/arch/loongarch/Makefile > index e5e190a..3b33b96 100644 > --- a/kexec/arch/loongarch/Makefile > +++ b/kexec/arch/loongarch/Makefile > @@ -3,6 +3,7 @@ > # > loongarch_KEXEC_SRCS = kexec/arch/loongarch/kexec-loongarch.c > loongarch_KEXEC_SRCS += kexec/arch/loongarch/kexec-elf-loongarch.c > +loongarch_KEXEC_SRCS += kexec/arch/loongarch/kexec-pei-loongarch.c > loongarch_KEXEC_SRCS += kexec/arch/loongarch/kexec-elf-rel-loongarch.c > loongarch_KEXEC_SRCS += kexec/arch/loongarch/crashdump-loongarch.c > > @@ -16,5 +17,6 @@ loongarch_VIRT_TO_PHYS = > > dist += kexec/arch/loongarch/Makefile $(loongarch_KEXEC_SRCS) \ > kexec/arch/loongarch/kexec-loongarch.h \ > + kexec/arch/loongarch/image-header.h \ > kexec/arch/loongarch/crashdump-loongarch.h \ > kexec/arch/loongarch/include/arch/options.h > diff --git a/kexec/arch/loongarch/image-header.h b/kexec/arch/loongarch/image-header.h > new file mode 100644 > index 0000000..3b75765 > --- /dev/null > +++ b/kexec/arch/loongarch/image-header.h > @@ -0,0 +1,79 @@ > +/* > + * LoongArch binary image header. > + */ > + > +#if !defined(__LOONGARCH_IMAGE_HEADER_H) > +#define __LOONGARCH_IMAGE_HEADER_H > + > +#include <endian.h> > +#include <stdint.h> > + > +/** > + * struct loongarch_image_header > + * > + * @pe_sig: Optional PE format 'MZ' signature. > + * @reserved_1: Reserved. > + * @kernel_entry: Kernel image entry pointer. > + * @image_size: An estimated size of the memory image size in LSB byte order. > + * @text_offset: The image load offset in LSB byte order. > + * @reserved_2: Reserved. > + * @reserved_3: Reserved. > + * @pe_header: Optional offset to a PE format header. > + **/ > + > +struct loongarch_image_header { > + uint8_t pe_sig[2]; > + uint16_t reserved_1[3]; > + uint64_t kernel_entry; > + uint64_t image_size; > + uint64_t text_offset; > + uint64_t reserved_2[3]; > + uint32_t reserved_3; > + uint32_t pe_header; > +}; > + > +static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'}; > + > +/** > + * loongarch_header_check_pe_sig - Helper to check the loongarch image header. > + * > + * Returns non-zero if 'MZ' signature is found. > + */ > + > +static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h) > +{ > + if (!h) > + return 0; > + > + return (h->pe_sig[0] == loongarch_image_pe_sig[0] > + && h->pe_sig[1] == loongarch_image_pe_sig[1]); > +} > + > +static inline uint64_t loongarch_header_text_offset( > + const struct loongarch_image_header *h) > +{ > + if (!h) > + return 0; > + > + return le64toh(h->text_offset); > +} > + > +static inline uint64_t loongarch_header_image_size( > + const struct loongarch_image_header *h) > +{ > + if (!h) > + return 0; > + > + return le64toh(h->image_size); > +} > + > +static inline uint64_t loongarch_header_kernel_entry( > + const struct loongarch_image_header *h) > +{ > + if (!h) > + return 0; > + > + return le64toh(h->kernel_entry); > +} > + > +#endif > diff --git a/kexec/arch/loongarch/kexec-elf-loongarch.c b/kexec/arch/loongarch/kexec-elf-loongarch.c > index a5ec356..2bf128f 100644 > --- a/kexec/arch/loongarch/kexec-elf-loongarch.c > +++ b/kexec/arch/loongarch/kexec-elf-loongarch.c > @@ -50,6 +50,7 @@ out: > int elf_loongarch_load(int argc, char **argv, const char *kernel_buf, > off_t kernel_size, struct kexec_info *info) > { > + const struct loongarch_image_header *header = NULL; > unsigned long kernel_segment; > struct mem_ehdr ehdr; > int result; > @@ -76,6 +77,8 @@ int elf_loongarch_load(int argc, char **argv, const char *kernel_buf, > loongarch_mem.text_offset); > dbgprintf("%s: phys_offset: %016lx\n", __func__, > loongarch_mem.phys_offset); > + dbgprintf("%s: PE format: %s\n", __func__, > + (loongarch_header_check_pe_sig(header) ? "yes" : "no")); > > /* create and initialize elf core header segment */ > if (info->kexec_flags & KEXEC_ON_CRASH) { > diff --git a/kexec/arch/loongarch/kexec-loongarch.c b/kexec/arch/loongarch/kexec-loongarch.c > index ce7db2c..3fdba01 100644 > --- a/kexec/arch/loongarch/kexec-loongarch.c > +++ b/kexec/arch/loongarch/kexec-loongarch.c > @@ -165,6 +165,7 @@ int get_memory_ranges(struct memory_range **range, int *ranges, > > struct file_type file_type[] = { > {"elf-loongarch", elf_loongarch_probe, elf_loongarch_load, elf_loongarch_usage}, > + {"pei-loongarch", pei_loongarch_probe, pei_loongarch_load, pei_loongarch_usage}, > }; > int file_types = sizeof(file_type) / sizeof(file_type[0]); > > @@ -172,6 +173,24 @@ int file_types = sizeof(file_type) / sizeof(file_type[0]); > > struct loongarch_mem loongarch_mem; > > +/** > + * loongarch_process_image_header - Process the loongarch image header. > + */ > + > +int loongarch_process_image_header(const struct loongarch_image_header *h) > +{ > + > + if (!loongarch_header_check_pe_sig(h)) > + return EFAILED; > + > + if (h->image_size) { > + loongarch_mem.text_offset = loongarch_header_text_offset(h); > + loongarch_mem.image_size = loongarch_header_image_size(h); > + } > + > + return 0; > +} > + > void arch_usage(void) > { > printf(loongarch_opts_usage); > diff --git a/kexec/arch/loongarch/kexec-loongarch.h b/kexec/arch/loongarch/kexec-loongarch.h > index cb9b79a..5120a26 100644 > --- a/kexec/arch/loongarch/kexec-loongarch.h > +++ b/kexec/arch/loongarch/kexec-loongarch.h > @@ -3,6 +3,8 @@ > > #include <sys/types.h> > > +#include "image-header.h" > + > #define BOOT_BLOCK_VERSION 17 > #define BOOT_BLOCK_LAST_COMP_VERSION 16 > > @@ -21,6 +23,13 @@ int elf_loongarch_load(int argc, char **argv, const char *buf, off_t len, > struct kexec_info *info); > void elf_loongarch_usage(void); > > +int pei_loongarch_probe(const char *buf, off_t len); > +int pei_loongarch_load(int argc, char **argv, const char *buf, off_t len, > + struct kexec_info *info); > +void pei_loongarch_usage(void); > + > +int loongarch_process_image_header(const struct loongarch_image_header *h); > + > unsigned long loongarch_locate_kernel_segment(struct kexec_info *info); > int loongarch_load_other_segments(struct kexec_info *info, > unsigned long hole_min); > diff --git a/kexec/arch/loongarch/kexec-pei-loongarch.c b/kexec/arch/loongarch/kexec-pei-loongarch.c > new file mode 100644 > index 0000000..f86ac61 > --- /dev/null > +++ b/kexec/arch/loongarch/kexec-pei-loongarch.c > @@ -0,0 +1,117 @@ > +/* > + * LoongArch kexec PE format binary image support. > + * > + * Copyright (C) 2022 Loongson Technology Corporation Limited. > + * Youling Tang <tangyouling@xxxxxxxxxxx> > + * > + * derived from kexec-image-arm64.c > + * > + * This source code is licensed under the GNU General Public License, > + * Version 2. See the file COPYING for more details. > + */ > + > +#define _GNU_SOURCE > + > +#include <limits.h> > +#include <errno.h> > +#include <elf.h> > + > +#include "kexec.h" > +#include "kexec-elf.h" > +#include "image-header.h" > +#include "kexec-syscall.h" > +#include "crashdump-loongarch.h" > +#include "kexec-loongarch.h" > +#include "arch/options.h" > + > +int pei_loongarch_probe(const char *kernel_buf, off_t kernel_size) > +{ > + const struct loongarch_image_header *h; > + > + if (kernel_size < sizeof(struct loongarch_image_header)) { > + dbgprintf("%s: No loongarch image header.\n", __func__); > + return -1; > + } > + > + h = (const struct loongarch_image_header *)(kernel_buf); > + > + if (!loongarch_header_check_pe_sig(h)) { > + dbgprintf("%s: Bad loongarch PE image header.\n", __func__); > + return -1; > + } > + > + return 0; > +} > + > +int pei_loongarch_load(int argc, char **argv, const char *buf, > + off_t len, struct kexec_info *info) > +{ > + int result; > + unsigned long hole_min = 0; > + unsigned long kernel_segment, kernel_entry; > + const struct loongarch_image_header *header; > + > + header = (const struct loongarch_image_header *)(buf); > + > + if (loongarch_process_image_header(header)) > + return EFAILED; > + > + kernel_segment = loongarch_locate_kernel_segment(info); > + > + if (kernel_segment == ULONG_MAX) { > + dbgprintf("%s: Kernel segment is not allocated\n", __func__); > + result = EFAILED; > + goto exit; > + } > + > + kernel_entry = virt_to_phys(loongarch_header_kernel_entry(header)); > + > + dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment); > + dbgprintf("%s: kernel_entry: %016lx\n", __func__, kernel_entry); > + dbgprintf("%s: image_size: %016lx\n", __func__, > + loongarch_mem.image_size); > + dbgprintf("%s: text_offset: %016lx\n", __func__, > + loongarch_mem.text_offset); > + dbgprintf("%s: phys_offset: %016lx\n", __func__, > + loongarch_mem.phys_offset); > + dbgprintf("%s: PE format: %s\n", __func__, > + (loongarch_header_check_pe_sig(header) ? "yes" : "no")); > + > + /* Get kernel entry point */ > + info->entry = (void *)kernel_entry; > + > + hole_min = kernel_segment + loongarch_mem.image_size; > + > + /* Create and initialize elf core header segment */ > + if (info->kexec_flags & KEXEC_ON_CRASH) { > + result = load_crashdump_segments(info); > + if (result) { > + dbgprintf("%s: Creating eflcorehdr failed.\n", > + __func__); > + goto exit; > + } > + } > + > + /* Load the kernel */ > + add_segment(info, buf, len, kernel_segment, loongarch_mem.image_size); > + > + /* Prepare and load dtb and initrd data */ > + result = loongarch_load_other_segments(info, hole_min); > + if (result) { > + fprintf(stderr, "kexec: Load dtb and initrd segments failed.\n"); > + goto exit; > + } > + > +exit: > + if (result) > + fprintf(stderr, "kexec: load failed.\n"); > + > + return result; > +} > + > +void pei_loongarch_usage(void) > +{ > + printf( > +" An LoongArch PE format binary image, uncompressed, little endian.\n" > +" Typically a vmlinux.efi file.\n\n"); > +} > -- > 2.36.0 > > > _______________________________________________ > kexec mailing list > kexec@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/kexec _______________________________________________ kexec mailing list kexec@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/kexec