Hello community, here is the log from the commit of package kexec-tools for openSUSE:Factory checked in at 2016-08-12 15:36:17 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/kexec-tools (Old) and /work/SRC/openSUSE:Factory/.kexec-tools.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "kexec-tools" Changes: -------- --- /work/SRC/openSUSE:Factory/kexec-tools/kexec-tools.changes 2016-07-01 09:56:35.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.kexec-tools.new/kexec-tools.changes 2016-08-12 15:36:19.000000000 +0200 @@ -1,0 +2,8 @@ +Mon Aug 8 10:47:36 UTC 2016 - ptesa...@suse.com + +- Update to version 2.0.13 + Changelog: http://git.kernel.org/cgit/utils/kernel/kexec/kexec-tools.git/log/?id=refs/tags/v2.0.12..v2.0.13 + +- Refresh kexec-tools-enable-aarch64.patch + +------------------------------------------------------------------- Old: ---- kexec-tools-2.0.12.tar.xz New: ---- kexec-tools-2.0.13.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ kexec-tools.spec ++++++ --- /var/tmp/diff_new_pack.S5wK7V/_old 2016-08-12 15:36:20.000000000 +0200 +++ /var/tmp/diff_new_pack.S5wK7V/_new 2016-08-12 15:36:20.000000000 +0200 @@ -28,7 +28,7 @@ Summary: Tools for fast kernel loading License: GPL-2.0+ Group: System/Kernel -Version: 2.0.12 +Version: 2.0.13 Release: 0 Source: ftp://kernel.org/pub/linux/utils/kernel/kexec/%{name}-%{version}.tar.xz Source1: kexec-bootloader ++++++ kexec-tools-2.0.12.tar.xz -> kexec-tools-2.0.13.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/configure new/kexec-tools-2.0.13/configure --- old/kexec-tools-2.0.12/configure 2016-03-22 02:08:10.000000000 +0100 +++ new/kexec-tools-2.0.13/configure 2016-08-08 12:27:25.000000000 +0200 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for kexec-tools 2.0.12. +# Generated by GNU Autoconf 2.69 for kexec-tools 2.0.13. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -577,8 +577,8 @@ # Identity of this package. PACKAGE_NAME='kexec-tools' PACKAGE_TARNAME='kexec-tools' -PACKAGE_VERSION='2.0.12' -PACKAGE_STRING='kexec-tools 2.0.12' +PACKAGE_VERSION='2.0.13' +PACKAGE_STRING='kexec-tools 2.0.13' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -1268,7 +1268,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures kexec-tools 2.0.12 to adapt to many kinds of systems. +\`configure' configures kexec-tools 2.0.13 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1334,7 +1334,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of kexec-tools 2.0.12:";; + short | recursive ) echo "Configuration of kexec-tools 2.0.13:";; esac cat <<\_ACEOF @@ -1424,7 +1424,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -kexec-tools configure 2.0.12 +kexec-tools configure 2.0.13 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1722,7 +1722,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by kexec-tools $as_me 2.0.12, which was +It was created by kexec-tools $as_me 2.0.13, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -5325,7 +5325,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by kexec-tools $as_me 2.0.12, which was +This file was extended by kexec-tools $as_me 2.0.13, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5387,7 +5387,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -kexec-tools config.status 2.0.12 +kexec-tools config.status 2.0.13 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/configure.ac new/kexec-tools-2.0.13/configure.ac --- old/kexec-tools-2.0.12/configure.ac 2016-03-22 02:07:37.000000000 +0100 +++ new/kexec-tools-2.0.13/configure.ac 2016-08-08 12:25:58.000000000 +0200 @@ -4,7 +4,7 @@ dnl dnl ---Required -AC_INIT(kexec-tools, 2.0.12) +AC_INIT(kexec-tools, 2.0.13) AC_CONFIG_AUX_DIR(./config) AC_CONFIG_HEADERS([include/config.h]) AC_LANG(C) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/include/config.h new/kexec-tools-2.0.13/include/config.h --- old/kexec-tools-2.0.12/include/config.h 2016-03-22 02:08:17.000000000 +0100 +++ new/kexec-tools-2.0.13/include/config.h 2016-08-08 12:27:27.000000000 +0200 @@ -11,7 +11,7 @@ /* #undef HAVE_LIBLZMA */ /* Define to 1 if you have the `xenctrl' library (-lxenctrl). */ -#define HAVE_LIBXENCTRL 1 +/* #undef HAVE_LIBXENCTRL */ /* Define to 1 if you have the `z' library (-lz). */ #define HAVE_LIBZ 1 @@ -47,7 +47,7 @@ #define PACKAGE_NAME "kexec-tools" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "kexec-tools 2.0.12" +#define PACKAGE_STRING "kexec-tools 2.0.13" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "kexec-tools" @@ -56,7 +56,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "2.0.12" +#define PACKAGE_VERSION "2.0.13" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kdump/kdump.c new/kexec-tools-2.0.13/kdump/kdump.c --- old/kexec-tools-2.0.12/kdump/kdump.c 2011-10-03 00:56:38.000000000 +0200 +++ new/kexec-tools-2.0.13/kdump/kdump.c 2016-06-08 02:21:52.000000000 +0200 @@ -25,22 +25,35 @@ #define MAP_WINDOW_SIZE (64*1024*1024) #define DEV_MEM "/dev/mem" +#define ALIGN_MASK(x,y) (((x) + (y)) & ~(y)) +#define ALIGN(x,y) ALIGN_MASK(x, (y) - 1) + static void *map_addr(int fd, unsigned long size, off_t offset) { + unsigned long page_size = getpagesize(); + unsigned long map_offset = offset & (page_size - 1); + size_t len = ALIGN(size + map_offset, page_size); void *result; - result = mmap(0, size, PROT_READ, MAP_SHARED, fd, offset); + + result = mmap(0, len, PROT_READ, MAP_SHARED, fd, offset - map_offset); if (result == MAP_FAILED) { - fprintf(stderr, "Cannot mmap " DEV_MEM " offset: %llu size: %lu: %s\n", + fprintf(stderr, "Cannot mmap " DEV_MEM " offset: %#llx size: %lu: %s\n", (unsigned long long)offset, size, strerror(errno)); exit(5); } - return result; + return result + map_offset; } static void unmap_addr(void *addr, unsigned long size) { + unsigned long page_size = getpagesize(); + unsigned long map_offset = (uintptr_t)addr & (page_size - 1); + size_t len = ALIGN(size + map_offset, page_size); int ret; - ret = munmap(addr, size); + + addr -= map_offset; + + ret = munmap(addr, len); if (ret < 0) { fprintf(stderr, "munmap failed: %s\n", strerror(errno)); @@ -179,6 +192,7 @@ } memcpy(nphdr, &phdr[i], sizeof(*nphdr)); nphdr->p_offset = offset; + nphdr++; offset += phdr[i].p_filesz; } @@ -270,7 +284,8 @@ } /* Get the program header */ - phdr = map_addr(fd, sizeof(*phdr)*(ehdr->e_phnum), ehdr->e_phoff); + phdr = map_addr(fd, sizeof(*phdr)*(ehdr->e_phnum), + start_addr + ehdr->e_phoff); /* Collect up the notes */ note_bytes = 0; @@ -286,7 +301,7 @@ for(i = 0; i < ehdr->e_phnum; i++) { unsigned long long offset, size; size_t wsize; - if (phdr[i].p_type != PT_NOTE) { + if (phdr[i].p_type == PT_NOTE) { continue; } offset = phdr[i].p_offset; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/Makefile new/kexec-tools-2.0.13/kexec/Makefile --- old/kexec-tools-2.0.12/kexec/Makefile 2014-10-14 06:58:06.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/Makefile 2016-06-08 02:21:52.000000000 +0200 @@ -69,6 +69,10 @@ $(ARCH)_FS2DT = KEXEC_SRCS += $($(ARCH)_FS2DT) +dist += kexec/mem_regions.c kexec/mem_regions.h +$(ARCH)_MEM_REGIONS = +KEXEC_SRCS += $($(ARCH)_MEM_REGIONS) + include $(srcdir)/kexec/arch/alpha/Makefile include $(srcdir)/kexec/arch/arm/Makefile include $(srcdir)/kexec/arch/i386/Makefile diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/arm/Makefile new/kexec-tools-2.0.13/kexec/arch/arm/Makefile --- old/kexec-tools-2.0.12/kexec/arch/arm/Makefile 2014-10-14 06:58:06.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/arm/Makefile 2016-06-08 02:24:09.000000000 +0200 @@ -7,6 +7,8 @@ arm_FS2DT_INCLUDE = -include $(srcdir)/kexec/arch/arm/crashdump-arm.h \ -include $(srcdir)/kexec/arch/arm/kexec-arm.h +arm_MEM_REGIONS = kexec/mem_regions.c + arm_KEXEC_SRCS= kexec/arch/arm/kexec-elf-rel-arm.c arm_KEXEC_SRCS+= kexec/arch/arm/kexec-zImage-arm.c arm_KEXEC_SRCS+= kexec/arch/arm/kexec-uImage-arm.c @@ -18,6 +20,9 @@ arm_CPPFLAGS = -I$(srcdir)/kexec/libfdt +# We want 64-bit file IO for kdump to work correctly on LPAE systems +arm_CPPFLAGS += -D_FILE_OFFSET_BITS=64 + arm_KEXEC_SRCS += $(libfdt_SRCS) arm_UIMAGE = kexec/kexec-uImage.c diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/arm/crashdump-arm.c new/kexec-tools-2.0.13/kexec/arch/arm/crashdump-arm.c --- old/kexec-tools-2.0.12/kexec/arch/arm/crashdump-arm.c 2014-10-14 06:58:06.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/arm/crashdump-arm.c 2016-06-08 02:24:10.000000000 +0200 @@ -30,7 +30,10 @@ #include "../../kexec.h" #include "../../kexec-elf.h" #include "../../crashdump.h" +#include "../../mem_regions.h" #include "crashdump-arm.h" +#include "iomem.h" +#include "phys_to_virt.h" #if __BYTE_ORDER == __LITTLE_ENDIAN #define ELFDATANATIVE ELFDATA2LSB @@ -46,12 +49,20 @@ */ static struct memory_range crash_memory_ranges[CRASH_MAX_MEMORY_RANGES]; struct memory_ranges usablemem_rgns = { - .size = 0, - .ranges = crash_memory_ranges, + .max_size = CRASH_MAX_MEMORY_RANGES, + .ranges = crash_memory_ranges, }; -/* memory range reserved for crashkernel */ -static struct memory_range crash_reserved_mem; +/* The boot-time physical memory range reserved for crashkernel region */ +static struct memory_range crash_kernel_mem; + +/* reserved regions */ +#define CRASH_MAX_RESERVED_RANGES 2 +static struct memory_range crash_reserved_ranges[CRASH_MAX_RESERVED_RANGES]; +static struct memory_ranges crash_reserved_rgns = { + .max_size = CRASH_MAX_RESERVED_RANGES, + .ranges = crash_reserved_ranges, +}; static struct crash_elf_info elf_info = { .class = ELFCLASS32, @@ -60,7 +71,6 @@ .page_offset = DEFAULT_PAGE_OFFSET, }; -unsigned long phys_offset; extern unsigned long long user_page_offset; /* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */ @@ -71,25 +81,34 @@ char sym[128]; char line[128]; FILE *fp; - unsigned long long vaddr; + unsigned long long vaddr = 0; char type; - fp = fopen(kallsyms, "r"); if (!fp) { + fp = fopen(kallsyms, "r"); + if (!fp) { fprintf(stderr, "Cannot open %s\n", kallsyms); return 0; } while(fgets(line, sizeof(line), fp) != NULL) { - if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3) + unsigned long long addr; + + if (sscanf(line, "%Lx %c %s", &addr, &type, sym) != 3) continue; + if (strcmp(sym, stext) == 0) { - dbgprintf("kernel symbol %s vaddr = %16llx\n", stext, vaddr); - return vaddr; + dbgprintf("kernel symbol %s vaddr = %#llx\n", stext, addr); + vaddr = addr; + break; } } - fprintf(stderr, "Cannot get kernel %s symbol address\n", stext); - return 0; + fclose(fp); + + if (vaddr == 0) + fprintf(stderr, "Cannot get kernel %s symbol address\n", stext); + + return vaddr; } static int get_kernel_page_offset(struct kexec_info *info, @@ -117,96 +136,6 @@ user_page_offset); } elf_info->page_offset = stext_sym_addr & (~KVBASE_MASK); - dbgprintf("page_offset is set to %llx\n", elf_info->page_offset); - return 0; -} - -/** - * crash_range_callback() - callback called for each iomem region - * @data: not used - * @nr: not used - * @str: name of the memory region - * @base: start address of the memory region - * @length: size of the memory region - * - * This function is called once for each memory region found in /proc/iomem. It - * locates system RAM and crashkernel reserved memory and places these to - * variables: @crash_memory_ranges and @crash_reserved_mem. Number of memory - * regions is placed in @crash_memory_nr_ranges. - */ -static int crash_range_callback(void *UNUSED(data), int UNUSED(nr), - char *str, unsigned long long base, - unsigned long long length) -{ - struct memory_range *range; - - if (usablemem_rgns.size >= CRASH_MAX_MEMORY_RANGES) - return 1; - - range = usablemem_rgns.ranges + usablemem_rgns.size; - - if (strncmp(str, "System RAM\n", 11) == 0) { - range->start = base; - range->end = base + length - 1; - range->type = RANGE_RAM; - usablemem_rgns.size++; - } else if (strncmp(str, "Crash kernel\n", 13) == 0) { - crash_reserved_mem.start = base; - crash_reserved_mem.end = base + length - 1; - crash_reserved_mem.type = RANGE_RAM; - } - - return 0; -} - -/** - * crash_exclude_range() - excludes memory region reserved for crashkernel - * - * Function locates where crashkernel reserved memory is and removes that region - * from the available memory regions. - */ -static void crash_exclude_range(void) -{ - const struct memory_range *range = &crash_reserved_mem; - int i; - - for (i = 0; i < usablemem_rgns.size; i++) { - struct memory_range *r = usablemem_rgns.ranges + i; - - /* - * We assume that crash area is fully contained in - * some larger memory area. - */ - if (r->start <= range->start && r->end >= range->end) { - struct memory_range *new; - /* - * Let's split this area into 2 smaller ones and - * remove excluded range from between. First create - * new entry for the remaining area. - */ - new = usablemem_rgns.ranges + usablemem_rgns.size; - new->start = range->end + 1; - new->end = r->end; - usablemem_rgns.size++; - /* - * Next update this area to end before excluded range. - */ - r->end = range->start - 1; - break; - } - } -} - -static int range_cmp(const void *a1, const void *a2) -{ - const struct memory_range *r1 = a1; - const struct memory_range *r2 = a2; - - if (r1->start > r2->start) - return 1; - if (r1->start < r2->start) - return -1; - return 0; } @@ -221,28 +150,40 @@ */ static int crash_get_memory_ranges(void) { - /* - * First read all memory regions that can be considered as - * system memory including the crash area. - */ - kexec_iomem_for_each_line(NULL, crash_range_callback, NULL); + int i; if (usablemem_rgns.size < 1) { errno = EINVAL; return -1; } + dbgprint_mem_range("Reserved memory ranges", + crash_reserved_rgns.ranges, + crash_reserved_rgns.size); + /* - * Exclude memory reserved for crashkernel (this may result a split memory - * region). + * Exclude all reserved memory from the usable memory regions. + * We want to avoid dumping the crashkernel region itself. Note + * that this may result memory regions in usablemem_rgns being + * split. */ - crash_exclude_range(); + for (i = 0; i < crash_reserved_rgns.size; i++) { + if (mem_regions_exclude(&usablemem_rgns, + &crash_reserved_rgns.ranges[i])) { + fprintf(stderr, + "Error: Number of crash memory ranges excedeed the max limit\n"); + errno = ENOMEM; + return -1; + } + } /* * Make sure that the memory regions are sorted. */ - qsort(usablemem_rgns.ranges, usablemem_rgns.size, - sizeof(*usablemem_rgns.ranges), range_cmp); + mem_regions_sort(&usablemem_rgns); + + dbgprint_mem_range("Coredump memory ranges", + usablemem_rgns.ranges, usablemem_rgns.size); return 0; } @@ -309,8 +250,8 @@ return; dbgprintf("crashkernel: [%#llx - %#llx] (%ldM)\n", - crash_reserved_mem.start, crash_reserved_mem.end, - (unsigned long)range_size(&crash_reserved_mem) >> 20); + crash_kernel_mem.start, crash_kernel_mem.end, + (unsigned long)range_size(&crash_kernel_mem) >> 20); for (i = 0; i < usablemem_rgns.size; i++) { struct memory_range *r = usablemem_rgns.ranges + i; @@ -351,16 +292,30 @@ * region as PHYS_OFFSET. */ phys_offset = usablemem_rgns.ranges->start; - dbgprintf("phys_offset: %#lx\n", phys_offset); if (get_kernel_page_offset(info, &elf_info)) return -1; + dbgprintf("phys offset = %#llx, page offset = %llx\n", + phys_offset, elf_info.page_offset); + + /* + * Ensure that the crash kernel memory range is sane. The crash kernel + * must be located within memory which is visible during booting. + */ + if (crash_kernel_mem.end > ARM_MAX_VIRTUAL) { + fprintf(stderr, + "Crash kernel memory [0x%llx-0x%llx] is inaccessible at boot - unable to load crash kernel\n", + crash_kernel_mem.start, crash_kernel_mem.end); + return -1; + } + last_ranges = usablemem_rgns.size - 1; if (last_ranges < 0) last_ranges = 0; - if (crash_memory_ranges[last_ranges].end > ULONG_MAX) { + if (crash_memory_ranges[last_ranges].end > UINT32_MAX) { + dbgprintf("Using 64-bit ELF core format\n"); /* for support LPAE enabled kernel*/ elf_info.class = ELFCLASS64; @@ -370,6 +325,7 @@ usablemem_rgns.size, &buf, &bufsz, ELF_CORE_HEADER_ALIGN); } else { + dbgprintf("Using 32-bit ELF core format\n"); err = crash_create_elf32_headers(info, &elf_info, usablemem_rgns.ranges, usablemem_rgns.size, &buf, &bufsz, @@ -386,8 +342,8 @@ * regions to be aligned to SECTION_SIZE. */ elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 1 << 20, - crash_reserved_mem.start, - crash_reserved_mem.end, -1, 0); + crash_kernel_mem.start, + crash_kernel_mem.end, -1, 0); dbgprintf("elfcorehdr: %#lx\n", elfcorehdr); cmdline_add_elfcorehdr(mod_cmdline, elfcorehdr); @@ -397,7 +353,7 @@ * prevents the dump capture kernel from using any other memory regions * which belong to the primary kernel. */ - cmdline_add_mem(mod_cmdline, elfcorehdr - crash_reserved_mem.start); + cmdline_add_mem(mod_cmdline, elfcorehdr - crash_kernel_mem.start); dump_memory_ranges(); dbgprintf("kernel command line: \"%s\"\n", mod_cmdline); @@ -405,12 +361,55 @@ return 0; } -int is_crashkernel_mem_reserved(void) +/** + * iomem_range_callback() - callback called for each iomem region + * @data: not used + * @nr: not used + * @str: name of the memory region (not NULL terminated) + * @base: start address of the memory region + * @length: size of the memory region + * + * This function is called for each memory range in /proc/iomem, stores + * the location of the crash kernel range into @crash_kernel_mem, and + * stores the system RAM into @usablemem_rgns. + */ +static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr), + char *str, unsigned long long base, + unsigned long long length) { - uint64_t start, end; + if (strncmp(str, CRASH_KERNEL_BOOT, strlen(CRASH_KERNEL_BOOT)) == 0) { + crash_kernel_mem.start = base; + crash_kernel_mem.end = base + length - 1; + crash_kernel_mem.type = RANGE_RAM; + return mem_regions_add(&crash_reserved_rgns, + base, length, RANGE_RAM); + } + else if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) { + if (crash_kernel_mem.start == crash_kernel_mem.end) { + crash_kernel_mem.start = base; + crash_kernel_mem.end = base + length - 1; + crash_kernel_mem.type = RANGE_RAM; + } + return mem_regions_add(&crash_reserved_rgns, + base, length, RANGE_RAM); + } + else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) { + return mem_regions_add(&usablemem_rgns, + base, length, RANGE_RAM); + } + return 0; +} - if (parse_iomem_single("Crash kernel\n", &start, &end) == 0) - return start != end; +/** + * is_crashkernel_mem_reserved() - check for the crashkernel reserved region + * + * Check for the crashkernel reserved region in /proc/iomem, and return + * true if it is present, or false otherwise. We use this to store the + * location of this region, and system RAM regions. + */ +int is_crashkernel_mem_reserved(void) +{ + kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); - return 0; + return crash_kernel_mem.start != crash_kernel_mem.end; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/arm/crashdump-arm.h new/kexec-tools-2.0.13/kexec/arch/arm/crashdump-arm.h --- old/kexec-tools-2.0.12/kexec/arch/arm/crashdump-arm.h 2014-10-14 06:58:06.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/arm/crashdump-arm.h 2016-06-08 02:24:10.000000000 +0200 @@ -9,13 +9,13 @@ #define DEFAULT_PAGE_OFFSET (0xc0000000) #define KVBASE_MASK (0x1ffffff) #define CRASH_MAX_MEMORY_RANGES 32 +#define ARM_MAX_VIRTUAL UINT32_MAX extern struct memory_ranges usablemem_rgns; struct kexec_info; -extern unsigned long phys_offset; extern int load_crashdump_segments(struct kexec_info *, char *); #ifdef __cplusplus diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/arm/kexec-arm.c new/kexec-tools-2.0.13/kexec/arch/arm/kexec-arm.c --- old/kexec-tools-2.0.12/kexec/arch/arm/kexec-arm.c 2015-11-24 08:04:10.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/arch/arm/kexec-arm.c 2016-06-08 02:24:09.000000000 +0200 @@ -18,6 +18,7 @@ #include "kexec-arm.h" #include <arch/options.h> #include "../../fs2dt.h" +#include "iomem.h" #define MAX_MEMORY_RANGES 64 #define MAX_LINE 160 @@ -51,9 +52,9 @@ if (count != 2) continue; str = line + consumed; - end = end + 1; - if (memcmp(str, "System RAM\n", 11) == 0) { + if (memcmp(str, SYSTEM_RAM_BOOT, strlen(SYSTEM_RAM_BOOT)) == 0 || + memcmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) { type = RANGE_RAM; } else if (memcmp(str, "reserved\n", 9) == 0) { @@ -71,6 +72,9 @@ fclose(fp); *range = memory_range; *ranges = memory_ranges; + + dbgprint_mem_range("MEMORY RANGES", *range, *ranges); + return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/arm/kexec-elf-rel-arm.c new/kexec-tools-2.0.13/kexec/arch/arm/kexec-elf-rel-arm.c --- old/kexec-tools-2.0.12/kexec/arch/arm/kexec-elf-rel-arm.c 2011-10-03 00:56:38.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/arm/kexec-elf-rel-arm.c 2016-03-24 05:59:57.000000000 +0100 @@ -18,8 +18,9 @@ return 1; } -void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), unsigned long r_type, - void *location, unsigned long address, unsigned long value) +void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), + struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, + unsigned long address, unsigned long value) { switch(r_type) { case R_ARM_ABS32: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/arm/kexec-uImage-arm.c new/kexec-tools-2.0.13/kexec/arch/arm/kexec-uImage-arm.c --- old/kexec-tools-2.0.12/kexec/arch/arm/kexec-uImage-arm.c 2013-11-19 02:05:49.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/arch/arm/kexec-uImage-arm.c 2016-06-08 02:22:20.000000000 +0200 @@ -11,7 +11,8 @@ int uImage_arm_probe(const char *buf, off_t len) { - return uImage_probe_kernel(buf, len, IH_ARCH_ARM); + return uImage_probe_kernel((const unsigned char *)buf, len, + IH_ARCH_ARM); } int uImage_arm_load(int argc, char **argv, const char *buf, off_t len, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/arm/kexec-zImage-arm.c new/kexec-tools-2.0.13/kexec/arch/arm/kexec-zImage-arm.c --- old/kexec-tools-2.0.12/kexec/arch/arm/kexec-zImage-arm.c 2015-11-24 08:04:10.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/arch/arm/kexec-zImage-arm.c 2016-07-15 06:12:28.000000000 +0200 @@ -20,6 +20,7 @@ #include "kexec-arm.h" #include "../../fs2dt.h" #include "crashdump-arm.h" +#include "iomem.h" #define BOOT_PARAMS_SIZE 1536 @@ -27,6 +28,31 @@ unsigned int kexec_arm_image_size = 0; unsigned long long user_page_offset = (-1ULL); +struct zimage_header { + uint32_t instr[9]; + uint32_t magic; +#define ZIMAGE_MAGIC cpu_to_le32(0x016f2818) + uint32_t start; + uint32_t end; +}; + +struct android_image { + char magic[8]; + uint32_t kernel_size; + uint32_t kernel_addr; + uint32_t ramdisk_size; + uint32_t ramdisk_addr; + uint32_t stage2_size; + uint32_t stage2_addr; + uint32_t tags_addr; + uint32_t page_size; + uint32_t reserved1; + uint32_t reserved2; + char name[16]; + char command_line[512]; + uint32_t chksum[8]; +}; + struct tag_header { uint32_t size; uint32_t tag; @@ -257,8 +283,9 @@ return 0; } -static int setup_dtb_prop(char **bufp, off_t *sizep, const char *node_name, - const char *prop_name, const void *val, int len) +static int setup_dtb_prop(char **bufp, off_t *sizep, int parentoffset, + const char *node_name, const char *prop_name, + const void *val, int len) { char *dtb_buf; off_t dtb_size; @@ -273,14 +300,14 @@ dtb_size = *sizep; /* check if the subnode has already exist */ - off = fdt_path_offset(dtb_buf, node_name); + off = fdt_subnode_offset(dtb_buf, parentoffset, node_name); if (off == -FDT_ERR_NOTFOUND) { dtb_size += fdt_node_len(node_name); fdt_set_totalsize(dtb_buf, dtb_size); dtb_buf = xrealloc(dtb_buf, dtb_size); if (dtb_buf == NULL) die("xrealloc failed\n"); - off = fdt_add_subnode(dtb_buf, off, node_name); + off = fdt_add_subnode(dtb_buf, parentoffset, node_name); } if (off < 0) { @@ -321,14 +348,15 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info) { - unsigned long base; + unsigned long base, kernel_base; unsigned int atag_offset = 0x1000; /* 4k offset from memory start */ unsigned int extra_size = 0x8000; /* TEXT_OFFSET */ + size_t kernel_mem_size; const char *command_line; char *modified_cmdline = NULL; off_t command_line_len; const char *ramdisk; - char *ramdisk_buf; + const char *ramdisk_buf; int opt; int use_atags; char *dtb_buf; @@ -415,6 +443,75 @@ if (dtb_file) dtb_buf = slurp_file(dtb_file, &dtb_length); + if (len > 0x34) { + const struct zimage_header *hdr; + off_t size; + + hdr = (const struct zimage_header *)buf; + + dbgprintf("zImage header: 0x%08x 0x%08x 0x%08x\n", + hdr->magic, hdr->start, hdr->end); + + if (hdr->magic == ZIMAGE_MAGIC) { + size = le32_to_cpu(hdr->end) - le32_to_cpu(hdr->start); + + dbgprintf("zImage size 0x%llx, file size 0x%llx\n", + (unsigned long long)size, + (unsigned long long)len); + + if (size > len) { + fprintf(stderr, + "zImage is truncated - file 0x%llx vs header 0x%llx\n", + (unsigned long long)len, + (unsigned long long)size); + return -1; + } + if (size < len) + len = size; + } + } + + /* Handle android images, 2048 is the minimum page size */ + if (len > 2048 && !strncmp(buf, "ANDROID!", 8)) { + const struct android_image *aimg = (const void *)buf; + uint32_t page_size = le32_to_cpu(aimg->page_size); + uint32_t kernel_size = le32_to_cpu(aimg->kernel_size); + uint32_t ramdisk_size = le32_to_cpu(aimg->ramdisk_size); + uint32_t stage2_size = le32_to_cpu(aimg->stage2_size); + off_t aimg_size = page_size + _ALIGN(kernel_size, page_size) + + _ALIGN(ramdisk_size, page_size) + stage2_size; + + if (len < aimg_size) { + fprintf(stderr, "Android image size is incorrect\n"); + return -1; + } + + /* Get the kernel */ + buf = buf + page_size; + len = kernel_size; + + /* And the ramdisk if none was given on the command line */ + if (!ramdisk && ramdisk_size) { + initrd_size = ramdisk_size; + ramdisk_buf = buf + _ALIGN(kernel_size, page_size); + } + + /* Likewise for the command line */ + if (!command_line && aimg->command_line[0]) { + command_line = aimg->command_line; + if (command_line[sizeof(aimg->command_line) - 1]) + command_line_len = sizeof(aimg->command_line); + else + command_line_len = strlen(command_line) + 1; + } + } + + /* + * Always extend the zImage by four bytes to ensure that an appended + * DTB image always sees an initialised value after _edata. + */ + kernel_mem_size = len + 4; + /* * If we are loading a dump capture kernel, we need to update kernel * command line and also add some additional segments. @@ -446,12 +543,13 @@ * We put the dump capture kernel at the start of crashkernel * reserved memory. */ - if (parse_iomem_single("Crash kernel\n", &start, &end)) { + if (parse_iomem_single(CRASH_KERNEL_BOOT, &start, &end) && + parse_iomem_single(CRASH_KERNEL, &start, &end)) { /* * No crash kernel memory reserved. We cannot do more * but just bail out. */ - return -1; + return ENOCRASHKERNEL; } base = start; } else { @@ -462,15 +560,19 @@ if (base == ULONG_MAX) return -1; + kernel_base = base + extra_size; + if (kexec_arm_image_size) { /* If the image size was passed as command line argument, * use that value for determining the address for initrd, * atags and dtb images. page-align the given length.*/ - initrd_base = base + _ALIGN(kexec_arm_image_size, getpagesize()); + initrd_base = kernel_base + _ALIGN(kexec_arm_image_size, getpagesize()); } else { /* Otherwise, assume the maximum kernel compression ratio - * is 4, and just to be safe, place ramdisk after that */ - initrd_base = base + _ALIGN(len * 4, getpagesize()); + * is 4, and just to be safe, place ramdisk after that. + * Note that we must include space for the compressed + * image here as well. */ + initrd_base = kernel_base + _ALIGN(len * 5, getpagesize()); } if (use_atags) { @@ -496,7 +598,7 @@ * Error should have been reported so * directly return -1 */ - if (setup_dtb_prop(&dtb_buf, &dtb_length, "/chosen", + if (setup_dtb_prop(&dtb_buf, &dtb_length, 0, "chosen", "bootargs", command_line, strlen(command_line) + 1)) return -1; @@ -529,12 +631,12 @@ unsigned long initrd_base_new = locate_hole(info, hole_size, page_size, initrd_base, ULONG_MAX, INT_MAX); - if (base == ULONG_MAX) + if (initrd_base_new == ULONG_MAX) return -1; initrd_base = initrd_base_new; } - if (ramdisk) { + if (ramdisk_buf) { add_segment(info, ramdisk_buf, initrd_size, initrd_base, initrd_size); @@ -542,11 +644,11 @@ start = cpu_to_be32((unsigned long)(initrd_base)); end = cpu_to_be32((unsigned long)(initrd_base + initrd_size)); - if (setup_dtb_prop(&dtb_buf, &dtb_length, "/chosen", + if (setup_dtb_prop(&dtb_buf, &dtb_length, 0, "chosen", "linux,initrd-start", &start, sizeof(start))) return -1; - if (setup_dtb_prop(&dtb_buf, &dtb_length, "/chosen", + if (setup_dtb_prop(&dtb_buf, &dtb_length, 0, "chosen", "linux,initrd-end", &end, sizeof(end))) return -1; @@ -562,9 +664,9 @@ dtb_offset, dtb_length); } - add_segment(info, buf, len, base + extra_size, len); + add_segment(info, buf, len, kernel_base, kernel_mem_size); - info->entry = (void*)base + extra_size; + info->entry = (void*)kernel_base; return 0; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/arm/phys_to_virt.c new/kexec-tools-2.0.13/kexec/arch/arm/phys_to_virt.c --- old/kexec-tools-2.0.12/kexec/arch/arm/phys_to_virt.c 2011-10-03 00:56:38.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/arm/phys_to_virt.c 2016-06-08 02:24:10.000000000 +0200 @@ -1,6 +1,8 @@ #include "../../kexec.h" #include "../../crashdump.h" -#include "crashdump-arm.h" +#include "phys_to_virt.h" + +uint64_t phys_offset; /** * phys_to_virt() - translate physical address to virtual address @@ -14,7 +16,7 @@ * http://lists.arm.linux.org.uk/lurker/message/20010723.185051.94ce743c.en.html */ unsigned long -phys_to_virt(struct crash_elf_info *elf_info, unsigned long paddr) +phys_to_virt(struct crash_elf_info *elf_info, unsigned long long paddr) { return paddr + elf_info->page_offset - phys_offset; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/cris/kexec-elf-rel-cris.c new/kexec-tools-2.0.13/kexec/arch/cris/kexec-elf-rel-cris.c --- old/kexec-tools-2.0.12/kexec/arch/cris/kexec-elf-rel-cris.c 2010-07-29 11:22:16.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/cris/kexec-elf-rel-cris.c 2016-03-24 05:59:57.000000000 +0100 @@ -29,8 +29,9 @@ return 1; } -void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, - void *location, unsigned long address, unsigned long value) +void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), + struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, + unsigned long address, unsigned long value) { switch(r_type) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/i386/kexec-elf-rel-x86.c new/kexec-tools-2.0.13/kexec/arch/i386/kexec-elf-rel-x86.c --- old/kexec-tools-2.0.12/kexec/arch/i386/kexec-elf-rel-x86.c 2011-10-03 00:56:38.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/i386/kexec-elf-rel-x86.c 2016-03-24 05:59:57.000000000 +0100 @@ -18,8 +18,9 @@ return 1; } -void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), unsigned long r_type, - void *location, unsigned long address, unsigned long value) +void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), + struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, + unsigned long address, unsigned long value) { switch(r_type) { case R_386_32: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/ia64/kexec-elf-rel-ia64.c new/kexec-tools-2.0.13/kexec/arch/ia64/kexec-elf-rel-ia64.c --- old/kexec-tools-2.0.12/kexec/arch/ia64/kexec-elf-rel-ia64.c 2010-07-29 11:22:16.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/ia64/kexec-elf-rel-ia64.c 2016-03-24 05:59:57.000000000 +0100 @@ -72,8 +72,9 @@ return insn & ~0xfUL; } -void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, - void *location, unsigned long address, unsigned long value) +void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), + struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, + unsigned long address, unsigned long value) { uint64_t gp_value = ehdr->rel_addr + 0x200000; switch(r_type) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/m68k/kexec-elf-rel-m68k.c new/kexec-tools-2.0.13/kexec/arch/m68k/kexec-elf-rel-m68k.c --- old/kexec-tools-2.0.12/kexec/arch/m68k/kexec-elf-rel-m68k.c 2014-10-14 06:58:06.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/m68k/kexec-elf-rel-m68k.c 2016-03-24 05:59:57.000000000 +0100 @@ -23,7 +23,9 @@ return 1; } -void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), unsigned long r_type, +void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), + struct mem_sym *UNUSED(sym), + unsigned long r_type, void *UNUSED(location), unsigned long UNUSED(address), unsigned long UNUSED(value)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/mips/kexec-elf-rel-mips.c new/kexec-tools-2.0.13/kexec/arch/mips/kexec-elf-rel-mips.c --- old/kexec-tools-2.0.12/kexec/arch/mips/kexec-elf-rel-mips.c 2011-10-03 00:56:38.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/mips/kexec-elf-rel-mips.c 2016-03-24 05:59:57.000000000 +0100 @@ -29,7 +29,9 @@ return 1; } -void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), unsigned long r_type, +void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), + struct mem_sym *UNUSED(sym), + unsigned long r_type, void *UNUSED(location), unsigned long UNUSED(address), unsigned long UNUSED(value)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/ppc/kexec-elf-rel-ppc.c new/kexec-tools-2.0.13/kexec/arch/ppc/kexec-elf-rel-ppc.c --- old/kexec-tools-2.0.12/kexec/arch/ppc/kexec-elf-rel-ppc.c 2011-10-03 00:56:38.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/ppc/kexec-elf-rel-ppc.c 2016-03-24 05:59:57.000000000 +0100 @@ -17,8 +17,9 @@ return 1; } -void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), unsigned long r_type, - void *location, unsigned long address, unsigned long value) +void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), + struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, + unsigned long address, unsigned long value) { switch(r_type) { case R_PPC_ADDR32: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/ppc64/kexec-elf-rel-ppc64.c new/kexec-tools-2.0.13/kexec/arch/ppc64/kexec-elf-rel-ppc64.c --- old/kexec-tools-2.0.12/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2014-10-14 06:58:06.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2016-03-24 05:59:57.000000000 +0100 @@ -5,17 +5,23 @@ #include "../../kexec-elf.h" #include "kexec-ppc64.h" -int machine_verify_elf_rel(struct mem_ehdr *ehdr) -{ - if (ehdr->ei_class != ELFCLASS64) { - return 0; - } - if (ehdr->e_machine != EM_PPC64) { - return 0; - } +#if defined(_CALL_ELF) && _CALL_ELF == 2 +#define STO_PPC64_LOCAL_BIT 5 +#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT) +#define PPC64_LOCAL_ENTRY_OFFSET(other) \ + (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2) - return 1; +static unsigned int local_entry_offset(struct mem_sym *sym) +{ + /* If this symbol has a local entry point, use it. */ + return PPC64_LOCAL_ENTRY_OFFSET(sym->st_other); } +#else +static unsigned int local_entry_offset(struct mem_sym *UNUSED(sym)) +{ + return 0; +} +#endif static struct mem_shdr *toc_section(const struct mem_ehdr *ehdr) { @@ -34,6 +40,24 @@ return NULL; } +int machine_verify_elf_rel(struct mem_ehdr *ehdr) +{ + struct mem_shdr *toc; + + if (ehdr->ei_class != ELFCLASS64) { + return 0; + } + if (ehdr->e_machine != EM_PPC64) { + return 0; + } + + /* Ensure .toc is sufficiently aligned. */ + toc = toc_section(ehdr); + if (toc && toc->sh_addralign < 256) + toc->sh_addralign = 256; + return 1; +} + /* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this gives the value maximum span in an instruction which uses a signed offset) */ @@ -63,8 +87,9 @@ *location = (*location & ~mask) | (value & mask); } -void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, - void *location, unsigned long address, unsigned long value) +void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *sym, + unsigned long r_type, void *location, unsigned long address, + unsigned long value) { switch(r_type) { case R_PPC64_ADDR32: @@ -113,6 +138,7 @@ break; case R_PPC64_REL24: + value += local_entry_offset(sym); /* Convert value to relative */ value -= address; if (value + 0x2000000 > 0x3ffffff || (value & 3) != 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/s390/kexec-elf-rel-s390.c new/kexec-tools-2.0.13/kexec/arch/s390/kexec-elf-rel-s390.c --- old/kexec-tools-2.0.12/kexec/arch/s390/kexec-elf-rel-s390.c 2011-10-03 00:56:38.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/s390/kexec-elf-rel-s390.c 2016-03-24 05:59:57.000000000 +0100 @@ -23,7 +23,8 @@ return 1; } -void machine_apply_elf_rel(struct mem_ehdr *ehdr, +void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), + struct mem_sym *UNUSED(sym), unsigned long r_type, void *loc, unsigned long address, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/sh/kexec-elf-rel-sh.c new/kexec-tools-2.0.13/kexec/arch/sh/kexec-elf-rel-sh.c --- old/kexec-tools-2.0.12/kexec/arch/sh/kexec-elf-rel-sh.c 2011-10-03 00:56:38.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/sh/kexec-elf-rel-sh.c 2016-03-24 05:59:57.000000000 +0100 @@ -28,8 +28,9 @@ return 1; } -void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), unsigned long r_type, - void *orig_loc, unsigned long UNUSED(address), unsigned long relocation) +void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), + struct mem_sym *UNUSED(sym), unsigned long r_type, void *orig_loc, + unsigned long UNUSED(address), unsigned long relocation) { uint32_t *location = orig_loc; uint32_t value; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/arch/x86_64/kexec-elf-rel-x86_64.c new/kexec-tools-2.0.13/kexec/arch/x86_64/kexec-elf-rel-x86_64.c --- old/kexec-tools-2.0.12/kexec/arch/x86_64/kexec-elf-rel-x86_64.c 2015-05-01 03:13:09.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/arch/x86_64/kexec-elf-rel-x86_64.c 2016-03-24 05:59:57.000000000 +0100 @@ -57,8 +57,9 @@ return name; } -void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), unsigned long r_type, - void *location, unsigned long address, unsigned long value) +void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), + struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, + unsigned long address, unsigned long value) { dbgprintf("%s\n", reloc_name(r_type)); switch(r_type) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/crashdump.h new/kexec-tools-2.0.13/kexec/crashdump.h --- old/kexec-tools-2.0.12/kexec/crashdump.h 2015-12-01 07:21:02.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/crashdump.h 2016-06-08 02:21:52.000000000 +0200 @@ -55,7 +55,7 @@ unsigned long crash_architecture(struct crash_elf_info *elf_info); unsigned long phys_to_virt(struct crash_elf_info *elf_info, - unsigned long paddr); + unsigned long long paddr); unsigned long xen_architecture(struct crash_elf_info *elf_info); int xen_get_nr_phys_cpus(void); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/kexec-elf-rel.c new/kexec-tools-2.0.13/kexec/kexec-elf-rel.c --- old/kexec-tools-2.0.12/kexec/kexec-elf-rel.c 2014-10-14 06:58:06.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/kexec-elf-rel.c 2016-03-24 05:59:57.000000000 +0100 @@ -408,7 +408,7 @@ dbgprintf("sym: %s value: %lx addr: %lx\n", name, value, address); - machine_apply_elf_rel(ehdr, rel.r_type, + machine_apply_elf_rel(ehdr, &sym, rel.r_type, (void *)location, address, value); } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/kexec-elf.h new/kexec-tools-2.0.13/kexec/kexec-elf.h --- old/kexec-tools-2.0.12/kexec/kexec-elf.h 2013-11-19 02:05:49.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/kexec-elf.h 2016-03-24 05:59:57.000000000 +0100 @@ -129,7 +129,8 @@ /* Architecture specific helper functions */ extern int machine_verify_elf_rel(struct mem_ehdr *ehdr); -extern void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, - void *location, unsigned long address, unsigned long value); +extern void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *sym, + unsigned long r_type, void *location, unsigned long address, + unsigned long value); #endif /* KEXEC_ELF_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/kexec-uImage.c new/kexec-tools-2.0.13/kexec/kexec-uImage.c --- old/kexec-tools-2.0.12/kexec/kexec-uImage.c 2015-11-17 18:30:30.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/kexec-uImage.c 2016-06-08 02:21:52.000000000 +0200 @@ -82,7 +82,8 @@ if (be32_to_cpu(header.ih_size) > len - sizeof(header)) { printf("uImage header claims that image has %d bytes\n", be32_to_cpu(header.ih_size)); - printf("we read only %ld bytes.\n", len - sizeof(header)); + printf("we read only %lld bytes.\n", + (long long)len - sizeof(header)); return -1; } #ifdef HAVE_LIBZ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/kexec.c new/kexec-tools-2.0.13/kexec/kexec.c --- old/kexec-tools-2.0.12/kexec/kexec.c 2015-12-01 07:21:02.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/kexec.c 2016-06-08 02:21:52.000000000 +0200 @@ -707,8 +707,8 @@ /* slurp in the input kernel */ kernel_buf = slurp_decompress_file(kernel, &kernel_size); - dbgprintf("kernel: %p kernel_size: 0x%lx\n", - kernel_buf, kernel_size); + dbgprintf("kernel: %p kernel_size: %#llx\n", + kernel_buf, (unsigned long long)kernel_size); if (get_memory_ranges(&info.memory_range, &info.memory_ranges, info.kexec_flags) < 0 || info.memory_ranges == 0) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/kexec.h new/kexec-tools-2.0.13/kexec/kexec.h --- old/kexec-tools-2.0.12/kexec/kexec.h 2015-12-01 07:21:02.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/kexec.h 2016-06-08 02:21:52.000000000 +0200 @@ -142,6 +142,7 @@ struct memory_ranges { unsigned int size; + unsigned int max_size; struct memory_range *ranges; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/mem_regions.c new/kexec-tools-2.0.13/kexec/mem_regions.c --- old/kexec-tools-2.0.12/kexec/mem_regions.c 1970-01-01 01:00:00.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/mem_regions.c 2016-06-23 02:39:46.000000000 +0200 @@ -0,0 +1,127 @@ +#include <stdlib.h> + +#include "kexec.h" +#include "mem_regions.h" + +static int mem_range_cmp(const void *a1, const void *a2) +{ + const struct memory_range *r1 = a1; + const struct memory_range *r2 = a2; + + if (r1->start > r2->start) + return 1; + if (r1->start < r2->start) + return -1; + + return 0; +} + +/** + * mem_regions_sort() - sort ranges into ascending address order + * @ranges: ranges to sort + * + * Sort the memory regions into ascending address order. + */ +void mem_regions_sort(struct memory_ranges *ranges) +{ + qsort(ranges->ranges, ranges->size, sizeof(ranges->ranges), + mem_range_cmp); +} + +/** + * mem_regions_add() - add a memory region to a set of ranges + * @ranges: ranges to add the memory region to + * @base: base address of memory region + * @length: length of memory region in bytes + * @type: type of memory region + * + * Add the memory region to the set of ranges, and return %0 if successful, + * or %-1 if we ran out of space. + */ +int mem_regions_add(struct memory_ranges *ranges, unsigned long long base, + unsigned long long length, int type) +{ + struct memory_range *range; + + if (ranges->size >= ranges->max_size) + return -1; + + range = ranges->ranges + ranges->size++; + range->start = base; + range->end = base + length - 1; + range->type = type; + + return 0; +} + +static void mem_regions_remove(struct memory_ranges *ranges, int index) +{ + int tail_entries; + + /* we are assured to have at least one entry */ + ranges->size -= 1; + + /* if we have following entries, shuffle them down one place */ + tail_entries = ranges->size - index; + if (tail_entries) + memmove(ranges->ranges + index, ranges->ranges + index + 1, + tail_entries * sizeof(*ranges->ranges)); + + /* zero the new tail entry */ + memset(ranges->ranges + ranges->size, 0, sizeof(*ranges->ranges)); +} + +/** + * mem_regions_exclude() - excludes a memory region from a set of memory ranges + * @ranges: memory ranges to exclude the region from + * @range: memory range to exclude + * + * Exclude a memory region from a set of memory ranges. We assume that + * the region to be excluded is either wholely located within one of the + * memory ranges, or not at all. + */ +int mem_regions_exclude(struct memory_ranges *ranges, + const struct memory_range *range) +{ + int i, ret; + + for (i = 0; i < ranges->size; i++) { + struct memory_range *r = ranges->ranges + i; + + /* + * We assume that crash area is fully contained in + * some larger memory area. + */ + if (r->start <= range->start && r->end >= range->end) { + if (r->start == range->start) { + if (r->end == range->end) + /* Remove this entry */ + mem_regions_remove(ranges, i); + else + /* Shrink the start of this memory range */ + r->start = range->end + 1; + } else if (r->end == range->end) { + /* Shrink the end of this memory range */ + r->end = range->start - 1; + } else { + /* + * Split this area into 2 smaller ones and + * remove excluded range from between. First + * create new entry for the remaining area. + */ + ret = mem_regions_add(ranges, range->end + 1, + r->end - range->end, 0); + if (ret < 0) + return ret; + + /* + * Update this area to end before excluded + * range. + */ + r->end = range->start - 1; + break; + } + } + } + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/mem_regions.h new/kexec-tools-2.0.13/kexec/mem_regions.h --- old/kexec-tools-2.0.12/kexec/mem_regions.h 1970-01-01 01:00:00.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/mem_regions.h 2016-06-08 02:21:52.000000000 +0200 @@ -0,0 +1,15 @@ +#ifndef MEM_REGIONS_H +#define MEM_REGIONS_H + +struct memory_ranges; +struct memory_range; + +void mem_regions_sort(struct memory_ranges *ranges); + +int mem_regions_exclude(struct memory_ranges *ranges, + const struct memory_range *range); + +int mem_regions_add(struct memory_ranges *ranges, unsigned long long base, + unsigned long long length, int type); + +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/phys_to_virt.c new/kexec-tools-2.0.13/kexec/phys_to_virt.c --- old/kexec-tools-2.0.12/kexec/phys_to_virt.c 2011-10-11 15:04:50.000000000 +0200 +++ new/kexec-tools-2.0.13/kexec/phys_to_virt.c 2016-06-08 02:21:52.000000000 +0200 @@ -10,7 +10,7 @@ * their own implementation. */ unsigned long -phys_to_virt(struct crash_elf_info *elf_info, unsigned long paddr) +phys_to_virt(struct crash_elf_info *elf_info, unsigned long long paddr) { return paddr + elf_info->page_offset; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec/zlib.c new/kexec-tools-2.0.13/kexec/zlib.c --- old/kexec-tools-2.0.12/kexec/zlib.c 2015-02-09 07:00:12.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec/zlib.c 2016-06-08 02:21:52.000000000 +0200 @@ -60,8 +60,8 @@ if ((errno == EINTR) || (errno == EAGAIN)) continue; _gzerror(fp, &errnum, &msg); - dbgprintf("Read on %s of %ld bytes failed: %s\n", - filename, (allocated - size) + 0UL, msg); + dbgprintf("Read on %s of %d bytes failed: %s\n", + filename, (int)(allocated - size), msg); size = 0; goto fail; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kexec-tools-2.0.12/kexec-tools.spec new/kexec-tools-2.0.13/kexec-tools.spec --- old/kexec-tools-2.0.12/kexec-tools.spec 2016-03-22 02:10:46.000000000 +0100 +++ new/kexec-tools-2.0.13/kexec-tools.spec 2016-08-08 12:27:27.000000000 +0200 @@ -1,6 +1,6 @@ Summary: Load one kernel from another Name: kexec-tools -Version: 2.0.12 +Version: 2.0.13 Release: 0 License: GPL Group: Development/Tools ++++++ kexec-tools-enable-aarch64.patch ++++++ --- /var/tmp/diff_new_pack.S5wK7V/_old 2016-08-12 15:36:20.000000000 +0200 +++ /var/tmp/diff_new_pack.S5wK7V/_new 2016-08-12 15:36:20.000000000 +0200 @@ -9,11 +9,20 @@ Signed-off-by: Geoff Levand <ge...@infradead.org> -diff --git a/configure.ac b/configure.ac -index 31d1bbe..c6e8bd6 100644 +--- + configure.ac | 3 + kexec/Makefile | 1 + kexec/arch/arm64/Makefile | 17 ++ + kexec/arch/arm64/include/arch/options.h | 30 ++++ + kexec/arch/arm64/kexec-arm64.c | 223 ++++++++++++++++++++++++++++++++ + kexec/arch/arm64/kexec-arm64.h | 28 ++++ + kexec/arch/arm64/kexec-elf-arm64.c | 147 +++++++++++++++++++++ + kexec/kexec-syscall.h | 9 + + 8 files changed, 456 insertions(+), 2 deletions(-) + --- a/configure.ac +++ b/configure.ac -@@ -35,6 +35,9 @@ case $target_cpu in +@@ -34,6 +34,9 @@ case $target_cpu in ARCH="ppc64" SUBARCH="LE" ;; @@ -23,11 +32,9 @@ arm* ) ARCH="arm" ;; -diff --git a/kexec/Makefile b/kexec/Makefile -index 7d3175b..9777ec3 100644 --- a/kexec/Makefile +++ b/kexec/Makefile -@@ -71,6 +71,7 @@ KEXEC_SRCS += $($(ARCH)_FS2DT) +@@ -75,6 +75,7 @@ KEXEC_SRCS += $($(ARCH)_MEM_REGIONS) include $(srcdir)/kexec/arch/alpha/Makefile include $(srcdir)/kexec/arch/arm/Makefile @@ -35,9 +42,6 @@ include $(srcdir)/kexec/arch/i386/Makefile include $(srcdir)/kexec/arch/ia64/Makefile include $(srcdir)/kexec/arch/m68k/Makefile -diff --git a/kexec/arch/arm64/Makefile b/kexec/arch/arm64/Makefile -new file mode 100644 -index 0000000..8b7f8a5 --- /dev/null +++ b/kexec/arch/arm64/Makefile @@ -0,0 +1,17 @@ @@ -58,9 +62,6 @@ + kexec/arch/arm64/kexec-arm64.h + +LIBS += -lfdt -diff --git a/kexec/arch/arm64/include/arch/options.h b/kexec/arch/arm64/include/arch/options.h -new file mode 100644 -index 0000000..c9a0287 --- /dev/null +++ b/kexec/arch/arm64/include/arch/options.h @@ -0,0 +1,30 @@ @@ -94,12 +95,9 @@ +struct arm64_opts arm64_opts; + +#endif /* KEXEC_ARCH_ARM64_OPTIONS_H */ -diff --git a/kexec/arch/arm64/kexec-arm64.c b/kexec/arch/arm64/kexec-arm64.c -new file mode 100644 -index 0000000..e02c38d --- /dev/null +++ b/kexec/arch/arm64/kexec-arm64.c -@@ -0,0 +1,228 @@ +@@ -0,0 +1,223 @@ +/* + * ARM64 kexec support. + */ @@ -293,7 +291,7 @@ + unsigned long kexec_flags) +{ + /* FIXME: Should get this info from device tree. */ -+ ++ + return get_memory_ranges_1(range, ranges, kexec_flags); +} + @@ -310,27 +308,19 @@ +} + + -+int machine_verify_elf_rel(struct mem_ehdr *ehdr) ++int machine_verify_elf_rel(struct mem_ehdr *UNUSED(ehdr)) +{ -+ (void)ehdr; -+ + fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); + return 0; +} + -+void machine_apply_elf_rel(struct mem_ehdr *ehdr, unsigned long r_type, -+ void *location, unsigned long address, unsigned long value) ++void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), ++ struct mem_sym *UNUSED(sym), unsigned long UNUSED(r_type), ++ void *UNUSED(location), unsigned long UNUSED(address), ++ unsigned long UNUSED(value)) +{ -+ (void)ehdr; -+ (void)r_type; -+ (void)location; -+ (void)address; -+ (void)value; + fprintf(stderr, "%s:%d: do\n", __func__, __LINE__); +} -diff --git a/kexec/arch/arm64/kexec-arm64.h b/kexec/arch/arm64/kexec-arm64.h -new file mode 100644 -index 0000000..673d525 --- /dev/null +++ b/kexec/arch/arm64/kexec-arm64.h @@ -0,0 +1,28 @@ @@ -362,9 +352,6 @@ +off_t initrd_size; + +#endif -diff --git a/kexec/arch/arm64/kexec-elf-arm64.c b/kexec/arch/arm64/kexec-elf-arm64.c -new file mode 100644 -index 0000000..b267a15 --- /dev/null +++ b/kexec/arch/arm64/kexec-elf-arm64.c @@ -0,0 +1,147 @@ @@ -395,7 +382,7 @@ + struct mem_ehdr ehdr; + + fprintf(stderr, "%s:%d: ->\n", __func__, __LINE__); -+ ++ + result = build_elf_exec_info(buf, len, &ehdr, 0); + + if (result < 0) { @@ -459,7 +446,7 @@ + char *buf; + + buf = slurp_file(arm64_opts.ramdisk, &initrd_size); -+ ++ + if (!buf) + fprintf(stderr, "kexec: empty ramdisk file\n"); + else { @@ -483,7 +470,7 @@ + fdt32_to_cpu(*(uint32_t*)dtb_buf), *(uint32_t*)dtb_buf); + + result = fdt_check_header(dtb_buf); -+ ++ + if (result) { + fprintf(stderr, "Invalid FDT.\n"); + return -1; @@ -515,8 +502,6 @@ +{ + fprintf(stderr, "%s:%d\n", __func__, __LINE__); +} -diff --git a/kexec/kexec-syscall.h b/kexec/kexec-syscall.h -index 6238044..ccca19c 100644 --- a/kexec/kexec-syscall.h +++ b/kexec/kexec-syscall.h @@ -39,8 +39,8 @@ @@ -530,7 +515,7 @@ #endif #if defined(__mips__) #define __NR_kexec_load 4311 -@@ -76,6 +76,8 @@ static inline long kexec_load(void *entry, unsigned long nr_segments, +@@ -108,6 +108,8 @@ static inline long kexec_file_load(int k #define KEXEC_ARCH_PPC64 (21 << 16) #define KEXEC_ARCH_IA_64 (50 << 16) #define KEXEC_ARCH_ARM (40 << 16) @@ -539,7 +524,7 @@ #define KEXEC_ARCH_S390 (22 << 16) #define KEXEC_ARCH_SH (42 << 16) #define KEXEC_ARCH_MIPS_LE (10 << 16) -@@ -121,5 +123,8 @@ static inline long kexec_load(void *entry, unsigned long nr_segments, +@@ -153,5 +155,8 @@ static inline long kexec_file_load(int k #ifdef __m68k__ #define KEXEC_ARCH_NATIVE KEXEC_ARCH_68K #endif