diff -Nru kexec-tools-2.0.10/configure kexec-tools-2.0.16/configure --- kexec-tools-2.0.10/configure 2015-06-25 10:09:47.000000000 +0000 +++ kexec-tools-2.0.16/configure 2017-11-20 09:17:11.000000000 +0000 @@ -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.10. +# Generated by GNU Autoconf 2.69 for kexec-tools 2.0.16. # # # 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.10' -PACKAGE_STRING='kexec-tools 2.0.10' +PACKAGE_VERSION='2.0.16' +PACKAGE_STRING='kexec-tools 2.0.16' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -690,6 +690,7 @@ docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -766,6 +767,7 @@ sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1018,6 +1020,15 @@ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1155,7 +1166,7 @@ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1268,7 +1279,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.10 to adapt to many kinds of systems. +\`configure' configures kexec-tools 2.0.16 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1308,6 +1319,7 @@ --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1334,7 +1346,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of kexec-tools 2.0.10:";; + short | recursive ) echo "Configuration of kexec-tools 2.0.16:";; esac cat <<\_ACEOF @@ -1424,7 +1436,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -kexec-tools configure 2.0.10 +kexec-tools configure 2.0.16 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1722,7 +1734,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.10, which was +It was created by kexec-tools $as_me 2.0.16, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2898,12 +2910,6 @@ -cat >>confdefs.h <<_ACEOF -#define PACKAGE_DATE "`date '+%d %B %Y'`" -_ACEOF - - - # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 @@ -3021,6 +3027,7 @@ ;; powerpc ) ARCH="ppc" + SUBARCH="BE" ;; powerpc64 ) ARCH="ppc64" @@ -3030,6 +3037,9 @@ ARCH="ppc64" SUBARCH="LE" ;; + aarch64* ) + ARCH="arm64" + ;; arm* ) ARCH="arm" ;; @@ -4789,6 +4799,53 @@ fi + if test "$ac_cv_lib_xenctrl_xc_kexec_load" = yes ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for xc_kexec_status in -lxenctrl" >&5 +$as_echo_n "checking for xc_kexec_status in -lxenctrl... " >&6; } +if ${ac_cv_lib_xenctrl_xc_kexec_status+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lxenctrl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char xc_kexec_status (); +int +main () +{ +return xc_kexec_status (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_xenctrl_xc_kexec_status=yes +else + ac_cv_lib_xenctrl_xc_kexec_status=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xenctrl_xc_kexec_status" >&5 +$as_echo "$ac_cv_lib_xenctrl_xc_kexec_status" >&6; } +if test "x$ac_cv_lib_xenctrl_xc_kexec_status" = xyes; then : + +$as_echo "#define HAVE_KEXEC_CMD_STATUS 1" >>confdefs.h + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: The kexec_status call is not available" >&5 +$as_echo "$as_me: The kexec_status call is not available" >&6;} +fi + + fi fi if test "$CC" = "no"; then as_fn_error $? "cc not found" "$LINENO" 5; fi @@ -5330,7 +5387,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.10, which was +This file was extended by kexec-tools $as_me 2.0.16, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -5392,7 +5449,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.10 +kexec-tools config.status 2.0.16 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru kexec-tools-2.0.10/configure.ac kexec-tools-2.0.16/configure.ac --- kexec-tools-2.0.10/configure.ac 2015-06-25 10:09:23.000000000 +0000 +++ kexec-tools-2.0.16/configure.ac 2017-11-20 09:16:13.000000000 +0000 @@ -4,15 +4,12 @@ dnl dnl ---Required -AC_INIT(kexec-tools, 2.0.10) +AC_INIT(kexec-tools, 2.0.16) AC_CONFIG_AUX_DIR(./config) AC_CONFIG_HEADERS([include/config.h]) AC_LANG(C) AC_PROG_CC -AC_DEFINE_UNQUOTED(PACKAGE_DATE, "`date '+%d %B %Y'`", - [Define to the release date of this package]) - dnl -- Compilation platform configuration dnl -- the host specifices the host machine for the kexec binary, the @@ -27,6 +24,7 @@ ;; powerpc ) ARCH="ppc" + SUBARCH="BE" ;; powerpc64 ) ARCH="ppc64" @@ -36,6 +34,9 @@ ARCH="ppc64" SUBARCH="LE" ;; + aarch64* ) + ARCH="arm64" + ;; arm* ) ARCH="arm" ;; @@ -166,6 +167,12 @@ AC_CHECK_HEADER(xenctrl.h, [AC_CHECK_LIB(xenctrl, xc_kexec_load, , AC_MSG_NOTICE([Xen support disabled]))]) + if test "$ac_cv_lib_xenctrl_xc_kexec_load" = yes ; then + AC_CHECK_LIB(xenctrl, xc_kexec_status, + AC_DEFINE(HAVE_KEXEC_CMD_STATUS, 1, + [The kexec_status call is available]), + AC_MSG_NOTICE([The kexec_status call is not available])) + fi fi dnl ---Sanity checks diff -Nru kexec-tools-2.0.10/debian/changelog kexec-tools-2.0.16/debian/changelog --- kexec-tools-2.0.10/debian/changelog 2018-04-13 23:50:27.000000000 +0000 +++ kexec-tools-2.0.16/debian/changelog 2018-02-23 15:11:36.000000000 +0000 @@ -1,56 +1,201 @@ -kexec-tools (1:2.0.10-1ubuntu2.5) xenial; urgency=medium +kexec-tools (1:2.0.16-1ubuntu1~16.04.1) xenial; urgency=low - * The default crashkernel parameter didn't work on any known arm64 - systems, set a reasonable default instead (LP: #1763532). + * Backport latest kexec-tools from bionic to xenial (LP: #1743529). - -- dann frazier Fri, 13 Apr 2018 17:50:27 -0600 + -- Thadeu Lima de Souza Cascardo Fri, 23 Feb 2018 12:11:36 -0300 -kexec-tools (1:2.0.10-1ubuntu2.4) xenial; urgency=medium +kexec-tools (1:2.0.16-1ubuntu1) bionic; urgency=low - [Marcelo Henrique Cerri] - * [Hyper-V] 16.04 kexec-tools doesn't match linux-azure (LP: #1712867) - - [PATCH] build_mem_phdrs(): check if p_paddr is invalid - - [PATCH] kexec-tools/x86: get_kernel_vaddr_and_size off-by-one fix - - Increase crashkernel size to 256M for machines with 2G or more of memory. + * Merge from Debian unstable. Remaining changes: + - Default to not kexecing a kernel on boot in the automatically + generated conffile + - Don't call db_stop from the postinst. + - Adjust INITCONFFILE to vmlinux if used + - Add maintainer script helper to handle removal of conffile + /etc/default/grub.d/kexec-tools.cfg has been removed. + Handle it properly + - Add Breaks: statement toward kdump-tools + Starting with kdump-tools 1:1.5.9-6, this package takes + over the addition of crashkernel= parameter which has + been removed from kexec-tools. + Make sure that it is upgraded accordingly. + * New upstream release (LP: #1743529) + + -- Thadeu Lima de Souza Cascardo Fri, 23 Feb 2018 12:11:36 -0300 + +kexec-tools (1:2.0.16-1) unstable; urgency=medium + + * New upstream release (Closes: #890818) + * Updated pointer to kexec-tools home page (Closes: #888565) + * Updtaed russian translation (Thanks, Lev) (Closes: #883918) + * Remove obsolete configuration file (Closes: #868100) + + -- Khalid Aziz Tue, 20 Feb 2018 11:13:24 -0700 + +kexec-tools (1:2.0.15-1) unstable; urgency=medium + + * New upstream release (Closes: #876318, Closes: #854826) + * Enable compressed kernel support for ARM64 - Manoj Iyer + (Closes: #854093) + * Updated Portuguese translation (Closes: #857728) + * Updated German translation (Closes: #857737) + + -- Khalid Aziz Thu, 21 Sep 2017 15:07:18 -0600 + +kexec-tools (1:2.0.15-0ubuntu1) artful; urgency=medium + + * New upstream version (LP: #1713940): + - Modified: + - distclean_fix.patch + Hunk which modified purgatory makefile went upstream + - Dropped (already upstream): + - format-security.patch + - kexec-Increase-the-upper-limit-for-RAM-segments.patch + - ppc64-Reduce-number-of-ELF-LOAD-segments.patch + - 0001-kexec-extend-the-semantics-of-kexec_iomem_for_each_l.patch + - 0002-kexec-generalize-and-rename-get_kernel_stext_sym.patch + - 0003-arm64-identify-PHYS_OFFSET-correctly.patch + - 0004-arm64-change-return-values-on-error-to-negative.patch + - 0005-arm64-kdump-identify-memory-regions.patch + - 0006-arm64-kdump-add-elf-core-header-segment.patch + - 0007-arm64-kdump-set-up-kernel-image-segment.patch + - 0008-arm64-kdump-set-up-other-segments.patch + - 0009-arm64-kdump-add-DT-properties-to-crash-dump-kernel-s.patch + - 0010-arm64-kdump-Add-support-for-binary-image-files.patch + + -- Stefan Bader Wed, 30 Aug 2017 10:02:25 +0200 + +kexec-tools (1:2.0.14-1ubuntu5) artful; urgency=medium + + * Packaging cleanup, no functional change: + - Remove patch accidentally added, but not applied, in last upload: + 0011-Handle-additional-e820-memmap-type-strings.patch. + - Remove patch dropped from series in 2.0.14-1, but still being + carried after Ubuntu merge: lp1546260-fix-purgatory-fail-gcc5.patch. - -- Stefan Bader Tue, 12 Sep 2017 09:12:32 +0200 + -- dann frazier Fri, 09 Jun 2017 09:58:43 -0600 -kexec-tools (1:2.0.10-1ubuntu2.3) xenial; urgency=medium +kexec-tools (1:2.0.14-1ubuntu4) artful; urgency=medium * Add backport of upstream arm64 crashdump support (LP: #1694859). - -- dann frazier Fri, 23 Jun 2017 12:27:52 -0600 + -- dann frazier Thu, 08 Jun 2017 17:18:49 -0600 -kexec-tools (1:2.0.10-1ubuntu2.2) xenial; urgency=medium +kexec-tools (1:2.0.14-1ubuntu3) zesty; urgency=medium - [ Manoj Iyer ] - * d/p/arm-do-not-build-iomem.o-target-with-no-soruce.patch: - Fix regression in previous release that caused armhf to FTBFS. - (LP: #1671246) + * kexec: Increase the upper limit for RAM segments (LP: #1663400) - [ dann frazier ] - * Expanded above changelog entry for clarity. + -- Manoj Iyer Tue, 14 Feb 2017 14:00:14 +0000 - -- dann frazier Wed, 08 Mar 2017 17:57:31 -0700 +kexec-tools (1:2.0.14-1ubuntu2) zesty; urgency=medium -kexec-tools (1:2.0.10-1ubuntu2.1) xenial; urgency=medium + [ Manoj Iyer ] + * Enable compressed kernel support for ARM64 (LP: #1661363). - * kexec: Increase the upper limit for RAM segments (LP: #1663400) - * Enable ARM64 support in kexec-tools (LP: #1659618) - - [PATCH] kexec: Add common device tree routines - - [PATCH] arm64: Add arm64 kexec support - - [PATCH] arm64: Add support for binary image files - - [PATCH] arm: include phys_to_virt.h and iomem.h in distribution - - [PATCH] arm64: Cleanup kexec Makefile - - [PATCH] arm64: Add missing kexec dist files - - [PATCH] arm64: Add support for additional relocations in the kexec - - [PATCH] arm64: Add support of R_AARCH64_PREL32 relocation in - - [PATCH] purgatory: Change default sha256 optimization to -O2 - - [PATCH] arm64: Fix initrd requierements - - [PATCH] kexec: phys_to_virt() must take unsigned long long - * Enable support for compressed kernels on ARM64 (LP: #1661363) + [ dann frazier ] + * ppc64-Reduce-number-of-ELF-LOAD-segments.patch: Cherry-pick + from upstream, fixing kexec on some large memory configurations + (LP: #1661168). + + -- dann frazier Fri, 03 Feb 2017 14:49:31 -0700 + +kexec-tools (1:2.0.14-1ubuntu1) zesty; urgency=medium + + * Merge from Debian unstable. Remaining changes: + - Default to not kexecing a kernel on boot in the automatically + generated conffile + - Don't call db_stop from the postinst. + - Adjust INITCONFFILE to vmlinux if used + - Use format-security.patch instead of const_string_warning.patch + - Add maintainer script helper to handle removal of conffile + /etc/default/grub.d/kexec-tools.cfg has been removed. + Handle it properly + - Add Breaks: statement toward kdump-tools + Starting with kdump-tools 1:1.5.9-6, this package takes + over the addition of crashkernel= parameter which has + been removed from kexec-tools. + Make sure that it is upgraded accordingly. + * Debian merge adds arm64 support (LP: #1659618). + + -- dann frazier Wed, 01 Feb 2017 12:48:15 -0700 + +kexec-tools (1:2.0.14-1) unstable; urgency=medium + + * New upstream release + * Removed the patch lp1546260-fix-purgatory-fail-gcc5.patch which + has been accepted into this upstream version + * Updated Danish translation (Closes: #830594) + * Updated Brazilian Portuguese translation (Closes: #852445) + * Enabled build for arm64 (Closes: #791943) + * Fix FTCBFS: Invoke configure script through dh_auto_configure + in debian/rules (Closes: #850875) + * Added patch to add -fno-PIC to purgatory/arch/arm64/Makefile to + enable build on arm64 + + -- Khalid Aziz Wed, 25 Jan 2017 12:36:57 -0700 + +kexec-tools (1:2.0.12-1) unstable; urgency=medium + + * New upstream release + * Upstream release no longer uses build date in version + (Closes: #783239) + * Fix kexec failures when compiled with gcc > v5 (Closes: #825189) + * Add support for scripts in /etc/defauls/kexec.d (Closes: #752790) + * Update japaneses translation (Closes: #819601) + * Update french translation (Closes: #821073) + * Update dutch translation (Closes: #821441) + + -- Khalid Aziz Fri, 24 Jun 2016 14:22:01 -0600 + +kexec-tools (1:2.0.10-2ubuntu1) yakkety; urgency=medium + + * Merge from Debian unstable.(LP: #1587479) Remaining changes: + - Default to not kexecing a kernel on boot in the automatically + generated conffile + - Don't call db_stop from the postinst. + - Adjust INITCONFFILE to vmlinux if used + - Use format-security.patch instead of const_string_warning.patch + - Drop unneeded patches (all fixed upstream and not in series) : + d/p/fix-callback-functions-given-to-kexec_iomem_for_each_line.patch + d/p/kdump_makefile.patch + d/p/kexec-p-fails-to-load-kernels-with-version-x.y.patch + - [PowerPC64] Fix failure in purgatory when compiled with gcc5 + Application of upstream fixes so kexec-tools work with gcc5 on PowerPC64 + commit 4a2ae3a39c64dc43e9d094be9541253234ff4822, + 1e423dc297d10eb7ff25c829d2856ef12fc81d77, + 3debb8cf3272216119cb2e59a4963ce3c18fe8e3 + * New changes: + - Add maintainer script helper to handle removal of conffile + /etc/default/grub.d/kexec-tools.cfg has been removed. + Handle it properly + - Add Breaks: statement toward kdump-tools + Starting with kdump-tools 1:1.5.9-6, this package takes + over the addition of crashkernel= parameter which has + been removed from kexec-tools. + Make sure that it is upgraded accordingly. + * Dropped changes from previous merge + - Add and install kdump init script and initramfs snippet : + kdump script in initramfs replaced by kexec-tools long ago + - Call to update-grub to update boot args with crashkernel= : + Now handled by kexec-tools (>= 1:1.5.9-6) + + -- Louis Bouchard Thu, 02 Jun 2016 13:22:49 +0200 + +kexec-tools (1:2.0.10-2) unstable; urgency=medium + + * Fix for systemd bug, many thanks to Thomas Stangner. systemd users + must use "systemctl kexec" for a kexec reboot (Closes: #785714) + * Added -f option to update-rc.d in preinstall script (Closes: #807018) + * Updated code for USE_GRUB_CONFIG to work with new grub.cfg format which + also is back to using entry number for saved_entry (Closes: #766367) + * Changed the location of flag file for cold reboot to a safer location + (Closes : #766772) + * Added mips64 and mips64el to supported arches (Closes: #800953, + Closes: #809220) + * Make the package build reproducibly (Closes: #783239) + * Add Brazilian Portuguese debconf templates translation (Closes: #811512) - -- Manoj Iyer Tue, 07 Feb 2017 12:52:41 -0600 + -- Khalid Aziz Tue, 22 Mar 2016 17:27:30 -0600 kexec-tools (1:2.0.10-1ubuntu2) xenial; urgency=medium diff -Nru kexec-tools-2.0.10/debian/compat kexec-tools-2.0.16/debian/compat --- kexec-tools-2.0.10/debian/compat 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/compat 2018-02-20 22:19:47.000000000 +0000 @@ -1 +1 @@ -7 +9 diff -Nru kexec-tools-2.0.10/debian/control kexec-tools-2.0.16/debian/control --- kexec-tools-2.0.10/debian/control 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/control 2018-02-23 14:26:07.000000000 +0000 @@ -1,15 +1,16 @@ Source: kexec-tools Section: admin -Homepage: http://kernel.org/pub/linux/utils/kernel/kexec/ +Homepage: https://git.kernel.org/pub/scm/utils/kernel/kexec/kexec-tools.git/ Priority: optional Maintainer: Ubuntu Developers XSBC-Original-Maintainer: Khalid Aziz -Build-Depends: debhelper (>= 7.0.0), dh-autoreconf, gnu-efi (>=3.0a-4)[ia64], libz-dev [arm64 ia64], po-debconf -Standards-Version: 3.9.6 +Build-Depends: debhelper (>= 7.0.0), dh-autoreconf, gnu-efi (>=3.0a-4)[ia64], libz-dev[arm64 ia64], po-debconf +Standards-Version: 4.1.0 Package: kexec-tools -Architecture: i386 amd64 ppc64el ppc64 powerpc powerpcspe ia64 s390x arm arm64 armel armhf sh4 mips mipsel -Depends: ${shlibs:Depends}, ${misc:Depends}, debconf +Architecture: i386 amd64 ppc64el ppc64 powerpc powerpcspe ia64 s390x arm arm64 armel armhf sh4 mips mipsel mips64 mips64el +Depends: ${shlibs:Depends}, ${misc:Depends}, debconf, lsb-base (>=3.0-6), dpkg (>= 1.15.7.2) +Breaks: kdump-tools ( << 1:1.5.9-6) Description: tools to support fast kexec reboots This package provides tools to load a kernel into memory and then "reboot" directly into that kernel using the kexec system call, @@ -17,7 +18,7 @@ Package: kexec-tools-udeb Section: debian-installer -Architecture: i386 amd64 ppc64el ppc64 powerpc powerpcspe ia64 s390x arm arm64 armel armhf sh4 mips mipsel +Architecture: i386 amd64 ppc64el ppc64 powerpc powerpcspe ia64 s390x arm arm64 armel armhf sh4 mips mipsel mips64 mips64el XC-Package-Type: udeb Depends: ${misc:Depends}, ${shlibs:Depends} Description: tools to support fast kexec reboots (udeb) diff -Nru kexec-tools-2.0.10/debian/kdump.initramfs kexec-tools-2.0.16/debian/kdump.initramfs --- kexec-tools-2.0.10/debian/kdump.initramfs 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/kdump.initramfs 1970-01-01 00:00:00.000000000 +0000 @@ -1,78 +0,0 @@ -#!/bin/sh - -PREREQ="" -prereqs() -{ - echo "$PREREQ" -} -case $1 in -# get pre-requisites -prereqs) - prereqs - exit 0 - ;; -esac - -KVER="`uname -r`" -CRASHFILE="/var/crash/vmcore" -MAKEDUMPFILE="/usr/bin/makedumpfile" -LOG="$rootmnt/var/crash/vmcore.log" -VMCORE="/proc/vmcore" - -# Check that this is a kexec kernel. -grep -q kdump_needed /proc/cmdline || exit 0 - -# Do NOT exit the script after this point, or the system will start -# booting inside the crash kernel. - -. ./scripts/functions - -# Unconditionally mount /dev in the target, in case it's needed. -mount -n --bind /dev ${rootmnt}/dev - -# Check if any additional filesystems need to be mounted in order to run -# makedumpfile -# We assume that the system rootfs is now mounted on ${rootmnt} -for target in /usr /boot /var -do - # We write to /var; everything else should be mounted ro - if [ "$target" = /var ]; then - opts= - else - opts=-oro - fi - if [ -n "$(awk '$2 == "'$target'" { print $2 }' ${rootmnt}/etc/fstab)" ] - then - chroot ${rootmnt} mount -n $opts $target - mounted="$target $mounted" - fi -done - -# Make sure makedumpfile assumptions are satisfied. -while ! test -x "$rootmnt/$MAKEDUMPFILE"; do - panic "kdump: Missing $rootmnt/$MAKEDUMPFILE" -done - -log_begin_msg "Saving vmcore from kernel crash" - -mount $rootmnt -o remount,rw - -mount -n --bind /proc $rootmnt/proc - -# Delete it if the copy fails, mainly to keep from filling up filesystems -# by accident. -# -chroot $rootmnt $MAKEDUMPFILE -E -d 31 $VMCORE $CRASHFILE > $LOG 2>&1 || \ - rm -f $rootmnt/$CRASHFILE - -chmod 400 $rootmnt/$CRASHFILE - -# Unmount any extra filesystems we had to mount -for target in $mounted; do - umount -n ${rootmnt}$target -done - -mount $rootmnt -o remount,ro -reboot - -log_end_msg diff -Nru kexec-tools-2.0.10/debian/kexec.init.d kexec-tools-2.0.16/debian/kexec.init.d --- kexec-tools-2.0.10/debian/kexec.init.d 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/kexec.init.d 2018-02-20 22:19:47.000000000 +0000 @@ -15,6 +15,11 @@ . /lib/lsb/init-functions test -r /etc/default/kexec && . /etc/default/kexec +if [ -d /etc/default/kexec.d ] ; then + for snippet in $(run-parts --list /etc/default/kexec.d) ; do + . "$snippet" + done +fi do_stop () { test "x`cat /sys/kernel/kexec_loaded`y" = "x1y" || exit 0 @@ -36,7 +41,11 @@ exit 3 ;; stop) - do_stop + # Systemd has its own kexec service (which will call the kexec + # binary), so skip, if running with systemd + if [ ! -d /run/systemd/system ]; then + do_stop + fi ;; *) echo "Usage: $0 start|stop" >&2 diff -Nru kexec-tools-2.0.10/debian/kexec-load.init.d kexec-tools-2.0.16/debian/kexec-load.init.d --- kexec-tools-2.0.10/debian/kexec-load.init.d 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/kexec-load.init.d 2018-02-20 22:19:47.000000000 +0000 @@ -11,11 +11,16 @@ ### END INIT INFO PATH=/sbin:/bin:/usr/sbin:/usr/bin -NOKEXECFILE=/tmp/no-kexec-reboot +NOKEXECFILE=/no-kexec-reboot . /lib/lsb/init-functions test -r /etc/default/kexec && . /etc/default/kexec +if [ -d /etc/default/kexec.d ] ; then + for snippet in $(run-parts --list /etc/default/kexec.d) ; do + . "$snippet" + done +fi process_grub_entry() { initrd_image= @@ -38,7 +43,7 @@ mountpoint -q /boot && prefix=/boot || prefix= data=$(cat /boot/grub/grub.cfg) - default=$(echo "$data" | awk '/^set default/ {print $2}' | cut -d'"' -f2) + default=$(echo "$data" | awk '/set default/ {print $2}' | cut -d'"' -f2 | tail -1) if [ "$default" = '${saved_entry}' ]; then default=$(sed -ne 's/^saved_entry=//p' /boot/grub/grubenv) fi @@ -106,7 +111,7 @@ # runlevel has been changed to 6 which indicates we are # rebooting if [ -d /run/systemd/system ]; then - systemctl list-jobs systemd-reboot.service | grep -q systemd-reboot.service + systemctl list-jobs systemd-kexec.service | grep -q systemd-kexec.service if [ $? -ne 0 ]; then exit 0 fi diff -Nru kexec-tools-2.0.10/debian/kexec-tools.dirs kexec-tools-2.0.16/debian/kexec-tools.dirs --- kexec-tools-2.0.10/debian/kexec-tools.dirs 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/kexec-tools.dirs 2018-02-20 22:19:47.000000000 +0000 @@ -1,2 +1,2 @@ sbin -etc/default/grub.d +etc/default/kexec.d diff -Nru kexec-tools-2.0.10/debian/kexec-tools.grub kexec-tools-2.0.16/debian/kexec-tools.grub --- kexec-tools-2.0.10/debian/kexec-tools.grub 2017-09-08 20:24:19.000000000 +0000 +++ kexec-tools-2.0.16/debian/kexec-tools.grub 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT crashkernel=384M-2G:128M,2G-:256M" diff -Nru kexec-tools-2.0.10/debian/kexec-tools.grub.arm64 kexec-tools-2.0.16/debian/kexec-tools.grub.arm64 --- kexec-tools-2.0.10/debian/kexec-tools.grub.arm64 2018-04-11 22:02:26.000000000 +0000 +++ kexec-tools-2.0.16/debian/kexec-tools.grub.arm64 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -GRUB_CMDLINE_LINUX_DEFAULT="$GRUB_CMDLINE_LINUX_DEFAULT crashkernel=2G-4G:320M,4G-32G:512M,32G-64G:1024M,64G-128G:2048M,128G-:4096M" diff -Nru kexec-tools-2.0.10/debian/kexec-tools.maintscript kexec-tools-2.0.16/debian/kexec-tools.maintscript --- kexec-tools-2.0.10/debian/kexec-tools.maintscript 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/debian/kexec-tools.maintscript 2017-08-25 08:37:00.000000000 +0000 @@ -0,0 +1 @@ +rm_conffile /etc/default/grub.d/kexec-tools.cfg diff -Nru kexec-tools-2.0.10/debian/kexec-tools.postinst kexec-tools-2.0.16/debian/kexec-tools.postinst --- kexec-tools-2.0.10/debian/kexec-tools.postinst 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/kexec-tools.postinst 2018-02-20 22:19:47.000000000 +0000 @@ -42,6 +42,10 @@ fi ;; + install|upgrade) + dpkg-maintscript-helper rm_conffile /etc/default/kexec 1:2.0.16-1 -- "$@" + ;; + abort-upgrade|abort-remove|abort-deconfigure) exit 0 ;; @@ -54,7 +58,7 @@ # Handle debconf . /usr/share/debconf/confmodule - + INITCONFFILE=/etc/default/kexec # We generate several files during the postinst, and we don't want @@ -131,12 +135,6 @@ # ------------------------- Debconf questions end --------------------- -# no triggers in grub2, -# see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=481542 -if [ -x /usr/sbin/update-grub ] && [ -e /boot/grub/grub.cfg ]; then - update-grub -fi - #DEBHELPER# exit 0 diff -Nru kexec-tools-2.0.10/debian/kexec-tools.postrm kexec-tools-2.0.16/debian/kexec-tools.postrm --- kexec-tools-2.0.10/debian/kexec-tools.postrm 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/kexec-tools.postrm 2018-02-20 22:19:47.000000000 +0000 @@ -27,6 +27,7 @@ ;; remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) + dpkg-maintscript-helper rm_conffile /etc/default/kexec 1:2.0.16-1 -- "$@" ;; diff -Nru kexec-tools-2.0.10/debian/kexec-tools.preinst kexec-tools-2.0.16/debian/kexec-tools.preinst --- kexec-tools-2.0.10/debian/kexec-tools.preinst 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/kexec-tools.preinst 2018-02-20 22:19:47.000000000 +0000 @@ -22,8 +22,9 @@ # kexec init script runlevels have been updated for systemd for # kexec-tools 1:2.0.7-2. Remove current init scripts if upgrading if dpkg --compare-versions "$2" lt "1:2.0.7-2"; then - update-rc.d kexec remove - update-rc.d kexec-load remove + dpkg-maintscript-helper rm_conffile /etc/default/kexec 1:2.0.16-1 -- "$@" + update-rc.d -f kexec remove + update-rc.d -f kexec-load remove fi ;; diff -Nru kexec-tools-2.0.10/debian/kexec-tools.templates kexec-tools-2.0.16/debian/kexec-tools.templates --- kexec-tools-2.0.10/debian/kexec-tools.templates 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/kexec-tools.templates 2018-02-23 14:55:34.000000000 +0000 @@ -10,7 +10,7 @@ Template: kexec-tools/load_kexec Type: boolean Default: false -_Description: Should kexec-tools handle reboots? +_Description: Should kexec-tools handle reboots (sysvinit only)? If you choose this option, a system reboot will trigger a restart into a kernel loaded by kexec instead of going through the full system boot loader process. diff -Nru kexec-tools-2.0.10/debian/patches/0001-kexec-extend-the-semantics-of-kexec_iomem_for_each_l.patch kexec-tools-2.0.16/debian/patches/0001-kexec-extend-the-semantics-of-kexec_iomem_for_each_l.patch --- kexec-tools-2.0.10/debian/patches/0001-kexec-extend-the-semantics-of-kexec_iomem_for_each_l.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/0001-kexec-extend-the-semantics-of-kexec_iomem_for_each_l.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,79 +0,0 @@ -From c95df0e099b14757de483245d7b1b45e2d6e2c91 Mon Sep 17 00:00:00 2001 -From: AKASHI Takahiro -Date: Wed, 17 May 2017 14:51:41 +0900 -Subject: [PATCH 01/11] kexec: extend the semantics of - kexec_iomem_for_each_line - -The current kexec_iomem_for_each_line() counts up all the lines for which -a callback function returns zero(0) or positive, and otherwise it stops -further scanning. -This behavior is inconvenient in some cases. For instance, on arm64, we want -to count up "System RAM" entries, but need to skip "reserved" entries. - -So this patch extends the semantics so that we will continue to scan -succeeding entries but not count lines for which a callback function -returns positive. - -The current users of kexec_iomem_for_each_line(), arm, sh and x86, will not -be affected by this change because -* arm - The callback function only returns -1 or 0, and the return value of - kexec_iomem_for_each_line() will never be used. -* sh, x86 - The callback function may return (-1 for sh,) 0 or 1, but always returns - 1 once we have reached the maximum number of entries allowed. - Even so the current kexec_iomem_for_each_line() counts them up. - This change actually fixes this bug. - -Signed-off-by: AKASHI Takahiro -Tested-by: David Woodhouse -Tested-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/kexec-iomem.c | 15 ++++++++++----- - 1 file changed, 10 insertions(+), 5 deletions(-) - -diff --git a/kexec/kexec-iomem.c b/kexec/kexec-iomem.c -index 7ec3853..b5b52b1 100644 ---- a/kexec/kexec-iomem.c -+++ b/kexec/kexec-iomem.c -@@ -18,6 +18,9 @@ - * Iterate over each line in the file returned by proc_iomem(). If match is - * NULL or if the line matches with our match-pattern then call the - * callback if non-NULL. -+ * If match is NULL, callback should return a negative if error. -+ * Otherwise the interation goes on, incrementing nr but only if callback -+ * returns 0 (matched). - * - * Return the number of lines matched. - */ -@@ -37,7 +40,7 @@ int kexec_iomem_for_each_line(char *match, - char *str; - int consumed; - int count; -- int nr = 0; -+ int nr = 0, ret; - - fp = fopen(iomem, "r"); - if (!fp) -@@ -50,11 +53,13 @@ int kexec_iomem_for_each_line(char *match, - str = line + consumed; - size = end - start + 1; - if (!match || memcmp(str, match, strlen(match)) == 0) { -- if (callback -- && callback(data, nr, str, start, size) < 0) { -- break; -+ if (callback) { -+ ret = callback(data, nr, str, start, size); -+ if (ret < 0) -+ break; -+ else if (ret == 0) -+ nr++; - } -- nr++; - } - } - --- -2.11.0 - diff -Nru kexec-tools-2.0.10/debian/patches/0002-kexec-generalize-and-rename-get_kernel_stext_sym.patch kexec-tools-2.0.16/debian/patches/0002-kexec-generalize-and-rename-get_kernel_stext_sym.patch --- kexec-tools-2.0.10/debian/patches/0002-kexec-generalize-and-rename-get_kernel_stext_sym.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/0002-kexec-generalize-and-rename-get_kernel_stext_sym.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,183 +0,0 @@ -From 325804055e99dbf40af5e6fa546320b821d9d821 Mon Sep 17 00:00:00 2001 -From: Pratyush Anand -Date: Wed, 17 May 2017 14:51:42 +0900 -Subject: [PATCH 02/11] kexec: generalize and rename get_kernel_stext_sym() - -get_kernel_stext_sym() has been defined for both arm and i386. Other -architecture might need some other kernel symbol address. Therefore rewrite -this function as generic function to get any kernel symbol address. - -More over, kallsyms is not arch specific representation, therefore have -common function for all arches. - -Signed-off-by: Pratyush Anand -[created symbols.c] -Signed-off-by: AKASHI Takahiro -Tested-by: David Woodhouse -Tested-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/Makefile | 1 + - kexec/arch/arm/crashdump-arm.c | 40 +--------------------------------------- - kexec/arch/i386/crashdump-x86.c | 29 ----------------------------- - kexec/kexec.h | 2 ++ - kexec/symbols.c | 34 ++++++++++++++++++++++++++++++++++ - 5 files changed, 38 insertions(+), 68 deletions(-) - create mode 100644 kexec/symbols.c - -Index: kexec-tools-2.0.10/kexec/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/Makefile -+++ kexec-tools-2.0.10/kexec/Makefile -@@ -26,6 +26,7 @@ KEXEC_SRCS_base += kexec/kernel_version. - KEXEC_SRCS_base += kexec/lzma.c - KEXEC_SRCS_base += kexec/zlib.c - KEXEC_SRCS_base += kexec/kexec-xen.c -+KEXEC_SRCS_base += kexec/symbols.c - - KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C) - -Index: kexec-tools-2.0.10/kexec/arch/arm/crashdump-arm.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm/crashdump-arm.c -+++ kexec-tools-2.0.10/kexec/arch/arm/crashdump-arm.c -@@ -63,48 +63,10 @@ static struct crash_elf_info elf_info = - unsigned long phys_offset; - extern unsigned long long user_page_offset; - --/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */ --static unsigned long long get_kernel_stext_sym(void) --{ -- const char *kallsyms = "/proc/kallsyms"; -- const char *stext = "_stext"; -- char sym[128]; -- char line[128]; -- FILE *fp; -- unsigned long long vaddr = 0; -- char type; -- -- fp = fopen(kallsyms, "r"); -- if (!fp) { -- fprintf(stderr, "Cannot open %s\n", kallsyms); -- return 0; -- } -- -- while(fgets(line, sizeof(line), fp) != NULL) { -- 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 = %#llx\n", stext, addr); -- vaddr = addr; -- break; -- } -- } -- -- 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, - struct crash_elf_info *elf_info) - { -- unsigned long long stext_sym_addr = get_kernel_stext_sym(); -+ unsigned long long stext_sym_addr = get_kernel_sym("_stext"); - if (stext_sym_addr == 0) { - if (user_page_offset != (-1ULL)) { - elf_info->page_offset = user_page_offset; -Index: kexec-tools-2.0.10/kexec/kexec.h -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/kexec.h -+++ kexec-tools-2.0.10/kexec/kexec.h -@@ -308,4 +308,6 @@ int xen_kexec_load(struct kexec_info *in - int xen_kexec_unload(uint64_t kexec_flags); - void xen_kexec_exec(void); - -+extern unsigned long long get_kernel_sym(const char *text); -+ - #endif /* KEXEC_H */ -Index: kexec-tools-2.0.10/kexec/symbols.c -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/symbols.c -@@ -0,0 +1,34 @@ -+#include -+#include -+#include "kexec.h" -+ -+/* Retrieve kernel symbol virtual address from /proc/kallsyms */ -+unsigned long long get_kernel_sym(const char *symbol) -+{ -+ const char *kallsyms = "/proc/kallsyms"; -+ char sym[128]; -+ char line[128]; -+ FILE *fp; -+ unsigned long long vaddr; -+ char type; -+ -+ 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, "%llx %c %s", &vaddr, &type, sym) != 3) -+ continue; -+ if (strcmp(sym, symbol) == 0) { -+ dbgprintf("kernel symbol %s vaddr = %16llx\n", -+ symbol, vaddr); -+ return vaddr; -+ } -+ } -+ -+ dbgprintf("Cannot get kernel %s symbol address\n", symbol); -+ -+ return 0; -+} -Index: kexec-tools-2.0.10/kexec/arch/i386/crashdump-x86.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/i386/crashdump-x86.c -+++ kexec-tools-2.0.10/kexec/arch/i386/crashdump-x86.c -@@ -101,35 +101,6 @@ static int get_kernel_paddr(struct kexec - return -1; - } - --/* Retrieve kernel symbol virtual address from /proc/kallsyms */ --static unsigned long long get_kernel_sym(const char *symbol) --{ -- const char *kallsyms = "/proc/kallsyms"; -- char sym[128]; -- char line[128]; -- FILE *fp; -- unsigned long long vaddr; -- char type; -- -- 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) -- continue; -- if (strcmp(sym, symbol) == 0) { -- dbgprintf("kernel symbol %s vaddr = %16llx\n", symbol, vaddr); -- return vaddr; -- } -- } -- -- fprintf(stderr, "Cannot get kernel %s symbol address\n", symbol); -- return 0; --} -- - /* Retrieve info regarding virtual address kernel has been compiled for and - * size of the kernel from /proc/kcore. Current /proc/kcore parsing from - * from kexec-tools fails because of malformed elf notes. A kernel patch has diff -Nru kexec-tools-2.0.10/debian/patches/0003-arm64-identify-PHYS_OFFSET-correctly.patch kexec-tools-2.0.16/debian/patches/0003-arm64-identify-PHYS_OFFSET-correctly.patch --- kexec-tools-2.0.10/debian/patches/0003-arm64-identify-PHYS_OFFSET-correctly.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/0003-arm64-identify-PHYS_OFFSET-correctly.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ -From ef26cc33b8d66460c555600b0e388f55c5cd6f21 Mon Sep 17 00:00:00 2001 -From: AKASHI Takahiro -Date: Wed, 17 May 2017 14:51:43 +0900 -Subject: [PATCH 03/11] arm64: identify PHYS_OFFSET correctly - -Due to the kernel patch, commit e7cd190385d1 ("arm64: mark reserved -memblock regions explicitly in iomem"), the current code will not be able -to identify the correct value of PHYS_OFFSET if some "reserved" memory -region, which is likely to be UEFI runtime services code/data, exists at -an address below the first "System RAM" regions. - -This patch fixes this issue. - -Signed-off-by: AKASHI Takahiro -Tested-by: David Woodhouse -Tested-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/Makefile | 1 + - kexec/arch/arm64/iomem.h | 7 +++++++ - kexec/arch/arm64/kexec-arm64.c | 12 ++++++++++-- - 3 files changed, 18 insertions(+), 2 deletions(-) - create mode 100644 kexec/arch/arm64/iomem.h - -Index: kexec-tools-2.0.14/kexec/arch/arm64/Makefile -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/Makefile -+++ kexec-tools-2.0.14/kexec/arch/arm64/Makefile -@@ -23,6 +23,7 @@ dist += $(arm64_KEXEC_SRCS) \ - kexec/arch/arm64/include/arch/options.h \ - kexec/arch/arm64/crashdump-arm64.h \ - kexec/arch/arm64/image-header.h \ -+ kexec/arch/arm64/iomem.h \ - kexec/arch/arm64/kexec-arm64.h \ - kexec/arch/arm64/Makefile - -Index: kexec-tools-2.0.14/kexec/arch/arm64/iomem.h -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.14/kexec/arch/arm64/iomem.h -@@ -0,0 +1,7 @@ -+#ifndef IOMEM_H -+#define IOMEM_H -+ -+#define SYSTEM_RAM "System RAM\n" -+#define IOMEM_RESERVED "reserved\n" -+ -+#endif -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-arm64.c -@@ -21,6 +21,7 @@ - #include "crashdump-arm64.h" - #include "dt-ops.h" - #include "fs2dt.h" -+#include "iomem.h" - #include "kexec-syscall.h" - #include "arch/options.h" - -@@ -476,7 +477,14 @@ static int get_memory_ranges_iomem_cb(vo - return -1; - - r = (struct memory_range *)data + nr; -- r->type = RANGE_RAM; -+ -+ if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM))) -+ r->type = RANGE_RAM; -+ else if (!strncmp(str, IOMEM_RESERVED, strlen(IOMEM_RESERVED))) -+ r->type = RANGE_RESERVED; -+ else -+ return 1; -+ - r->start = base; - r->end = base + length - 1; - -@@ -495,7 +503,7 @@ static int get_memory_ranges_iomem_cb(vo - static int get_memory_ranges_iomem(struct memory_range *array, - unsigned int *count) - { -- *count = kexec_iomem_for_each_line("System RAM\n", -+ *count = kexec_iomem_for_each_line(NULL, - get_memory_ranges_iomem_cb, array); - - if (!*count) { diff -Nru kexec-tools-2.0.10/debian/patches/0004-arm64-change-return-values-on-error-to-negative.patch kexec-tools-2.0.16/debian/patches/0004-arm64-change-return-values-on-error-to-negative.patch --- kexec-tools-2.0.10/debian/patches/0004-arm64-change-return-values-on-error-to-negative.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/0004-arm64-change-return-values-on-error-to-negative.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,179 +0,0 @@ -From a17234fe94bce780ac36a0ba9bfc9b6e8ffd84f0 Mon Sep 17 00:00:00 2001 -From: AKASHI Takahiro -Date: Wed, 17 May 2017 14:51:44 +0900 -Subject: [PATCH 04/11] arm64: change return values on error to negative - -EFAILED is defined "-1" and so we don't need to negate it as a return value. - -Signed-off-by: AKASHI Takahiro -Tested-by: David Woodhouse -Tested-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/kexec-arm64.c | 24 ++++++++++++------------ - kexec/arch/arm64/kexec-elf-arm64.c | 6 +++--- - kexec/arch/arm64/kexec-image-arm64.c | 4 ++-- - 3 files changed, 17 insertions(+), 17 deletions(-) - -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-arm64.c -@@ -78,7 +78,7 @@ int arm64_process_image_header(const str - #endif - - if (!arm64_header_check_magic(h)) -- return -EFAILED; -+ return EFAILED; - - if (h->image_size) { - arm64_mem.text_offset = arm64_header_text_offset(h); -@@ -201,7 +201,7 @@ static int set_bootargs(struct dtb *dtb, - if (result) { - fprintf(stderr, - "kexec: Set device tree bootargs failed.\n"); -- return -EFAILED; -+ return EFAILED; - } - - return 0; -@@ -221,7 +221,7 @@ static int read_proc_dtb(struct dtb *dtb - - if (result) { - dbgprintf("%s: %s\n", __func__, strerror(errno)); -- return -EFAILED; -+ return EFAILED; - } - - dtb->path = path; -@@ -244,7 +244,7 @@ static int read_sys_dtb(struct dtb *dtb) - - if (result) { - dbgprintf("%s: %s\n", __func__, strerror(errno)); -- return -EFAILED; -+ return EFAILED; - } - - dtb->path = path; -@@ -274,7 +274,7 @@ static int read_1st_dtb(struct dtb *dtb) - goto on_success; - - dbgprintf("%s: not found\n", __func__); -- return -EFAILED; -+ return EFAILED; - - on_success: - dbgprintf("%s: found %s\n", __func__, dtb->path); -@@ -293,7 +293,7 @@ static int setup_2nd_dtb(struct dtb *dtb - - if (result) { - fprintf(stderr, "kexec: Invalid 2nd device tree.\n"); -- return -EFAILED; -+ return EFAILED; - } - - result = set_bootargs(dtb, command_line); -@@ -348,14 +348,14 @@ int arm64_load_other_segments(struct kex - if (result) { - fprintf(stderr, - "kexec: Error: No device tree available.\n"); -- return -EFAILED; -+ return EFAILED; - } - } - - result = setup_2nd_dtb(&dtb, command_line); - - if (result) -- return -EFAILED; -+ return EFAILED; - - /* Put the other segments after the image. */ - -@@ -383,7 +383,7 @@ int arm64_load_other_segments(struct kex - - if (_ALIGN_UP(initrd_end, GiB(1)) - _ALIGN_DOWN(image_base, GiB(1)) > GiB(32)) { - fprintf(stderr, "kexec: Error: image + initrd too big.\n"); -- return -EFAILED; -+ return EFAILED; - } - - dbgprintf("initrd: base %lx, size %lxh (%ld)\n", -@@ -394,7 +394,7 @@ int arm64_load_other_segments(struct kex - initrd_base + initrd_size); - - if (result) -- return -EFAILED; -+ return EFAILED; - } - } - -@@ -402,7 +402,7 @@ int arm64_load_other_segments(struct kex - - if (dtb.size > MiB(2)) { - fprintf(stderr, "kexec: Error: dtb too big.\n"); -- return -EFAILED; -+ return EFAILED; - } - - dtb_base = add_buffer_phys_virt(info, dtb.buf, dtb.size, dtb.size, -@@ -508,7 +508,7 @@ static int get_memory_ranges_iomem(struc - - if (!*count) { - dbgprintf("%s: failed: No RAM found.\n", __func__); -- return -EFAILED; -+ return EFAILED; - } - - return 0; -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-elf-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-elf-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-elf-arm64.c -@@ -48,7 +48,7 @@ int elf_arm64_load(int argc, char **argv - - if (info->kexec_flags & KEXEC_ON_CRASH) { - fprintf(stderr, "kexec: kdump not yet supported on arm64\n"); -- return -EFAILED; -+ return EFAILED; - } - - result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0); -@@ -92,7 +92,7 @@ int elf_arm64_load(int argc, char **argv - - if (i == ehdr.e_phnum) { - dbgprintf("%s: Valid arm64 header not found\n", __func__); -- result = -EFAILED; -+ result = EFAILED; - goto exit; - } - -@@ -100,7 +100,7 @@ int elf_arm64_load(int argc, char **argv - - if (kernel_segment == ULONG_MAX) { - dbgprintf("%s: Kernel segment is not allocated\n", __func__); -- result = -EFAILED; -+ result = EFAILED; - goto exit; - } - -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-image-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-image-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-image-arm64.c -@@ -36,13 +36,13 @@ int image_arm64_load(int argc, char **ar - header = (const struct arm64_image_header *)(kernel_buf); - - if (arm64_process_image_header(header)) -- return -1; -+ return EFAILED; - - kernel_segment = arm64_locate_kernel_segment(info); - - if (kernel_segment == ULONG_MAX) { - dbgprintf("%s: Kernel segment is not allocated\n", __func__); -- result = -EFAILED; -+ result = EFAILED; - goto exit; - } - diff -Nru kexec-tools-2.0.10/debian/patches/0005-arm64-kdump-identify-memory-regions.patch kexec-tools-2.0.16/debian/patches/0005-arm64-kdump-identify-memory-regions.patch --- kexec-tools-2.0.10/debian/patches/0005-arm64-kdump-identify-memory-regions.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/0005-arm64-kdump-identify-memory-regions.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,195 +0,0 @@ -From c0672c93edcb5bb32800f8d48afa05861ef32a79 Mon Sep 17 00:00:00 2001 -From: AKASHI Takahiro -Date: Wed, 17 May 2017 14:51:45 +0900 -Subject: [PATCH 05/11] arm64: kdump: identify memory regions - -The following regions need to be identified for later use: - a) memory regions which belong to the 1st kernel - b) usable memory reserved for crash dump kernel - -We go through /proc/iomem to find out a) and b) which are marked -as "System RAM" and "Crash kernel", respectively. - -Signed-off-by: AKASHI Takahiro -Tested-by: David Woodhouse -Tested-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/Makefile | 2 + - kexec/arch/arm64/crashdump-arm64.c | 109 +++++++++++++++++++++++++++++++++++-- - kexec/arch/arm64/crashdump-arm64.h | 14 ++++- - kexec/arch/arm64/iomem.h | 1 + - 4 files changed, 120 insertions(+), 6 deletions(-) - -Index: kexec-tools-2.0.14/kexec/arch/arm64/Makefile -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/Makefile -+++ kexec-tools-2.0.14/kexec/arch/arm64/Makefile -@@ -6,6 +6,8 @@ arm64_FS2DT_INCLUDE += \ - - arm64_DT_OPS += kexec/dt-ops.c - -+arm64_MEM_REGIONS = kexec/mem_regions.c -+ - arm64_CPPFLAGS += -I $(srcdir)/kexec/ - - arm64_KEXEC_SRCS += \ -Index: kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/crashdump-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.c -@@ -1,5 +1,13 @@ - /* - * ARM64 crashdump. -+ * partly derived from arm implementation -+ * -+ * Copyright (c) 2014-2017 Linaro Limited -+ * Author: AKASHI Takahiro -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. - */ - - #define _GNU_SOURCE -@@ -10,12 +18,97 @@ - #include "kexec.h" - #include "crashdump.h" - #include "crashdump-arm64.h" -+#include "iomem.h" - #include "kexec-arm64.h" - #include "kexec-elf.h" -+#include "mem_regions.h" - --struct memory_ranges usablemem_rgns = {}; -+/* memory ranges on crashed kernel */ -+static struct memory_range system_memory_ranges[CRASH_MAX_MEMORY_RANGES]; -+static struct memory_ranges system_memory_rgns = { -+ .size = 0, -+ .max_size = CRASH_MAX_MEMORY_RANGES, -+ .ranges = system_memory_ranges, -+}; - --int is_crashkernel_mem_reserved(void) -+/* memory range reserved for crashkernel */ -+struct memory_range crash_reserved_mem; -+struct memory_ranges usablemem_rgns = { -+ .size = 0, -+ .max_size = 1, -+ .ranges = &crash_reserved_mem, -+}; -+ -+/* -+ * iomem_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, respectively, system_memory_ranges and crash_reserved_mem. -+ */ -+ -+static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr), -+ char *str, unsigned long long base, -+ unsigned long long length) - { -+ if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) -+ return mem_regions_add(&usablemem_rgns, -+ base, length, RANGE_RAM); -+ else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) -+ return mem_regions_add(&system_memory_rgns, -+ base, length, RANGE_RAM); -+ - return 0; - } -+ -+int is_crashkernel_mem_reserved(void) -+{ -+ if (!usablemem_rgns.size) -+ kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); -+ -+ return crash_reserved_mem.start != crash_reserved_mem.end; -+} -+ -+/* -+ * crash_get_memory_ranges() - read system physical memory -+ * -+ * Function reads through system physical memory and stores found memory -+ * regions in system_memory_ranges. -+ * Regions are sorted in ascending order. -+ * -+ * Returns 0 in case of success and a negative value otherwise. -+ */ -+static int crash_get_memory_ranges(void) -+{ -+ /* -+ * First read all memory regions that can be considered as -+ * system memory including the crash area. -+ */ -+ if (!usablemem_rgns.size) -+ kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); -+ -+ /* allow only a single region for crash dump kernel */ -+ if (usablemem_rgns.size != 1) -+ return -EINVAL; -+ -+ dbgprint_mem_range("Reserved memory range", &crash_reserved_mem, 1); -+ -+ if (mem_regions_exclude(&system_memory_rgns, &crash_reserved_mem)) { -+ fprintf(stderr, -+ "Error: Number of crash memory ranges excedeed the max limit\n"); -+ return -ENOMEM; -+ } -+ -+ /* -+ * Make sure that the memory regions are sorted. -+ */ -+ mem_regions_sort(&system_memory_rgns); -+ -+ dbgprint_mem_range("Coredump memory ranges", -+ system_memory_rgns.ranges, system_memory_rgns.size); -+} -Index: kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.h -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/crashdump-arm64.h -+++ kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.h -@@ -1,12 +1,22 @@ - /* - * ARM64 crashdump. -+ * -+ * Copyright (c) 2014-2017 Linaro Limited -+ * Author: AKASHI Takahiro -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. - */ - --#if !defined(CRASHDUMP_ARM64_H) -+#ifndef CRASHDUMP_ARM64_H - #define CRASHDUMP_ARM64_H - - #include "kexec.h" - -+#define CRASH_MAX_MEMORY_RANGES 32 -+ - extern struct memory_ranges usablemem_rgns; -+extern struct memory_range crash_reserved_mem; - --#endif -+#endif /* CRASHDUMP_ARM64_H */ -Index: kexec-tools-2.0.14/kexec/arch/arm64/iomem.h -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/iomem.h -+++ kexec-tools-2.0.14/kexec/arch/arm64/iomem.h -@@ -2,6 +2,7 @@ - #define IOMEM_H - - #define SYSTEM_RAM "System RAM\n" -+#define CRASH_KERNEL "Crash kernel\n" - #define IOMEM_RESERVED "reserved\n" - - #endif diff -Nru kexec-tools-2.0.10/debian/patches/0006-arm64-kdump-add-elf-core-header-segment.patch kexec-tools-2.0.16/debian/patches/0006-arm64-kdump-add-elf-core-header-segment.patch --- kexec-tools-2.0.10/debian/patches/0006-arm64-kdump-add-elf-core-header-segment.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/0006-arm64-kdump-add-elf-core-header-segment.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,197 +0,0 @@ -From 0bd5219da953639276cd17e067c030ac97feca97 Mon Sep 17 00:00:00 2001 -From: AKASHI Takahiro -Date: Wed, 17 May 2017 14:51:46 +0900 -Subject: [PATCH 06/11] arm64: kdump: add elf core header segment - -Elf core header contains the information necessary for the coredump of -the 1st kernel, including its physcal memory layout as well as cpu register -states at the panic. -The segment is allocated inside the reserved memory of crash dump kernel. - -Signed-off-by: AKASHI Takahiro -Tested-by: David Woodhouse -Tested-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/crashdump-arm64.c | 98 ++++++++++++++++++++++++++++++++++++++ - kexec/arch/arm64/crashdump-arm64.h | 3 ++ - kexec/arch/arm64/iomem.h | 2 + - kexec/arch/arm64/kexec-elf-arm64.c | 11 +++++ - 4 files changed, 114 insertions(+) - -Index: kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/crashdump-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.c -@@ -39,6 +39,39 @@ struct memory_ranges usablemem_rgns = { - .ranges = &crash_reserved_mem, - }; - -+struct memory_range elfcorehdr_mem; -+ -+static struct crash_elf_info elf_info = { -+ .class = ELFCLASS64, -+#if (__BYTE_ORDER == __LITTLE_ENDIAN) -+ .data = ELFDATA2LSB, -+#else -+ .data = ELFDATA2MSB, -+#endif -+ .machine = EM_AARCH64, -+}; -+ -+/* -+ * Note: The returned value is correct only if !CONFIG_RANDOMIZE_BASE. -+ */ -+static uint64_t get_kernel_page_offset(void) -+{ -+ int i; -+ -+ if (elf_info.kern_vaddr_start == UINT64_MAX) -+ return UINT64_MAX; -+ -+ /* Current max virtual memory range is 48-bits. */ -+ for (i = 48; i > 0; i--) -+ if (!(elf_info.kern_vaddr_start & (1UL << i))) -+ break; -+ -+ if (i <= 0) -+ return UINT64_MAX; -+ else -+ return UINT64_MAX << i; -+} -+ - /* - * iomem_range_callback() - callback called for each iomem region - * @data: not used -@@ -62,6 +95,10 @@ static int iomem_range_callback(void *UN - else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) - return mem_regions_add(&system_memory_rgns, - base, length, RANGE_RAM); -+ else if (strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) == 0) -+ elf_info.kern_paddr_start = base; -+ else if (strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) == 0) -+ elf_info.kern_size = base + length - elf_info.kern_paddr_start; - - return 0; - } -@@ -111,4 +148,65 @@ static int crash_get_memory_ranges(void) - - dbgprint_mem_range("Coredump memory ranges", - system_memory_rgns.ranges, system_memory_rgns.size); -+ -+ /* -+ * For additional kernel code/data segment. -+ * kern_paddr_start/kern_size are determined in iomem_range_callback -+ */ -+ elf_info.kern_vaddr_start = get_kernel_sym("_text"); -+ if (!elf_info.kern_vaddr_start) -+ elf_info.kern_vaddr_start = UINT64_MAX; -+ -+ return 0; -+} -+ -+/* -+ * load_crashdump_segments() - load the elf core header -+ * @info: kexec info structure -+ * -+ * This function creates and loads an additional segment of elf core header -+ : which is used to construct /proc/vmcore on crash dump kernel. -+ * -+ * Return 0 in case of success and -1 in case of error. -+ */ -+ -+int load_crashdump_segments(struct kexec_info *info) -+{ -+ unsigned long elfcorehdr; -+ unsigned long bufsz; -+ void *buf; -+ int err; -+ -+ /* -+ * First fetch all the memory (RAM) ranges that we are going to -+ * pass to the crash dump kernel during panic. -+ */ -+ -+ err = crash_get_memory_ranges(); -+ -+ if (err) -+ return EFAILED; -+ -+ elf_info.page_offset = get_kernel_page_offset(); -+ dbgprintf("%s: page_offset: %016llx\n", __func__, -+ elf_info.page_offset); -+ -+ err = crash_create_elf64_headers(info, &elf_info, -+ system_memory_rgns.ranges, system_memory_rgns.size, -+ &buf, &bufsz, ELF_CORE_HEADER_ALIGN); -+ -+ if (err) -+ return EFAILED; -+ -+ elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 0, -+ crash_reserved_mem.start, crash_reserved_mem.end, -+ -1, 0); -+ -+ elfcorehdr_mem.start = elfcorehdr; -+ elfcorehdr_mem.end = elfcorehdr + bufsz - 1; -+ -+ dbgprintf("%s: elfcorehdr 0x%llx-0x%llx\n", __func__, -+ elfcorehdr_mem.start, elfcorehdr_mem.end); -+ -+ return 0; - } -Index: kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.h -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/crashdump-arm64.h -+++ kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.h -@@ -18,5 +18,8 @@ - - extern struct memory_ranges usablemem_rgns; - extern struct memory_range crash_reserved_mem; -+extern struct memory_range elfcorehdr_mem; -+ -+extern int load_crashdump_segments(struct kexec_info *info); - - #endif /* CRASHDUMP_ARM64_H */ -Index: kexec-tools-2.0.14/kexec/arch/arm64/iomem.h -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/iomem.h -+++ kexec-tools-2.0.14/kexec/arch/arm64/iomem.h -@@ -2,6 +2,8 @@ - #define IOMEM_H - - #define SYSTEM_RAM "System RAM\n" -+#define KERNEL_CODE "Kernel code\n" -+#define KERNEL_DATA "Kernel data\n" - #define CRASH_KERNEL "Crash kernel\n" - #define IOMEM_RESERVED "reserved\n" - -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-elf-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-elf-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-elf-arm64.c -@@ -119,6 +119,16 @@ int elf_arm64_load(int argc, char **argv - dbgprintf("%s: PE format: %s\n", __func__, - (arm64_header_check_pe_sig(header) ? "yes" : "no")); - -+ /* 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 */ - result = elf_exec_load(&ehdr, info); - -@@ -127,6 +137,7 @@ int elf_arm64_load(int argc, char **argv - goto exit; - } - -+ /* load additional data */ - result = arm64_load_other_segments(info, kernel_segment - + arm64_mem.text_offset); - diff -Nru kexec-tools-2.0.10/debian/patches/0007-arm64-kdump-set-up-kernel-image-segment.patch kexec-tools-2.0.16/debian/patches/0007-arm64-kdump-set-up-kernel-image-segment.patch --- kexec-tools-2.0.10/debian/patches/0007-arm64-kdump-set-up-kernel-image-segment.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/0007-arm64-kdump-set-up-kernel-image-segment.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,136 +0,0 @@ -From 1591926df5a602ffcbf55e99aa8a96fbebd0bafe Mon Sep 17 00:00:00 2001 -From: AKASHI Takahiro -Date: Wed, 17 May 2017 14:51:47 +0900 -Subject: [PATCH 07/11] arm64: kdump: set up kernel image segment - -On arm64, we can use the same kernel image as 1st kernel, but -we have to modify the entry point as well as segments' addresses -in the kernel's elf header in order to load them into correct places. - -Signed-off-by: AKASHI Takahiro -Tested-by: David Woodhouse -Tested-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/crashdump-arm64.c | 24 ++++++++++++++++++++++++ - kexec/arch/arm64/crashdump-arm64.h | 1 + - kexec/arch/arm64/kexec-arm64.c | 25 ++++++++++++++++++++----- - kexec/arch/arm64/kexec-elf-arm64.c | 11 ++++++++++- - 4 files changed, 55 insertions(+), 6 deletions(-) - -Index: kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/crashdump-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.c -@@ -210,3 +210,27 @@ int load_crashdump_segments(struct kexec - - return 0; - } -+ -+/* -+ * e_entry and p_paddr are actually in virtual address space. -+ * Those values will be translated to physcal addresses by using -+ * virt_to_phys() in add_segment(). -+ * So let's fix up those values for later use so the memory base -+ * (arm64_mm.phys_offset) will be correctly replaced with -+ * crash_reserved_mem.start. -+ */ -+void fixup_elf_addrs(struct mem_ehdr *ehdr) -+{ -+ struct mem_phdr *phdr; -+ int i; -+ -+ ehdr->e_entry += - arm64_mem.phys_offset + crash_reserved_mem.start; -+ -+ for (i = 0; i < ehdr->e_phnum; i++) { -+ phdr = &ehdr->e_phdr[i]; -+ if (phdr->p_type != PT_LOAD) -+ continue; -+ phdr->p_paddr += -+ (-arm64_mem.phys_offset + crash_reserved_mem.start); -+ } -+} -Index: kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.h -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/crashdump-arm64.h -+++ kexec-tools-2.0.14/kexec/arch/arm64/crashdump-arm64.h -@@ -21,5 +21,6 @@ extern struct memory_range crash_reserve - extern struct memory_range elfcorehdr_mem; - - extern int load_crashdump_segments(struct kexec_info *info); -+extern void fixup_elf_addrs(struct mem_ehdr *ehdr); - - #endif /* CRASHDUMP_ARM64_H */ -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-arm64.c -@@ -307,12 +307,27 @@ unsigned long arm64_locate_kernel_segmen - { - unsigned long hole; - -- hole = locate_hole(info, -- arm64_mem.text_offset + arm64_mem.image_size, -- MiB(2), 0, ULONG_MAX, 1); -+ if (info->kexec_flags & KEXEC_ON_CRASH) { -+ unsigned long hole_end; - -- if (hole == ULONG_MAX) -- dbgprintf("%s: locate_hole failed\n", __func__); -+ hole = (crash_reserved_mem.start < mem_min ? -+ mem_min : crash_reserved_mem.start); -+ hole = _ALIGN_UP(hole, MiB(2)); -+ hole_end = hole + arm64_mem.text_offset + arm64_mem.image_size; -+ -+ if ((hole_end > mem_max) || -+ (hole_end > crash_reserved_mem.end)) { -+ dbgprintf("%s: Crash kernel out of range\n", __func__); -+ hole = ULONG_MAX; -+ } -+ } else { -+ hole = locate_hole(info, -+ arm64_mem.text_offset + arm64_mem.image_size, -+ MiB(2), 0, ULONG_MAX, 1); -+ -+ if (hole == ULONG_MAX) -+ dbgprintf("%s: locate_hole failed\n", __func__); -+ } - - return hole; - } -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-elf-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-elf-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-elf-arm64.c -@@ -9,6 +9,7 @@ - #include - #include - -+#include "crashdump-arm64.h" - #include "kexec-arm64.h" - #include "kexec-elf.h" - #include "kexec-syscall.h" -@@ -105,7 +106,8 @@ int elf_arm64_load(int argc, char **argv - } - - arm64_mem.vp_offset = _ALIGN_DOWN(ehdr.e_entry, MiB(2)); -- arm64_mem.vp_offset -= kernel_segment - get_phys_offset(); -+ if (!(info->kexec_flags & KEXEC_ON_CRASH)) -+ arm64_mem.vp_offset -= kernel_segment - get_phys_offset(); - - dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment); - dbgprintf("%s: text_offset: %016lx\n", __func__, -@@ -130,6 +132,13 @@ int elf_arm64_load(int argc, char **argv - } - - /* load the kernel */ -+ if (info->kexec_flags & KEXEC_ON_CRASH) -+ /* -+ * offset addresses in elf header in order to load -+ * vmlinux (elf_exec) into crash kernel's memory -+ */ -+ fixup_elf_addrs(&ehdr); -+ - result = elf_exec_load(&ehdr, info); - - if (result) { diff -Nru kexec-tools-2.0.10/debian/patches/0008-arm64-kdump-set-up-other-segments.patch kexec-tools-2.0.16/debian/patches/0008-arm64-kdump-set-up-other-segments.patch --- kexec-tools-2.0.10/debian/patches/0008-arm64-kdump-set-up-other-segments.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/0008-arm64-kdump-set-up-other-segments.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -From defad947feff0d0135f79893e99ca94ec9a59e0f Mon Sep 17 00:00:00 2001 -From: AKASHI Takahiro -Date: Wed, 17 May 2017 14:51:48 +0900 -Subject: [PATCH 08/11] arm64: kdump: set up other segments - -We make sure that all the other segments, initrd and device-tree blob, -also be loaded into the reserved memory of crash dump kernel. - -Signed-off-by: AKASHI Takahiro -Tested-by: David Woodhouse -Tested-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/kexec-arm64.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-arm64.c -@@ -375,7 +375,10 @@ int arm64_load_other_segments(struct kex - /* Put the other segments after the image. */ - - hole_min = image_base + arm64_mem.image_size; -- hole_max = ULONG_MAX; -+ if (info->kexec_flags & KEXEC_ON_CRASH) -+ hole_max = crash_reserved_mem.end; -+ else -+ hole_max = ULONG_MAX; - - if (arm64_opts.initrd) { - initrd_buf = slurp_file(arm64_opts.initrd, &initrd_size); diff -Nru kexec-tools-2.0.10/debian/patches/0009-arm64-kdump-add-DT-properties-to-crash-dump-kernel-s.patch kexec-tools-2.0.16/debian/patches/0009-arm64-kdump-add-DT-properties-to-crash-dump-kernel-s.patch --- kexec-tools-2.0.10/debian/patches/0009-arm64-kdump-add-DT-properties-to-crash-dump-kernel-s.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/0009-arm64-kdump-add-DT-properties-to-crash-dump-kernel-s.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,279 +0,0 @@ -From 5f955585c7c9166da5b8f33e3d8a4c43845ee70b Mon Sep 17 00:00:00 2001 -From: AKASHI Takahiro -Date: Wed, 17 May 2017 14:51:49 +0900 -Subject: [PATCH 09/11] arm64: kdump: add DT properties to crash dump kernel's - dtb - -We pass the following properties to crash dump kernel: -linux,elfcorehdr: elf core header segment, - same as "elfcorehdr=" kernel parameter on other archs -linux,usable-memory-range: usable memory reserved for crash dump kernel - -Signed-off-by: AKASHI Takahiro -Tested-by: David Woodhouse -Tested-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/kexec-arm64.c | 197 ++++++++++++++++++++++++++++++++++++- - kexec/arch/arm64/kexec-elf-arm64.c | 5 - - 2 files changed, 192 insertions(+), 10 deletions(-) - -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-arm64.c -@@ -25,6 +25,14 @@ - #include "kexec-syscall.h" - #include "arch/options.h" - -+#define ROOT_NODE_ADDR_CELLS_DEFAULT 1 -+#define ROOT_NODE_SIZE_CELLS_DEFAULT 1 -+ -+#define PROP_ADDR_CELLS "#address-cells" -+#define PROP_SIZE_CELLS "#size-cells" -+#define PROP_ELFCOREHDR "linux,elfcorehdr" -+#define PROP_USABLE_MEM_RANGE "linux,usable-memory-range" -+ - /* Global varables the core kexec routines expect. */ - - unsigned char reuse_initrd; -@@ -128,9 +136,6 @@ int arch_process_options(int argc, char - case OPT_INITRD: - arm64_opts.initrd = optarg; - break; -- case OPT_PANIC: -- die("load-panic (-p) not supported"); -- break; - default: - break; /* Ignore core and unknown options. */ - } -@@ -281,12 +286,115 @@ on_success: - return 0; - } - -+static int get_cells_size(void *fdt, uint32_t *address_cells, -+ uint32_t *size_cells) -+{ -+ int nodeoffset; -+ const uint32_t *prop = NULL; -+ int prop_len; -+ -+ /* default values */ -+ *address_cells = ROOT_NODE_ADDR_CELLS_DEFAULT; -+ *size_cells = ROOT_NODE_SIZE_CELLS_DEFAULT; -+ -+ /* under root node */ -+ nodeoffset = fdt_path_offset(fdt, "/"); -+ if (nodeoffset < 0) -+ goto on_error; -+ -+ prop = fdt_getprop(fdt, nodeoffset, PROP_ADDR_CELLS, &prop_len); -+ if (prop) { -+ if (prop_len == sizeof(*prop)) -+ *address_cells = fdt32_to_cpu(*prop); -+ else -+ goto on_error; -+ } -+ -+ prop = fdt_getprop(fdt, nodeoffset, PROP_SIZE_CELLS, &prop_len); -+ if (prop) { -+ if (prop_len == sizeof(*prop)) -+ *size_cells = fdt32_to_cpu(*prop); -+ else -+ goto on_error; -+ } -+ -+ dbgprintf("%s: #address-cells:%d #size-cells:%d\n", __func__, -+ *address_cells, *size_cells); -+ return 0; -+ -+on_error: -+ return EFAILED; -+} -+ -+static bool cells_size_fitted(uint32_t address_cells, uint32_t size_cells, -+ struct memory_range *range) -+{ -+ dbgprintf("%s: %llx-%llx\n", __func__, range->start, range->end); -+ -+ /* if *_cells >= 2, cells can hold 64-bit values anyway */ -+ if ((address_cells == 1) && (range->start >= (1ULL << 32))) -+ return false; -+ -+ if ((size_cells == 1) && -+ ((range->end - range->start + 1) >= (1ULL << 32))) -+ return false; -+ -+ return true; -+} -+ -+static void fill_property(void *buf, uint64_t val, uint32_t cells) -+{ -+ uint32_t val32; -+ int i; -+ -+ if (cells == 1) { -+ val32 = cpu_to_fdt32((uint32_t)val); -+ memcpy(buf, &val32, sizeof(uint32_t)); -+ } else { -+ for (i = 0; -+ i < (cells * sizeof(uint32_t) - sizeof(uint64_t)); i++) -+ *(char *)buf++ = 0; -+ -+ val = cpu_to_fdt64(val); -+ memcpy(buf, &val, sizeof(uint64_t)); -+ } -+} -+ -+static int fdt_setprop_range(void *fdt, int nodeoffset, -+ const char *name, struct memory_range *range, -+ uint32_t address_cells, uint32_t size_cells) -+{ -+ void *buf, *prop; -+ size_t buf_size; -+ int result; -+ -+ buf_size = (address_cells + size_cells) * sizeof(uint32_t); -+ prop = buf = xmalloc(buf_size); -+ -+ fill_property(prop, range->start, address_cells); -+ prop += address_cells * sizeof(uint32_t); -+ -+ fill_property(prop, range->end - range->start + 1, size_cells); -+ prop += size_cells * sizeof(uint32_t); -+ -+ result = fdt_setprop(fdt, nodeoffset, name, buf, buf_size); -+ -+ free(buf); -+ -+ return result; -+} -+ - /** - * setup_2nd_dtb - Setup the 2nd stage kernel's dtb. - */ - --static int setup_2nd_dtb(struct dtb *dtb, char *command_line) -+static int setup_2nd_dtb(struct dtb *dtb, char *command_line, int on_crash) - { -+ uint32_t address_cells, size_cells; -+ int range_len; -+ int nodeoffset; -+ char *new_buf = NULL; -+ int new_size; - int result; - - result = fdt_check_header(dtb->buf); -@@ -298,8 +406,86 @@ static int setup_2nd_dtb(struct dtb *dtb - - result = set_bootargs(dtb, command_line); - -+ if (on_crash) { -+ /* determine #address-cells and #size-cells */ -+ result = get_cells_size(dtb->buf, &address_cells, &size_cells); -+ if (result) { -+ fprintf(stderr, -+ "kexec: cannot determine cells-size.\n"); -+ result = -EINVAL; -+ goto on_error; -+ } -+ -+ if (!cells_size_fitted(address_cells, size_cells, -+ &elfcorehdr_mem)) { -+ fprintf(stderr, -+ "kexec: elfcorehdr doesn't fit cells-size.\n"); -+ result = -EINVAL; -+ goto on_error; -+ } -+ -+ if (!cells_size_fitted(address_cells, size_cells, -+ &crash_reserved_mem)) { -+ fprintf(stderr, -+ "kexec: usable memory range doesn't fit cells-size.\n"); -+ result = -EINVAL; -+ goto on_error; -+ } -+ -+ /* duplicate dt blob */ -+ range_len = sizeof(uint32_t) * (address_cells + size_cells); -+ new_size = fdt_totalsize(dtb->buf) -+ + fdt_prop_len(PROP_ELFCOREHDR, range_len) -+ + fdt_prop_len(PROP_USABLE_MEM_RANGE, range_len); -+ -+ new_buf = xmalloc(new_size); -+ result = fdt_open_into(dtb->buf, new_buf, new_size); -+ if (result) { -+ dbgprintf("%s: fdt_open_into failed: %s\n", __func__, -+ fdt_strerror(result)); -+ result = -ENOSPC; -+ goto on_error; -+ } -+ -+ /* add linux,elfcorehdr */ -+ nodeoffset = fdt_path_offset(new_buf, "/chosen"); -+ result = fdt_setprop_range(new_buf, nodeoffset, -+ PROP_ELFCOREHDR, &elfcorehdr_mem, -+ address_cells, size_cells); -+ if (result) { -+ dbgprintf("%s: fdt_setprop failed: %s\n", __func__, -+ fdt_strerror(result)); -+ result = -EINVAL; -+ goto on_error; -+ } -+ -+ /* add linux,usable-memory-range */ -+ nodeoffset = fdt_path_offset(new_buf, "/chosen"); -+ result = fdt_setprop_range(new_buf, nodeoffset, -+ PROP_USABLE_MEM_RANGE, &crash_reserved_mem, -+ address_cells, size_cells); -+ if (result) { -+ dbgprintf("%s: fdt_setprop failed: %s\n", __func__, -+ fdt_strerror(result)); -+ result = -EINVAL; -+ goto on_error; -+ } -+ -+ fdt_pack(new_buf); -+ dtb->buf = new_buf; -+ dtb->size = fdt_totalsize(new_buf); -+ } -+ - dump_reservemap(dtb); - -+ -+ return result; -+ -+on_error: -+ fprintf(stderr, "kexec: %s failed.\n", __func__); -+ if (new_buf) -+ free(new_buf); -+ - return result; - } - -@@ -367,7 +553,8 @@ int arm64_load_other_segments(struct kex - } - } - -- result = setup_2nd_dtb(&dtb, command_line); -+ result = setup_2nd_dtb(&dtb, command_line, -+ info->kexec_flags & KEXEC_ON_CRASH); - - if (result) - return EFAILED; -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-elf-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-elf-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-elf-arm64.c -@@ -47,11 +47,6 @@ int elf_arm64_load(int argc, char **argv - int result; - int i; - -- if (info->kexec_flags & KEXEC_ON_CRASH) { -- fprintf(stderr, "kexec: kdump not yet supported on arm64\n"); -- return EFAILED; -- } -- - result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0); - - if (result < 0) { diff -Nru kexec-tools-2.0.10/debian/patches/0010-arm64-kdump-Add-support-for-binary-image-files.patch kexec-tools-2.0.16/debian/patches/0010-arm64-kdump-Add-support-for-binary-image-files.patch --- kexec-tools-2.0.10/debian/patches/0010-arm64-kdump-Add-support-for-binary-image-files.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/0010-arm64-kdump-Add-support-for-binary-image-files.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -From c504ff5d85aa035aed9f14f5ce96c5d959952dd9 Mon Sep 17 00:00:00 2001 -From: Pratyush Anand -Date: Wed, 17 May 2017 14:51:50 +0900 -Subject: [PATCH 10/11] arm64: kdump: Add support for binary image files - -This patch adds support to use binary image ie arch/arm64/boot/Image with -kdump. - -Signed-off-by: Pratyush Anand -[takahiro.akashi@linaro.org: a bit reworked] -Signed-off-by: AKASHI Takahiro -Tested-by: David Woodhouse -Tested-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/kexec-image-arm64.c | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -Index: kexec-tools-2.0.14/kexec/arch/arm64/kexec-image-arm64.c -=================================================================== ---- kexec-tools-2.0.14.orig/kexec/arch/arm64/kexec-image-arm64.c -+++ kexec-tools-2.0.14/kexec/arch/arm64/kexec-image-arm64.c -@@ -4,7 +4,9 @@ - - #define _GNU_SOURCE - -+#include "crashdump-arm64.h" - #include "kexec-arm64.h" -+#include "kexec-syscall.h" - #include - - int image_arm64_probe(const char *kernel_buf, off_t kernel_size) -@@ -58,11 +60,22 @@ int image_arm64_load(int argc, char **ar - dbgprintf("%s: PE format: %s\n", __func__, - (arm64_header_check_pe_sig(header) ? "yes" : "no")); - -+ /* 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_phys_virt(info, kernel_buf, kernel_size, - kernel_segment + arm64_mem.text_offset, - arm64_mem.image_size, 0); - -+ /* load additional data */ - result = arm64_load_other_segments(info, kernel_segment - + arm64_mem.text_offset); - diff -Nru kexec-tools-2.0.10/debian/patches/arm64-Add-arm64-kexec-support.patch kexec-tools-2.0.16/debian/patches/arm64-Add-arm64-kexec-support.patch --- kexec-tools-2.0.10/debian/patches/arm64-Add-arm64-kexec-support.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm64-Add-arm64-kexec-support.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,1363 +0,0 @@ -From 522df5f7217fda01ece3f6ac3e9987b0320c2bb0 Mon Sep 17 00:00:00 2001 -From: Geoff Levand -Date: Wed, 21 Sep 2016 18:14:25 +0000 -Subject: [PATCH] arm64: Add arm64 kexec support - -Add kexec reboot support for ARM64 platforms. - -Signed-off-by: Geoff Levand -Tested-By: Pratyush Anand -Tested-By: Matthias Brugger -Signed-off-by: Simon Horman -[dannf: kexec/kexec-syscall.h: Adjust offsets to apply] - -Index: kexec-tools-2.0.10/configure.ac -=================================================================== ---- kexec-tools-2.0.10.orig/configure.ac -+++ kexec-tools-2.0.10/configure.ac -@@ -39,6 +39,9 @@ case $target_cpu in - ARCH="ppc64" - SUBARCH="LE" - ;; -+ aarch64* ) -+ ARCH="arm64" -+ ;; - arm* ) - ARCH="arm" - ;; -Index: kexec-tools-2.0.10/kexec/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/Makefile -+++ kexec-tools-2.0.10/kexec/Makefile -@@ -75,6 +75,7 @@ KEXEC_SRCS += $($(ARCH)_DT_OPS) - - include $(srcdir)/kexec/arch/alpha/Makefile - include $(srcdir)/kexec/arch/arm/Makefile -+include $(srcdir)/kexec/arch/arm64/Makefile - include $(srcdir)/kexec/arch/i386/Makefile - include $(srcdir)/kexec/arch/ia64/Makefile - include $(srcdir)/kexec/arch/m68k/Makefile -Index: kexec-tools-2.0.10/kexec/arch/arm64/Makefile -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/arch/arm64/Makefile -@@ -0,0 +1,40 @@ -+ -+arm64_FS2DT += kexec/fs2dt.c -+arm64_FS2DT_INCLUDE += -include $(srcdir)/kexec/arch/arm64/kexec-arm64.h \ -+ -include $(srcdir)/kexec/arch/arm64/crashdump-arm64.h -+ -+arm64_DT_OPS += kexec/dt-ops.c -+ -+arm64_CPPFLAGS += -I $(srcdir)/kexec/ -+ -+arm64_KEXEC_SRCS += \ -+ kexec/arch/arm64/kexec-arm64.c \ -+ kexec/arch/arm64/kexec-image-arm64.c \ -+ kexec/arch/arm64/kexec-elf-arm64.c \ -+ kexec/arch/arm64/crashdump-arm64.c -+ -+arm64_ARCH_REUSE_INITRD = -+arm64_ADD_SEGMENT = -+arm64_VIRT_TO_PHYS = -+arm64_PHYS_TO_VIRT = -+ -+dist += $(arm64_KEXEC_SRCS) \ -+ kexec/arch/arm64/Makefile \ -+ kexec/arch/arm64/kexec-arm64.h \ -+ kexec/arch/arm64/crashdump-arm64.h -+ -+ifdef HAVE_LIBFDT -+ -+LIBS += -lfdt -+ -+else -+ -+include $(srcdir)/kexec/libfdt/Makefile.libfdt -+ -+libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) -+ -+arm64_CPPFLAGS += -I$(srcdir)/kexec/libfdt -+ -+arm64_KEXEC_SRCS += $(libfdt_SRCS) -+ -+endif -Index: kexec-tools-2.0.10/kexec/arch/arm64/crashdump-arm64.c -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/arch/arm64/crashdump-arm64.c -@@ -0,0 +1,21 @@ -+/* -+ * ARM64 crashdump. -+ */ -+ -+#define _GNU_SOURCE -+ -+#include -+#include -+ -+#include "kexec.h" -+#include "crashdump.h" -+#include "crashdump-arm64.h" -+#include "kexec-arm64.h" -+#include "kexec-elf.h" -+ -+struct memory_ranges usablemem_rgns = {}; -+ -+int is_crashkernel_mem_reserved(void) -+{ -+ return 0; -+} -Index: kexec-tools-2.0.10/kexec/arch/arm64/crashdump-arm64.h -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/arch/arm64/crashdump-arm64.h -@@ -0,0 +1,12 @@ -+/* -+ * ARM64 crashdump. -+ */ -+ -+#if !defined(CRASHDUMP_ARM64_H) -+#define CRASHDUMP_ARM64_H -+ -+#include "kexec.h" -+ -+extern struct memory_ranges usablemem_rgns; -+ -+#endif -Index: kexec-tools-2.0.10/kexec/arch/arm64/image-header.h -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/arch/arm64/image-header.h -@@ -0,0 +1,146 @@ -+/* -+ * ARM64 binary image header. -+ */ -+ -+#if !defined(__ARM64_IMAGE_HEADER_H) -+#define __ARM64_IMAGE_HEADER_H -+ -+#include -+#include -+ -+/** -+ * struct arm64_image_header - arm64 kernel image header. -+ * -+ * @pe_sig: Optional PE format 'MZ' signature. -+ * @branch_code: Reserved for instructions to branch to stext. -+ * @text_offset: The image load offset in LSB byte order. -+ * @image_size: An estimated size of the memory image size in LSB byte order. -+ * @flags: Bit flags in LSB byte order: -+ * Bit 0: Image byte order: 1=MSB. -+ * Bit 1-2: Kernel page size: 1=4K, 2=16K, 3=64K. -+ * Bit 3: Image placement: 0=low. -+ * @reserved_1: Reserved. -+ * @magic: Magic number, "ARM\x64". -+ * @pe_header: Optional offset to a PE format header. -+ **/ -+ -+struct arm64_image_header { -+ uint8_t pe_sig[2]; -+ uint16_t branch_code[3]; -+ uint64_t text_offset; -+ uint64_t image_size; -+ uint64_t flags; -+ uint64_t reserved_1[3]; -+ uint8_t magic[4]; -+ uint32_t pe_header; -+}; -+ -+static const uint8_t arm64_image_magic[4] = {'A', 'R', 'M', 0x64U}; -+static const uint8_t arm64_image_pe_sig[2] = {'M', 'Z'}; -+static const uint64_t arm64_image_flag_be = (1UL << 0); -+static const uint64_t arm64_image_flag_page_size = (3UL << 1); -+static const uint64_t arm64_image_flag_placement = (1UL << 3); -+ -+/** -+ * enum arm64_header_page_size -+ */ -+ -+enum arm64_header_page_size { -+ arm64_header_page_size_invalid = 0, -+ arm64_header_page_size_4k, -+ arm64_header_page_size_16k, -+ arm64_header_page_size_64k -+}; -+ -+/** -+ * arm64_header_check_magic - Helper to check the arm64 image header. -+ * -+ * Returns non-zero if header is OK. -+ */ -+ -+static inline int arm64_header_check_magic(const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ return (h->magic[0] == arm64_image_magic[0] -+ && h->magic[1] == arm64_image_magic[1] -+ && h->magic[2] == arm64_image_magic[2] -+ && h->magic[3] == arm64_image_magic[3]); -+} -+ -+/** -+ * arm64_header_check_pe_sig - Helper to check the arm64 image header. -+ * -+ * Returns non-zero if 'MZ' signature is found. -+ */ -+ -+static inline int arm64_header_check_pe_sig(const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ return (h->pe_sig[0] == arm64_image_pe_sig[0] -+ && h->pe_sig[1] == arm64_image_pe_sig[1]); -+} -+ -+/** -+ * arm64_header_check_msb - Helper to check the arm64 image header. -+ * -+ * Returns non-zero if the image was built as big endian. -+ */ -+ -+static inline int arm64_header_check_msb(const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ return (le64toh(h->flags) & arm64_image_flag_be) >> 0; -+} -+ -+/** -+ * arm64_header_page_size -+ */ -+ -+static inline enum arm64_header_page_size arm64_header_page_size( -+ const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ return (le64toh(h->flags) & arm64_image_flag_page_size) >> 1; -+} -+ -+/** -+ * arm64_header_placement -+ * -+ * Returns non-zero if the image has no physical placement restrictions. -+ */ -+ -+static inline int arm64_header_placement(const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ return (le64toh(h->flags) & arm64_image_flag_placement) >> 3; -+} -+ -+static inline uint64_t arm64_header_text_offset( -+ const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ return le64toh(h->text_offset); -+} -+ -+static inline uint64_t arm64_header_image_size( -+ const struct arm64_image_header *h) -+{ -+ if (!h) -+ return 0; -+ -+ return le64toh(h->image_size); -+} -+ -+#endif -Index: kexec-tools-2.0.10/kexec/arch/arm64/include/arch/options.h -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/arch/arm64/include/arch/options.h -@@ -0,0 +1,39 @@ -+#if !defined(KEXEC_ARCH_ARM64_OPTIONS_H) -+#define KEXEC_ARCH_ARM64_OPTIONS_H -+ -+#define OPT_APPEND ((OPT_MAX)+0) -+#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 KEXEC_ARCH_OPTIONS \ -+ KEXEC_OPTIONS \ -+ { "append", 1, NULL, OPT_APPEND }, \ -+ { "command-line", 1, NULL, OPT_APPEND }, \ -+ { "dtb", 1, NULL, OPT_DTB }, \ -+ { "initrd", 1, NULL, OPT_INITRD }, \ -+ { "ramdisk", 1, NULL, OPT_INITRD }, \ -+ { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \ -+ -+#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */ -+#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS -+#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR -+ -+static const char arm64_opts_usage[] __attribute__ ((unused)) = -+" --append=STRING Set the kernel command line to STRING.\n" -+" --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" -+" --ramdisk=FILE Use FILE as the kernel initial ramdisk.\n" -+" --reuse-cmdline Use kernel command line from running system.\n"; -+ -+struct arm64_opts { -+ const char *command_line; -+ const char *dtb; -+ const char *initrd; -+}; -+ -+extern struct arm64_opts arm64_opts; -+ -+#endif -Index: kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.c -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.c -@@ -0,0 +1,615 @@ -+/* -+ * ARM64 kexec. -+ */ -+ -+#define _GNU_SOURCE -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "kexec.h" -+#include "kexec-arm64.h" -+#include "crashdump.h" -+#include "crashdump-arm64.h" -+#include "dt-ops.h" -+#include "fs2dt.h" -+#include "kexec-syscall.h" -+#include "arch/options.h" -+ -+/* Global varables the core kexec routines expect. */ -+ -+unsigned char reuse_initrd; -+ -+off_t initrd_base; -+off_t initrd_size; -+ -+const struct arch_map_entry arches[] = { -+ { "aarch64", KEXEC_ARCH_ARM64 }, -+ { "aarch64_be", KEXEC_ARCH_ARM64 }, -+ { NULL, 0 }, -+}; -+ -+struct file_type file_type[] = { -+ {"vmlinux", elf_arm64_probe, elf_arm64_load, elf_arm64_usage}, -+ {"Image", image_arm64_probe, image_arm64_load, image_arm64_usage}, -+}; -+ -+int file_types = sizeof(file_type) / sizeof(file_type[0]); -+ -+/* arm64 global varables. */ -+ -+struct arm64_opts arm64_opts; -+struct arm64_mem arm64_mem = { -+ .phys_offset = arm64_mem_ngv, -+ .vp_offset = arm64_mem_ngv, -+}; -+ -+uint64_t get_phys_offset(void) -+{ -+ assert(arm64_mem.phys_offset != arm64_mem_ngv); -+ return arm64_mem.phys_offset; -+} -+ -+uint64_t get_vp_offset(void) -+{ -+ assert(arm64_mem.vp_offset != arm64_mem_ngv); -+ return arm64_mem.vp_offset; -+} -+ -+/** -+ * arm64_process_image_header - Process the arm64 image header. -+ * -+ * Make a guess that KERNEL_IMAGE_SIZE will be enough for older kernels. -+ */ -+ -+int arm64_process_image_header(const struct arm64_image_header *h) -+{ -+#if !defined(KERNEL_IMAGE_SIZE) -+# define KERNEL_IMAGE_SIZE MiB(16) -+#endif -+ -+ if (!arm64_header_check_magic(h)) -+ return -EFAILED; -+ -+ if (h->image_size) { -+ arm64_mem.text_offset = arm64_header_text_offset(h); -+ arm64_mem.image_size = arm64_header_image_size(h); -+ } else { -+ /* For 3.16 and older kernels. */ -+ arm64_mem.text_offset = 0x80000; -+ arm64_mem.image_size = KERNEL_IMAGE_SIZE; -+ fprintf(stderr, -+ "kexec: %s: Warning: Kernel image size set to %lu MiB.\n" -+ " Please verify compatability with lodaed kernel.\n", -+ __func__, KERNEL_IMAGE_SIZE / 1024UL / 1024UL); -+ } -+ -+ return 0; -+} -+ -+void arch_usage(void) -+{ -+ printf(arm64_opts_usage); -+} -+ -+int arch_process_options(int argc, char **argv) -+{ -+ static const char short_options[] = KEXEC_OPT_STR ""; -+ static const struct option options[] = { -+ KEXEC_ARCH_OPTIONS -+ { 0 } -+ }; -+ int opt; -+ char *cmdline = NULL; -+ const char *append = NULL; -+ -+ for (opt = 0; opt != -1; ) { -+ opt = getopt_long(argc, argv, short_options, options, 0); -+ -+ switch (opt) { -+ case OPT_APPEND: -+ append = optarg; -+ break; -+ case OPT_REUSE_CMDLINE: -+ cmdline = get_command_line(); -+ break; -+ case OPT_DTB: -+ arm64_opts.dtb = optarg; -+ break; -+ case OPT_INITRD: -+ arm64_opts.initrd = optarg; -+ break; -+ case OPT_PANIC: -+ die("load-panic (-p) not supported"); -+ break; -+ default: -+ break; /* Ignore core and unknown options. */ -+ } -+ } -+ -+ arm64_opts.command_line = concat_cmdline(cmdline, append); -+ -+ dbgprintf("%s:%d: command_line: %s\n", __func__, __LINE__, -+ arm64_opts.command_line); -+ dbgprintf("%s:%d: initrd: %s\n", __func__, __LINE__, -+ arm64_opts.initrd); -+ dbgprintf("%s:%d: dtb: %s\n", __func__, __LINE__, arm64_opts.dtb); -+ -+ return 0; -+} -+ -+/** -+ * struct dtb - Info about a binary device tree. -+ * -+ * @buf: Device tree data. -+ * @size: Device tree data size. -+ * @name: Shorthand name of this dtb for messages. -+ * @path: Filesystem path. -+ */ -+ -+struct dtb { -+ char *buf; -+ off_t size; -+ const char *name; -+ const char *path; -+}; -+ -+/** -+ * dump_reservemap - Dump the dtb's reservemap. -+ */ -+ -+static void dump_reservemap(const struct dtb *dtb) -+{ -+ int i; -+ -+ for (i = 0; ; i++) { -+ uint64_t address; -+ uint64_t size; -+ -+ fdt_get_mem_rsv(dtb->buf, i, &address, &size); -+ -+ if (!size) -+ break; -+ -+ dbgprintf("%s: %s {%" PRIx64 ", %" PRIx64 "}\n", __func__, -+ dtb->name, address, size); -+ } -+} -+ -+/** -+ * set_bootargs - Set the dtb's bootargs. -+ */ -+ -+static int set_bootargs(struct dtb *dtb, const char *command_line) -+{ -+ int result; -+ -+ if (!command_line || !command_line[0]) -+ return 0; -+ -+ result = dtb_set_bootargs(&dtb->buf, &dtb->size, command_line); -+ -+ if (result) { -+ fprintf(stderr, -+ "kexec: Set device tree bootargs failed.\n"); -+ return -EFAILED; -+ } -+ -+ return 0; -+} -+ -+/** -+ * read_proc_dtb - Read /proc/device-tree. -+ */ -+ -+static int read_proc_dtb(struct dtb *dtb) -+{ -+ int result; -+ struct stat s; -+ static const char path[] = "/proc/device-tree"; -+ -+ result = stat(path, &s); -+ -+ if (result) { -+ dbgprintf("%s: %s\n", __func__, strerror(errno)); -+ return -EFAILED; -+ } -+ -+ dtb->path = path; -+ create_flatten_tree((char **)&dtb->buf, &dtb->size, NULL); -+ -+ return 0; -+} -+ -+/** -+ * read_sys_dtb - Read /sys/firmware/fdt. -+ */ -+ -+static int read_sys_dtb(struct dtb *dtb) -+{ -+ int result; -+ struct stat s; -+ static const char path[] = "/sys/firmware/fdt"; -+ -+ result = stat(path, &s); -+ -+ if (result) { -+ dbgprintf("%s: %s\n", __func__, strerror(errno)); -+ return -EFAILED; -+ } -+ -+ dtb->path = path; -+ dtb->buf = slurp_file(path, &dtb->size); -+ -+ return 0; -+} -+ -+/** -+ * read_1st_dtb - Read the 1st stage kernel's dtb. -+ */ -+ -+static int read_1st_dtb(struct dtb *dtb) -+{ -+ int result; -+ -+ dtb->name = "dtb_sys"; -+ result = read_sys_dtb(dtb); -+ -+ if (!result) -+ goto on_success; -+ -+ dtb->name = "dtb_proc"; -+ result = read_proc_dtb(dtb); -+ -+ if (!result) -+ goto on_success; -+ -+ dbgprintf("%s: not found\n", __func__); -+ return -EFAILED; -+ -+on_success: -+ dbgprintf("%s: found %s\n", __func__, dtb->path); -+ return 0; -+} -+ -+/** -+ * setup_2nd_dtb - Setup the 2nd stage kernel's dtb. -+ */ -+ -+static int setup_2nd_dtb(struct dtb *dtb, char *command_line) -+{ -+ int result; -+ -+ result = fdt_check_header(dtb->buf); -+ -+ if (result) { -+ fprintf(stderr, "kexec: Invalid 2nd device tree.\n"); -+ return -EFAILED; -+ } -+ -+ result = set_bootargs(dtb, command_line); -+ -+ dump_reservemap(dtb); -+ -+ return result; -+} -+ -+unsigned long arm64_locate_kernel_segment(struct kexec_info *info) -+{ -+ unsigned long hole; -+ -+ hole = locate_hole(info, -+ arm64_mem.text_offset + arm64_mem.image_size, -+ MiB(2), 0, ULONG_MAX, 1); -+ -+ if (hole == ULONG_MAX) -+ dbgprintf("%s: locate_hole failed\n", __func__); -+ -+ return hole; -+} -+ -+/** -+ * arm64_load_other_segments - Prepare the dtb, initrd and purgatory segments. -+ */ -+ -+int arm64_load_other_segments(struct kexec_info *info, -+ unsigned long image_base) -+{ -+ int result; -+ unsigned long dtb_base; -+ unsigned long hole_min; -+ unsigned long hole_max; -+ char *initrd_buf = NULL; -+ struct dtb dtb; -+ char command_line[COMMAND_LINE_SIZE] = ""; -+ -+ if (arm64_opts.command_line) { -+ strncpy(command_line, arm64_opts.command_line, -+ sizeof(command_line)); -+ command_line[sizeof(command_line) - 1] = 0; -+ } -+ -+ if (arm64_opts.dtb) { -+ dtb.name = "dtb_user"; -+ dtb.buf = slurp_file(arm64_opts.dtb, &dtb.size); -+ } else { -+ result = read_1st_dtb(&dtb); -+ -+ if (result) { -+ fprintf(stderr, -+ "kexec: Error: No device tree available.\n"); -+ return -EFAILED; -+ } -+ } -+ -+ result = setup_2nd_dtb(&dtb, command_line); -+ -+ if (result) -+ return -EFAILED; -+ -+ /* Put the other segments after the image. */ -+ -+ hole_min = image_base + arm64_mem.image_size; -+ hole_max = ULONG_MAX; -+ -+ if (arm64_opts.initrd) { -+ initrd_buf = slurp_file(arm64_opts.initrd, &initrd_size); -+ -+ if (!initrd_buf) -+ fprintf(stderr, "kexec: Empty ramdisk file.\n"); -+ else { -+ /* -+ * Put the initrd after the kernel. As specified in -+ * booting.txt, align to 1 GiB. -+ */ -+ -+ initrd_base = add_buffer_phys_virt(info, initrd_buf, -+ initrd_size, initrd_size, GiB(1), -+ hole_min, hole_max, 1, 0); -+ -+ /* initrd_base is valid if we got here. */ -+ -+ dbgprintf("initrd: base %lx, size %lxh (%ld)\n", -+ initrd_base, initrd_size, initrd_size); -+ -+ /* Check size limit as specified in booting.txt. */ -+ -+ if (initrd_base - image_base + initrd_size > GiB(32)) { -+ fprintf(stderr, "kexec: Error: image + initrd too big.\n"); -+ return -EFAILED; -+ } -+ -+ result = dtb_set_initrd((char **)&dtb.buf, -+ &dtb.size, initrd_base, -+ initrd_base + initrd_size); -+ -+ if (result) -+ return -EFAILED; -+ } -+ } -+ -+ /* Check size limit as specified in booting.txt. */ -+ -+ if (dtb.size > MiB(2)) { -+ fprintf(stderr, "kexec: Error: dtb too big.\n"); -+ return -EFAILED; -+ } -+ -+ dtb_base = add_buffer_phys_virt(info, dtb.buf, dtb.size, dtb.size, -+ 0, hole_min, hole_max, 1, 0); -+ -+ /* dtb_base is valid if we got here. */ -+ -+ dbgprintf("dtb: base %lx, size %lxh (%ld)\n", dtb_base, dtb.size, -+ dtb.size); -+ -+ elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, -+ hole_min, hole_max, 1, 0); -+ -+ info->entry = (void *)elf_rel_get_addr(&info->rhdr, "purgatory_start"); -+ -+ elf_rel_set_symbol(&info->rhdr, "arm64_kernel_entry", &image_base, -+ sizeof(image_base)); -+ -+ elf_rel_set_symbol(&info->rhdr, "arm64_dtb_addr", &dtb_base, -+ sizeof(dtb_base)); -+ -+ return 0; -+} -+ -+/** -+ * virt_to_phys - For processing elf file values. -+ */ -+ -+unsigned long virt_to_phys(unsigned long v) -+{ -+ unsigned long p; -+ -+ p = v - get_vp_offset() + get_phys_offset(); -+ -+ return p; -+} -+ -+/** -+ * phys_to_virt - For crashdump setup. -+ */ -+ -+unsigned long phys_to_virt(struct crash_elf_info *elf_info, -+ unsigned long long p) -+{ -+ unsigned long v; -+ -+ v = p - get_phys_offset() + elf_info->page_offset; -+ -+ return v; -+} -+ -+/** -+ * add_segment - Use virt_to_phys when loading elf files. -+ */ -+ -+void add_segment(struct kexec_info *info, const void *buf, size_t bufsz, -+ unsigned long base, size_t memsz) -+{ -+ add_segment_phys_virt(info, buf, bufsz, base, memsz, 1); -+} -+ -+/** -+ * get_memory_ranges_iomem_cb - Helper for get_memory_ranges_iomem. -+ */ -+ -+static int get_memory_ranges_iomem_cb(void *data, int nr, char *str, -+ unsigned long long base, unsigned long long length) -+{ -+ struct memory_range *r; -+ -+ if (nr >= KEXEC_SEGMENT_MAX) -+ return -1; -+ -+ r = (struct memory_range *)data + nr; -+ r->type = RANGE_RAM; -+ r->start = base; -+ r->end = base + length - 1; -+ -+ set_phys_offset(r->start); -+ -+ dbgprintf("%s: %016llx - %016llx : %s", __func__, r->start, -+ r->end, str); -+ -+ return 0; -+} -+ -+/** -+ * get_memory_ranges_iomem - Try to get the memory ranges from /proc/iomem. -+ */ -+ -+static int get_memory_ranges_iomem(struct memory_range *array, -+ unsigned int *count) -+{ -+ *count = kexec_iomem_for_each_line("System RAM\n", -+ get_memory_ranges_iomem_cb, array); -+ -+ if (!*count) { -+ dbgprintf("%s: failed: No RAM found.\n", __func__); -+ return -EFAILED; -+ } -+ -+ return 0; -+} -+ -+/** -+ * get_memory_ranges - Try to get the memory ranges some how. -+ */ -+ -+int get_memory_ranges(struct memory_range **range, int *ranges, -+ unsigned long kexec_flags) -+{ -+ static struct memory_range array[KEXEC_SEGMENT_MAX]; -+ unsigned int count; -+ int result; -+ -+ result = get_memory_ranges_iomem(array, &count); -+ -+ *range = result ? NULL : array; -+ *ranges = result ? 0 : count; -+ -+ return result; -+} -+ -+int arch_compat_trampoline(struct kexec_info *info) -+{ -+ return 0; -+} -+ -+int machine_verify_elf_rel(struct mem_ehdr *ehdr) -+{ -+ return (ehdr->e_machine == EM_AARCH64); -+} -+ -+void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym), -+ unsigned long r_type, void *ptr, unsigned long address, -+ unsigned long value) -+{ -+#if !defined(R_AARCH64_ABS64) -+# define R_AARCH64_ABS64 257 -+#endif -+ -+#if !defined(R_AARCH64_LD_PREL_LO19) -+# define R_AARCH64_LD_PREL_LO19 273 -+#endif -+ -+#if !defined(R_AARCH64_ADR_PREL_LO21) -+# define R_AARCH64_ADR_PREL_LO21 274 -+#endif -+ -+#if !defined(R_AARCH64_JUMP26) -+# define R_AARCH64_JUMP26 282 -+#endif -+ -+#if !defined(R_AARCH64_CALL26) -+# define R_AARCH64_CALL26 283 -+#endif -+ -+ uint64_t *loc64; -+ uint32_t *loc32; -+ uint64_t *location = (uint64_t *)ptr; -+ uint64_t data = *location; -+ const char *type = NULL; -+ -+ switch(r_type) { -+ case R_AARCH64_ABS64: -+ type = "ABS64"; -+ loc64 = ptr; -+ *loc64 = cpu_to_elf64(ehdr, elf64_to_cpu(ehdr, *loc64) + value); -+ break; -+ case R_AARCH64_LD_PREL_LO19: -+ type = "LD_PREL_LO19"; -+ loc32 = ptr; -+ *loc32 = cpu_to_le32(le32_to_cpu(*loc32) -+ + (((value - address) << 3) & 0xffffe0)); -+ break; -+ case R_AARCH64_ADR_PREL_LO21: -+ if (value & 3) -+ die("%s: ERROR Unaligned value: %lx\n", __func__, -+ value); -+ type = "ADR_PREL_LO21"; -+ loc32 = ptr; -+ *loc32 = cpu_to_le32(le32_to_cpu(*loc32) -+ + (((value - address) << 3) & 0xffffe0)); -+ break; -+ case R_AARCH64_JUMP26: -+ type = "JUMP26"; -+ loc32 = ptr; -+ *loc32 = cpu_to_le32(le32_to_cpu(*loc32) -+ + (((value - address) >> 2) & 0x3ffffff)); -+ break; -+ case R_AARCH64_CALL26: -+ type = "CALL26"; -+ loc32 = ptr; -+ *loc32 = cpu_to_le32(le32_to_cpu(*loc32) -+ + (((value - address) >> 2) & 0x3ffffff)); -+ break; -+ default: -+ die("%s: ERROR Unknown type: %lu\n", __func__, r_type); -+ break; -+ } -+ -+ dbgprintf("%s: %s %016lx->%016lx\n", __func__, type, data, *location); -+} -+ -+void arch_reuse_initrd(void) -+{ -+ reuse_initrd = 1; -+} -+ -+void arch_update_purgatory(struct kexec_info *UNUSED(info)) -+{ -+} -Index: kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.h -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.h -@@ -0,0 +1,71 @@ -+/* -+ * ARM64 kexec. -+ */ -+ -+#if !defined(KEXEC_ARM64_H) -+#define KEXEC_ARM64_H -+ -+#include -+#include -+ -+#include "image-header.h" -+#include "kexec.h" -+ -+#define KEXEC_SEGMENT_MAX 16 -+ -+#define BOOT_BLOCK_VERSION 17 -+#define BOOT_BLOCK_LAST_COMP_VERSION 16 -+#define COMMAND_LINE_SIZE 512 -+ -+#define KiB(x) ((x) * 1024UL) -+#define MiB(x) (KiB(x) * 1024UL) -+#define GiB(x) (MiB(x) * 1024UL) -+ -+int elf_arm64_probe(const char *kernel_buf, off_t kernel_size); -+int elf_arm64_load(int argc, char **argv, const char *kernel_buf, -+ off_t kernel_size, struct kexec_info *info); -+void elf_arm64_usage(void); -+ -+int image_arm64_probe(const char *kernel_buf, off_t kernel_size); -+int image_arm64_load(int argc, char **argv, const char *kernel_buf, -+ off_t kernel_size, struct kexec_info *info); -+void image_arm64_usage(void); -+ -+off_t initrd_base; -+off_t initrd_size; -+ -+/** -+ * struct arm64_mem - Memory layout info. -+ */ -+ -+struct arm64_mem { -+ uint64_t phys_offset; -+ uint64_t text_offset; -+ uint64_t image_size; -+ uint64_t vp_offset; -+}; -+ -+#define arm64_mem_ngv UINT64_MAX -+struct arm64_mem arm64_mem; -+ -+uint64_t get_phys_offset(void); -+uint64_t get_vp_offset(void); -+ -+static inline void reset_vp_offset(void) -+{ -+ arm64_mem.vp_offset = arm64_mem_ngv; -+} -+ -+static inline void set_phys_offset(uint64_t v) -+{ -+ if (arm64_mem.phys_offset == arm64_mem_ngv -+ || v < arm64_mem.phys_offset) -+ arm64_mem.phys_offset = v; -+} -+ -+int arm64_process_image_header(const struct arm64_image_header *h); -+unsigned long arm64_locate_kernel_segment(struct kexec_info *info); -+int arm64_load_other_segments(struct kexec_info *info, -+ unsigned long image_base); -+ -+#endif -Index: kexec-tools-2.0.10/kexec/arch/arm64/kexec-elf-arm64.c -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/arch/arm64/kexec-elf-arm64.c -@@ -0,0 +1,146 @@ -+/* -+ * ARM64 kexec elf support. -+ */ -+ -+#define _GNU_SOURCE -+ -+#include -+#include -+#include -+#include -+ -+#include "kexec-arm64.h" -+#include "kexec-elf.h" -+#include "kexec-syscall.h" -+ -+int elf_arm64_probe(const char *kernel_buf, off_t kernel_size) -+{ -+ struct mem_ehdr ehdr; -+ int result; -+ -+ result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0); -+ -+ if (result < 0) { -+ dbgprintf("%s: Not an ELF executable.\n", __func__); -+ goto on_exit; -+ } -+ -+ if (ehdr.e_machine != EM_AARCH64) { -+ dbgprintf("%s: Not an AARCH64 ELF executable.\n", __func__); -+ result = -1; -+ goto on_exit; -+ } -+ -+ result = 0; -+on_exit: -+ free_elf_info(&ehdr); -+ return result; -+} -+ -+int elf_arm64_load(int argc, char **argv, const char *kernel_buf, -+ off_t kernel_size, struct kexec_info *info) -+{ -+ const struct arm64_image_header *header = NULL; -+ unsigned long kernel_segment; -+ struct mem_ehdr ehdr; -+ int result; -+ int i; -+ -+ if (info->kexec_flags & KEXEC_ON_CRASH) { -+ fprintf(stderr, "kexec: kdump not yet supported on arm64\n"); -+ return -EFAILED; -+ } -+ -+ result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0); -+ -+ if (result < 0) { -+ dbgprintf("%s: build_elf_exec_info failed\n", __func__); -+ goto exit; -+ } -+ -+ /* Find and process the arm64 image header. */ -+ -+ for (i = 0; i < ehdr.e_phnum; i++) { -+ struct mem_phdr *phdr = &ehdr.e_phdr[i]; -+ unsigned long header_offset; -+ -+ if (phdr->p_type != PT_LOAD) -+ continue; -+ -+ /* -+ * When CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET=y the image header -+ * could be offset in the elf segment. The linker script sets -+ * ehdr.e_entry to the start of text. -+ */ -+ -+ header_offset = ehdr.e_entry - phdr->p_vaddr; -+ -+ header = (const struct arm64_image_header *)( -+ kernel_buf + phdr->p_offset + header_offset); -+ -+ if (!arm64_process_image_header(header)) { -+ dbgprintf("%s: e_entry: %016llx\n", __func__, -+ ehdr.e_entry); -+ dbgprintf("%s: p_vaddr: %016llx\n", __func__, -+ phdr->p_vaddr); -+ dbgprintf("%s: header_offset: %016lx\n", __func__, -+ header_offset); -+ -+ break; -+ } -+ } -+ -+ if (i == ehdr.e_phnum) { -+ dbgprintf("%s: Valid arm64 header not found\n", __func__); -+ result = -EFAILED; -+ goto exit; -+ } -+ -+ kernel_segment = arm64_locate_kernel_segment(info); -+ -+ if (kernel_segment == ULONG_MAX) { -+ dbgprintf("%s: Kernel segment is not allocated\n", __func__); -+ result = -EFAILED; -+ goto exit; -+ } -+ -+ arm64_mem.vp_offset = _ALIGN_DOWN(ehdr.e_entry, MiB(2)); -+ arm64_mem.vp_offset -= kernel_segment - get_phys_offset(); -+ -+ dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment); -+ dbgprintf("%s: text_offset: %016lx\n", __func__, -+ arm64_mem.text_offset); -+ dbgprintf("%s: image_size: %016lx\n", __func__, -+ arm64_mem.image_size); -+ dbgprintf("%s: phys_offset: %016lx\n", __func__, -+ arm64_mem.phys_offset); -+ dbgprintf("%s: vp_offset: %016lx\n", __func__, -+ arm64_mem.vp_offset); -+ dbgprintf("%s: PE format: %s\n", __func__, -+ (arm64_header_check_pe_sig(header) ? "yes" : "no")); -+ -+ /* load the kernel */ -+ result = elf_exec_load(&ehdr, info); -+ -+ if (result) { -+ dbgprintf("%s: elf_exec_load failed\n", __func__); -+ goto exit; -+ } -+ -+ result = arm64_load_other_segments(info, kernel_segment -+ + arm64_mem.text_offset); -+ -+exit: -+ reset_vp_offset(); -+ free_elf_info(&ehdr); -+ if (result) -+ fprintf(stderr, "kexec: Bad elf image file, load failed.\n"); -+ return result; -+} -+ -+void elf_arm64_usage(void) -+{ -+ printf( -+" An ARM64 ELF image, big or little endian.\n" -+" Typically vmlinux or a stripped version of vmlinux.\n\n"); -+} -Index: kexec-tools-2.0.10/kexec/arch/arm64/kexec-image-arm64.c -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/arch/arm64/kexec-image-arm64.c -@@ -0,0 +1,41 @@ -+/* -+ * ARM64 kexec binary image support. -+ */ -+ -+#define _GNU_SOURCE -+#include "kexec-arm64.h" -+ -+int image_arm64_probe(const char *kernel_buf, off_t kernel_size) -+{ -+ const struct arm64_image_header *h; -+ -+ if (kernel_size < sizeof(struct arm64_image_header)) { -+ dbgprintf("%s: No arm64 image header.\n", __func__); -+ return -1; -+ } -+ -+ h = (const struct arm64_image_header *)(kernel_buf); -+ -+ if (!arm64_header_check_magic(h)) { -+ dbgprintf("%s: Bad arm64 image header.\n", __func__); -+ return -1; -+ } -+ -+ fprintf(stderr, "kexec: ARM64 binary image files are currently NOT SUPPORTED.\n"); -+ return -1; -+} -+ -+int image_arm64_load(int argc, char **argv, const char *kernel_buf, -+ off_t kernel_size, struct kexec_info *info) -+{ -+ return -1; -+} -+ -+void image_arm64_usage(void) -+{ -+ printf( -+" An ARM64 binary image, compressed or not, big or little endian.\n" -+" Typically an Image, Image.gz or Image.lzma file.\n\n"); -+ printf( -+" ARM64 binary image files are currently NOT SUPPORTED.\n\n"); -+} -Index: kexec-tools-2.0.10/kexec/kexec-syscall.h -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/kexec-syscall.h -+++ kexec-tools-2.0.10/kexec/kexec-syscall.h -@@ -39,8 +39,8 @@ - #ifdef __s390__ - #define __NR_kexec_load 277 - #endif --#ifdef __arm__ --#define __NR_kexec_load __NR_SYSCALL_BASE + 347 -+#if defined(__arm__) || defined(__arm64__) -+#define __NR_kexec_load __NR_SYSCALL_BASE + 347 - #endif - #if defined(__mips__) - #define __NR_kexec_load 4311 -@@ -108,6 +108,7 @@ 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) -+#define KEXEC_ARCH_ARM64 (183 << 16) - #define KEXEC_ARCH_S390 (22 << 16) - #define KEXEC_ARCH_SH (42 << 16) - #define KEXEC_ARCH_MIPS_LE (10 << 16) -@@ -153,5 +154,8 @@ static inline long kexec_file_load(int k - #ifdef __m68k__ - #define KEXEC_ARCH_NATIVE KEXEC_ARCH_68K - #endif -+#if defined(__arm64__) -+#define KEXEC_ARCH_NATIVE KEXEC_ARCH_ARM64 -+#endif - - #endif /* KEXEC_SYSCALL_H */ -Index: kexec-tools-2.0.10/purgatory/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/purgatory/Makefile -+++ kexec-tools-2.0.10/purgatory/Makefile -@@ -19,6 +19,7 @@ dist += purgatory/Makefile $(PURGATORY_S - - include $(srcdir)/purgatory/arch/alpha/Makefile - include $(srcdir)/purgatory/arch/arm/Makefile -+include $(srcdir)/purgatory/arch/arm64/Makefile - include $(srcdir)/purgatory/arch/i386/Makefile - include $(srcdir)/purgatory/arch/ia64/Makefile - include $(srcdir)/purgatory/arch/mips/Makefile -Index: kexec-tools-2.0.10/purgatory/arch/arm64/Makefile -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/purgatory/arch/arm64/Makefile -@@ -0,0 +1,18 @@ -+ -+arm64_PURGATORY_EXTRA_CFLAGS = \ -+ -mcmodel=large \ -+ -fno-stack-protector \ -+ -fno-asynchronous-unwind-tables \ -+ -Wundef \ -+ -Werror-implicit-function-declaration \ -+ -Wdeclaration-after-statement \ -+ -Werror=implicit-int \ -+ -Werror=strict-prototypes -+ -+arm64_PURGATORY_SRCS += \ -+ purgatory/arch/arm64/entry.S \ -+ purgatory/arch/arm64/purgatory-arm64.c -+ -+dist += \ -+ $(arm64_PURGATORY_SRCS) \ -+ purgatory/arch/arm64/Makefile -Index: kexec-tools-2.0.10/purgatory/arch/arm64/entry.S -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/purgatory/arch/arm64/entry.S -@@ -0,0 +1,51 @@ -+/* -+ * ARM64 purgatory. -+ */ -+ -+.macro size, sym:req -+ .size \sym, . - \sym -+.endm -+ -+.text -+ -+.globl purgatory_start -+purgatory_start: -+ -+ adr x19, .Lstack -+ mov sp, x19 -+ -+ bl purgatory -+ -+ /* Start new image. */ -+ ldr x17, arm64_kernel_entry -+ ldr x0, arm64_dtb_addr -+ mov x1, xzr -+ mov x2, xzr -+ mov x3, xzr -+ br x17 -+ -+size purgatory_start -+ -+.ltorg -+ -+.align 4 -+ .rept 256 -+ .quad 0 -+ .endr -+.Lstack: -+ -+.data -+ -+.align 3 -+ -+.globl arm64_kernel_entry -+arm64_kernel_entry: -+ .quad 0 -+size arm64_kernel_entry -+ -+.globl arm64_dtb_addr -+arm64_dtb_addr: -+ .quad 0 -+size arm64_dtb_addr -+ -+.end -\ No newline at end of file -Index: kexec-tools-2.0.10/purgatory/arch/arm64/purgatory-arm64.c -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/purgatory/arch/arm64/purgatory-arm64.c -@@ -0,0 +1,19 @@ -+/* -+ * ARM64 purgatory. -+ */ -+ -+#include -+#include -+ -+void putchar(int ch) -+{ -+ /* Nothing for now */ -+} -+ -+void post_verification_setup_arch(void) -+{ -+} -+ -+void setup_arch(void) -+{ -+} diff -Nru kexec-tools-2.0.10/debian/patches/arm64-Add-missing-kexec-dist-files.patch kexec-tools-2.0.16/debian/patches/arm64-Add-missing-kexec-dist-files.patch --- kexec-tools-2.0.10/debian/patches/arm64-Add-missing-kexec-dist-files.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm64-Add-missing-kexec-dist-files.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,26 +0,0 @@ -From e345e27417db00a9e754ca0ca14b2ec87d0552f7 Mon Sep 17 00:00:00 2001 -From: Geoff Levand -Date: Mon, 10 Oct 2016 21:22:59 +0000 -Subject: [PATCH] arm64: Add missing kexec dist files - -Signed-off-by: Geoff Levand -Reviewed-by: Matthias Brugger -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/Makefile | 2 ++ - 1 file changed, 2 insertions(+) - -Index: kexec-tools-2.0.10/kexec/arch/arm64/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm64/Makefile -+++ kexec-tools-2.0.10/kexec/arch/arm64/Makefile -@@ -20,7 +20,9 @@ arm64_VIRT_TO_PHYS = - arm64_PHYS_TO_VIRT = - - dist += $(arm64_KEXEC_SRCS) \ -+ kexec/arch/arm64/include/arch/options.h \ - kexec/arch/arm64/crashdump-arm64.h \ -+ kexec/arch/arm64/image-header.h \ - kexec/arch/arm64/kexec-arm64.h \ - kexec/arch/arm64/Makefile - diff -Nru kexec-tools-2.0.10/debian/patches/arm64-Add-support-for-additional-relocations-in-the-.patch kexec-tools-2.0.16/debian/patches/arm64-Add-support-for-additional-relocations-in-the-.patch --- kexec-tools-2.0.10/debian/patches/arm64-Add-support-for-additional-relocations-in-the-.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm64-Add-support-for-additional-relocations-in-the-.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -From c743758d77b8a935fca7d72ecd6aa61300eb96da Mon Sep 17 00:00:00 2001 -From: Catalin Marinas -Date: Thu, 20 Oct 2016 11:43:31 +0100 -Subject: [PATCH] arm64: Add support for additional relocations in the kexec - purgatory code - -When compiling the kexec-tools with gcc6, the following additional -reolcations are generated in the purgatory.ro file: - -R_AARCH64_ADR_PREL_PG_HI21 -R_AARCH64_ADD_ABS_LO12_NC -R_AARCH64_LDST64_ABS_LO12_NC - -This patch modifies the arm64 machine_apply_elf_rel() function to handle -these relocations. - -Signed-off-by: Catalin Marinas -Reviewed-by: Geoff Levand -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/kexec-arm64.c | 35 +++++++++++++++++++++++++++++++++++ - 1 file changed, 35 insertions(+) - -Index: kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm64/kexec-arm64.c -+++ kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.c -@@ -550,6 +550,14 @@ void machine_apply_elf_rel(struct mem_eh - # define R_AARCH64_ADR_PREL_LO21 274 - #endif - -+#if !defined(R_AARCH64_ADR_PREL_PG_HI21) -+# define R_AARCH64_ADR_PREL_PG_HI21 275 -+#endif -+ -+#if !defined(R_AARCH64_ADD_ABS_LO12_NC) -+# define R_AARCH64_ADD_ABS_LO12_NC 277 -+#endif -+ - #if !defined(R_AARCH64_JUMP26) - # define R_AARCH64_JUMP26 282 - #endif -@@ -558,10 +566,15 @@ void machine_apply_elf_rel(struct mem_eh - # define R_AARCH64_CALL26 283 - #endif - -+#if !defined(R_AARCH64_LDST64_ABS_LO12_NC) -+# define R_AARCH64_LDST64_ABS_LO12_NC 286 -+#endif -+ - uint64_t *loc64; - uint32_t *loc32; - uint64_t *location = (uint64_t *)ptr; - uint64_t data = *location; -+ uint64_t imm; - const char *type = NULL; - - switch(r_type) { -@@ -585,6 +598,19 @@ void machine_apply_elf_rel(struct mem_eh - *loc32 = cpu_to_le32(le32_to_cpu(*loc32) - + (((value - address) << 3) & 0xffffe0)); - break; -+ case R_AARCH64_ADR_PREL_PG_HI21: -+ type = "ADR_PREL_PG_HI21"; -+ imm = ((value & ~0xfff) - (address & ~0xfff)) >> 12; -+ loc32 = ptr; -+ *loc32 = cpu_to_le32(le32_to_cpu(*loc32) -+ + ((imm & 3) << 29) + ((imm & 0x1ffffc) << (5 - 2))); -+ break; -+ case R_AARCH64_ADD_ABS_LO12_NC: -+ type = "ADD_ABS_LO12_NC"; -+ loc32 = ptr; -+ *loc32 = cpu_to_le32(le32_to_cpu(*loc32) -+ + ((value & 0xfff) << 10)); -+ break; - case R_AARCH64_JUMP26: - type = "JUMP26"; - loc32 = ptr; -@@ -597,6 +623,15 @@ void machine_apply_elf_rel(struct mem_eh - *loc32 = cpu_to_le32(le32_to_cpu(*loc32) - + (((value - address) >> 2) & 0x3ffffff)); - break; -+ case R_AARCH64_LDST64_ABS_LO12_NC: -+ if (value & 7) -+ die("%s: ERROR Unaligned value: %lx\n", __func__, -+ value); -+ type = "LDST64_ABS_LO12_NC"; -+ loc32 = ptr; -+ *loc32 = cpu_to_le32(le32_to_cpu(*loc32) -+ + ((value & 0xff8) << (10 - 3))); -+ break; - default: - die("%s: ERROR Unknown type: %lu\n", __func__, r_type); - break; diff -Nru kexec-tools-2.0.10/debian/patches/arm64-Add-support-for-binary-image-files.patch kexec-tools-2.0.16/debian/patches/arm64-Add-support-for-binary-image-files.patch --- kexec-tools-2.0.10/debian/patches/arm64-Add-support-for-binary-image-files.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm64-Add-support-for-binary-image-files.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ -From abdfe97736f89d9bc73662b9134604b0229a599e Mon Sep 17 00:00:00 2001 -From: Pratyush Anand -Date: Wed, 21 Sep 2016 18:14:25 +0000 -Subject: [PATCH] arm64: Add support for binary image files - -Signed-off-by: Pratyush Anand -[Reworked and cleaned up] -Signed-off-by: Geoff Levand -Tested-By: Pratyush Anand -Tested-By: Matthias Brugger -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/kexec-image-arm64.c | 49 ++++++++++++++++++++++++++++++++---- - 1 file changed, 44 insertions(+), 5 deletions(-) - -Index: kexec-tools-2.0.10/kexec/arch/arm64/kexec-image-arm64.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm64/kexec-image-arm64.c -+++ kexec-tools-2.0.10/kexec/arch/arm64/kexec-image-arm64.c -@@ -3,7 +3,9 @@ - */ - - #define _GNU_SOURCE -+ - #include "kexec-arm64.h" -+#include - - int image_arm64_probe(const char *kernel_buf, off_t kernel_size) - { -@@ -21,14 +23,53 @@ int image_arm64_probe(const char *kernel - return -1; - } - -- fprintf(stderr, "kexec: ARM64 binary image files are currently NOT SUPPORTED.\n"); -- return -1; -+ return 0; - } - - int image_arm64_load(int argc, char **argv, const char *kernel_buf, - off_t kernel_size, struct kexec_info *info) - { -- return -1; -+ const struct arm64_image_header *header; -+ unsigned long kernel_segment; -+ int result; -+ -+ header = (const struct arm64_image_header *)(kernel_buf); -+ -+ if (arm64_process_image_header(header)) -+ return -1; -+ -+ kernel_segment = arm64_locate_kernel_segment(info); -+ -+ if (kernel_segment == ULONG_MAX) { -+ dbgprintf("%s: Kernel segment is not allocated\n", __func__); -+ result = -EFAILED; -+ goto exit; -+ } -+ -+ dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment); -+ dbgprintf("%s: text_offset: %016lx\n", __func__, -+ arm64_mem.text_offset); -+ dbgprintf("%s: image_size: %016lx\n", __func__, -+ arm64_mem.image_size); -+ dbgprintf("%s: phys_offset: %016lx\n", __func__, -+ arm64_mem.phys_offset); -+ dbgprintf("%s: vp_offset: %016lx\n", __func__, -+ arm64_mem.vp_offset); -+ dbgprintf("%s: PE format: %s\n", __func__, -+ (arm64_header_check_pe_sig(header) ? "yes" : "no")); -+ -+ /* load the kernel */ -+ add_segment_phys_virt(info, kernel_buf, kernel_size, -+ kernel_segment + arm64_mem.text_offset, -+ arm64_mem.image_size, 0); -+ -+ result = arm64_load_other_segments(info, kernel_segment -+ + arm64_mem.text_offset); -+ -+exit: -+ if (result) -+ fprintf(stderr, "kexec: load failed.\n"); -+ return result; - } - - void image_arm64_usage(void) -@@ -36,6 +77,4 @@ void image_arm64_usage(void) - printf( - " An ARM64 binary image, compressed or not, big or little endian.\n" - " Typically an Image, Image.gz or Image.lzma file.\n\n"); -- printf( --" ARM64 binary image files are currently NOT SUPPORTED.\n\n"); - } diff -Nru kexec-tools-2.0.10/debian/patches/arm64-Add-support-of-R_AARCH64_PREL32-relocation-in-.patch kexec-tools-2.0.16/debian/patches/arm64-Add-support-of-R_AARCH64_PREL32-relocation-in-.patch --- kexec-tools-2.0.10/debian/patches/arm64-Add-support-of-R_AARCH64_PREL32-relocation-in-.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm64-Add-support-of-R_AARCH64_PREL32-relocation-in-.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -From ec271d6c298839916009474a9736728c77d959f1 Mon Sep 17 00:00:00 2001 -From: Pratyush Anand -Date: Fri, 28 Oct 2016 09:46:09 +0530 -Subject: [PATCH] arm64: Add support of R_AARCH64_PREL32 relocation in - purgatory - -gcc version in fedora koji is 6.2.1-2.fc25. kexec-tools compiled with this -gcc produced another relocation error: - -machine_apply_elf_rel: ERROR Unknown type: 261 - -This patch fixes the above error. - -Signed-off-by: Pratyush Anand -Reviewed-by: Geoff Levand -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/kexec-arm64.c | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -Index: kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm64/kexec-arm64.c -+++ kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.c -@@ -542,6 +542,10 @@ void machine_apply_elf_rel(struct mem_eh - # define R_AARCH64_ABS64 257 - #endif - -+#if !defined(R_AARCH64_PREL32) -+# define R_AARCH64_PREL32 261 -+#endif -+ - #if !defined(R_AARCH64_LD_PREL_LO19) - # define R_AARCH64_LD_PREL_LO19 273 - #endif -@@ -583,6 +587,12 @@ void machine_apply_elf_rel(struct mem_eh - loc64 = ptr; - *loc64 = cpu_to_elf64(ehdr, elf64_to_cpu(ehdr, *loc64) + value); - break; -+ case R_AARCH64_PREL32: -+ type = "PREL32"; -+ loc32 = ptr; -+ *loc32 = cpu_to_elf32(ehdr, -+ elf32_to_cpu(ehdr, *loc32) + value - address); -+ break; - case R_AARCH64_LD_PREL_LO19: - type = "LD_PREL_LO19"; - loc32 = ptr; diff -Nru kexec-tools-2.0.10/debian/patches/arm64_build.patch kexec-tools-2.0.16/debian/patches/arm64_build.patch --- kexec-tools-2.0.10/debian/patches/arm64_build.patch 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm64_build.patch 2018-02-20 22:19:48.000000000 +0000 @@ -0,0 +1,10 @@ +--- a/purgatory/arch/arm64/Makefile ++++ b/purgatory/arch/arm64/Makefile +@@ -1,6 +1,7 @@ + + arm64_PURGATORY_EXTRA_CFLAGS = \ + -mcmodel=large \ ++ -fno-PIC \ + -fno-stack-protector \ + -fno-asynchronous-unwind-tables \ + -Wundef \ diff -Nru kexec-tools-2.0.10/debian/patches/arm64-Cleanup-kexec-Makefile.patch kexec-tools-2.0.16/debian/patches/arm64-Cleanup-kexec-Makefile.patch --- kexec-tools-2.0.10/debian/patches/arm64-Cleanup-kexec-Makefile.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm64-Cleanup-kexec-Makefile.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -From 402cf1427293b248b8a0ecdbf093be54298db530 Mon Sep 17 00:00:00 2001 -From: Geoff Levand -Date: Mon, 10 Oct 2016 21:22:58 +0000 -Subject: [PATCH] arm64: Cleanup kexec Makefile - -Put files in alphabetical order, reformat whitspace. - -Signed-off-by: Geoff Levand -Reviewed-by: Matthias Brugger -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/Makefile | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -Index: kexec-tools-2.0.10/kexec/arch/arm64/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm64/Makefile -+++ kexec-tools-2.0.10/kexec/arch/arm64/Makefile -@@ -1,17 +1,18 @@ - - arm64_FS2DT += kexec/fs2dt.c --arm64_FS2DT_INCLUDE += -include $(srcdir)/kexec/arch/arm64/kexec-arm64.h \ -- -include $(srcdir)/kexec/arch/arm64/crashdump-arm64.h -+arm64_FS2DT_INCLUDE += \ -+ -include $(srcdir)/kexec/arch/arm64/crashdump-arm64.h \ -+ -include $(srcdir)/kexec/arch/arm64/kexec-arm64.h - - arm64_DT_OPS += kexec/dt-ops.c - - arm64_CPPFLAGS += -I $(srcdir)/kexec/ - - arm64_KEXEC_SRCS += \ -+ kexec/arch/arm64/crashdump-arm64.c \ - kexec/arch/arm64/kexec-arm64.c \ -- kexec/arch/arm64/kexec-image-arm64.c \ - kexec/arch/arm64/kexec-elf-arm64.c \ -- kexec/arch/arm64/crashdump-arm64.c -+ kexec/arch/arm64/kexec-image-arm64.c - - arm64_ARCH_REUSE_INITRD = - arm64_ADD_SEGMENT = -@@ -19,9 +20,9 @@ arm64_VIRT_TO_PHYS = - arm64_PHYS_TO_VIRT = - - dist += $(arm64_KEXEC_SRCS) \ -- kexec/arch/arm64/Makefile \ -+ kexec/arch/arm64/crashdump-arm64.h \ - kexec/arch/arm64/kexec-arm64.h \ -- kexec/arch/arm64/crashdump-arm64.h -+ kexec/arch/arm64/Makefile - - ifdef HAVE_LIBFDT - diff -Nru kexec-tools-2.0.10/debian/patches/arm64-Fix-initrd-requierements.patch kexec-tools-2.0.16/debian/patches/arm64-Fix-initrd-requierements.patch --- kexec-tools-2.0.10/debian/patches/arm64-Fix-initrd-requierements.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm64-Fix-initrd-requierements.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,66 +0,0 @@ -From a2451670230c5687ae6a6af0685f22c1659fb94a Mon Sep 17 00:00:00 2001 -From: Matthias Brugger -Date: Wed, 7 Dec 2016 17:26:15 +0100 -Subject: [PATCH] arm64: Fix initrd requierements - -The initrd doesn't need to be aligend to 1 GB, which breaks kexec for system with -RAM <= 1 GB. Instead the memory size between the kernel start rounded down to 1 GB -and the end of the initrd rounded up to 1 GB can't be bigger then 32 GB. - -Signed-off-by: Matthias Brugger -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/kexec-arm64.c | 23 ++++++++++++----------- - 1 file changed, 12 insertions(+), 11 deletions(-) - -Index: kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm64/kexec-arm64.c -+++ kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.c -@@ -327,6 +327,7 @@ int arm64_load_other_segments(struct kex - unsigned long dtb_base; - unsigned long hole_min; - unsigned long hole_max; -+ unsigned long initrd_end; - char *initrd_buf = NULL; - struct dtb dtb; - char command_line[COMMAND_LINE_SIZE] = ""; -@@ -366,27 +367,27 @@ int arm64_load_other_segments(struct kex - if (!initrd_buf) - fprintf(stderr, "kexec: Empty ramdisk file.\n"); - else { -- /* -- * Put the initrd after the kernel. As specified in -- * booting.txt, align to 1 GiB. -- */ -+ /* Put the initrd after the kernel. */ - - initrd_base = add_buffer_phys_virt(info, initrd_buf, -- initrd_size, initrd_size, GiB(1), -+ initrd_size, initrd_size, 0, - hole_min, hole_max, 1, 0); - -- /* initrd_base is valid if we got here. */ -- -- dbgprintf("initrd: base %lx, size %lxh (%ld)\n", -- initrd_base, initrd_size, initrd_size); -+ initrd_end = initrd_base + initrd_size; - -- /* Check size limit as specified in booting.txt. */ -+ /* Check limits as specified in booting.txt. -+ * The kernel may have as little as 32 GB of address space to map -+ * system memory and both kernel and initrd must be 1GB aligend. -+ */ - -- if (initrd_base - image_base + initrd_size > GiB(32)) { -+ if (_ALIGN_UP(initrd_end, GiB(1)) - _ALIGN_DOWN(image_base, GiB(1)) > GiB(32)) { - fprintf(stderr, "kexec: Error: image + initrd too big.\n"); - return -EFAILED; - } - -+ dbgprintf("initrd: base %lx, size %lxh (%ld)\n", -+ initrd_base, initrd_size, initrd_size); -+ - result = dtb_set_initrd((char **)&dtb.buf, - &dtb.size, initrd_base, - initrd_base + initrd_size); diff -Nru kexec-tools-2.0.10/debian/patches/arm-do-not-build-iomem.o-target-with-no-soruce.patch kexec-tools-2.0.16/debian/patches/arm-do-not-build-iomem.o-target-with-no-soruce.patch --- kexec-tools-2.0.10/debian/patches/arm-do-not-build-iomem.o-target-with-no-soruce.patch 2017-03-09 00:57:31.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm-do-not-build-iomem.o-target-with-no-soruce.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -From c901bae8683c59a7bc002bd6a1e3e4b6b7d9c5f1 Mon Sep 17 00:00:00 2001 -From: Simon Horman -Date: Fri, 9 Dec 2016 10:10:49 +0100 -Subject: [PATCH] arm: do not build iomem.o target with no soruce - -Header files should be added to the distribution but not -used to derive targets for compilation. In this an attempt was -made to build iomem.o, but iomem.c does not exist so this fails. - -Fixes: 1574ff1aae4f ("arm: include phys_to_virt.h and iomem.h in distribution") -Signed-off-by: Simon Horman -Reviewed-by: Pratyush Anand ---- - kexec/arch/arm/Makefile | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -Index: kexec-tools-2.0.10/kexec/arch/arm/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm/Makefile -+++ kexec-tools-2.0.10/kexec/arch/arm/Makefile -@@ -22,9 +22,8 @@ arm_KEXEC_SRCS += $(libfdt_SRCS) - - arm_UIMAGE = kexec/kexec-uImage.c - arm_PHYS_TO_VIRT = kexec/arch/arm/phys_to_virt.c --arm_PHYS_TO_VIRT += kexec/arch/arm/iomem.h --arm_PHYS_TO_VIRT += kexec/arch/arm/phys_to_virt.h - - dist += kexec/arch/arm/Makefile $(arm_KEXEC_SRCS) $(arm_PHYS_TO_VIRT) \ -- kexec/arch/arm/crashdump-arm.h kexec/arch/arm/kexec-arm.h \ -+ kexec/arch/arm/iomem.h kexec/arch/arm/phys_to_virt.h \ -+ kexec/arch/arm/crashdump-arm.h kexec/arch/arm/kexec-arm.h \ - kexec/arch/arm/include/arch/options.h diff -Nru kexec-tools-2.0.10/debian/patches/arm-fix-get_kernel_stext_sym-to-close-its-file.patch kexec-tools-2.0.16/debian/patches/arm-fix-get_kernel_stext_sym-to-close-its-file.patch --- kexec-tools-2.0.10/debian/patches/arm-fix-get_kernel_stext_sym-to-close-its-file.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm-fix-get_kernel_stext_sym-to-close-its-file.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,64 +0,0 @@ -From 38c18bb7d1e2db23491619928ca722750d510ce5 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 6 Jun 2016 18:00:00 +0100 -Subject: [PATCH 01/16] arm: fix get_kernel_stext_sym() to close its file - -Fix get_kernel_stext_sym() so that it closes its file once it's -finsihed with it - there's no need to leak file descriptors. - -Reviewed-by: Pratyush Anand -Signed-off-by: Russell King -Signed-off-by: Simon Horman ---- - kexec/arch/arm/crashdump-arm.c | 23 ++++++++++++++++------- - 1 file changed, 16 insertions(+), 7 deletions(-) - -diff --git a/kexec/arch/arm/crashdump-arm.c b/kexec/arch/arm/crashdump-arm.c -index b523e5f..a390187 100644 ---- a/kexec/arch/arm/crashdump-arm.c -+++ b/kexec/arch/arm/crashdump-arm.c -@@ -71,25 +71,34 @@ static unsigned long long get_kernel_stext_sym(void) - 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, --- -2.11.0 - diff -Nru kexec-tools-2.0.10/debian/patches/arm-include-phys_to_virt.h-and-iomem.h-in-distributi.patch kexec-tools-2.0.16/debian/patches/arm-include-phys_to_virt.h-and-iomem.h-in-distributi.patch --- kexec-tools-2.0.10/debian/patches/arm-include-phys_to_virt.h-and-iomem.h-in-distributi.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/arm-include-phys_to_virt.h-and-iomem.h-in-distributi.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -From 1574ff1aae4f3a2396187b4fe4f75a9be2ba2cc3 Mon Sep 17 00:00:00 2001 -From: Dave Young -Date: Tue, 9 Aug 2016 15:57:47 +0800 -Subject: [PATCH] arm: include phys_to_virt.h and iomem.h in distribution - -These files are required to build kexec-tools on arm. - -Signed-off-by: Dave Young -[simon: added changelog] -Signed-off-by: Simon Horman ---- - kexec/arch/arm/Makefile | 2 ++ - 1 file changed, 2 insertions(+) - -Index: kexec-tools-2.0.10/kexec/arch/arm/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm/Makefile -+++ kexec-tools-2.0.10/kexec/arch/arm/Makefile -@@ -22,6 +22,8 @@ arm_KEXEC_SRCS += $(libfdt_SRCS) - - arm_UIMAGE = kexec/kexec-uImage.c - arm_PHYS_TO_VIRT = kexec/arch/arm/phys_to_virt.c -+arm_PHYS_TO_VIRT += kexec/arch/arm/iomem.h -+arm_PHYS_TO_VIRT += kexec/arch/arm/phys_to_virt.h - - dist += kexec/arch/arm/Makefile $(arm_KEXEC_SRCS) $(arm_PHYS_TO_VIRT) \ - kexec/arch/arm/crashdump-arm.h kexec/arch/arm/kexec-arm.h \ diff -Nru kexec-tools-2.0.10/debian/patches/build_mem_phdrs-check-if-p_paddr-is-invalid.patch kexec-tools-2.0.16/debian/patches/build_mem_phdrs-check-if-p_paddr-is-invalid.patch --- kexec-tools-2.0.10/debian/patches/build_mem_phdrs-check-if-p_paddr-is-invalid.patch 2017-09-08 20:18:58.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/build_mem_phdrs-check-if-p_paddr-is-invalid.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -From ed15ba1b9977e506637ff1697821d97127b2c919 Mon Sep 17 00:00:00 2001 -From: Pratyush Anand -Date: Wed, 1 Mar 2017 11:19:42 +0530 -Subject: [PATCH] build_mem_phdrs(): check if p_paddr is invalid - -Currently, all the p_paddr of PT_LOAD headers are assigned to 0, which -is not correct and could be misleading, since 0 is a valid physical -address. - -Upstream kernel commit "464920104bf7 /proc/kcore: update physical -address for kcore ram and text" fixed it and now invalid PT_LOAD is -assigned as -1. - -kexec/arch/i386/crashdump-x86.c:get_kernel_vaddr_and_size() uses kcore -interface and so calls build_mem_phdrs() for kcore PT_LOAD headers. - -This patch fixes build_mem_phdrs() to check if p_paddr is invalid. - -Signed-off-by: Pratyush Anand -Acked-by: Dave Young -Signed-off-by: Simon Horman ---- - kexec/kexec-elf.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -Index: kexec-tools-2.0.10/kexec/kexec-elf.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/kexec-elf.c 2017-09-08 17:18:48.192494797 -0300 -+++ kexec-tools-2.0.10/kexec/kexec-elf.c 2017-09-08 17:18:48.192494797 -0300 -@@ -432,7 +432,8 @@ - } - return -1; - } -- if ((phdr->p_paddr + phdr->p_memsz) < phdr->p_paddr) { -+ if (phdr->p_paddr != (unsigned long long)-1 && -+ (phdr->p_paddr + phdr->p_memsz) < phdr->p_paddr) { - /* The memory address wraps */ - if (probe_debug) { - fprintf(stderr, "ELF address wrap around\n"); diff -Nru kexec-tools-2.0.10/debian/patches/coldreboot.patch kexec-tools-2.0.16/debian/patches/coldreboot.patch --- kexec-tools-2.0.10/debian/patches/coldreboot.patch 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/coldreboot.patch 2018-02-20 22:19:48.000000000 +0000 @@ -1,6 +1,6 @@ --- a/Makefile.in +++ b/Makefile.in -@@ -178,11 +178,13 @@ PSRCS:=$(foreach s, $(SRCS), $(PACKAGE_N +@@ -178,11 +178,13 @@ PGSRCS:=$(foreach s, $(GENERATED_SRCS), $(PACKAGE_NAME)-$(PACKAGE_VERSION)/$(s)) MAN_PAGES:=$(KEXEC_MANPAGE) $(KDUMP_MANPAGE) $(VMCORE_DMESG_MANPAGE) @@ -17,7 +17,7 @@ --- a/kexec/Makefile +++ b/kexec/Makefile -@@ -92,6 +92,8 @@ clean += $(KEXEC_OBJS) $(KEXEC_DEPS) $(K +@@ -92,6 +92,8 @@ KEXEC = $(SBINDIR)/kexec KEXEC_MANPAGE = $(MANDIR)/man8/kexec.8 @@ -26,7 +26,7 @@ -include $(KEXEC_DEPS) -@@ -106,6 +108,16 @@ kexec/fs2dt.o: CPPFLAGS+=$($(ARCH)_FS2DT +@@ -106,6 +108,16 @@ $(KEXEC_MANPAGE): kexec/kexec.8 @$(MKDIR) -p $(MANDIR)/man8 cp $^ $(KEXEC_MANPAGE) @@ -47,7 +47,7 @@ +++ b/kexec/coldreboot @@ -0,0 +1,6 @@ +#!/bin/sh -+NOKEXECFILE=/tmp/no-kexec-reboot ++NOKEXECFILE=/no-kexec-reboot + +/bin/rm -f $NOKEXECFILE +touch $NOKEXECFILE diff -Nru kexec-tools-2.0.10/debian/patches/const_string_warning.patch kexec-tools-2.0.16/debian/patches/const_string_warning.patch --- kexec-tools-2.0.10/debian/patches/const_string_warning.patch 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/const_string_warning.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,190 +0,0 @@ ---- a/kexec/arch/i386/kexec-elf-x86.c -+++ b/kexec/arch/i386/kexec-elf-x86.c -@@ -91,7 +91,7 @@ int elf_x86_load(int argc, char **argv, - char *command_line = NULL, *modified_cmdline = NULL; - const char *append = NULL; - char *tmp_cmdline = NULL; -- char *error_msg = NULL; -+ int error_code = 0; - int result; - int command_line_len; - const char *ramdisk; -@@ -218,7 +218,7 @@ int elf_x86_load(int argc, char **argv, - elf_rel_set_symbol(&info->rhdr, "entry32_regs", ®s, sizeof(regs)); - - if (ramdisk) { -- error_msg = "Ramdisks not supported with generic elf arguments"; -+ error_code = 1; - goto out; - } - } -@@ -289,13 +289,20 @@ int elf_x86_load(int argc, char **argv, - elf_rel_set_symbol(&info->rhdr, "entry32_regs", ®s, sizeof(regs)); - } - else { -- error_msg = "Unknown argument style\n"; -+ error_code = 2; - } - - out: - free(command_line); - free(modified_cmdline); -- if (error_msg) -- die(error_msg); -+ switch (error_code) { -+ case 1: -+ die("Ramdisks not supported with generic elf arguments"); -+ case 2: -+ die("Unknown argument style\n"); -+ -+ default: -+ break; -+ } - return result; - } ---- a/kexec/arch/x86_64/kexec-elf-x86_64.c -+++ b/kexec/arch/x86_64/kexec-elf-x86_64.c -@@ -99,7 +99,7 @@ int elf_x86_64_load(int argc, char **arg - #define ARG_STYLE_NONE 2 - int opt; - int result = 0; -- char *error_msg = NULL; -+ int error_code = 0; - - /* See options.h and add any new options there too! */ - static const struct option options[] = { -@@ -207,7 +207,7 @@ int elf_x86_64_load(int argc, char **arg - elf_rel_set_symbol(&info->rhdr, "entry64_regs", ®s, sizeof(regs)); - - if (ramdisk) { -- error_msg = "Ramdisks not supported with generic elf arguments"; -+ error_code = 1; - goto out; - } - } -@@ -269,13 +269,21 @@ int elf_x86_64_load(int argc, char **arg - elf_rel_set_symbol(&info->rhdr, "entry64_regs", ®s, sizeof(regs)); - } - else { -- error_msg = "Unknown argument style\n"; -+ error_code = 2; - } - - out: - free(command_line); - free(modified_cmdline); -- if (error_msg) -- die(error_msg); -+ switch (error_code) { -+ case 1: -+ die("Ramdisks not supported with generic elf arguments"); -+ -+ case 2: -+ die("Unknown argument style\n"); -+ -+ default: -+ break; -+ } - return result; - } ---- a/kexec/arch/ppc/kexec-elf-ppc.c -+++ b/kexec/arch/ppc/kexec-elf-ppc.c -@@ -160,7 +160,7 @@ int elf_ppc_load(int argc, char **argv, - int command_line_len, crash_cmdline_len; - char *dtb; - int result; -- char *error_msg; -+ int error_code = 0; - unsigned long max_addr, hole_addr; - struct mem_phdr *phdr; - size_t size; -@@ -199,7 +199,6 @@ int elf_ppc_load(int argc, char **argv, - kernel_addr = 0; - ramdisk = 0; - result = 0; -- error_msg = NULL; - - while ((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { - switch (opt) { -@@ -360,7 +359,7 @@ int elf_ppc_load(int argc, char **argv, - (unsigned long *)&blob_size, cmdline_buf); - } - if (!blob_buf || !blob_size) { -- error_msg = "Device tree seems to be an empty file.\n"; -+ error_code = 1; - goto out2; - } - -@@ -397,7 +396,7 @@ int elf_ppc_load(int argc, char **argv, - dtb_addr_actual = add_buffer(info, blob_buf, blob_size, blob_size, 0, dtb_addr, - kernel_addr + KERNEL_ACCESS_TOP, 1); - if (dtb_addr_actual != dtb_addr) { -- error_msg = "Error device tree not loadded to address it was expecting to be loaded too!\n"; -+ error_code = 2; - goto out2; - } - -@@ -452,8 +451,14 @@ out: - free(crash_cmdline); - if (!tmp_cmdline) - free(command_line); -- if (error_msg) -- die(error_msg); -+ switch (error_code) { -+ case 1: -+ die("Device tree seems to be an empty file.\n"); -+ case 2: -+ die("Error device tree not loadded to address it was expecting to be loaded too!\n"); -+ default: -+ break; -+ } - - return result; - } ---- a/kexec/arch/ppc/kexec-uImage-ppc.c -+++ b/kexec/arch/ppc/kexec-uImage-ppc.c -@@ -103,7 +103,7 @@ static int ppc_load_bare_bits(int argc, - unsigned long max_addr; - char *blob_buf = NULL; - off_t blob_size = 0; -- char *error_msg = NULL; -+ int error_code = 0; - - cmdline_buf = NULL; - command_line = NULL; -@@ -223,7 +223,7 @@ static int ppc_load_bare_bits(int argc, - (unsigned long *)&blob_size, cmdline_buf); - } - if (!blob_buf || !blob_size) { -- error_msg = "Device tree seems to be an empty file.\n"; -+ error_code = 1; - goto out2; - } - -@@ -261,7 +261,7 @@ static int ppc_load_bare_bits(int argc, - load_addr + KERNEL_ACCESS_TOP, 1); - if (dtb_addr_actual != dtb_addr) { - printf("dtb_addr_actual: %lx, dtb_addr: %lx\n", dtb_addr_actual, dtb_addr); -- error_msg = "Error device tree not loadded to address it was expecting to be loaded too!\n"; -+ error_code = 2; - goto out2; - } - -@@ -305,8 +305,15 @@ out: - free(crash_cmdline); - if (!tmp_cmdline) - free(command_line); -- if (error_msg) -- die(error_msg); -+ switch (error_code) { -+ case 1: -+ die("Device tree seems to be an empty file.\n"); -+ case 2: -+ die("Error device tree not loadded to address it was expecting to be loaded too!\n"); -+ default: -+ break; -+ } -+ - return ret; - } - diff -Nru kexec-tools-2.0.10/debian/patches/distclean_fix.patch kexec-tools-2.0.16/debian/patches/distclean_fix.patch --- kexec-tools-2.0.10/debian/patches/distclean_fix.patch 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/distclean_fix.patch 2018-02-20 22:19:48.000000000 +0000 @@ -9,14 +9,3 @@ $(RM) -f include/config.h.in configure $(SPEC) $(RM) -rf autom4te.cache ---- a/purgatory/Makefile -+++ b/purgatory/Makefile -@@ -33,7 +33,7 @@ PURGATORY_SRCS+=$($(ARCH)_PURGATORY_SRCS - PURGATORY_OBJS = $(call objify, $(PURGATORY_SRCS)) purgatory/sha256.o - PURGATORY_DEPS = $(call depify, $(PURGATORY_OBJS)) - --clean += $(PURGATORY_OBJS) $(PURGATORY_DEPS) $(PURGATORY) -+clean += $(PURGATORY_OBJS) $(PURGATORY_DEPS) $(PURGATORY) purgatory/purgatory.ro.sym $(PURGATORY_MAP) - - -include $(PURGATORY_DEPS) - diff -Nru kexec-tools-2.0.10/debian/patches/format-security.patch kexec-tools-2.0.16/debian/patches/format-security.patch --- kexec-tools-2.0.10/debian/patches/format-security.patch 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/format-security.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -Description: Fix FTBFS with -Werror=format-security -Author: Adam Conrad - -Index: kexec-tools-2.0.6/kexec/arch/i386/kexec-elf-x86.c -=================================================================== ---- kexec-tools-2.0.6.orig/kexec/arch/i386/kexec-elf-x86.c 2013-11-18 18:06:56.000000000 -0700 -+++ kexec-tools-2.0.6/kexec/arch/i386/kexec-elf-x86.c 2014-03-31 15:37:50.000000000 -0600 -@@ -299,6 +299,6 @@ - free(command_line); - free(modified_cmdline); - if (error_msg) -- die(error_msg); -+ die("%s", error_msg); - return result; - } -Index: kexec-tools-2.0.6/kexec/arch/x86_64/kexec-elf-x86_64.c -=================================================================== ---- kexec-tools-2.0.6.orig/kexec/arch/x86_64/kexec-elf-x86_64.c 2013-11-18 18:06:56.000000000 -0700 -+++ kexec-tools-2.0.6/kexec/arch/x86_64/kexec-elf-x86_64.c 2014-03-31 15:38:37.425630613 -0600 -@@ -276,6 +276,6 @@ - free(command_line); - free(modified_cmdline); - if (error_msg) -- die(error_msg); -+ die("%s", error_msg); - return result; - } -Index: kexec-tools-2.0.6/kexec/arch/ppc/kexec-elf-ppc.c -=================================================================== ---- kexec-tools-2.0.6.orig/kexec/arch/ppc/kexec-elf-ppc.c 2013-11-18 18:06:56.000000000 -0700 -+++ kexec-tools-2.0.6/kexec/arch/ppc/kexec-elf-ppc.c 2014-03-31 15:41:20.749624836 -0600 -@@ -453,7 +453,7 @@ - if (!tmp_cmdline) - free(command_line); - if (error_msg) -- die(error_msg); -+ die("%s", error_msg); - - return result; - } -Index: kexec-tools-2.0.6/kexec/arch/ppc/kexec-uImage-ppc.c -=================================================================== ---- kexec-tools-2.0.6.orig/kexec/arch/ppc/kexec-uImage-ppc.c 2013-11-18 18:06:56.000000000 -0700 -+++ kexec-tools-2.0.6/kexec/arch/ppc/kexec-uImage-ppc.c 2014-03-31 15:41:45.053623977 -0600 -@@ -306,7 +306,7 @@ - if (!tmp_cmdline) - free(command_line); - if (error_msg) -- die(error_msg); -+ die("%s", error_msg); - return ret; - } - diff -Nru kexec-tools-2.0.10/debian/patches/kexec-Add-common-device-tree-routines.patch kexec-tools-2.0.16/debian/patches/kexec-Add-common-device-tree-routines.patch --- kexec-tools-2.0.10/debian/patches/kexec-Add-common-device-tree-routines.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/kexec-Add-common-device-tree-routines.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,203 +0,0 @@ -From 217bcc00c9309416a6c6cd0584196559d28a9259 Mon Sep 17 00:00:00 2001 -From: Geoff Levand -Date: Wed, 21 Sep 2016 18:14:25 +0000 -Subject: [PATCH] kexec: Add common device tree routines - -Common device tree routines that can be shared between all arches -that have device tree support. - -Signed-off-by: Geoff Levand -Tested-By: Pratyush Anand -Tested-By: Matthias Brugger -Signed-off-by: Simon Horman ---- - kexec/Makefile | 4 ++ - kexec/dt-ops.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - kexec/dt-ops.h | 13 ++++++ - 3 files changed, 162 insertions(+) - create mode 100644 kexec/dt-ops.c - create mode 100644 kexec/dt-ops.h - -Index: kexec-tools-2.0.10/kexec/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/Makefile -+++ kexec-tools-2.0.10/kexec/Makefile -@@ -69,6 +69,10 @@ dist += kexec/fs2dt.c kexec/fs2dt.h - $(ARCH)_FS2DT = - KEXEC_SRCS += $($(ARCH)_FS2DT) - -+dist += kexec/dt-ops.c kexec/dt-ops.h -+$(ARCH)_DT_OPS = -+KEXEC_SRCS += $($(ARCH)_DT_OPS) -+ - include $(srcdir)/kexec/arch/alpha/Makefile - include $(srcdir)/kexec/arch/arm/Makefile - include $(srcdir)/kexec/arch/i386/Makefile -Index: kexec-tools-2.0.10/kexec/dt-ops.c -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/dt-ops.c -@@ -0,0 +1,145 @@ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "kexec.h" -+#include "dt-ops.h" -+ -+static const char n_chosen[] = "/chosen"; -+ -+static const char p_bootargs[] = "bootargs"; -+static const char p_initrd_start[] = "linux,initrd-start"; -+static const char p_initrd_end[] = "linux,initrd-end"; -+ -+int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end) -+{ -+ int result; -+ uint64_t value; -+ -+ dbgprintf("%s: start %jd, end %jd, size %jd (%jd KiB)\n", -+ __func__, (intmax_t)start, (intmax_t)end, -+ (intmax_t)(end - start), -+ (intmax_t)(end - start) / 1024); -+ -+ value = cpu_to_fdt64(start); -+ -+ result = dtb_set_property(dtb, dtb_size, n_chosen, p_initrd_start, -+ &value, sizeof(value)); -+ -+ if (result) -+ return result; -+ -+ value = cpu_to_fdt64(end); -+ -+ result = dtb_set_property(dtb, dtb_size, n_chosen, p_initrd_end, -+ &value, sizeof(value)); -+ -+ if (result) { -+ dtb_delete_property(*dtb, n_chosen, p_initrd_start); -+ return result; -+ } -+ -+ return 0; -+} -+ -+int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line) -+{ -+ return dtb_set_property(dtb, dtb_size, n_chosen, p_bootargs, -+ command_line, strlen(command_line) + 1); -+} -+ -+int dtb_set_property(char **dtb, off_t *dtb_size, const char *node, -+ const char *prop, const void *value, int value_len) -+{ -+ int result; -+ int nodeoffset; -+ void *new_dtb; -+ int new_size; -+ -+ value_len = FDT_TAGALIGN(value_len); -+ -+ new_size = FDT_TAGALIGN(*dtb_size + fdt_node_len(node) -+ + fdt_prop_len(prop, value_len)); -+ -+ new_dtb = malloc(new_size); -+ -+ if (!new_dtb) { -+ dbgprintf("%s: malloc failed\n", __func__); -+ return -ENOMEM; -+ } -+ -+ result = fdt_open_into(*dtb, new_dtb, new_size); -+ -+ if (result) { -+ dbgprintf("%s: fdt_open_into failed: %s\n", __func__, -+ fdt_strerror(result)); -+ goto on_error; -+ } -+ -+ nodeoffset = fdt_path_offset(new_dtb, node); -+ -+ if (nodeoffset == -FDT_ERR_NOTFOUND) { -+ result = fdt_add_subnode(new_dtb, nodeoffset, node); -+ -+ if (result) { -+ dbgprintf("%s: fdt_add_subnode failed: %s\n", __func__, -+ fdt_strerror(result)); -+ goto on_error; -+ } -+ } else if (nodeoffset < 0) { -+ dbgprintf("%s: fdt_path_offset failed: %s\n", __func__, -+ fdt_strerror(nodeoffset)); -+ goto on_error; -+ } -+ -+ result = fdt_setprop(new_dtb, nodeoffset, prop, value, value_len); -+ -+ if (result) { -+ dbgprintf("%s: fdt_setprop failed: %s\n", __func__, -+ fdt_strerror(result)); -+ goto on_error; -+ } -+ -+ /* -+ * Can't call free on dtb since dtb may have been mmaped by -+ * slurp_file(). -+ */ -+ -+ result = fdt_pack(new_dtb); -+ -+ if (result) -+ dbgprintf("%s: Unable to pack device tree: %s\n", __func__, -+ fdt_strerror(result)); -+ -+ *dtb = new_dtb; -+ *dtb_size = fdt_totalsize(*dtb); -+ -+ return 0; -+ -+on_error: -+ free(new_dtb); -+ return result; -+} -+ -+int dtb_delete_property(char *dtb, const char *node, const char *prop) -+{ -+ int result; -+ int nodeoffset = fdt_path_offset(dtb, node); -+ -+ if (nodeoffset < 0) { -+ dbgprintf("%s: fdt_path_offset failed: %s\n", __func__, -+ fdt_strerror(nodeoffset)); -+ return nodeoffset; -+ } -+ -+ result = fdt_delprop(dtb, nodeoffset, prop); -+ -+ if (result) -+ dbgprintf("%s: fdt_delprop failed: %s\n", __func__, -+ fdt_strerror(nodeoffset)); -+ -+ return result; -+} -Index: kexec-tools-2.0.10/kexec/dt-ops.h -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/dt-ops.h -@@ -0,0 +1,13 @@ -+#if !defined(KEXEC_DT_OPS_H) -+#define KEXEC_DT_OPS_H -+ -+#include -+ -+int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end); -+int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line); -+int dtb_set_property(char **dtb, off_t *dtb_size, const char *node, -+ const char *prop, const void *value, int value_len); -+ -+int dtb_delete_property(char *dtb, const char *node, const char *prop); -+ -+#endif diff -Nru kexec-tools-2.0.10/debian/patches/kexec-add-generic-helper-to-add-to-memory_regions.patch kexec-tools-2.0.16/debian/patches/kexec-add-generic-helper-to-add-to-memory_regions.patch --- kexec-tools-2.0.10/debian/patches/kexec-add-generic-helper-to-add-to-memory_regions.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/kexec-add-generic-helper-to-add-to-memory_regions.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ -From ba1e37a8ede8d7d981c677ef7273e01aec88da7f Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 6 Jun 2016 17:59:34 +0100 -Subject: [PATCH] kexec: add generic helper to add to memory_regions - -Add a helper to add a memory range to a memory_regions array. - -Reviewed-by: Pratyush Anand -Signed-off-by: Russell King -Signed-off-by: Simon Horman ---- - kexec/Makefile | 4 ++++ - kexec/mem_regions.c | 29 +++++++++++++++++++++++++++++ - kexec/mem_regions.h | 9 +++++++++ - 3 files changed, 42 insertions(+) - create mode 100644 kexec/mem_regions.c - create mode 100644 kexec/mem_regions.h - -Index: kexec-tools-2.0.10/kexec/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/Makefile -+++ kexec-tools-2.0.10/kexec/Makefile -@@ -73,6 +73,10 @@ dist += kexec/dt-ops.c kexec/dt-ops.h - $(ARCH)_DT_OPS = - KEXEC_SRCS += $($(ARCH)_DT_OPS) - -+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/arm64/Makefile -Index: kexec-tools-2.0.10/kexec/mem_regions.c -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/mem_regions.c -@@ -0,0 +1,29 @@ -+#include "kexec.h" -+#include "mem_regions.h" -+ -+/** -+ * mem_regions_add() - add a memory region to a set of ranges -+ * @ranges: ranges to add the memory region to -+ * @max: maximum number of entries in memory region -+ * @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; -+} -Index: kexec-tools-2.0.10/kexec/mem_regions.h -=================================================================== ---- /dev/null -+++ kexec-tools-2.0.10/kexec/mem_regions.h -@@ -0,0 +1,9 @@ -+#ifndef MEM_REGIONS_H -+#define MEM_REGIONS_H -+ -+struct memory_ranges; -+ -+int mem_regions_add(struct memory_ranges *ranges, unsigned long long base, -+ unsigned long long length, int type); -+ -+#endif diff -Nru kexec-tools-2.0.10/debian/patches/kexec-add-helper-to-exlude-a-region-from-a-set-of-me.patch kexec-tools-2.0.16/debian/patches/kexec-add-helper-to-exlude-a-region-from-a-set-of-me.patch --- kexec-tools-2.0.10/debian/patches/kexec-add-helper-to-exlude-a-region-from-a-set-of-me.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/kexec-add-helper-to-exlude-a-region-from-a-set-of-me.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -From 61ac72aefb9e7c2c3b8ae79cb031a2cc84e27dd8 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 6 Jun 2016 17:59:44 +0100 -Subject: [PATCH] kexec: add helper to exlude a region from a set of memory - ranges - -Add a helper to exclude a region from a set of memory ranges. - -Signed-off-by: Russell King -Reviewed-by: Pratyush Anand -Signed-off-by: Simon Horman ---- - kexec/mem_regions.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++ - kexec/mem_regions.h | 4 +++ - 2 files changed, 76 insertions(+) - -diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c -index 7b4bcf3..b01a5c8 100644 ---- a/kexec/mem_regions.c -+++ b/kexec/mem_regions.c -@@ -54,3 +54,75 @@ int mem_regions_add(struct memory_ranges *ranges, unsigned long long base, - - 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 --git a/kexec/mem_regions.h b/kexec/mem_regions.h -index da7b5e8..ae9e972 100644 ---- a/kexec/mem_regions.h -+++ b/kexec/mem_regions.h -@@ -2,9 +2,13 @@ - #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); - --- -2.11.0 - diff -Nru kexec-tools-2.0.10/debian/patches/kexec-add-max_size-to-memory_ranges.patch kexec-tools-2.0.16/debian/patches/kexec-add-max_size-to-memory_ranges.patch --- kexec-tools-2.0.10/debian/patches/kexec-add-max_size-to-memory_ranges.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/kexec-add-max_size-to-memory_ranges.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -From 5450d34a886445e0787c432ff9aaa04b55b0f4c0 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 6 Jun 2016 17:59:24 +0100 -Subject: [PATCH] kexec: add max_size to memory_ranges - -Many implementations statically allocate the memory range array, which -therefore will have a maximum allowable size. Add this information to -the memory_ranges structure, so we don't have to carry it around. - -Reviewed-by: Pratyush Anand -Signed-off-by: Russell King -Signed-off-by: Simon Horman ---- - kexec/kexec.h | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/kexec/kexec.h b/kexec/kexec.h -index c02ac8f..9194f1c 100644 ---- a/kexec/kexec.h -+++ b/kexec/kexec.h -@@ -142,6 +142,7 @@ struct memory_range { - - struct memory_ranges { - unsigned int size; -+ unsigned int max_size; - struct memory_range *ranges; - }; - --- -2.11.0 - diff -Nru kexec-tools-2.0.10/debian/patches/kexec-add-mem_regions-sorting-implementation.patch kexec-tools-2.0.16/debian/patches/kexec-add-mem_regions-sorting-implementation.patch --- kexec-tools-2.0.10/debian/patches/kexec-add-mem_regions-sorting-implementation.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/kexec-add-mem_regions-sorting-implementation.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -From 7dc06a544ffd192634d624af163791dca791e845 Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 6 Jun 2016 17:59:39 +0100 -Subject: [PATCH] kexec: add mem_regions sorting implementation - -Add a mem_regions sorting implementation taken from the arm code. - -Reviewed-by: Pratyush Anand -Signed-off-by: Russell King -Signed-off-by: Simon Horman ---- - kexec/mem_regions.c | 27 +++++++++++++++++++++++++++ - kexec/mem_regions.h | 2 ++ - 2 files changed, 29 insertions(+) - -diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c -index 4425b86..7b4bcf3 100644 ---- a/kexec/mem_regions.c -+++ b/kexec/mem_regions.c -@@ -1,6 +1,33 @@ -+#include -+ - #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 -diff --git a/kexec/mem_regions.h b/kexec/mem_regions.h -index b9cfba1..da7b5e8 100644 ---- a/kexec/mem_regions.h -+++ b/kexec/mem_regions.h -@@ -3,6 +3,8 @@ - - struct memory_ranges; - -+void mem_regions_sort(struct memory_ranges *ranges); -+ - int mem_regions_add(struct memory_ranges *ranges, unsigned long long base, - unsigned long long length, int type); - --- -2.11.0 - diff -Nru kexec-tools-2.0.10/debian/patches/kexec-arch-i386-Add-support-for-KASLR-memory-randomi.patch kexec-tools-2.0.16/debian/patches/kexec-arch-i386-Add-support-for-KASLR-memory-randomi.patch --- kexec-tools-2.0.10/debian/patches/kexec-arch-i386-Add-support-for-KASLR-memory-randomi.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/kexec-arch-i386-Add-support-for-KASLR-memory-randomi.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,94 +0,0 @@ -From 9f62cbddddfc93d78d9aafbddf3e1208cb242f7b Mon Sep 17 00:00:00 2001 -From: Thomas Garnier -Date: Tue, 13 Sep 2016 15:10:05 +0800 -Subject: [PATCH] kexec/arch/i386: Add support for KASLR memory randomization - -Multiple changes were made on KASLR (right now in linux-next). One of -them is randomizing the virtual address of the physical mapping, vmalloc -and vmemmap memory sections. It breaks kdump ability to read physical -memory. - -This change identifies if KASLR memories randomization is used by -checking if the page_offset_base variable exists. It search for the -correct PAGE_OFFSET value by looking at the loaded memory section and -find the lowest aligned on PUD (the randomization level). - -Related commits on linux-next: - - 0483e1fa6e09d4948272680f691dccb1edb9677f: Base for randomization - - 021182e52fe01c1f7b126f97fd6ba048dc4234fd: Enable for PAGE_OFFSET - -Signed-off-by: Thomas Garnier -Signed-off-by: Simon Horman ---- - kexec/arch/i386/crashdump-x86.c | 29 ++++++++++++++++++++++------- - 1 file changed, 22 insertions(+), 7 deletions(-) - -Index: kexec-tools-2.0.10/kexec/arch/i386/crashdump-x86.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/i386/crashdump-x86.c -+++ kexec-tools-2.0.10/kexec/arch/i386/crashdump-x86.c -@@ -101,11 +101,10 @@ static int get_kernel_paddr(struct kexec - return -1; - } - --/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */ --static unsigned long long get_kernel_stext_sym(void) -+/* Retrieve kernel symbol virtual address from /proc/kallsyms */ -+static unsigned long long get_kernel_sym(const char *symbol) - { - const char *kallsyms = "/proc/kallsyms"; -- const char *stext = "_stext"; - char sym[128]; - char line[128]; - FILE *fp; -@@ -121,13 +120,13 @@ static unsigned long long get_kernel_ste - while(fgets(line, sizeof(line), fp) != NULL) { - if (sscanf(line, "%Lx %c %s", &vaddr, &type, sym) != 3) - continue; -- if (strcmp(sym, stext) == 0) { -- dbgprintf("kernel symbol %s vaddr = %16llx\n", stext, vaddr); -+ if (strcmp(sym, symbol) == 0) { -+ dbgprintf("kernel symbol %s vaddr = %16llx\n", symbol, vaddr); - return vaddr; - } - } - -- fprintf(stderr, "Cannot get kernel %s symbol address\n", stext); -+ fprintf(stderr, "Cannot get kernel %s symbol address\n", symbol); - return 0; - } - -@@ -150,6 +149,8 @@ static int get_kernel_vaddr_and_size(str - off_t size; - uint32_t elf_flags = 0; - uint64_t stext_sym; -+ const unsigned long long pud_mask = ~((1 << 30) - 1); -+ unsigned long long vaddr, lowest_vaddr = 0; - - if (elf_info->machine != EM_X86_64) - return 0; -@@ -179,9 +180,23 @@ static int get_kernel_vaddr_and_size(str - - end_phdr = &ehdr.e_phdr[ehdr.e_phnum]; - -+ /* Search for the real PAGE_OFFSET when KASLR memory randomization -+ * is enabled */ -+ if (get_kernel_sym("page_offset_base") != 0) { -+ for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) { -+ if (phdr->p_type == PT_LOAD) { -+ vaddr = phdr->p_vaddr & pud_mask; -+ if (lowest_vaddr == 0 || lowest_vaddr > vaddr) -+ lowest_vaddr = vaddr; -+ } -+ } -+ if (lowest_vaddr != 0) -+ elf_info->page_offset = lowest_vaddr; -+ } -+ - /* Traverse through the Elf headers and find the region where - * _stext symbol is located in. That's where kernel is mapped */ -- stext_sym = get_kernel_stext_sym(); -+ stext_sym = get_kernel_sym("_stext"); - for(phdr = ehdr.e_phdr; stext_sym && phdr != end_phdr; phdr++) { - if (phdr->p_type == PT_LOAD) { - unsigned long long saddr = phdr->p_vaddr; diff -Nru kexec-tools-2.0.10/debian/patches/kexec-fix-mem_regions_sort.patch kexec-tools-2.0.16/debian/patches/kexec-fix-mem_regions_sort.patch --- kexec-tools-2.0.10/debian/patches/kexec-fix-mem_regions_sort.patch 2017-06-23 18:27:21.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/kexec-fix-mem_regions_sort.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,32 +0,0 @@ -From 9fd57cad8a0f1e0c7a342f014e1cc8ee31d72261 Mon Sep 17 00:00:00 2001 -From: Pratyush Anand -Date: Wed, 27 Jul 2016 23:19:42 +0530 -Subject: [PATCH] kexec: fix mem_regions_sort() - -ranges->ranges is "struct memory_range *", however each element which need -to be sorted is of type "struct memory_range". So, correct "size" argument -of qsort() as sizeof(*ranges->ranges). - -Signed-off-by: Pratyush Anand -Acked-by: Russell King -Signed-off-by: Simon Horman ---- - kexec/mem_regions.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/kexec/mem_regions.c b/kexec/mem_regions.c -index e61c074..50c8abc 100644 ---- a/kexec/mem_regions.c -+++ b/kexec/mem_regions.c -@@ -24,7 +24,7 @@ static int mem_range_cmp(const void *a1, const void *a2) - */ - void mem_regions_sort(struct memory_ranges *ranges) - { -- qsort(ranges->ranges, ranges->size, sizeof(ranges->ranges), -+ qsort(ranges->ranges, ranges->size, sizeof(*ranges->ranges), - mem_range_cmp); - } - --- -2.11.0 - diff -Nru kexec-tools-2.0.10/debian/patches/kexec-Increase-the-upper-limit-for-RAM-segments.patch kexec-tools-2.0.16/debian/patches/kexec-Increase-the-upper-limit-for-RAM-segments.patch --- kexec-tools-2.0.10/debian/patches/kexec-Increase-the-upper-limit-for-RAM-segments.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/kexec-Increase-the-upper-limit-for-RAM-segments.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -From 24aa2d93cac316657a2c20f28b8687bbf7e22991 Mon Sep 17 00:00:00 2001 -From: Sameer Goel -Date: Wed, 18 Jan 2017 16:15:12 -0700 -Subject: [PATCH] kexec: Increase the upper limit for RAM segments - -On a newer UEFI based Qualcomm target the number of system ram regions -retrieved from /proc/iomem are ~40. So increasing the current hardcoded -values to 64 from 16. - -Signed-off-by: Sameer Goel -Signed-off-by: Simon Horman ---- - kexec/arch/arm64/kexec-arm64.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.h -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm64/kexec-arm64.h -+++ kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.h -@@ -11,7 +11,7 @@ - #include "image-header.h" - #include "kexec.h" - --#define KEXEC_SEGMENT_MAX 16 -+#define KEXEC_SEGMENT_MAX 64 - - #define BOOT_BLOCK_VERSION 17 - #define BOOT_BLOCK_LAST_COMP_VERSION 16 diff -Nru kexec-tools-2.0.10/debian/patches/kexec-phys_to_virt-must-take-unsigned-long-long.patch kexec-tools-2.0.16/debian/patches/kexec-phys_to_virt-must-take-unsigned-long-long.patch --- kexec-tools-2.0.10/debian/patches/kexec-phys_to_virt-must-take-unsigned-long-long.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/kexec-phys_to_virt-must-take-unsigned-long-long.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -From 8d8d2229a3afe6323a737c42c25a101ea104efbe Mon Sep 17 00:00:00 2001 -From: Russell King -Date: Mon, 6 Jun 2016 17:59:29 +0100 -Subject: [PATCH] kexec: phys_to_virt() must take unsigned long long - -crashdump-elf.c passes unsigned long long addresses into phys_to_virt() -so make phys_to_virt() accept such addresses without truncating them. -This is important for ARM LPAE systems. - -Reviewed-by: Pratyush Anand -Signed-off-by: Russell King -Signed-off-by: Simon Horman ---- - kexec/arch/arm/phys_to_virt.c | 2 +- - kexec/crashdump.h | 2 +- - kexec/phys_to_virt.c | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -Index: kexec-tools-2.0.10/kexec/arch/arm/phys_to_virt.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/arm/phys_to_virt.c -+++ kexec-tools-2.0.10/kexec/arch/arm/phys_to_virt.c -@@ -14,7 +14,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; - } -Index: kexec-tools-2.0.10/kexec/crashdump.h -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/crashdump.h -+++ kexec-tools-2.0.10/kexec/crashdump.h -@@ -55,7 +55,7 @@ int crash_create_elf64_headers(struct ke - 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); -Index: kexec-tools-2.0.10/kexec/phys_to_virt.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/phys_to_virt.c -+++ kexec-tools-2.0.10/kexec/phys_to_virt.c -@@ -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 -Nru kexec-tools-2.0.10/debian/patches/kexec-tools-x86-get_kernel_vaddr_and_size-off-by-one.patch kexec-tools-2.0.16/debian/patches/kexec-tools-x86-get_kernel_vaddr_and_size-off-by-one.patch --- kexec-tools-2.0.10/debian/patches/kexec-tools-x86-get_kernel_vaddr_and_size-off-by-one.patch 2017-09-08 20:20:14.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/kexec-tools-x86-get_kernel_vaddr_and_size-off-by-one.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -From dbb99d938810b60035122a1bcc68c4d585a0e57f Mon Sep 17 00:00:00 2001 -From: Dave Young -Date: Thu, 8 Dec 2016 10:52:22 +0800 -Subject: [PATCH] kexec-tools/x86: get_kernel_vaddr_and_size off-by-one fix - -I got below error while tesing kexec -p: -"Can't find kernel text map area from kcore" - -The case is the pt_load start addr was same as stext_sym. The checking -code should really be saddr <= stext_sym so that the right pt_load area -includes stext_sym can be matched. - -This was not reported by people previously because it will fail over to -use hardcode X86_64__START_KERNEL_map to match the pt_load areas again -in later code and it sometimes succeeds because of kernel address -randomization. - -With this change according to my test stext_sym checking can garantee -falling into right pt_load area if we get correct stext_sym. - -Signed-off-by: Dave Young -Signed-off-by: Simon Horman ---- - kexec/arch/i386/crashdump-x86.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -Index: kexec-tools-2.0.10/kexec/arch/i386/crashdump-x86.c -=================================================================== ---- kexec-tools-2.0.10.orig/kexec/arch/i386/crashdump-x86.c 2017-09-08 17:20:11.621385081 -0300 -+++ kexec-tools-2.0.10/kexec/arch/i386/crashdump-x86.c 2017-09-08 17:20:11.617385041 -0300 -@@ -175,7 +175,7 @@ - unsigned long long size; - - /* Look for kernel text mapping header. */ -- if (saddr < stext_sym && eaddr > stext_sym) { -+ if (saddr <= stext_sym && eaddr > stext_sym) { - saddr = _ALIGN_DOWN(saddr, X86_64_KERN_VADDR_ALIGN); - elf_info->kern_vaddr_start = saddr; - size = eaddr - saddr; diff -Nru kexec-tools-2.0.10/debian/patches/lp1546260-fix-purgatory-fail-gcc5.patch kexec-tools-2.0.16/debian/patches/lp1546260-fix-purgatory-fail-gcc5.patch --- kexec-tools-2.0.10/debian/patches/lp1546260-fix-purgatory-fail-gcc5.patch 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/lp1546260-fix-purgatory-fail-gcc5.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,265 +0,0 @@ -Description: [PowerPC64] Fix failure in purgatory when compiled with gcc5 - Application of upstream fixes so kexec-tools work with gcc5 on PowerPC64 - - commit 4a2ae3a39c64dc43e9d094be9541253234ff4822 - Pass struct mem_sym into machine_apply_elf_rel() - On PowerPC64 ABIv2 we need to look at the symbol to determine - if it has a local entry point. Pass struct mem_sym into - machine_apply_elf_rel() so we can. - - commit 1e423dc297d10eb7ff25c829d2856ef12fc81d77 - ppc64: purgatory: Handle local symbols in ELF ABIv2 - The PowerPC64 ELF ABIv2 has the concept of global and local symbols - and information on this is encoded in sym->st_other. When doing a - R_PPC64_REL24 branch we want to hit the local entry point, so adjust - it as necessary. - - commit 3debb8cf3272216119cb2e59a4963ce3c18fe8e3 - Properly align powerpc64 .toc - gcc leaves .toc byte aligned, relying on the linker to align the section. - * kexec/arch/ppc64/kexec-elf-rel-ppc64.c (machine_verify_elf_rel): - Fudge alignment of .toc section. - -Author: Anton Blanchard , Alan Modra -Origin: -Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/kexec-tools/+bug/1546260 ---- a/kexec/arch/arm/kexec-elf-rel-arm.c -+++ b/kexec/arch/arm/kexec-elf-rel-arm.c -@@ -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: ---- a/kexec/arch/cris/kexec-elf-rel-cris.c -+++ b/kexec/arch/cris/kexec-elf-rel-cris.c -@@ -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) { - ---- a/kexec/arch/i386/kexec-elf-rel-x86.c -+++ b/kexec/arch/i386/kexec-elf-rel-x86.c -@@ -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: ---- a/kexec/arch/ia64/kexec-elf-rel-ia64.c -+++ b/kexec/arch/ia64/kexec-elf-rel-ia64.c -@@ -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) { ---- a/kexec/arch/m68k/kexec-elf-rel-m68k.c -+++ b/kexec/arch/m68k/kexec-elf-rel-m68k.c -@@ -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)) ---- a/kexec/arch/mips/kexec-elf-rel-mips.c -+++ b/kexec/arch/mips/kexec-elf-rel-mips.c -@@ -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)) ---- a/kexec/arch/ppc64/kexec-elf-rel-ppc64.c -+++ b/kexec/arch/ppc64/kexec-elf-rel-ppc64.c -@@ -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) { ---- a/kexec/arch/ppc/kexec-elf-rel-ppc.c -+++ b/kexec/arch/ppc/kexec-elf-rel-ppc.c -@@ -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: ---- a/kexec/arch/s390/kexec-elf-rel-s390.c -+++ b/kexec/arch/s390/kexec-elf-rel-s390.c -@@ -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, ---- a/kexec/arch/sh/kexec-elf-rel-sh.c -+++ b/kexec/arch/sh/kexec-elf-rel-sh.c -@@ -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; ---- a/kexec/arch/x86_64/kexec-elf-rel-x86_64.c -+++ b/kexec/arch/x86_64/kexec-elf-rel-x86_64.c -@@ -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) { ---- a/kexec/kexec-elf.h -+++ b/kexec/kexec-elf.h -@@ -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 */ - ---- a/kexec/kexec-elf-rel.c -+++ b/kexec/kexec-elf-rel.c -@@ -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 -Nru kexec-tools-2.0.10/debian/patches/purgatory-Change-default-sha256-optimization-to-O2.patch kexec-tools-2.0.16/debian/patches/purgatory-Change-default-sha256-optimization-to-O2.patch --- kexec-tools-2.0.10/debian/patches/purgatory-Change-default-sha256-optimization-to-O2.patch 2017-02-07 18:52:41.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/purgatory-Change-default-sha256-optimization-to-O2.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,57 +0,0 @@ -From 0a7fba8b145306af4909950f64f2797a08db68d4 Mon Sep 17 00:00:00 2001 -From: Geoff Levand -Date: Thu, 1 Dec 2016 11:09:37 -0800 -Subject: [PATCH] purgatory: Change default sha256 optimization to -O2 - -Change the default purgatory sha256 code optimization from -O0 to -O2, and add a -new arch specific makefile variable $(ARCH)_PURGATORY_SHA256_CFLAGS which can -over ride this default. Set ia64_PURGATORY_SHA256_CFLAGS to -O0 to retain the -previous optimization level for ia64. - -The purgatory sha256 code needs the be built with -O0 for the ia64 -architecture. Currently this code is built with -O0 for all architectures, -which slows down the calculations for architectures which could otherwise -use -O2. - -On arm64, it takes around 20 second to verify SHA in purgatory when -vmlinuz image is around 13MB and initramfs is around 30M with -O2 -enabled. Otherwise, it takes more than 2 minutes. - -Cc: Pratyush Anand -Signed-off-by: Geoff Levand -Signed-off-by: Simon Horman ---- - purgatory/Makefile | 4 +--- - purgatory/arch/ia64/Makefile | 4 ++++ - 2 files changed, 5 insertions(+), 3 deletions(-) - -Index: kexec-tools-2.0.10/purgatory/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/purgatory/Makefile -+++ kexec-tools-2.0.10/purgatory/Makefile -@@ -38,9 +38,7 @@ clean += $(PURGATORY_OBJS) $(PURGATORY_D - - -include $(PURGATORY_DEPS) - --# sha256.c needs to be compiled without optimization, else --# purgatory fails to execute on ia64. --purgatory/sha256.o: CFLAGS += -O0 -+purgatory/sha256.o: CFLAGS += -O2 $($(ARCH)_PURGATORY_SHA256_CFLAGS) - - purgatory/sha256.o: $(srcdir)/util_lib/sha256.c - mkdir -p $(@D) -Index: kexec-tools-2.0.10/purgatory/arch/ia64/Makefile -=================================================================== ---- kexec-tools-2.0.10.orig/purgatory/arch/ia64/Makefile -+++ kexec-tools-2.0.10/purgatory/arch/ia64/Makefile -@@ -8,6 +8,10 @@ ia64_PURGATORY_SRCS += purgatory/arch/ia - - ia64_PURGATORY_EXTRA_CFLAGS = -ffixed-r28 - -+# sha256.c needs to be compiled without optimization, else -+# purgatory fails to execute on ia64. -+ia64_PURGATORY_SHA256_CFLAGS = -O0 -+ - dist += purgatory/arch/ia64/Makefile $(ia64_PURGATORY_SRCS) \ - purgatory/arch/ia64/io.h purgatory/arch/ia64/purgatory-ia64.h - diff -Nru kexec-tools-2.0.10/debian/patches/series kexec-tools-2.0.16/debian/patches/series --- kexec-tools-2.0.10/debian/patches/series 2017-09-08 20:20:08.000000000 +0000 +++ kexec-tools-2.0.16/debian/patches/series 2018-02-20 22:19:48.000000000 +0000 @@ -4,39 +4,5 @@ add_debian_readme.patch coldreboot.patch linker-option.patch -# const_string_warning.patch - use format-security.patch instead powerpcspe_support.patch -format-security.patch -lp1546260-fix-purgatory-fail-gcc5.patch -kexec-Add-common-device-tree-routines.patch -arm64-Add-arm64-kexec-support.patch -arm64-Add-support-for-binary-image-files.patch -arm-include-phys_to_virt.h-and-iomem.h-in-distributi.patch -arm64-Cleanup-kexec-Makefile.patch -arm64-Add-missing-kexec-dist-files.patch -arm64-Add-support-for-additional-relocations-in-the-.patch -arm64-Add-support-of-R_AARCH64_PREL32-relocation-in-.patch -purgatory-Change-default-sha256-optimization-to-O2.patch -arm64-Fix-initrd-requierements.patch -kexec-phys_to_virt-must-take-unsigned-long-long.patch -kexec-Increase-the-upper-limit-for-RAM-segments.patch -arm-do-not-build-iomem.o-target-with-no-soruce.patch -arm-fix-get_kernel_stext_sym-to-close-its-file.patch -kexec-add-max_size-to-memory_ranges.patch -kexec-add-generic-helper-to-add-to-memory_regions.patch -kexec-add-mem_regions-sorting-implementation.patch -kexec-add-helper-to-exlude-a-region-from-a-set-of-me.patch -kexec-fix-mem_regions_sort.patch -kexec-arch-i386-Add-support-for-KASLR-memory-randomi.patch -0001-kexec-extend-the-semantics-of-kexec_iomem_for_each_l.patch -0002-kexec-generalize-and-rename-get_kernel_stext_sym.patch -0003-arm64-identify-PHYS_OFFSET-correctly.patch -0004-arm64-change-return-values-on-error-to-negative.patch -0005-arm64-kdump-identify-memory-regions.patch -0006-arm64-kdump-add-elf-core-header-segment.patch -0007-arm64-kdump-set-up-kernel-image-segment.patch -0008-arm64-kdump-set-up-other-segments.patch -0009-arm64-kdump-add-DT-properties-to-crash-dump-kernel-s.patch -0010-arm64-kdump-Add-support-for-binary-image-files.patch -build_mem_phdrs-check-if-p_paddr-is-invalid.patch -kexec-tools-x86-get_kernel_vaddr_and_size-off-by-one.patch +arm64_build.patch diff -Nru kexec-tools-2.0.10/debian/po/cs.po kexec-tools-2.0.16/debian/po/cs.po --- kexec-tools-2.0.10/debian/po/cs.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/cs.po 2018-02-23 15:05:01.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: kexec-tools\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" "PO-Revision-Date: 2011-09-03 15:12+0200\n" "Last-Translator: Miroslav Kure \n" "Language-Team: Czech \n" @@ -19,7 +19,9 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" +#, fuzzy +#| msgid "Should kexec-tools handle reboots?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" msgstr "Mají se kexec-tools starat o restarty?" #. Type: boolean diff -Nru kexec-tools-2.0.10/debian/po/da.po kexec-tools-2.0.16/debian/po/da.po --- kexec-tools-2.0.10/debian/po/da.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/da.po 2018-02-23 15:05:01.000000000 +0000 @@ -1,17 +1,17 @@ # Danish translation kexec-tools. -# Copyright (C) 2011 kexec-tools & nedenstående oversættere. +# Copyright (C) 2016 kexec-tools & nedenstående oversættere. # This file is distributed under the same license as the kexec-tools package. -# Joe Hansen , 2010, 2011. +# Joe Hansen , 2010, 2011, 2016. # msgid "" msgstr "" "Project-Id-Version: kexec-tools\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" -"PO-Revision-Date: 2011-09-04 05:26+0100\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" +"PO-Revision-Date: 2016-07-09 05:26+0100\n" "Last-Translator: Joe Hansen \n" "Language-Team: Danish \n" -"Language: \n" +"Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -19,8 +19,8 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" -msgstr "Skal kexec-tools håndtere genstarter?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" +msgstr "Skal kexec-tools håndtere genstarter (kun sysvinit)?" #. Type: boolean #. Description diff -Nru kexec-tools-2.0.10/debian/po/de.po kexec-tools-2.0.16/debian/po/de.po --- kexec-tools-2.0.10/debian/po/de.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/de.po 2018-02-23 15:05:01.000000000 +0000 @@ -1,14 +1,14 @@ # German translation of the kexec-tools debconf template # Copyright 2008 Kai Wasserbäch -# Copyright 2011 Helge Kreutzmann +# Copyright 2011,2017 Helge Kreutzmann # This file is distributed under the same license as the kexec-tools package. # msgid "" msgstr "" -"Project-Id-Version: kexec-tools 20080324-1\n" +"Project-Id-Version: kexec-tools 1:2.0.14-1\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" -"PO-Revision-Date: 2011-09-10 20:36+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" +"PO-Revision-Date: 2017-03-10 21:15+0100\n" "Last-Translator: Helge Kreutzmann \n" "Language-Team: German \n" "Language: de\n" @@ -17,11 +17,12 @@ "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +#, new #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" -msgstr "Soll »kexec-tools« Neustarts verwalten?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" +msgstr "Soll »kexec-tools« Neustarts verwalten? (Nur SysvInit)" #. Type: boolean #. Description diff -Nru kexec-tools-2.0.10/debian/po/es.po kexec-tools-2.0.16/debian/po/es.po --- kexec-tools-2.0.10/debian/po/es.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/es.po 2018-02-23 15:05:01.000000000 +0000 @@ -31,7 +31,7 @@ msgstr "" "Project-Id-Version: kexec-tools 2.0.2-3\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" "PO-Revision-Date: 2011-08-29 12:15+0200\n" "Last-Translator: Camaleón \n" "Language-Team: Debian Spanish \n" @@ -43,7 +43,9 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" +#, fuzzy +#| msgid "Should kexec-tools handle reboots?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" msgstr "¿Debe kexec-tools gestionar los reinicios del sistema?" #. Type: boolean diff -Nru kexec-tools-2.0.10/debian/po/fi.po kexec-tools-2.0.16/debian/po/fi.po --- kexec-tools-2.0.10/debian/po/fi.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/fi.po 2018-02-23 15:05:01.000000000 +0000 @@ -2,7 +2,7 @@ msgstr "" "Project-Id-Version: kexec-tools\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" "PO-Revision-Date: 2008-04-26 08:30+0200\n" "Last-Translator: Esko Arajärvi \n" "Language-Team: Finnish \n" @@ -16,7 +16,9 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" +#, fuzzy +#| msgid "Should kexec-tools handle reboots?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" msgstr "Tulisiko kexec-toolsin hallinnoida järjestelmän uudelleenkäynnistystä?" #. Type: boolean diff -Nru kexec-tools-2.0.10/debian/po/fr.po kexec-tools-2.0.16/debian/po/fr.po --- kexec-tools-2.0.10/debian/po/fr.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/fr.po 2018-02-23 15:05:01.000000000 +0000 @@ -1,14 +1,16 @@ -# kexec-tools debconf . -# Copyright (C) 2008 Steve Petruzzello +# Translation of kexec-tools debconf template to French +# Copyright (C) 2016 Debian French l10n team # This file is distributed under the same license as the kexec-tools package. -# Khalid Aziz +# +# Translator: +# Steve Petruzzello # msgid "" msgstr "" "Project-Id-Version: kexec-tools_2.0.0-2\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" -"PO-Revision-Date: 2011-09-02 10:54+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" +"PO-Revision-Date: 2016-04-05 12:18+0200\n" "Last-Translator: Steve Petruzzello \n" "Language-Team: French \n" "Language: fr\n" @@ -19,8 +21,9 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" -msgstr "Faut-il gérer les redémarrages avec kexec-tools ?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" +msgstr "" +"Faut-il gérer les redémarrages avec kexec-tools (seulement pour sysvinit) ?" #. Type: boolean #. Description diff -Nru kexec-tools-2.0.10/debian/po/gl.po kexec-tools-2.0.16/debian/po/gl.po --- kexec-tools-2.0.10/debian/po/gl.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/gl.po 2018-02-23 15:05:01.000000000 +0000 @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: kexec-tools\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" "PO-Revision-Date: 2008-04-25 21:26+0100\n" "Last-Translator: Jacobo Tarrio \n" "Language-Team: Galician \n" @@ -18,7 +18,9 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" +#, fuzzy +#| msgid "Should kexec-tools handle reboots?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" msgstr "¿Debe kexec-tools xestionar os reinicios?" #. Type: boolean diff -Nru kexec-tools-2.0.10/debian/po/it.po kexec-tools-2.0.16/debian/po/it.po --- kexec-tools-2.0.10/debian/po/it.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/it.po 2018-02-23 15:05:01.000000000 +0000 @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: kexec-tools\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" "PO-Revision-Date: 2010-10-13 06:52+0200\n" "Last-Translator: Vincenzo Campanella \n" "Language-Team: Italian \n" @@ -20,7 +20,9 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" +#, fuzzy +#| msgid "Should kexec-tools handle reboots?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" msgstr "Si desidera che kexec-tools gestisca i riavvii?" #. Type: boolean diff -Nru kexec-tools-2.0.10/debian/po/ja.po kexec-tools-2.0.16/debian/po/ja.po --- kexec-tools-2.0.10/debian/po/ja.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/ja.po 2018-02-23 15:05:01.000000000 +0000 @@ -1,25 +1,28 @@ # Copyright (C) 2008 Khalid Aziz # This file is distributed under the same license as kexec-tools package. # Hideki Yamane (Debian-JP) , 2008. -# +# Takuma Yamada , 2016. +# msgid "" msgstr "" "Project-Id-Version: kexec-tools 20080324-2\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" -"PO-Revision-Date: 2011-08-26 01:55+0900\n" -"Last-Translator: Hideki Yamane (Debian-JP) \n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" +"PO-Revision-Date: 2016-03-24 12:07+0900\n" +"Last-Translator: Takuma Yamada \n" "Language-Team: Japanese \n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Gtranslator 2.91.6\n" #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" -msgstr "kexec-tools で再起動処理を行いますか?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" +msgstr "kexec-tools で再起動処理を行いますか (sysvinit のみ)?" #. Type: boolean #. Description diff -Nru kexec-tools-2.0.10/debian/po/nl.po kexec-tools-2.0.16/debian/po/nl.po --- kexec-tools-2.0.10/debian/po/nl.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/nl.po 2018-02-23 15:05:01.000000000 +0000 @@ -2,25 +2,28 @@ # Copyright (C) 2011 THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the kexec-tools package. # Jeroen Schot , 2011. +# Frans Spiesschaert , 2016. # msgid "" msgstr "" "Project-Id-Version: kexec-tools 1:2.0.2-3\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" -"PO-Revision-Date: 2011-08-30 10:41+0200\n" -"Last-Translator: Jeroen Schot \n" -"Language-Team: Debian l10n Dutch \n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" +"PO-Revision-Date: 2016-04-01 18:25+0200\n" +"Last-Translator: Frans Spiesschaert \n" +"Language-Team: Debian Dutch l10n Team \n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Gtranslator 2.91.6\n" #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" -msgstr "Moet kexec-tools het herstarten afhandelen?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" +msgstr "Moet kexec-tools het herstarten afhandelen (enkel met sysvinit)?" #. Type: boolean #. Description diff -Nru kexec-tools-2.0.10/debian/po/pt_BR.po kexec-tools-2.0.16/debian/po/pt_BR.po --- kexec-tools-2.0.10/debian/po/pt_BR.po 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/pt_BR.po 2018-02-23 15:05:01.000000000 +0000 @@ -0,0 +1,55 @@ +# Debconf translations for kexec-tools. +# Copyright (C) 2016 THE kexec-tools'S COPYRIGHT HOLDER +# This file is distributed under the same license as the kexec-tools package. +# Adriano Rafael Gomes , 2016-2017. +# +msgid "" +msgstr "" +"Project-Id-Version: kexec-tools 1:2.0.12-1\n" +"Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" +"PO-Revision-Date: 2017-01-11 15:34-0200\n" +"Last-Translator: Adriano Rafael Gomes \n" +"Language-Team: Brazilian Portuguese \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Type: boolean +#. Description +#: ../kexec-tools.templates:2001 +msgid "Should kexec-tools handle reboots (sysvinit only)?" +msgstr "" +"O kexec-tools deve controlar as reinicializações (somente para sysvinit)?" + +#. Type: boolean +#. Description +#: ../kexec-tools.templates:2001 +msgid "" +"If you choose this option, a system reboot will trigger a restart into a " +"kernel loaded by kexec instead of going through the full system boot loader " +"process." +msgstr "" +"Se você escolher essa opção, uma reinicialização do sistema provocará um " +"reinício em um kernel carregado pelo kexec, ao invés de passar por todo o " +"processo do carregador de inicialização do sistema." + +#. Type: boolean +#. Description +#: ../kexec-tools.templates:3001 +msgid "Read GRUB configuration file to load the kernel?" +msgstr "Ler o arquivo de configuração do GRUB para carregar o kernel?" + +#. Type: boolean +#. Description +#: ../kexec-tools.templates:3001 +msgid "" +"If you choose this option, kexec will read the GRUB configuration file to " +"determine which kernel and options to load for kexec reboot, as opposed to " +"what is in /etc/default/kexec." +msgstr "" +"Se você escolher essa opção, o kexec lerá o arquivo de configuração do GRUB " +"para determinar qual kernel e quais opções carregar para a reinicialização " +"via kexec, em oposição ao que estiver em /etc/default/kexec." diff -Nru kexec-tools-2.0.10/debian/po/pt.po kexec-tools-2.0.16/debian/po/pt.po --- kexec-tools-2.0.10/debian/po/pt.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/pt.po 2018-02-23 15:05:01.000000000 +0000 @@ -2,27 +2,29 @@ # Copyright (C) 2008, 2011 # This file is distributed under the same license as the kexec-tools package. # Ricardo Silva , 2008. -# Rui Branco , 2011. +# Rui Branco , 2011, 2017. # msgid "" msgstr "" -"Project-Id-Version: kexec-tools 1:2.0.2-3\n" +"Project-Id-Version: kexec-tools_1-2.0.14-1_pt\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" -"PO-Revision-Date: 2011-09-08 00:27+0100\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" +"PO-Revision-Date: 2017-03-14 12:08+0000\n" "Last-Translator: Rui Branco \n" "Language-Team: Portuguese \n" "Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1)\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Gtranslator 2.91.7\n" #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" -msgstr "Usar o kexec-tools para reiniciar o computador?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" +msgstr "" +"Deve o kexec-tools gerir as reiniciações do computador (apenas sysvinit)?" #. Type: boolean #. Description diff -Nru kexec-tools-2.0.10/debian/po/ru.po kexec-tools-2.0.16/debian/po/ru.po --- kexec-tools-2.0.10/debian/po/ru.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/ru.po 2018-02-23 15:05:01.000000000 +0000 @@ -4,27 +4,30 @@ # # Yuri Kozlov , 2008. # Yuri Kozlov , 2011. +# Lev Lamberov , 2017. msgid "" msgstr "" "Project-Id-Version: kexec-tools 1:2.0.2-3\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" -"PO-Revision-Date: 2011-08-27 08:21+0400\n" -"Last-Translator: Yuri Kozlov \n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" +"PO-Revision-Date: 2017-12-09 15:28+0500\n" +"Last-Translator: Lev Lamberov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Lokalize 1.0\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"X-Generator: Poedit 2.0.4\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" -msgstr "Использовать kexec-tools для обработки команды на перезагрузку?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" +msgstr "" +"Использовать kexec-tools для обработки команды на перезагрузку (только для " +"sysvinit)?" #. Type: boolean #. Description diff -Nru kexec-tools-2.0.10/debian/po/sk.po kexec-tools-2.0.16/debian/po/sk.po --- kexec-tools-2.0.10/debian/po/sk.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/sk.po 2018-02-23 15:05:01.000000000 +0000 @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: kexec-tools 1:2.0.2-3\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" "PO-Revision-Date: 2011-08-25 21:13+0200\n" "Last-Translator: Slavko \n" "Language-Team: Slovak \n" @@ -22,7 +22,9 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" +#, fuzzy +#| msgid "Should kexec-tools handle reboots?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" msgstr "Majú reštarty obsluhovať nástroje kexec?" #. Type: boolean diff -Nru kexec-tools-2.0.10/debian/po/sv.po kexec-tools-2.0.16/debian/po/sv.po --- kexec-tools-2.0.10/debian/po/sv.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/sv.po 2018-02-23 15:05:01.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: kexec-tools\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" "PO-Revision-Date: 2011-09-01 22:40+0100\n" "Last-Translator: Martin Bagge / brother \n" "Language-Team: swedish \n" @@ -22,7 +22,9 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" +#, fuzzy +#| msgid "Should kexec-tools handle reboots?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" msgstr "Ska kexec-tools hantera omstarter?" #. Type: boolean diff -Nru kexec-tools-2.0.10/debian/po/templates.pot kexec-tools-2.0.16/debian/po/templates.pot --- kexec-tools-2.0.10/debian/po/templates.pot 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/templates.pot 2018-02-23 15:05:01.000000000 +0000 @@ -1,14 +1,14 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. +# This file is distributed under the same license as the kexec-tools package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: kexec-tools\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -20,7 +20,7 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" msgstr "" #. Type: boolean diff -Nru kexec-tools-2.0.10/debian/po/tr.po kexec-tools-2.0.16/debian/po/tr.po --- kexec-tools-2.0.10/debian/po/tr.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/tr.po 2018-02-23 15:05:01.000000000 +0000 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: kexec-tools 1%3a2.0.7-1\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" "PO-Revision-Date: 2014-08-01 17:02+0200\n" "Last-Translator: Mert Dirik \n" "Language-Team: Debian L10n Turkish \n" @@ -20,7 +20,9 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" +#, fuzzy +#| msgid "Should kexec-tools handle reboots?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" msgstr "kexec-tools yeniden başlatma işlerini idare etsin mi?" #. Type: boolean diff -Nru kexec-tools-2.0.10/debian/po/vi.po kexec-tools-2.0.16/debian/po/vi.po --- kexec-tools-2.0.10/debian/po/vi.po 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/po/vi.po 2018-02-23 15:05:01.000000000 +0000 @@ -6,7 +6,7 @@ msgstr "" "Project-Id-Version: kexec-tools 20080324-1\n" "Report-Msgid-Bugs-To: kexec-tools@packages.debian.org\n" -"POT-Creation-Date: 2011-08-25 18:55+0200\n" +"POT-Creation-Date: 2016-03-22 17:16-0600\n" "PO-Revision-Date: 2008-04-28 16:06+0930\n" "Last-Translator: Clytie Siddall \n" "Language-Team: Vietnamese \n" @@ -20,7 +20,9 @@ #. Type: boolean #. Description #: ../kexec-tools.templates:2001 -msgid "Should kexec-tools handle reboots?" +#, fuzzy +#| msgid "Should kexec-tools handle reboots?" +msgid "Should kexec-tools handle reboots (sysvinit only)?" msgstr "kexec-tools nên quản lý việc khởi động lại không?" #. Type: boolean diff -Nru kexec-tools-2.0.10/debian/rules kexec-tools-2.0.16/debian/rules --- kexec-tools-2.0.10/debian/rules 2018-04-11 22:06:58.000000000 +0000 +++ kexec-tools-2.0.16/debian/rules 2018-02-20 22:19:47.000000000 +0000 @@ -9,26 +9,21 @@ #export DH_VERBOSE=1 +BUILD_DATE = $(shell dpkg-parsechangelog -S Date | LC_ALL=C date -u +'%d %B %Y' -f -) +export BUILD_DATE + ifneq (,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS)))) NJOBS := -j $(subst parallel=,,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS)))) endif CFLAGS = -Wall -g -ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) - CFLAGS += -O0 -else - CFLAGS += -O2 -endif - -DEB_HOST_ARCH := $(shell dpkg-architecture -qDEB_HOST_ARCH) - configure: configure-stamp configure-stamp: dh_testdir # Add here commands to configure the package. dh_autoreconf - CPPFLAGS="$(shell dpkg-buildflags --get CPPFLAGS)" CFLAGS="$(shell dpkg-buildflags --get CFLAGS)" LDFLAGS="$(shell dpkg-buildflags --get LDFLAGS)" ./configure --prefix=/usr --sbindir=/sbin --mandir=/usr/share/man --datadir=/usr/share + CPPFLAGS="$(shell dpkg-buildflags --get CPPFLAGS)" CFLAGS="$(shell dpkg-buildflags --get CFLAGS)" LDFLAGS="$(shell dpkg-buildflags --get LDFLAGS)" dh_auto_configure -- --prefix=/usr --sbindir=/sbin --mandir=/usr/share/man --datadir=/usr/share touch configure-stamp @@ -67,14 +62,6 @@ # Add here commands to install the package into debian/tmp. $(MAKE) install DESTDIR=$(CURDIR)/debian/kexec-tools -ifneq (,$(filter $(DEB_HOST_ARCH),i386 amd64 powerpc ppc64 ppc64el ia64 arm64)) - [ ! -f debian/kexec-tools.grub.$(DEB_HOST_ARCH) ] || \ - install -m644 debian/kexec-tools.grub.$(DEB_HOST_ARCH) \ - debian/kexec-tools/etc/default/grub.d/kexec-tools.cfg - [ -f debian/kexec-tools.grub.$(DEB_HOST_ARCH) ] || \ - install -m644 debian/kexec-tools.grub \ - debian/kexec-tools/etc/default/grub.d/kexec-tools.cfg -endif ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) [ ! -f $(CURDIR)/debian/kexec-tools/usr/lib/kexec-tools-testing/kexec_test.static ] || strip $(CURDIR)/debian/kexec-tools/usr/lib/kexec-tools-testing/kexec_test.static endif diff -Nru kexec-tools-2.0.10/debian/watch kexec-tools-2.0.16/debian/watch --- kexec-tools-2.0.10/debian/watch 2016-03-25 15:55:53.000000000 +0000 +++ kexec-tools-2.0.16/debian/watch 2018-02-20 22:19:47.000000000 +0000 @@ -1,2 +1,4 @@ version=3 -http://kernel.org/pub/linux/utils/kernel/kexec/kexec-tools-(.*)\.(?:tar\.xz|txz|tar\.bz2|tbz2|tar\.gz|tgz) +opts=uversionmangle=s/-(rc\d*)$/~$1/ \ +http://kernel.org/pub/linux/utils/kernel/kexec/ \ +(?:|.*/)kexec-tools(?:[_\-]v?|)(\d[^\s/]*)\.(?:tar\.xz|txz|tar\.bz2|tbz2|tar\.gz|tgz) diff -Nru kexec-tools-2.0.10/include/config.h kexec-tools-2.0.16/include/config.h --- kexec-tools-2.0.10/include/config.h 2015-06-25 10:09:59.000000000 +0000 +++ kexec-tools-2.0.16/include/config.h 2017-11-20 09:17:12.000000000 +0000 @@ -7,6 +7,9 @@ /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 +/* The kexec_status call is available */ +/* #undef HAVE_KEXEC_CMD_STATUS */ + /* Define to 1 if you have the `lzma' library (-llzma). */ /* #undef HAVE_LIBLZMA */ @@ -14,7 +17,7 @@ /* #undef HAVE_LIBXENCTRL */ /* Define to 1 if you have the `z' library (-lz). */ -#define HAVE_LIBZ 1 +/* #undef HAVE_LIBZ */ /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 @@ -43,14 +46,11 @@ /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "" -/* Define to the release date of this package */ -#define PACKAGE_DATE "25 June 2015" - /* Define to the full name of this package. */ #define PACKAGE_NAME "kexec-tools" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "kexec-tools 2.0.10" +#define PACKAGE_STRING "kexec-tools 2.0.16" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "kexec-tools" @@ -59,7 +59,7 @@ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "2.0.10" +#define PACKAGE_VERSION "2.0.16" /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 diff -Nru kexec-tools-2.0.10/include/config.h.in kexec-tools-2.0.16/include/config.h.in --- kexec-tools-2.0.10/include/config.h.in 2015-02-25 04:38:46.000000000 +0000 +++ kexec-tools-2.0.16/include/config.h.in 2017-11-01 08:10:18.000000000 +0000 @@ -6,6 +6,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* The kexec_status call is available */ +#undef HAVE_KEXEC_CMD_STATUS + /* Define to 1 if you have the `lzma' library (-llzma). */ #undef HAVE_LIBLZMA @@ -42,9 +45,6 @@ /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT -/* Define to the release date of this package */ -#undef PACKAGE_DATE - /* Define to the full name of this package. */ #undef PACKAGE_NAME diff -Nru kexec-tools-2.0.10/include/image.h kexec-tools-2.0.16/include/image.h --- kexec-tools-2.0.10/include/image.h 2013-11-19 01:05:49.000000000 +0000 +++ kexec-tools-2.0.16/include/image.h 2017-03-13 09:00:45.000000000 +0000 @@ -79,6 +79,13 @@ #define IH_ARCH_BLACKFIN 16 /* Blackfin */ #define IH_ARCH_AVR32 17 /* AVR32 */ #define IH_ARCH_ST200 18 /* STMicroelectronics ST200 */ +#define IH_ARCH_SANDBOX 19 /* Sandbox architecture (test only) */ +#define IH_ARCH_NDS32 20 /* ANDES Technology - NDS32 */ +#define IH_ARCH_OPENRISC 21 /* OpenRISC 1000 */ +#define IH_ARCH_ARM64 22 /* ARM64 */ +#define IH_ARCH_ARC 23 /* Synopsys DesignWare ARC */ +#define IH_ARCH_X86_64 24 /* AMD x86_64, Intel and Via */ +#define IH_ARCH_XTENSA 25 /* Xtensa */ /* * Image Types diff -Nru kexec-tools-2.0.10/include/kexec-uImage.h kexec-tools-2.0.16/include/kexec-uImage.h --- kexec-tools-2.0.10/include/kexec-uImage.h 2013-11-19 01:05:49.000000000 +0000 +++ kexec-tools-2.0.16/include/kexec-uImage.h 2017-03-13 09:01:36.000000000 +0000 @@ -2,14 +2,14 @@ #define __KEXEC_UIMAGE_H__ struct Image_info { - const unsigned char *buf; + const char *buf; off_t len; unsigned int base; unsigned int ep; }; -int uImage_probe(const unsigned char *buf, off_t len, unsigned int arch); -int uImage_probe_kernel(const unsigned char *buf, off_t len, unsigned int arch); -int uImage_probe_ramdisk(const unsigned char *buf, off_t len, unsigned int arch); -int uImage_load(const unsigned char *buf, off_t len, struct Image_info *info); +int uImage_probe(const char *buf, off_t len, unsigned int arch); +int uImage_probe_kernel(const char *buf, off_t len, unsigned int arch); +int uImage_probe_ramdisk(const char *buf, off_t len, unsigned int arch); +int uImage_load(const char *buf, off_t len, struct Image_info *info); #endif diff -Nru kexec-tools-2.0.10/include/x86/x86-linux.h kexec-tools-2.0.16/include/x86/x86-linux.h --- kexec-tools-2.0.10/include/x86/x86-linux.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/include/x86/x86-linux.h 2016-12-09 09:42:06.000000000 +0000 @@ -21,6 +21,8 @@ #define E820_RESERVED 2 #define E820_ACPI 3 /* usable as RAM once ACPI tables have been read */ #define E820_NVS 4 +#define E820_PMEM 7 +#define E820_PRAM 12 } __attribute__((packed)); #endif diff -Nru kexec-tools-2.0.10/kdump/kdump.c kexec-tools-2.0.16/kdump/kdump.c --- kexec-tools-2.0.10/kdump/kdump.c 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kdump/kdump.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/arm/crashdump-arm.c kexec-tools-2.0.16/kexec/arch/arm/crashdump-arm.c --- kexec-tools-2.0.10/kexec/arch/arm/crashdump-arm.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/crashdump-arm.c 2017-05-22 11:33:20.000000000 +0000 @@ -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,42 +71,12 @@ .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 */ -static unsigned long long get_kernel_stext_sym(void) -{ - const char *kallsyms = "/proc/kallsyms"; - const char *stext = "_stext"; - char sym[128]; - char line[128]; - FILE *fp; - unsigned long long vaddr; - char type; - - 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) - continue; - if (strcmp(sym, stext) == 0) { - dbgprintf("kernel symbol %s vaddr = %16llx\n", stext, vaddr); - return vaddr; - } - } - - fprintf(stderr, "Cannot get kernel %s symbol address\n", stext); - return 0; -} - static int get_kernel_page_offset(struct kexec_info *info, struct crash_elf_info *elf_info) { - unsigned long long stext_sym_addr = get_kernel_stext_sym(); + unsigned long long stext_sym_addr = get_kernel_sym("_stext"); if (stext_sym_addr == 0) { if (user_page_offset != (-1ULL)) { elf_info->page_offset = user_page_offset; @@ -117,96 +98,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 +112,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 +212,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 +254,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 +287,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 +304,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 +315,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 +323,60 @@ return 0; } +/** + * 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) +{ + 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; +} + +/** + * 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) { - uint64_t start, end; + kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); - if (parse_iomem_single("Crash kernel\n", &start, &end) == 0) - return start != end; + return crash_kernel_mem.start != crash_kernel_mem.end; +} - return 0; +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) +{ + return parse_iomem_single("Crash kernel\n", start, end); } diff -Nru kexec-tools-2.0.10/kexec/arch/arm/crashdump-arm.h kexec-tools-2.0.16/kexec/arch/arm/crashdump-arm.h --- kexec-tools-2.0.10/kexec/arch/arm/crashdump-arm.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/crashdump-arm.h 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/arm/include/arch/options.h kexec-tools-2.0.16/kexec/arch/arm/include/arch/options.h --- kexec-tools-2.0.10/kexec/arch/arm/include/arch/options.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/include/arch/options.h 2016-12-09 09:42:06.000000000 +0000 @@ -1,7 +1,8 @@ #ifndef KEXEC_ARCH_ARM_OPTIONS_H #define KEXEC_ARCH_ARM_OPTIONS_H -#define OPT_ARCH_MAX (OPT_MAX+0) +#define OPT_DT_NO_OLD_ROOT (OPT_MAX+0) +#define OPT_ARCH_MAX (OPT_MAX+1) #define OPT_APPEND 'a' #define OPT_RAMDISK 'r' @@ -15,6 +16,7 @@ */ #define KEXEC_ARCH_OPTIONS \ KEXEC_OPTIONS \ + { "dt-no-old-root", 0, 0, OPT_DT_NO_OLD_ROOT }, \ #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" diff -Nru kexec-tools-2.0.10/kexec/arch/arm/iomem.h kexec-tools-2.0.16/kexec/arch/arm/iomem.h --- kexec-tools-2.0.10/kexec/arch/arm/iomem.h 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/iomem.h 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,9 @@ +#ifndef IOMEM_H +#define IOMEM_H + +#define SYSTEM_RAM "System RAM\n" +#define SYSTEM_RAM_BOOT "System RAM (boot alias)\n" +#define CRASH_KERNEL "Crash kernel\n" +#define CRASH_KERNEL_BOOT "Crash kernel (boot alias)\n" + +#endif diff -Nru kexec-tools-2.0.10/kexec/arch/arm/kexec-arm.c kexec-tools-2.0.16/kexec/arch/arm/kexec-arm.c --- kexec-tools-2.0.10/kexec/arch/arm/kexec-arm.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/kexec-arm.c 2017-03-14 09:23:02.000000000 +0000 @@ -12,10 +12,13 @@ #include #include #include +#include #include "../../kexec.h" #include "../../kexec-syscall.h" #include "kexec-arm.h" #include +#include "../../fs2dt.h" +#include "iomem.h" #define MAX_MEMORY_RANGES 64 #define MAX_LINE 160 @@ -44,14 +47,14 @@ int count; if (memory_ranges >= MAX_MEMORY_RANGES) break; - count = sscanf(line, "%Lx-%Lx : %n", + count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed); 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) { @@ -69,6 +72,9 @@ fclose(fp); *range = memory_range; *ranges = memory_ranges; + + dbgprint_mem_range("MEMORY RANGES", *range, *ranges); + return 0; } @@ -89,11 +95,37 @@ " including the .bss section, as reported\n" " by 'arm-linux-size vmlinux'. If not\n" " specified, this value is implicitly set\n" - " to the compressed images size * 4.\n"); + " to the compressed images size * 4.\n" + " --dt-no-old-root\n" + " do not reuse old kernel root= param.\n" + " while creating flatten device tree.\n"); } int arch_process_options(int argc, char **argv) { + /* We look for all options so getopt_long doesn't start reordering + * argv[] before file_type[n].load() gets a look in. + */ + static const struct option options[] = { + KEXEC_ALL_OPTIONS + { 0, 0, NULL, 0 }, + }; + static const char short_options[] = KEXEC_ALL_OPT_STR; + int opt; + + opterr = 0; /* Don't complain about unrecognized options here */ + while((opt = getopt_long(argc, argv, short_options, options, 0)) != -1) { + switch(opt) { + case OPT_DT_NO_OLD_ROOT: + dt_no_old_root = 1; + break; + default: + break; + } + } + /* Reset getopt for the next pass; called in other source modules */ + opterr = 1; + optind = 1; return 0; } @@ -110,3 +142,9 @@ void arch_update_purgatory(struct kexec_info *UNUSED(info)) { } + +/* return 1 if /sys/firmware/fdt exists, otherwise return 0 */ +int have_sysfs_fdt(void) +{ + return !access(SYSFS_FDT, F_OK); +} diff -Nru kexec-tools-2.0.10/kexec/arch/arm/kexec-arm.h kexec-tools-2.0.16/kexec/arch/arm/kexec-arm.h --- kexec-tools-2.0.10/kexec/arch/arm/kexec-arm.h 2013-11-19 01:05:49.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/kexec-arm.h 2016-12-09 09:42:06.000000000 +0000 @@ -3,6 +3,7 @@ #include +#define SYSFS_FDT "/sys/firmware/fdt" #define BOOT_BLOCK_VERSION 17 #define BOOT_BLOCK_LAST_COMP_VERSION 16 @@ -16,5 +17,6 @@ int uImage_arm_probe(const char *buf, off_t len); int uImage_arm_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info); +extern int have_sysfs_fdt(void); #endif /* KEXEC_ARM_H */ diff -Nru kexec-tools-2.0.10/kexec/arch/arm/kexec-elf-rel-arm.c kexec-tools-2.0.16/kexec/arch/arm/kexec-elf-rel-arm.c --- kexec-tools-2.0.10/kexec/arch/arm/kexec-elf-rel-arm.c 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/kexec-elf-rel-arm.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/arm/kexec-zImage-arm.c kexec-tools-2.0.16/kexec/arch/arm/kexec-zImage-arm.c --- kexec-tools-2.0.10/kexec/arch/arm/kexec-zImage-arm.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/kexec-zImage-arm.c 2017-11-01 08:09:46.000000000 +0000 @@ -20,13 +20,48 @@ #include "kexec-arm.h" #include "../../fs2dt.h" #include "crashdump-arm.h" +#include "iomem.h" #define BOOT_PARAMS_SIZE 1536 -off_t initrd_base = 0, initrd_size = 0; +off_t initrd_base, initrd_size; 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; + uint32_t endian; + + /* Extension to the data passed to the boot agent. The offset + * points at a tagged table following a similar format to the + * ATAGs. + */ + uint32_t magic2; +#define ZIMAGE_MAGIC2 (0x45454545) + uint32_t extension_tag_offset; +}; + +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; @@ -88,6 +123,17 @@ #define byte_size(t) ((t)->hdr.size << 2) #define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type) + 3) >> 2) +struct zimage_tag { + struct tag_header hdr; + union { +#define ZIMAGE_TAG_KRNL_SIZE cpu_to_le32(0x5a534c4b) + struct zimage_krnl_size { + uint32_t size_ptr; + uint32_t bss_size; + } krnl_size; + } u; +}; + int zImage_arm_probe(const char *UNUSED(buf), off_t UNUSED(len)) { /* @@ -139,17 +185,47 @@ return (struct tag *) buf; } +static +int create_mem32_tag(struct tag_mem32 *tag_mem32) +{ + const char fn[]= "/proc/device-tree/memory/reg"; + uint32_t tmp[2]; + FILE *fp; + + fp = fopen(fn, "r"); + if (!fp) { + fprintf(stderr, "Cannot open %s: %m\n", fn); + return -1; + } + + if (fread(tmp, sizeof(tmp[0]), 2, fp) != 2) { + fprintf(stderr, "Short read %s\n", fn); + fclose(fp); + return -1; + } + + if (ferror(fp)) { + fprintf(stderr, "Cannot read %s: %m\n", fn); + fclose(fp); + return -1; + } + + /* atags_mem32 has base/size fields reversed! */ + tag_mem32->size = be32_to_cpu(tmp[1]); + tag_mem32->start = be32_to_cpu(tmp[0]); + + fclose(fp); + return 0; +} static int atag_arm_load(struct kexec_info *info, unsigned long base, - const char *command_line, off_t command_line_len, - const char *initrd, off_t initrd_len, off_t initrd_off) + const char *command_line, off_t command_line_len, const char *initrd) { struct tag *saved_tags = atag_read_tags(); char *buf; off_t len; struct tag *params; - uint32_t *initrd_start = NULL; buf = xmalloc(getpagesize()); if (!buf) { @@ -182,13 +258,19 @@ params->hdr.size = 2; params->hdr.tag = ATAG_CORE; params = tag_next(params); + + if (!create_mem32_tag(¶ms->u.mem)) { + params->hdr.size = 4; + params->hdr.tag = ATAG_MEM; + params = tag_next(params); + } } if (initrd) { params->hdr.size = tag_size(tag_initrd); params->hdr.tag = ATAG_INITRD2; - initrd_start = ¶ms->u.initrd.start; - params->u.initrd.size = initrd_len; + params->u.initrd.start = initrd_base; + params->u.initrd.size = initrd_size; params = tag_next(params); } @@ -208,19 +290,12 @@ add_segment(info, buf, len, base, len); - if (initrd) { - *initrd_start = locate_hole(info, initrd_len, getpagesize(), - initrd_off, ULONG_MAX, INT_MAX); - if (*initrd_start == ULONG_MAX) - return -1; - add_segment(info, initrd, initrd_len, *initrd_start, initrd_len); - } - 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; @@ -235,14 +310,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) { @@ -283,14 +358,16 @@ int zImage_arm_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info) { - unsigned long base; + unsigned long page_size = getpagesize(); + 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; @@ -358,6 +435,14 @@ return -1; } + if (!use_atags && !dtb_file) { + int f; + + f = have_sysfs_fdt(); + if (f) + dtb_file = SYSFS_FDT; + } + if (command_line) { command_line_len = strlen(command_line) + 1; if (command_line_len > COMMAND_LINE_SIZE) @@ -369,6 +454,112 @@ if (dtb_file) dtb_buf = slurp_file(dtb_file, &dtb_length); + if (len > sizeof(struct zimage_header)) { + 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; + } + + /* Do we have an extension table? */ + if (hdr->magic2 == ZIMAGE_MAGIC2 && !kexec_arm_image_size) { + uint32_t offset = hdr->extension_tag_offset; + uint32_t max = len - sizeof(struct tag_header); + struct zimage_tag *tag; + + dbgprintf("zImage has tags\n"); + + for (offset = hdr->extension_tag_offset; + (tag = (void *)(buf + offset)) != NULL && + offset < max && byte_size(tag) && + offset + byte_size(tag) < len; + offset += byte_size(tag)) { + dbgprintf(" offset 0x%08x tag 0x%08x size %u\n", + offset, tag->hdr.tag, byte_size(tag)); + if (tag->hdr.tag == ZIMAGE_TAG_KRNL_SIZE) { + uint32_t *p = (void *)buf + + tag->u.krnl_size.size_ptr; + + kexec_arm_image_size = + get_unaligned(p) + + tag->u.krnl_size.bss_size; + } + } + + dbgprintf("kernel image size: 0x%08x\n", + kexec_arm_image_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 the user didn't specify the size of the image, assume the + * maximum kernel compression ratio is 4. Note that we must + * include space for the compressed image here as well. + */ + if (!kexec_arm_image_size) + kexec_arm_image_size = len * 5; + /* * If we are loading a dump capture kernel, we need to update kernel * command line and also add some additional segments. @@ -400,12 +591,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 { @@ -416,15 +608,30 @@ if (base == ULONG_MAX) return -1; - 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()); - } 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()); + kernel_base = base + extra_size; + + /* + * Calculate the minimum address of the initrd, which must be + * above the memory used by the zImage while it runs. This + * needs to be page-size aligned. + */ + initrd_base = kernel_base + _ALIGN(kexec_arm_image_size, page_size); + + if (ramdisk_buf) { + /* + * Find a hole to place the initrd. The crash kernel use + * fixed address, so no check is ok. + */ + if (!(info->kexec_flags & KEXEC_ON_CRASH)) { + initrd_base = locate_hole(info, initrd_size, page_size, + initrd_base, + ULONG_MAX, INT_MAX); + if (initrd_base == ULONG_MAX) + return -1; + } + + add_segment(info, ramdisk_buf, initrd_size, initrd_base, + initrd_size); } if (use_atags) { @@ -433,7 +640,7 @@ */ if (atag_arm_load(info, base + atag_offset, command_line, command_line_len, - ramdisk_buf, initrd_size, initrd_base) == -1) + ramdisk_buf) == -1) return -1; } else { /* @@ -450,7 +657,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; @@ -463,62 +670,50 @@ } /* - * Search in memory to make sure there is enough memory - * to hold initrd and dtb. - * - * Even if no initrd is used, this check is still - * required for dtb. - * - * Crash kernel use fixed address, no check is ok. + * Add the initrd parameters to the dtb */ - if ((info->kexec_flags & KEXEC_ON_CRASH) == 0) { - unsigned long page_size = getpagesize(); - /* - * DTB size may be increase a little - * when setup initrd size. Add a full page - * for it is enough. - */ - unsigned long hole_size = _ALIGN_UP(initrd_size, page_size) + - _ALIGN(dtb_length + page_size, page_size); - unsigned long initrd_base_new = locate_hole(info, - hole_size, page_size, - initrd_base, ULONG_MAX, INT_MAX); - if (base == ULONG_MAX) - return -1; - initrd_base = initrd_base_new; - } - - if (ramdisk) { - add_segment(info, ramdisk_buf, initrd_size, - initrd_base, initrd_size); - + if (ramdisk_buf) { unsigned long start, end; + 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; } - /* Stick the dtb at the end of the initrd and page - * align it. + /* + * The dtb must also be placed above the memory used by + * the zImage. We don't care about its position wrt the + * ramdisk, but we might as well place it after the initrd. + * We leave a buffer page between the initrd and the dtb. */ - dtb_offset = initrd_base + initrd_size + getpagesize(); - dtb_offset = _ALIGN_DOWN(dtb_offset, getpagesize()); + dtb_offset = initrd_base + initrd_size + page_size; + dtb_offset = _ALIGN_DOWN(dtb_offset, page_size); + + /* + * Find a hole to place the dtb above the initrd. + * Crash kernel use fixed address, no check is ok. + */ + if (!(info->kexec_flags & KEXEC_ON_CRASH)) { + dtb_offset = locate_hole(info, dtb_length, page_size, + dtb_offset, ULONG_MAX, INT_MAX); + if (dtb_offset == ULONG_MAX) + return -1; + } - add_segment(info, dtb_buf, dtb_length, - dtb_offset, dtb_length); + add_segment(info, dtb_buf, dtb_length, 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 -Nru kexec-tools-2.0.10/kexec/arch/arm/Makefile kexec-tools-2.0.16/kexec/arch/arm/Makefile --- kexec-tools-2.0.10/kexec/arch/arm/Makefile 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/Makefile 2016-12-20 08:28:23.000000000 +0000 @@ -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,11 +20,15 @@ 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 arm_PHYS_TO_VIRT = kexec/arch/arm/phys_to_virt.c dist += kexec/arch/arm/Makefile $(arm_KEXEC_SRCS) $(arm_PHYS_TO_VIRT) \ - kexec/arch/arm/crashdump-arm.h kexec/arch/arm/kexec-arm.h \ + kexec/arch/arm/iomem.h kexec/arch/arm/phys_to_virt.h \ + kexec/arch/arm/crashdump-arm.h kexec/arch/arm/kexec-arm.h \ kexec/arch/arm/include/arch/options.h diff -Nru kexec-tools-2.0.10/kexec/arch/arm/phys_to_virt.c kexec-tools-2.0.16/kexec/arch/arm/phys_to_virt.c --- kexec-tools-2.0.10/kexec/arch/arm/phys_to_virt.c 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/phys_to_virt.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/arm/phys_to_virt.h kexec-tools-2.0.16/kexec/arch/arm/phys_to_virt.h --- kexec-tools-2.0.10/kexec/arch/arm/phys_to_virt.h 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm/phys_to_virt.h 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,8 @@ +#ifndef PHYS_TO_VIRT_H +#define PHYS_TO_VIRT_H + +#include + +extern uint64_t phys_offset; + +#endif diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/crashdump-arm64.c kexec-tools-2.0.16/kexec/arch/arm64/crashdump-arm64.c --- kexec-tools-2.0.10/kexec/arch/arm64/crashdump-arm64.c 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/crashdump-arm64.c 2017-05-22 11:36:15.000000000 +0000 @@ -0,0 +1,250 @@ +/* + * ARM64 crashdump. + * partly derived from arm implementation + * + * Copyright (c) 2014-2017 Linaro Limited + * Author: AKASHI Takahiro + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define _GNU_SOURCE + +#include +#include + +#include "kexec.h" +#include "crashdump.h" +#include "crashdump-arm64.h" +#include "iomem.h" +#include "kexec-arm64.h" +#include "kexec-elf.h" +#include "mem_regions.h" + +/* memory ranges on crashed kernel */ +static struct memory_range system_memory_ranges[CRASH_MAX_MEMORY_RANGES]; +static struct memory_ranges system_memory_rgns = { + .size = 0, + .max_size = CRASH_MAX_MEMORY_RANGES, + .ranges = system_memory_ranges, +}; + +/* memory range reserved for crashkernel */ +struct memory_range crash_reserved_mem; +struct memory_ranges usablemem_rgns = { + .size = 0, + .max_size = 1, + .ranges = &crash_reserved_mem, +}; + +struct memory_range elfcorehdr_mem; + +static struct crash_elf_info elf_info = { + .class = ELFCLASS64, +#if (__BYTE_ORDER == __LITTLE_ENDIAN) + .data = ELFDATA2LSB, +#else + .data = ELFDATA2MSB, +#endif + .machine = EM_AARCH64, +}; + +/* + * Note: The returned value is correct only if !CONFIG_RANDOMIZE_BASE. + */ +static uint64_t get_kernel_page_offset(void) +{ + int i; + + if (elf_info.kern_vaddr_start == UINT64_MAX) + return UINT64_MAX; + + /* Current max virtual memory range is 48-bits. */ + for (i = 48; i > 0; i--) + if (!(elf_info.kern_vaddr_start & (1UL << i))) + break; + + if (i <= 0) + return UINT64_MAX; + else + return UINT64_MAX << i; +} + +/* + * iomem_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, respectively, system_memory_ranges and crash_reserved_mem. + */ + +static int iomem_range_callback(void *UNUSED(data), int UNUSED(nr), + char *str, unsigned long long base, + unsigned long long length) +{ + if (strncmp(str, CRASH_KERNEL, strlen(CRASH_KERNEL)) == 0) + return mem_regions_add(&usablemem_rgns, + base, length, RANGE_RAM); + else if (strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM)) == 0) + return mem_regions_add(&system_memory_rgns, + base, length, RANGE_RAM); + else if (strncmp(str, KERNEL_CODE, strlen(KERNEL_CODE)) == 0) + elf_info.kern_paddr_start = base; + else if (strncmp(str, KERNEL_DATA, strlen(KERNEL_DATA)) == 0) + elf_info.kern_size = base + length - elf_info.kern_paddr_start; + + return 0; +} + +int is_crashkernel_mem_reserved(void) +{ + if (!usablemem_rgns.size) + kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); + + return crash_reserved_mem.start != crash_reserved_mem.end; +} + +/* + * crash_get_memory_ranges() - read system physical memory + * + * Function reads through system physical memory and stores found memory + * regions in system_memory_ranges. + * Regions are sorted in ascending order. + * + * Returns 0 in case of success and a negative value otherwise. + */ +static int crash_get_memory_ranges(void) +{ + /* + * First read all memory regions that can be considered as + * system memory including the crash area. + */ + if (!usablemem_rgns.size) + kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); + + /* allow only a single region for crash dump kernel */ + if (usablemem_rgns.size != 1) + return -EINVAL; + + dbgprint_mem_range("Reserved memory range", &crash_reserved_mem, 1); + + if (mem_regions_exclude(&system_memory_rgns, &crash_reserved_mem)) { + fprintf(stderr, + "Error: Number of crash memory ranges excedeed the max limit\n"); + return -ENOMEM; + } + + /* + * Make sure that the memory regions are sorted. + */ + mem_regions_sort(&system_memory_rgns); + + dbgprint_mem_range("Coredump memory ranges", + system_memory_rgns.ranges, system_memory_rgns.size); + + /* + * For additional kernel code/data segment. + * kern_paddr_start/kern_size are determined in iomem_range_callback + */ + elf_info.kern_vaddr_start = get_kernel_sym("_text"); + if (!elf_info.kern_vaddr_start) + elf_info.kern_vaddr_start = UINT64_MAX; + + return 0; +} + +/* + * load_crashdump_segments() - load the elf core header + * @info: kexec info structure + * + * This function creates and loads an additional segment of elf core header + : which is used to construct /proc/vmcore on crash dump kernel. + * + * Return 0 in case of success and -1 in case of error. + */ + +int load_crashdump_segments(struct kexec_info *info) +{ + unsigned long elfcorehdr; + unsigned long bufsz; + void *buf; + int err; + + /* + * First fetch all the memory (RAM) ranges that we are going to + * pass to the crash dump kernel during panic. + */ + + err = crash_get_memory_ranges(); + + if (err) + return EFAILED; + + elf_info.page_offset = get_kernel_page_offset(); + dbgprintf("%s: page_offset: %016llx\n", __func__, + elf_info.page_offset); + + err = crash_create_elf64_headers(info, &elf_info, + system_memory_rgns.ranges, system_memory_rgns.size, + &buf, &bufsz, ELF_CORE_HEADER_ALIGN); + + if (err) + return EFAILED; + + elfcorehdr = add_buffer_phys_virt(info, buf, bufsz, bufsz, 0, + crash_reserved_mem.start, crash_reserved_mem.end, + -1, 0); + + elfcorehdr_mem.start = elfcorehdr; + elfcorehdr_mem.end = elfcorehdr + bufsz - 1; + + dbgprintf("%s: elfcorehdr 0x%llx-0x%llx\n", __func__, + elfcorehdr_mem.start, elfcorehdr_mem.end); + + return 0; +} + +/* + * e_entry and p_paddr are actually in virtual address space. + * Those values will be translated to physcal addresses by using + * virt_to_phys() in add_segment(). + * So let's fix up those values for later use so the memory base + * (arm64_mm.phys_offset) will be correctly replaced with + * crash_reserved_mem.start. + */ +void fixup_elf_addrs(struct mem_ehdr *ehdr) +{ + struct mem_phdr *phdr; + int i; + + ehdr->e_entry += - arm64_mem.phys_offset + crash_reserved_mem.start; + + for (i = 0; i < ehdr->e_phnum; i++) { + phdr = &ehdr->e_phdr[i]; + if (phdr->p_type != PT_LOAD) + continue; + phdr->p_paddr += + (-arm64_mem.phys_offset + crash_reserved_mem.start); + } +} + +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) +{ + if (!usablemem_rgns.size) + kexec_iomem_for_each_line(NULL, iomem_range_callback, NULL); + + if (!crash_reserved_mem.end) + return -1; + + *start = crash_reserved_mem.start; + *end = crash_reserved_mem.end; + + return 0; +} diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/crashdump-arm64.h kexec-tools-2.0.16/kexec/arch/arm64/crashdump-arm64.h --- kexec-tools-2.0.10/kexec/arch/arm64/crashdump-arm64.h 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/crashdump-arm64.h 2017-05-22 11:36:15.000000000 +0000 @@ -0,0 +1,26 @@ +/* + * ARM64 crashdump. + * + * Copyright (c) 2014-2017 Linaro Limited + * Author: AKASHI Takahiro + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef CRASHDUMP_ARM64_H +#define CRASHDUMP_ARM64_H + +#include "kexec.h" + +#define CRASH_MAX_MEMORY_RANGES 32 + +extern struct memory_ranges usablemem_rgns; +extern struct memory_range crash_reserved_mem; +extern struct memory_range elfcorehdr_mem; + +extern int load_crashdump_segments(struct kexec_info *info); +extern void fixup_elf_addrs(struct mem_ehdr *ehdr); + +#endif /* CRASHDUMP_ARM64_H */ diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/image-header.h kexec-tools-2.0.16/kexec/arch/arm64/image-header.h --- kexec-tools-2.0.10/kexec/arch/arm64/image-header.h 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/image-header.h 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,146 @@ +/* + * ARM64 binary image header. + */ + +#if !defined(__ARM64_IMAGE_HEADER_H) +#define __ARM64_IMAGE_HEADER_H + +#include +#include + +/** + * struct arm64_image_header - arm64 kernel image header. + * + * @pe_sig: Optional PE format 'MZ' signature. + * @branch_code: Reserved for instructions to branch to stext. + * @text_offset: The image load offset in LSB byte order. + * @image_size: An estimated size of the memory image size in LSB byte order. + * @flags: Bit flags in LSB byte order: + * Bit 0: Image byte order: 1=MSB. + * Bit 1-2: Kernel page size: 1=4K, 2=16K, 3=64K. + * Bit 3: Image placement: 0=low. + * @reserved_1: Reserved. + * @magic: Magic number, "ARM\x64". + * @pe_header: Optional offset to a PE format header. + **/ + +struct arm64_image_header { + uint8_t pe_sig[2]; + uint16_t branch_code[3]; + uint64_t text_offset; + uint64_t image_size; + uint64_t flags; + uint64_t reserved_1[3]; + uint8_t magic[4]; + uint32_t pe_header; +}; + +static const uint8_t arm64_image_magic[4] = {'A', 'R', 'M', 0x64U}; +static const uint8_t arm64_image_pe_sig[2] = {'M', 'Z'}; +static const uint64_t arm64_image_flag_be = (1UL << 0); +static const uint64_t arm64_image_flag_page_size = (3UL << 1); +static const uint64_t arm64_image_flag_placement = (1UL << 3); + +/** + * enum arm64_header_page_size + */ + +enum arm64_header_page_size { + arm64_header_page_size_invalid = 0, + arm64_header_page_size_4k, + arm64_header_page_size_16k, + arm64_header_page_size_64k +}; + +/** + * arm64_header_check_magic - Helper to check the arm64 image header. + * + * Returns non-zero if header is OK. + */ + +static inline int arm64_header_check_magic(const struct arm64_image_header *h) +{ + if (!h) + return 0; + + return (h->magic[0] == arm64_image_magic[0] + && h->magic[1] == arm64_image_magic[1] + && h->magic[2] == arm64_image_magic[2] + && h->magic[3] == arm64_image_magic[3]); +} + +/** + * arm64_header_check_pe_sig - Helper to check the arm64 image header. + * + * Returns non-zero if 'MZ' signature is found. + */ + +static inline int arm64_header_check_pe_sig(const struct arm64_image_header *h) +{ + if (!h) + return 0; + + return (h->pe_sig[0] == arm64_image_pe_sig[0] + && h->pe_sig[1] == arm64_image_pe_sig[1]); +} + +/** + * arm64_header_check_msb - Helper to check the arm64 image header. + * + * Returns non-zero if the image was built as big endian. + */ + +static inline int arm64_header_check_msb(const struct arm64_image_header *h) +{ + if (!h) + return 0; + + return (le64toh(h->flags) & arm64_image_flag_be) >> 0; +} + +/** + * arm64_header_page_size + */ + +static inline enum arm64_header_page_size arm64_header_page_size( + const struct arm64_image_header *h) +{ + if (!h) + return 0; + + return (le64toh(h->flags) & arm64_image_flag_page_size) >> 1; +} + +/** + * arm64_header_placement + * + * Returns non-zero if the image has no physical placement restrictions. + */ + +static inline int arm64_header_placement(const struct arm64_image_header *h) +{ + if (!h) + return 0; + + return (le64toh(h->flags) & arm64_image_flag_placement) >> 3; +} + +static inline uint64_t arm64_header_text_offset( + const struct arm64_image_header *h) +{ + if (!h) + return 0; + + return le64toh(h->text_offset); +} + +static inline uint64_t arm64_header_image_size( + const struct arm64_image_header *h) +{ + if (!h) + return 0; + + return le64toh(h->image_size); +} + +#endif diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/include/arch/options.h kexec-tools-2.0.16/kexec/arch/arm64/include/arch/options.h --- kexec-tools-2.0.10/kexec/arch/arm64/include/arch/options.h 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/include/arch/options.h 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,39 @@ +#if !defined(KEXEC_ARCH_ARM64_OPTIONS_H) +#define KEXEC_ARCH_ARM64_OPTIONS_H + +#define OPT_APPEND ((OPT_MAX)+0) +#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 KEXEC_ARCH_OPTIONS \ + KEXEC_OPTIONS \ + { "append", 1, NULL, OPT_APPEND }, \ + { "command-line", 1, NULL, OPT_APPEND }, \ + { "dtb", 1, NULL, OPT_DTB }, \ + { "initrd", 1, NULL, OPT_INITRD }, \ + { "ramdisk", 1, NULL, OPT_INITRD }, \ + { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \ + +#define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */ +#define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS +#define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR + +static const char arm64_opts_usage[] __attribute__ ((unused)) = +" --append=STRING Set the kernel command line to STRING.\n" +" --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" +" --ramdisk=FILE Use FILE as the kernel initial ramdisk.\n" +" --reuse-cmdline Use kernel command line from running system.\n"; + +struct arm64_opts { + const char *command_line; + const char *dtb; + const char *initrd; +}; + +extern struct arm64_opts arm64_opts; + +#endif diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/iomem.h kexec-tools-2.0.16/kexec/arch/arm64/iomem.h --- kexec-tools-2.0.10/kexec/arch/arm64/iomem.h 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/iomem.h 2017-05-22 11:35:46.000000000 +0000 @@ -0,0 +1,10 @@ +#ifndef IOMEM_H +#define IOMEM_H + +#define SYSTEM_RAM "System RAM\n" +#define KERNEL_CODE "Kernel code\n" +#define KERNEL_DATA "Kernel data\n" +#define CRASH_KERNEL "Crash kernel\n" +#define IOMEM_RESERVED "reserved\n" + +#endif diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.c kexec-tools-2.0.16/kexec/arch/arm64/kexec-arm64.c --- kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.c 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/kexec-arm64.c 2017-05-22 11:36:39.000000000 +0000 @@ -0,0 +1,875 @@ +/* + * ARM64 kexec. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kexec.h" +#include "kexec-arm64.h" +#include "crashdump.h" +#include "crashdump-arm64.h" +#include "dt-ops.h" +#include "fs2dt.h" +#include "iomem.h" +#include "kexec-syscall.h" +#include "arch/options.h" + +#define ROOT_NODE_ADDR_CELLS_DEFAULT 1 +#define ROOT_NODE_SIZE_CELLS_DEFAULT 1 + +#define PROP_ADDR_CELLS "#address-cells" +#define PROP_SIZE_CELLS "#size-cells" +#define PROP_ELFCOREHDR "linux,elfcorehdr" +#define PROP_USABLE_MEM_RANGE "linux,usable-memory-range" + +/* Global varables the core kexec routines expect. */ + +unsigned char reuse_initrd; + +off_t initrd_base; +off_t initrd_size; + +const struct arch_map_entry arches[] = { + { "aarch64", KEXEC_ARCH_ARM64 }, + { "aarch64_be", KEXEC_ARCH_ARM64 }, + { NULL, 0 }, +}; + +struct file_type file_type[] = { + {"vmlinux", elf_arm64_probe, elf_arm64_load, elf_arm64_usage}, + {"Image", image_arm64_probe, image_arm64_load, image_arm64_usage}, + {"uImage", uImage_arm64_probe, uImage_arm64_load, uImage_arm64_usage}, +}; + +int file_types = sizeof(file_type) / sizeof(file_type[0]); + +/* arm64 global varables. */ + +struct arm64_opts arm64_opts; +struct arm64_mem arm64_mem = { + .phys_offset = arm64_mem_ngv, + .vp_offset = arm64_mem_ngv, +}; + +uint64_t get_phys_offset(void) +{ + assert(arm64_mem.phys_offset != arm64_mem_ngv); + return arm64_mem.phys_offset; +} + +uint64_t get_vp_offset(void) +{ + assert(arm64_mem.vp_offset != arm64_mem_ngv); + return arm64_mem.vp_offset; +} + +/** + * arm64_process_image_header - Process the arm64 image header. + * + * Make a guess that KERNEL_IMAGE_SIZE will be enough for older kernels. + */ + +int arm64_process_image_header(const struct arm64_image_header *h) +{ +#if !defined(KERNEL_IMAGE_SIZE) +# define KERNEL_IMAGE_SIZE MiB(16) +#endif + + if (!arm64_header_check_magic(h)) + return EFAILED; + + if (h->image_size) { + arm64_mem.text_offset = arm64_header_text_offset(h); + arm64_mem.image_size = arm64_header_image_size(h); + } else { + /* For 3.16 and older kernels. */ + arm64_mem.text_offset = 0x80000; + arm64_mem.image_size = KERNEL_IMAGE_SIZE; + fprintf(stderr, + "kexec: %s: Warning: Kernel image size set to %lu MiB.\n" + " Please verify compatability with lodaed kernel.\n", + __func__, KERNEL_IMAGE_SIZE / 1024UL / 1024UL); + } + + return 0; +} + +void arch_usage(void) +{ + printf(arm64_opts_usage); +} + +int arch_process_options(int argc, char **argv) +{ + static const char short_options[] = KEXEC_OPT_STR ""; + static const struct option options[] = { + KEXEC_ARCH_OPTIONS + { 0 } + }; + int opt; + char *cmdline = NULL; + const char *append = NULL; + + for (opt = 0; opt != -1; ) { + opt = getopt_long(argc, argv, short_options, options, 0); + + switch (opt) { + case OPT_APPEND: + append = optarg; + break; + case OPT_REUSE_CMDLINE: + cmdline = get_command_line(); + break; + case OPT_DTB: + arm64_opts.dtb = optarg; + break; + case OPT_INITRD: + arm64_opts.initrd = optarg; + break; + default: + break; /* Ignore core and unknown options. */ + } + } + + arm64_opts.command_line = concat_cmdline(cmdline, append); + + dbgprintf("%s:%d: command_line: %s\n", __func__, __LINE__, + arm64_opts.command_line); + dbgprintf("%s:%d: initrd: %s\n", __func__, __LINE__, + arm64_opts.initrd); + dbgprintf("%s:%d: dtb: %s\n", __func__, __LINE__, arm64_opts.dtb); + + return 0; +} + +/** + * struct dtb - Info about a binary device tree. + * + * @buf: Device tree data. + * @size: Device tree data size. + * @name: Shorthand name of this dtb for messages. + * @path: Filesystem path. + */ + +struct dtb { + char *buf; + off_t size; + const char *name; + const char *path; +}; + +/** + * dump_reservemap - Dump the dtb's reservemap. + */ + +static void dump_reservemap(const struct dtb *dtb) +{ + int i; + + for (i = 0; ; i++) { + uint64_t address; + uint64_t size; + + fdt_get_mem_rsv(dtb->buf, i, &address, &size); + + if (!size) + break; + + dbgprintf("%s: %s {%" PRIx64 ", %" PRIx64 "}\n", __func__, + dtb->name, address, size); + } +} + +/** + * set_bootargs - Set the dtb's bootargs. + */ + +static int set_bootargs(struct dtb *dtb, const char *command_line) +{ + int result; + + if (!command_line || !command_line[0]) + return 0; + + result = dtb_set_bootargs(&dtb->buf, &dtb->size, command_line); + + if (result) { + fprintf(stderr, + "kexec: Set device tree bootargs failed.\n"); + return EFAILED; + } + + return 0; +} + +/** + * read_proc_dtb - Read /proc/device-tree. + */ + +static int read_proc_dtb(struct dtb *dtb) +{ + int result; + struct stat s; + static const char path[] = "/proc/device-tree"; + + result = stat(path, &s); + + if (result) { + dbgprintf("%s: %s\n", __func__, strerror(errno)); + return EFAILED; + } + + dtb->path = path; + create_flatten_tree((char **)&dtb->buf, &dtb->size, NULL); + + return 0; +} + +/** + * read_sys_dtb - Read /sys/firmware/fdt. + */ + +static int read_sys_dtb(struct dtb *dtb) +{ + int result; + struct stat s; + static const char path[] = "/sys/firmware/fdt"; + + result = stat(path, &s); + + if (result) { + dbgprintf("%s: %s\n", __func__, strerror(errno)); + return EFAILED; + } + + dtb->path = path; + dtb->buf = slurp_file(path, &dtb->size); + + return 0; +} + +/** + * read_1st_dtb - Read the 1st stage kernel's dtb. + */ + +static int read_1st_dtb(struct dtb *dtb) +{ + int result; + + dtb->name = "dtb_sys"; + result = read_sys_dtb(dtb); + + if (!result) + goto on_success; + + dtb->name = "dtb_proc"; + result = read_proc_dtb(dtb); + + if (!result) + goto on_success; + + dbgprintf("%s: not found\n", __func__); + return EFAILED; + +on_success: + dbgprintf("%s: found %s\n", __func__, dtb->path); + return 0; +} + +static int get_cells_size(void *fdt, uint32_t *address_cells, + uint32_t *size_cells) +{ + int nodeoffset; + const uint32_t *prop = NULL; + int prop_len; + + /* default values */ + *address_cells = ROOT_NODE_ADDR_CELLS_DEFAULT; + *size_cells = ROOT_NODE_SIZE_CELLS_DEFAULT; + + /* under root node */ + nodeoffset = fdt_path_offset(fdt, "/"); + if (nodeoffset < 0) + goto on_error; + + prop = fdt_getprop(fdt, nodeoffset, PROP_ADDR_CELLS, &prop_len); + if (prop) { + if (prop_len == sizeof(*prop)) + *address_cells = fdt32_to_cpu(*prop); + else + goto on_error; + } + + prop = fdt_getprop(fdt, nodeoffset, PROP_SIZE_CELLS, &prop_len); + if (prop) { + if (prop_len == sizeof(*prop)) + *size_cells = fdt32_to_cpu(*prop); + else + goto on_error; + } + + dbgprintf("%s: #address-cells:%d #size-cells:%d\n", __func__, + *address_cells, *size_cells); + return 0; + +on_error: + return EFAILED; +} + +static bool cells_size_fitted(uint32_t address_cells, uint32_t size_cells, + struct memory_range *range) +{ + dbgprintf("%s: %llx-%llx\n", __func__, range->start, range->end); + + /* if *_cells >= 2, cells can hold 64-bit values anyway */ + if ((address_cells == 1) && (range->start >= (1ULL << 32))) + return false; + + if ((size_cells == 1) && + ((range->end - range->start + 1) >= (1ULL << 32))) + return false; + + return true; +} + +static void fill_property(void *buf, uint64_t val, uint32_t cells) +{ + uint32_t val32; + int i; + + if (cells == 1) { + val32 = cpu_to_fdt32((uint32_t)val); + memcpy(buf, &val32, sizeof(uint32_t)); + } else { + for (i = 0; + i < (cells * sizeof(uint32_t) - sizeof(uint64_t)); i++) + *(char *)buf++ = 0; + + val = cpu_to_fdt64(val); + memcpy(buf, &val, sizeof(uint64_t)); + } +} + +static int fdt_setprop_range(void *fdt, int nodeoffset, + const char *name, struct memory_range *range, + uint32_t address_cells, uint32_t size_cells) +{ + void *buf, *prop; + size_t buf_size; + int result; + + buf_size = (address_cells + size_cells) * sizeof(uint32_t); + prop = buf = xmalloc(buf_size); + + fill_property(prop, range->start, address_cells); + prop += address_cells * sizeof(uint32_t); + + fill_property(prop, range->end - range->start + 1, size_cells); + prop += size_cells * sizeof(uint32_t); + + result = fdt_setprop(fdt, nodeoffset, name, buf, buf_size); + + free(buf); + + return result; +} + +/** + * setup_2nd_dtb - Setup the 2nd stage kernel's dtb. + */ + +static int setup_2nd_dtb(struct dtb *dtb, char *command_line, int on_crash) +{ + uint32_t address_cells, size_cells; + int range_len; + int nodeoffset; + char *new_buf = NULL; + int new_size; + int result; + + result = fdt_check_header(dtb->buf); + + if (result) { + fprintf(stderr, "kexec: Invalid 2nd device tree.\n"); + return EFAILED; + } + + result = set_bootargs(dtb, command_line); + + if (on_crash) { + /* determine #address-cells and #size-cells */ + result = get_cells_size(dtb->buf, &address_cells, &size_cells); + if (result) { + fprintf(stderr, + "kexec: cannot determine cells-size.\n"); + result = -EINVAL; + goto on_error; + } + + if (!cells_size_fitted(address_cells, size_cells, + &elfcorehdr_mem)) { + fprintf(stderr, + "kexec: elfcorehdr doesn't fit cells-size.\n"); + result = -EINVAL; + goto on_error; + } + + if (!cells_size_fitted(address_cells, size_cells, + &crash_reserved_mem)) { + fprintf(stderr, + "kexec: usable memory range doesn't fit cells-size.\n"); + result = -EINVAL; + goto on_error; + } + + /* duplicate dt blob */ + range_len = sizeof(uint32_t) * (address_cells + size_cells); + new_size = fdt_totalsize(dtb->buf) + + fdt_prop_len(PROP_ELFCOREHDR, range_len) + + fdt_prop_len(PROP_USABLE_MEM_RANGE, range_len); + + new_buf = xmalloc(new_size); + result = fdt_open_into(dtb->buf, new_buf, new_size); + if (result) { + dbgprintf("%s: fdt_open_into failed: %s\n", __func__, + fdt_strerror(result)); + result = -ENOSPC; + goto on_error; + } + + /* add linux,elfcorehdr */ + nodeoffset = fdt_path_offset(new_buf, "/chosen"); + result = fdt_setprop_range(new_buf, nodeoffset, + PROP_ELFCOREHDR, &elfcorehdr_mem, + address_cells, size_cells); + if (result) { + dbgprintf("%s: fdt_setprop failed: %s\n", __func__, + fdt_strerror(result)); + result = -EINVAL; + goto on_error; + } + + /* add linux,usable-memory-range */ + nodeoffset = fdt_path_offset(new_buf, "/chosen"); + result = fdt_setprop_range(new_buf, nodeoffset, + PROP_USABLE_MEM_RANGE, &crash_reserved_mem, + address_cells, size_cells); + if (result) { + dbgprintf("%s: fdt_setprop failed: %s\n", __func__, + fdt_strerror(result)); + result = -EINVAL; + goto on_error; + } + + fdt_pack(new_buf); + dtb->buf = new_buf; + dtb->size = fdt_totalsize(new_buf); + } + + dump_reservemap(dtb); + + + return result; + +on_error: + fprintf(stderr, "kexec: %s failed.\n", __func__); + if (new_buf) + free(new_buf); + + return result; +} + +unsigned long arm64_locate_kernel_segment(struct kexec_info *info) +{ + unsigned long hole; + + if (info->kexec_flags & KEXEC_ON_CRASH) { + unsigned long hole_end; + + hole = (crash_reserved_mem.start < mem_min ? + mem_min : crash_reserved_mem.start); + hole = _ALIGN_UP(hole, MiB(2)); + hole_end = hole + arm64_mem.text_offset + arm64_mem.image_size; + + if ((hole_end > mem_max) || + (hole_end > crash_reserved_mem.end)) { + dbgprintf("%s: Crash kernel out of range\n", __func__); + hole = ULONG_MAX; + } + } else { + hole = locate_hole(info, + arm64_mem.text_offset + arm64_mem.image_size, + MiB(2), 0, ULONG_MAX, 1); + + if (hole == ULONG_MAX) + dbgprintf("%s: locate_hole failed\n", __func__); + } + + return hole; +} + +/** + * arm64_load_other_segments - Prepare the dtb, initrd and purgatory segments. + */ + +int arm64_load_other_segments(struct kexec_info *info, + unsigned long image_base) +{ + int result; + unsigned long dtb_base; + unsigned long hole_min; + unsigned long hole_max; + unsigned long initrd_end; + char *initrd_buf = NULL; + struct dtb dtb; + char command_line[COMMAND_LINE_SIZE] = ""; + + if (arm64_opts.command_line) { + strncpy(command_line, arm64_opts.command_line, + sizeof(command_line)); + command_line[sizeof(command_line) - 1] = 0; + } + + if (arm64_opts.dtb) { + dtb.name = "dtb_user"; + dtb.buf = slurp_file(arm64_opts.dtb, &dtb.size); + } else { + result = read_1st_dtb(&dtb); + + if (result) { + fprintf(stderr, + "kexec: Error: No device tree available.\n"); + return EFAILED; + } + } + + result = setup_2nd_dtb(&dtb, command_line, + info->kexec_flags & KEXEC_ON_CRASH); + + if (result) + return EFAILED; + + /* Put the other segments after the image. */ + + hole_min = image_base + arm64_mem.image_size; + if (info->kexec_flags & KEXEC_ON_CRASH) + hole_max = crash_reserved_mem.end; + else + hole_max = ULONG_MAX; + + if (arm64_opts.initrd) { + initrd_buf = slurp_file(arm64_opts.initrd, &initrd_size); + + if (!initrd_buf) + fprintf(stderr, "kexec: Empty ramdisk file.\n"); + else { + /* Put the initrd after the kernel. */ + + initrd_base = add_buffer_phys_virt(info, initrd_buf, + initrd_size, initrd_size, 0, + hole_min, hole_max, 1, 0); + + initrd_end = initrd_base + initrd_size; + + /* Check limits as specified in booting.txt. + * The kernel may have as little as 32 GB of address space to map + * system memory and both kernel and initrd must be 1GB aligend. + */ + + if (_ALIGN_UP(initrd_end, GiB(1)) - _ALIGN_DOWN(image_base, GiB(1)) > GiB(32)) { + fprintf(stderr, "kexec: Error: image + initrd too big.\n"); + return EFAILED; + } + + dbgprintf("initrd: base %lx, size %lxh (%ld)\n", + initrd_base, initrd_size, initrd_size); + + result = dtb_set_initrd((char **)&dtb.buf, + &dtb.size, initrd_base, + initrd_base + initrd_size); + + if (result) + return EFAILED; + } + } + + /* Check size limit as specified in booting.txt. */ + + if (dtb.size > MiB(2)) { + fprintf(stderr, "kexec: Error: dtb too big.\n"); + return EFAILED; + } + + dtb_base = add_buffer_phys_virt(info, dtb.buf, dtb.size, dtb.size, + 0, hole_min, hole_max, 1, 0); + + /* dtb_base is valid if we got here. */ + + dbgprintf("dtb: base %lx, size %lxh (%ld)\n", dtb_base, dtb.size, + dtb.size); + + elf_rel_build_load(info, &info->rhdr, purgatory, purgatory_size, + hole_min, hole_max, 1, 0); + + info->entry = (void *)elf_rel_get_addr(&info->rhdr, "purgatory_start"); + + elf_rel_set_symbol(&info->rhdr, "arm64_kernel_entry", &image_base, + sizeof(image_base)); + + elf_rel_set_symbol(&info->rhdr, "arm64_dtb_addr", &dtb_base, + sizeof(dtb_base)); + + return 0; +} + +/** + * virt_to_phys - For processing elf file values. + */ + +unsigned long virt_to_phys(unsigned long v) +{ + unsigned long p; + + p = v - get_vp_offset() + get_phys_offset(); + + return p; +} + +/** + * phys_to_virt - For crashdump setup. + */ + +unsigned long phys_to_virt(struct crash_elf_info *elf_info, + unsigned long long p) +{ + unsigned long v; + + v = p - get_phys_offset() + elf_info->page_offset; + + return v; +} + +/** + * add_segment - Use virt_to_phys when loading elf files. + */ + +void add_segment(struct kexec_info *info, const void *buf, size_t bufsz, + unsigned long base, size_t memsz) +{ + add_segment_phys_virt(info, buf, bufsz, base, memsz, 1); +} + +/** + * get_memory_ranges_iomem_cb - Helper for get_memory_ranges_iomem. + */ + +static int get_memory_ranges_iomem_cb(void *data, int nr, char *str, + unsigned long long base, unsigned long long length) +{ + struct memory_range *r; + + if (nr >= KEXEC_SEGMENT_MAX) + return -1; + + r = (struct memory_range *)data + nr; + + if (!strncmp(str, SYSTEM_RAM, strlen(SYSTEM_RAM))) + r->type = RANGE_RAM; + else if (!strncmp(str, IOMEM_RESERVED, strlen(IOMEM_RESERVED))) + r->type = RANGE_RESERVED; + else + return 1; + + r->start = base; + r->end = base + length - 1; + + set_phys_offset(r->start); + + dbgprintf("%s: %016llx - %016llx : %s", __func__, r->start, + r->end, str); + + return 0; +} + +/** + * get_memory_ranges_iomem - Try to get the memory ranges from /proc/iomem. + */ + +static int get_memory_ranges_iomem(struct memory_range *array, + unsigned int *count) +{ + *count = kexec_iomem_for_each_line(NULL, + get_memory_ranges_iomem_cb, array); + + if (!*count) { + dbgprintf("%s: failed: No RAM found.\n", __func__); + return EFAILED; + } + + return 0; +} + +/** + * get_memory_ranges - Try to get the memory ranges some how. + */ + +int get_memory_ranges(struct memory_range **range, int *ranges, + unsigned long kexec_flags) +{ + static struct memory_range array[KEXEC_SEGMENT_MAX]; + unsigned int count; + int result; + + result = get_memory_ranges_iomem(array, &count); + + *range = result ? NULL : array; + *ranges = result ? 0 : count; + + return result; +} + +int arch_compat_trampoline(struct kexec_info *info) +{ + return 0; +} + +int machine_verify_elf_rel(struct mem_ehdr *ehdr) +{ + return (ehdr->e_machine == EM_AARCH64); +} + +void machine_apply_elf_rel(struct mem_ehdr *ehdr, struct mem_sym *UNUSED(sym), + unsigned long r_type, void *ptr, unsigned long address, + unsigned long value) +{ +#if !defined(R_AARCH64_ABS64) +# define R_AARCH64_ABS64 257 +#endif + +#if !defined(R_AARCH64_PREL32) +# define R_AARCH64_PREL32 261 +#endif + +#if !defined(R_AARCH64_LD_PREL_LO19) +# define R_AARCH64_LD_PREL_LO19 273 +#endif + +#if !defined(R_AARCH64_ADR_PREL_LO21) +# define R_AARCH64_ADR_PREL_LO21 274 +#endif + +#if !defined(R_AARCH64_ADR_PREL_PG_HI21) +# define R_AARCH64_ADR_PREL_PG_HI21 275 +#endif + +#if !defined(R_AARCH64_ADD_ABS_LO12_NC) +# define R_AARCH64_ADD_ABS_LO12_NC 277 +#endif + +#if !defined(R_AARCH64_JUMP26) +# define R_AARCH64_JUMP26 282 +#endif + +#if !defined(R_AARCH64_CALL26) +# define R_AARCH64_CALL26 283 +#endif + +#if !defined(R_AARCH64_LDST64_ABS_LO12_NC) +# define R_AARCH64_LDST64_ABS_LO12_NC 286 +#endif + + uint64_t *loc64; + uint32_t *loc32; + uint64_t *location = (uint64_t *)ptr; + uint64_t data = *location; + uint64_t imm; + const char *type = NULL; + + switch(r_type) { + case R_AARCH64_ABS64: + type = "ABS64"; + loc64 = ptr; + *loc64 = cpu_to_elf64(ehdr, elf64_to_cpu(ehdr, *loc64) + value); + break; + case R_AARCH64_PREL32: + type = "PREL32"; + loc32 = ptr; + *loc32 = cpu_to_elf32(ehdr, + elf32_to_cpu(ehdr, *loc32) + value - address); + break; + case R_AARCH64_LD_PREL_LO19: + type = "LD_PREL_LO19"; + loc32 = ptr; + *loc32 = cpu_to_le32(le32_to_cpu(*loc32) + + (((value - address) << 3) & 0xffffe0)); + break; + case R_AARCH64_ADR_PREL_LO21: + if (value & 3) + die("%s: ERROR Unaligned value: %lx\n", __func__, + value); + type = "ADR_PREL_LO21"; + loc32 = ptr; + *loc32 = cpu_to_le32(le32_to_cpu(*loc32) + + (((value - address) << 3) & 0xffffe0)); + break; + case R_AARCH64_ADR_PREL_PG_HI21: + type = "ADR_PREL_PG_HI21"; + imm = ((value & ~0xfff) - (address & ~0xfff)) >> 12; + loc32 = ptr; + *loc32 = cpu_to_le32(le32_to_cpu(*loc32) + + ((imm & 3) << 29) + ((imm & 0x1ffffc) << (5 - 2))); + break; + case R_AARCH64_ADD_ABS_LO12_NC: + type = "ADD_ABS_LO12_NC"; + loc32 = ptr; + *loc32 = cpu_to_le32(le32_to_cpu(*loc32) + + ((value & 0xfff) << 10)); + break; + case R_AARCH64_JUMP26: + type = "JUMP26"; + loc32 = ptr; + *loc32 = cpu_to_le32(le32_to_cpu(*loc32) + + (((value - address) >> 2) & 0x3ffffff)); + break; + case R_AARCH64_CALL26: + type = "CALL26"; + loc32 = ptr; + *loc32 = cpu_to_le32(le32_to_cpu(*loc32) + + (((value - address) >> 2) & 0x3ffffff)); + break; + case R_AARCH64_LDST64_ABS_LO12_NC: + if (value & 7) + die("%s: ERROR Unaligned value: %lx\n", __func__, + value); + type = "LDST64_ABS_LO12_NC"; + loc32 = ptr; + *loc32 = cpu_to_le32(le32_to_cpu(*loc32) + + ((value & 0xff8) << (10 - 3))); + break; + default: + die("%s: ERROR Unknown type: %lu\n", __func__, r_type); + break; + } + + dbgprintf("%s: %s %016lx->%016lx\n", __func__, type, data, *location); +} + +void arch_reuse_initrd(void) +{ + reuse_initrd = 1; +} + +void arch_update_purgatory(struct kexec_info *UNUSED(info)) +{ +} diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.h kexec-tools-2.0.16/kexec/arch/arm64/kexec-arm64.h --- kexec-tools-2.0.10/kexec/arch/arm64/kexec-arm64.h 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/kexec-arm64.h 2017-03-13 09:01:36.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * ARM64 kexec. + */ + +#if !defined(KEXEC_ARM64_H) +#define KEXEC_ARM64_H + +#include +#include + +#include "image-header.h" +#include "kexec.h" + +#define KEXEC_SEGMENT_MAX 64 + +#define BOOT_BLOCK_VERSION 17 +#define BOOT_BLOCK_LAST_COMP_VERSION 16 +#define COMMAND_LINE_SIZE 512 + +#define KiB(x) ((x) * 1024UL) +#define MiB(x) (KiB(x) * 1024UL) +#define GiB(x) (MiB(x) * 1024UL) + +int elf_arm64_probe(const char *kernel_buf, off_t kernel_size); +int elf_arm64_load(int argc, char **argv, const char *kernel_buf, + off_t kernel_size, struct kexec_info *info); +void elf_arm64_usage(void); + +int image_arm64_probe(const char *kernel_buf, off_t kernel_size); +int image_arm64_load(int argc, char **argv, const char *kernel_buf, + off_t kernel_size, struct kexec_info *info); +void image_arm64_usage(void); +int uImage_arm64_probe(const char *buf, off_t len); +int uImage_arm64_load(int argc, char **argv, const char *buf, off_t len, + struct kexec_info *info); +void uImage_arm64_usage(void); + +off_t initrd_base; +off_t initrd_size; + +/** + * struct arm64_mem - Memory layout info. + */ + +struct arm64_mem { + uint64_t phys_offset; + uint64_t text_offset; + uint64_t image_size; + uint64_t vp_offset; +}; + +#define arm64_mem_ngv UINT64_MAX +struct arm64_mem arm64_mem; + +uint64_t get_phys_offset(void); +uint64_t get_vp_offset(void); + +static inline void reset_vp_offset(void) +{ + arm64_mem.vp_offset = arm64_mem_ngv; +} + +static inline void set_phys_offset(uint64_t v) +{ + if (arm64_mem.phys_offset == arm64_mem_ngv + || v < arm64_mem.phys_offset) + arm64_mem.phys_offset = v; +} + +int arm64_process_image_header(const struct arm64_image_header *h); +unsigned long arm64_locate_kernel_segment(struct kexec_info *info); +int arm64_load_other_segments(struct kexec_info *info, + unsigned long image_base); + +#endif diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/kexec-elf-arm64.c kexec-tools-2.0.16/kexec/arch/arm64/kexec-elf-arm64.c --- kexec-tools-2.0.10/kexec/arch/arm64/kexec-elf-arm64.c 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/kexec-elf-arm64.c 2017-05-22 11:36:39.000000000 +0000 @@ -0,0 +1,161 @@ +/* + * ARM64 kexec elf support. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include + +#include "crashdump-arm64.h" +#include "kexec-arm64.h" +#include "kexec-elf.h" +#include "kexec-syscall.h" + +int elf_arm64_probe(const char *kernel_buf, off_t kernel_size) +{ + struct mem_ehdr ehdr; + int result; + + result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0); + + if (result < 0) { + dbgprintf("%s: Not an ELF executable.\n", __func__); + goto on_exit; + } + + if (ehdr.e_machine != EM_AARCH64) { + dbgprintf("%s: Not an AARCH64 ELF executable.\n", __func__); + result = -1; + goto on_exit; + } + + result = 0; +on_exit: + free_elf_info(&ehdr); + return result; +} + +int elf_arm64_load(int argc, char **argv, const char *kernel_buf, + off_t kernel_size, struct kexec_info *info) +{ + const struct arm64_image_header *header = NULL; + unsigned long kernel_segment; + struct mem_ehdr ehdr; + int result; + int i; + + result = build_elf_exec_info(kernel_buf, kernel_size, &ehdr, 0); + + if (result < 0) { + dbgprintf("%s: build_elf_exec_info failed\n", __func__); + goto exit; + } + + /* Find and process the arm64 image header. */ + + for (i = 0; i < ehdr.e_phnum; i++) { + struct mem_phdr *phdr = &ehdr.e_phdr[i]; + unsigned long header_offset; + + if (phdr->p_type != PT_LOAD) + continue; + + /* + * When CONFIG_ARM64_RANDOMIZE_TEXT_OFFSET=y the image header + * could be offset in the elf segment. The linker script sets + * ehdr.e_entry to the start of text. + */ + + header_offset = ehdr.e_entry - phdr->p_vaddr; + + header = (const struct arm64_image_header *)( + kernel_buf + phdr->p_offset + header_offset); + + if (!arm64_process_image_header(header)) { + dbgprintf("%s: e_entry: %016llx\n", __func__, + ehdr.e_entry); + dbgprintf("%s: p_vaddr: %016llx\n", __func__, + phdr->p_vaddr); + dbgprintf("%s: header_offset: %016lx\n", __func__, + header_offset); + + break; + } + } + + if (i == ehdr.e_phnum) { + dbgprintf("%s: Valid arm64 header not found\n", __func__); + result = EFAILED; + goto exit; + } + + kernel_segment = arm64_locate_kernel_segment(info); + + if (kernel_segment == ULONG_MAX) { + dbgprintf("%s: Kernel segment is not allocated\n", __func__); + result = EFAILED; + goto exit; + } + + arm64_mem.vp_offset = _ALIGN_DOWN(ehdr.e_entry, MiB(2)); + if (!(info->kexec_flags & KEXEC_ON_CRASH)) + arm64_mem.vp_offset -= kernel_segment - get_phys_offset(); + + dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment); + dbgprintf("%s: text_offset: %016lx\n", __func__, + arm64_mem.text_offset); + dbgprintf("%s: image_size: %016lx\n", __func__, + arm64_mem.image_size); + dbgprintf("%s: phys_offset: %016lx\n", __func__, + arm64_mem.phys_offset); + dbgprintf("%s: vp_offset: %016lx\n", __func__, + arm64_mem.vp_offset); + dbgprintf("%s: PE format: %s\n", __func__, + (arm64_header_check_pe_sig(header) ? "yes" : "no")); + + /* 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 */ + if (info->kexec_flags & KEXEC_ON_CRASH) + /* + * offset addresses in elf header in order to load + * vmlinux (elf_exec) into crash kernel's memory + */ + fixup_elf_addrs(&ehdr); + + result = elf_exec_load(&ehdr, info); + + if (result) { + dbgprintf("%s: elf_exec_load failed\n", __func__); + goto exit; + } + + /* load additional data */ + result = arm64_load_other_segments(info, kernel_segment + + arm64_mem.text_offset); + +exit: + reset_vp_offset(); + free_elf_info(&ehdr); + if (result) + fprintf(stderr, "kexec: Bad elf image file, load failed.\n"); + return result; +} + +void elf_arm64_usage(void) +{ + printf( +" An ARM64 ELF image, big or little endian.\n" +" Typically vmlinux or a stripped version of vmlinux.\n\n"); +} diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/kexec-image-arm64.c kexec-tools-2.0.16/kexec/arch/arm64/kexec-image-arm64.c --- kexec-tools-2.0.10/kexec/arch/arm64/kexec-image-arm64.c 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/kexec-image-arm64.c 2017-05-22 11:36:49.000000000 +0000 @@ -0,0 +1,93 @@ +/* + * ARM64 kexec binary image support. + */ + +#define _GNU_SOURCE + +#include "crashdump-arm64.h" +#include "kexec-arm64.h" +#include "kexec-syscall.h" +#include + +int image_arm64_probe(const char *kernel_buf, off_t kernel_size) +{ + const struct arm64_image_header *h; + + if (kernel_size < sizeof(struct arm64_image_header)) { + dbgprintf("%s: No arm64 image header.\n", __func__); + return -1; + } + + h = (const struct arm64_image_header *)(kernel_buf); + + if (!arm64_header_check_magic(h)) { + dbgprintf("%s: Bad arm64 image header.\n", __func__); + return -1; + } + + return 0; +} + +int image_arm64_load(int argc, char **argv, const char *kernel_buf, + off_t kernel_size, struct kexec_info *info) +{ + const struct arm64_image_header *header; + unsigned long kernel_segment; + int result; + + header = (const struct arm64_image_header *)(kernel_buf); + + if (arm64_process_image_header(header)) + return EFAILED; + + kernel_segment = arm64_locate_kernel_segment(info); + + if (kernel_segment == ULONG_MAX) { + dbgprintf("%s: Kernel segment is not allocated\n", __func__); + result = EFAILED; + goto exit; + } + + dbgprintf("%s: kernel_segment: %016lx\n", __func__, kernel_segment); + dbgprintf("%s: text_offset: %016lx\n", __func__, + arm64_mem.text_offset); + dbgprintf("%s: image_size: %016lx\n", __func__, + arm64_mem.image_size); + dbgprintf("%s: phys_offset: %016lx\n", __func__, + arm64_mem.phys_offset); + dbgprintf("%s: vp_offset: %016lx\n", __func__, + arm64_mem.vp_offset); + dbgprintf("%s: PE format: %s\n", __func__, + (arm64_header_check_pe_sig(header) ? "yes" : "no")); + + /* 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_phys_virt(info, kernel_buf, kernel_size, + kernel_segment + arm64_mem.text_offset, + arm64_mem.image_size, 0); + + /* load additional data */ + result = arm64_load_other_segments(info, kernel_segment + + arm64_mem.text_offset); + +exit: + if (result) + fprintf(stderr, "kexec: load failed.\n"); + return result; +} + +void image_arm64_usage(void) +{ + printf( +" An ARM64 binary image, compressed or not, big or little endian.\n" +" Typically an Image, Image.gz or Image.lzma file.\n\n"); +} diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/kexec-uImage-arm64.c kexec-tools-2.0.16/kexec/arch/arm64/kexec-uImage-arm64.c --- kexec-tools-2.0.10/kexec/arch/arm64/kexec-uImage-arm64.c 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/kexec-uImage-arm64.c 2017-03-13 09:01:36.000000000 +0000 @@ -0,0 +1,34 @@ +/* + * uImage support added by David Woodhouse + */ +#include +#include +#include +#include +#include +#include "../../kexec.h" +#include "kexec-arm64.h" + +int uImage_arm64_probe(const char *buf, off_t len) +{ + return uImage_probe_kernel(buf, len, IH_ARCH_ARM64); +} + +int uImage_arm64_load(int argc, char **argv, const char *buf, off_t len, + struct kexec_info *info) +{ + struct Image_info img; + int ret; + + ret = uImage_load(buf, len, &img); + if (ret) + return ret; + + return image_arm64_load(argc, argv, img.buf, img.len, info); +} + +void uImage_arm64_usage(void) +{ + printf( +" An ARM64 U-boot uImage file, compressed or not, big or little endian.\n\n"); +} diff -Nru kexec-tools-2.0.10/kexec/arch/arm64/Makefile kexec-tools-2.0.16/kexec/arch/arm64/Makefile --- kexec-tools-2.0.10/kexec/arch/arm64/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/arm64/Makefile 2017-05-22 11:35:15.000000000 +0000 @@ -0,0 +1,49 @@ + +arm64_FS2DT += kexec/fs2dt.c +arm64_FS2DT_INCLUDE += \ + -include $(srcdir)/kexec/arch/arm64/crashdump-arm64.h \ + -include $(srcdir)/kexec/arch/arm64/kexec-arm64.h + +arm64_DT_OPS += kexec/dt-ops.c + +arm64_MEM_REGIONS = kexec/mem_regions.c + +arm64_CPPFLAGS += -I $(srcdir)/kexec/ + +arm64_KEXEC_SRCS += \ + kexec/arch/arm64/crashdump-arm64.c \ + kexec/arch/arm64/kexec-arm64.c \ + kexec/arch/arm64/kexec-elf-arm64.c \ + kexec/arch/arm64/kexec-uImage-arm64.c \ + kexec/arch/arm64/kexec-image-arm64.c + +arm64_UIMAGE = kexec/kexec-uImage.c + +arm64_ARCH_REUSE_INITRD = +arm64_ADD_SEGMENT = +arm64_VIRT_TO_PHYS = +arm64_PHYS_TO_VIRT = + +dist += $(arm64_KEXEC_SRCS) \ + kexec/arch/arm64/include/arch/options.h \ + kexec/arch/arm64/crashdump-arm64.h \ + kexec/arch/arm64/image-header.h \ + kexec/arch/arm64/iomem.h \ + kexec/arch/arm64/kexec-arm64.h \ + kexec/arch/arm64/Makefile + +ifdef HAVE_LIBFDT + +LIBS += -lfdt + +else + +include $(srcdir)/kexec/libfdt/Makefile.libfdt + +libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) + +arm64_CPPFLAGS += -I$(srcdir)/kexec/libfdt + +arm64_KEXEC_SRCS += $(libfdt_SRCS) + +endif diff -Nru kexec-tools-2.0.10/kexec/arch/cris/kexec-cris.c kexec-tools-2.0.16/kexec/arch/cris/kexec-cris.c --- kexec-tools-2.0.10/kexec/arch/cris/kexec-cris.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/cris/kexec-cris.c 2017-03-02 09:49:55.000000000 +0000 @@ -77,6 +77,12 @@ return 0; } +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) +{ + /* Crash kernel region size is not exposed by the system */ + return -1; +} + unsigned long virt_to_phys(unsigned long addr) { return (addr) & 0x7fffffff; diff -Nru kexec-tools-2.0.10/kexec/arch/cris/kexec-elf-rel-cris.c kexec-tools-2.0.16/kexec/arch/cris/kexec-elf-rel-cris.c --- kexec-tools-2.0.10/kexec/arch/cris/kexec-elf-rel-cris.c 2010-07-29 09:22:16.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/cris/kexec-elf-rel-cris.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/i386/crashdump-x86.c kexec-tools-2.0.16/kexec/arch/i386/crashdump-x86.c --- kexec-tools-2.0.10/kexec/arch/i386/crashdump-x86.c 2015-02-25 04:41:32.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/i386/crashdump-x86.c 2017-05-22 11:33:20.000000000 +0000 @@ -21,6 +21,7 @@ #define _XOPEN_SOURCE 600 #define _BSD_SOURCE +#define _DEFAULT_SOURCE #include #include @@ -101,36 +102,6 @@ return -1; } -/* Retrieve kernel _stext symbol virtual address from /proc/kallsyms */ -static unsigned long long get_kernel_stext_sym(void) -{ - const char *kallsyms = "/proc/kallsyms"; - const char *stext = "_stext"; - char sym[128]; - char line[128]; - FILE *fp; - unsigned long long vaddr; - char type; - - 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) - continue; - if (strcmp(sym, stext) == 0) { - dbgprintf("kernel symbol %s vaddr = %16llx\n", stext, vaddr); - return vaddr; - } - } - - fprintf(stderr, "Cannot get kernel %s symbol address\n", stext); - return 0; -} - /* Retrieve info regarding virtual address kernel has been compiled for and * size of the kernel from /proc/kcore. Current /proc/kcore parsing from * from kexec-tools fails because of malformed elf notes. A kernel patch has @@ -150,6 +121,8 @@ off_t size; uint32_t elf_flags = 0; uint64_t stext_sym; + const unsigned long long pud_mask = ~((1 << 30) - 1); + unsigned long long vaddr, lowest_vaddr = 0; if (elf_info->machine != EM_X86_64) return 0; @@ -179,9 +152,23 @@ end_phdr = &ehdr.e_phdr[ehdr.e_phnum]; + /* Search for the real PAGE_OFFSET when KASLR memory randomization + * is enabled */ + if (get_kernel_sym("page_offset_base") != 0) { + for(phdr = ehdr.e_phdr; phdr != end_phdr; phdr++) { + if (phdr->p_type == PT_LOAD) { + vaddr = phdr->p_vaddr & pud_mask; + if (lowest_vaddr == 0 || lowest_vaddr > vaddr) + lowest_vaddr = vaddr; + } + } + if (lowest_vaddr != 0) + elf_info->page_offset = lowest_vaddr; + } + /* Traverse through the Elf headers and find the region where * _stext symbol is located in. That's where kernel is mapped */ - stext_sym = get_kernel_stext_sym(); + stext_sym = get_kernel_sym("_stext"); for(phdr = ehdr.e_phdr; stext_sym && phdr != end_phdr; phdr++) { if (phdr->p_type == PT_LOAD) { unsigned long long saddr = phdr->p_vaddr; @@ -189,7 +176,7 @@ unsigned long long size; /* Look for kernel text mapping header. */ - if (saddr < stext_sym && eaddr > stext_sym) { + if (saddr <= stext_sym && eaddr > stext_sym) { saddr = _ALIGN_DOWN(saddr, X86_64_KERN_VADDR_ALIGN); elf_info->kern_vaddr_start = saddr; size = eaddr - saddr; @@ -280,12 +267,12 @@ if (memory_ranges >= CRASH_MAX_MEMORY_RANGES) break; - count = sscanf(line, "%Lx-%Lx : %n", + count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed); if (count != 2) continue; str = line + consumed; - dbgprintf("%016Lx-%016Lx : %s", + dbgprintf("%016llx-%016llx : %s", start, end, str); /* Only Dumping memory of type System RAM. */ if (memcmp(str, "System RAM\n", 11) == 0) { @@ -301,6 +288,10 @@ type = RANGE_ACPI; } else if(memcmp(str,"ACPI Non-volatile Storage\n",26) == 0 ) { type = RANGE_ACPI_NVS; + } else if(memcmp(str,"Persistent Memory (legacy)\n",27) == 0 ) { + type = RANGE_PRAM; + } else if(memcmp(str,"Persistent Memory\n",18) == 0 ) { + type = RANGE_PMEM; } else if(memcmp(str,"reserved\n",9) == 0 ) { type = RANGE_RESERVED; } else if (memcmp(str, "GART\n", 5) == 0) { @@ -640,6 +631,8 @@ strcat (str_mmap, "K$"); else if (type == RANGE_ACPI || type == RANGE_ACPI_NVS) strcat (str_mmap, "K#"); + else if (type == RANGE_PRAM) + strcat (str_mmap, "K!"); ultoa(startk, str_tmp); strcat (str_mmap, str_tmp); @@ -674,10 +667,11 @@ endk = (memmap_p[i].end + 1)/1024; type = memmap_p[i].type; - /* Only adding memory regions of RAM and ACPI */ + /* Only adding memory regions of RAM and ACPI and Persistent Mem */ if (type != RANGE_RAM && type != RANGE_ACPI && - type != RANGE_ACPI_NVS) + type != RANGE_ACPI_NVS && + type != RANGE_PRAM) continue; if (type == RANGE_ACPI || type == RANGE_ACPI_NVS) @@ -755,7 +749,7 @@ *addr = x86__pa(vaddr + (cpu * MAX_NOTE_BYTES)); *len = MAX_NOTE_BYTES; - dbgprintf("crash_notes addr = %Lx\n", + dbgprintf("crash_notes addr = %llx\n", (unsigned long long)*addr); fclose(fp); @@ -997,7 +991,9 @@ unsigned long start, end, size, type; if ( !( mem_range[i].type == RANGE_ACPI || mem_range[i].type == RANGE_ACPI_NVS - || mem_range[i].type == RANGE_RESERVED)) + || mem_range[i].type == RANGE_RESERVED + || mem_range[i].type == RANGE_PMEM + || mem_range[i].type == RANGE_PRAM)) continue; start = mem_range[i].start; end = mem_range[i].end; @@ -1017,24 +1013,17 @@ return 0; } -int get_max_crash_kernel_limit(uint64_t *start, uint64_t *end) +/* On x86, the kernel may make a low reservation in addition to the + * normal reservation. However, the kernel refuses to load the panic + * kernel to low memory, so always choose the highest range. + */ +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) { - int i, idx = -1; - unsigned long sz_max = 0, sz; - if (!crash_reserved_mem_nr) return -1; - for (i = crash_reserved_mem_nr - 1; i >= 0; i--) { - sz = crash_reserved_mem[i].end - crash_reserved_mem[i].start +1; - if (sz <= sz_max) - continue; - sz_max = sz; - idx = i; - } - - *start = crash_reserved_mem[idx].start; - *end = crash_reserved_mem[idx].end; + *start = crash_reserved_mem[crash_reserved_mem_nr - 1].start; + *end = crash_reserved_mem[crash_reserved_mem_nr - 1].end; return 0; } diff -Nru kexec-tools-2.0.10/kexec/arch/i386/kexec-elf-rel-x86.c kexec-tools-2.0.16/kexec/arch/i386/kexec-elf-rel-x86.c --- kexec-tools-2.0.10/kexec/arch/i386/kexec-elf-rel-x86.c 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/i386/kexec-elf-rel-x86.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/i386/kexec-elf-x86.c kexec-tools-2.0.16/kexec/arch/i386/kexec-elf-x86.c --- kexec-tools-2.0.10/kexec/arch/i386/kexec-elf-x86.c 2015-02-25 04:40:36.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/i386/kexec-elf-x86.c 2017-03-14 13:38:32.000000000 +0000 @@ -91,7 +91,7 @@ char *command_line = NULL, *modified_cmdline = NULL; const char *append = NULL; char *tmp_cmdline = NULL; - char *error_msg = NULL; + const char *error_msg = NULL; int result; int command_line_len; const char *ramdisk; @@ -296,6 +296,6 @@ free(command_line); free(modified_cmdline); if (error_msg) - die(error_msg); + die("%s", error_msg); return result; } diff -Nru kexec-tools-2.0.10/kexec/arch/i386/kexec-multiboot-x86.c kexec-tools-2.0.16/kexec/arch/i386/kexec-multiboot-x86.c --- kexec-tools-2.0.10/kexec/arch/i386/kexec-multiboot-x86.c 2015-02-11 23:05:08.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/i386/kexec-multiboot-x86.c 2016-12-20 08:28:23.000000000 +0000 @@ -252,7 +252,7 @@ mmap = xmalloc(ranges * sizeof(*mmap)); for (i=0; i mem_upper + 0x100000)) mem_upper = range[i].end - 0x100000; } else { - mmap[i].Type = 0xbad; /* Not RAM */ + mmap[i].Type = 2; /* Not RAM (reserved) */ } } diff -Nru kexec-tools-2.0.10/kexec/arch/i386/kexec-x86-common.c kexec-tools-2.0.16/kexec/arch/i386/kexec-x86-common.c --- kexec-tools-2.0.10/kexec/arch/i386/kexec-x86-common.c 2015-03-20 00:44:41.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/i386/kexec-x86-common.c 2017-03-14 09:23:02.000000000 +0000 @@ -19,6 +19,7 @@ #define _XOPEN_SOURCE 600 #define _BSD_SOURCE +#define _DEFAULT_SOURCE #include #include @@ -43,6 +44,12 @@ #include #endif /* HAVE_LIBXENCTRL */ +/* Used below but not present in (older?) xenctrl.h */ +#ifndef E820_PMEM +#define E820_PMEM 7 +#define E820_PRAM 12 +#endif + static struct memory_range memory_range[MAX_MEMORY_RANGES]; /** @@ -74,7 +81,7 @@ int count; if (memory_ranges >= MAX_MEMORY_RANGES) break; - count = sscanf(line, "%Lx-%Lx : %n", + count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed); if (count != 2) continue; @@ -94,6 +101,12 @@ else if (memcmp(str, "ACPI Non-volatile Storage\n", 26) == 0) { type = RANGE_ACPI_NVS; } + else if (memcmp(str, "Persistent Memory (legacy)\n", 27) == 0) { + type = RANGE_PRAM; + } + else if (memcmp(str, "Persistent Memory\n", 18) == 0) { + type = RANGE_PMEM; + } else { continue; } @@ -149,6 +162,10 @@ return RANGE_ACPI; case E820_NVS: return RANGE_ACPI_NVS; + case E820_PMEM: + return RANGE_PMEM; + case E820_PRAM: + return RANGE_PRAM; case E820_RESERVED: default: return RANGE_RESERVED; @@ -361,9 +378,9 @@ !(kexec_flags & KEXEC_PRESERVE_CONTEXT)) { uint64_t start, end; - ret = get_max_crash_kernel_limit(&start, &end); + ret = get_crash_kernel_load_range(&start, &end); if (ret != 0) { - fprintf(stderr, "get_max_crash_kernel_limit failed.\n"); + fprintf(stderr, "get_crash_kernel_load_range failed.\n"); return -1; } diff -Nru kexec-tools-2.0.10/kexec/arch/i386/kexec-x86.h kexec-tools-2.0.16/kexec/arch/i386/kexec-x86.h --- kexec-tools-2.0.10/kexec/arch/i386/kexec-x86.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/i386/kexec-x86.h 2017-03-24 06:43:00.000000000 +0000 @@ -1,7 +1,7 @@ #ifndef KEXEC_X86_H #define KEXEC_X86_H -#define MAX_MEMORY_RANGES 1024 +#define MAX_MEMORY_RANGES 2048 enum coretype { CORE_TYPE_UNDEF = 0, diff -Nru kexec-tools-2.0.10/kexec/arch/i386/x86-linux-setup.c kexec-tools-2.0.16/kexec/arch/i386/x86-linux-setup.c --- kexec-tools-2.0.10/kexec/arch/i386/x86-linux-setup.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/i386/x86-linux-setup.c 2016-12-09 09:42:06.000000000 +0000 @@ -705,6 +705,12 @@ case RANGE_ACPI_NVS: e820[i].type = E820_NVS; break; + case RANGE_PMEM: + e820[i].type = E820_PMEM; + break; + case RANGE_PRAM: + e820[i].type = E820_PRAM; + break; default: case RANGE_RESERVED: e820[i].type = E820_RESERVED; diff -Nru kexec-tools-2.0.10/kexec/arch/ia64/crashdump-ia64.c kexec-tools-2.0.16/kexec/arch/ia64/crashdump-ia64.c --- kexec-tools-2.0.10/kexec/arch/ia64/crashdump-ia64.c 2013-11-19 01:05:49.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ia64/crashdump-ia64.c 2017-03-02 09:50:05.000000000 +0000 @@ -286,3 +286,8 @@ return parse_iomem_single("Crash kernel\n", &start, &end) == 0 ? (start != end) : 0; } + +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) +{ + return parse_iomem_single("Crash kernel\n", start, end); +} diff -Nru kexec-tools-2.0.10/kexec/arch/ia64/kexec-elf-rel-ia64.c kexec-tools-2.0.16/kexec/arch/ia64/kexec-elf-rel-ia64.c --- kexec-tools-2.0.10/kexec/arch/ia64/kexec-elf-rel-ia64.c 2010-07-29 09:22:16.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ia64/kexec-elf-rel-ia64.c 2017-03-14 09:23:02.000000000 +0000 @@ -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 *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) { @@ -154,6 +155,6 @@ } return; overflow: - die("overflow in relocation type %lu val %Lx\n", + die("overflow in relocation type %lu val %llx\n", r_type, value); } diff -Nru kexec-tools-2.0.10/kexec/arch/m68k/kexec-elf-rel-m68k.c kexec-tools-2.0.16/kexec/arch/m68k/kexec-elf-rel-m68k.c --- kexec-tools-2.0.10/kexec/arch/m68k/kexec-elf-rel-m68k.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/m68k/kexec-elf-rel-m68k.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/m68k/kexec-m68k.c kexec-tools-2.0.16/kexec/arch/m68k/kexec-m68k.c --- kexec-tools-2.0.10/kexec/arch/m68k/kexec-m68k.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/m68k/kexec-m68k.c 2017-03-02 09:50:17.000000000 +0000 @@ -89,6 +89,12 @@ return 0; } +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) +{ + /* Crash kernel region size is not exposed by the system */ + return -1; +} + unsigned long virt_to_phys(unsigned long addr) { return addr + m68k_memoffset; diff -Nru kexec-tools-2.0.10/kexec/arch/mips/crashdump-mips.c kexec-tools-2.0.16/kexec/arch/mips/crashdump-mips.c --- kexec-tools-2.0.10/kexec/arch/mips/crashdump-mips.c 2015-02-11 23:11:44.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/mips/crashdump-mips.c 2017-10-18 05:16:21.000000000 +0000 @@ -39,6 +39,9 @@ * A separate program header is created for backup region */ static struct memory_range crash_memory_range[CRASH_MAX_MEMORY_RANGES]; +/* Not used currently but required by generic fs2dt code */ +struct memory_ranges usablemem_rgns; + /* Memory region reserved for storing panic kernel and other data. */ static struct memory_range crash_reserved_mem; @@ -71,7 +74,10 @@ elf_info->kern_vaddr_start = elf_info->kern_paddr_start | start_offset; - if (parse_iomem_single("Kernel data\n", NULL, &end) == 0) { + /* If "Kernel bss" exists, the kernel ends there, else fall + * through and say that it ends at "Kernel data" */ + if (parse_iomem_single("Kernel bss\n", NULL, &end) == 0 || + parse_iomem_single("Kernel data\n", NULL, &end) == 0) { elf_info->kern_size = end - elf_info->kern_paddr_start; dbgprintf("kernel_vaddr= 0x%llx paddr %llx\n", elf_info->kern_vaddr_start, @@ -170,7 +176,7 @@ int type, consumed, count; if (memory_ranges >= CRASH_MAX_MEMORY_RANGES) break; - count = sscanf(line, "%Lx-%Lx : %n", + count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed); if (count != 2) continue; @@ -198,7 +204,7 @@ memory_ranges++; /* Segregate linearly mapped region. */ - if ((MAXMEM - 1) >= start && (MAXMEM - 1) <= end) { + if (MAXMEM && (MAXMEM - 1) >= start && (MAXMEM - 1) <= end) { crash_memory_range[memory_ranges - 1].end = MAXMEM - 1; /* Add segregated region. */ @@ -288,23 +294,54 @@ return 0; } -#ifdef __mips64 +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define ELFDATALOCAL ELFDATA2LSB +#elif __BYTE_ORDER == __BIG_ENDIAN +# define ELFDATALOCAL ELFDATA2MSB +#else +# error Unknown byte order +#endif + static struct crash_elf_info elf_info64 = { class: ELFCLASS64, - data : ELFDATA2MSB, + data : ELFDATALOCAL, machine : EM_MIPS, page_offset : PAGE_OFFSET, - lowmem_limit : MAXMEM, + lowmem_limit : 0, /* 0 == no limit */ }; -#endif + static struct crash_elf_info elf_info32 = { class: ELFCLASS32, - data : ELFDATA2MSB, + data : ELFDATALOCAL, machine : EM_MIPS, page_offset : PAGE_OFFSET, lowmem_limit : MAXMEM, }; +static int patch_elf_info(void) +{ + const char cpuinfo[] = "/proc/cpuinfo"; + char line[MAX_LINE]; + FILE *fp; + + fp = fopen(cpuinfo, "r"); + if (!fp) { + fprintf(stderr, "Cannot open %s: %s\n", + cpuinfo, strerror(errno)); + return -1; + } + while (fgets(line, sizeof(line), fp) != 0) { + if (strncmp(line, "cpu model", 9) == 0) { + /* OCTEON uses a different page_offset. */ + if (strstr(line, "Octeon")) + elf_info64.page_offset = 0x8000000000000000ULL; + break; + } + } + fclose(fp); + return 0; +} + /* Loads additional segments in case of a panic kernel is being loaded. * One segment for backup region, another segment for storing elf headers * for crash memory image. @@ -321,13 +358,14 @@ struct crash_elf_info *elf_info = &elf_info32; unsigned long start_offset = 0x80000000UL; -#ifdef __mips64 + if (patch_elf_info()) + return -1; + if (arch_options.core_header_type == CORE_TYPE_ELF64) { elf_info = &elf_info64; crash_create = crash_create_elf64_headers; - start_offset = 0xffffffff80000000UL; + start_offset = (unsigned long)0xffffffff80000000UL; } -#endif if (get_kernel_paddr(elf_info)) return -1; @@ -377,3 +415,7 @@ (start != end) : 0; } +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) +{ + return parse_iomem_single("Crash kernel\n", start, end); +} diff -Nru kexec-tools-2.0.10/kexec/arch/mips/crashdump-mips.h kexec-tools-2.0.16/kexec/arch/mips/crashdump-mips.h --- kexec-tools-2.0.10/kexec/arch/mips/crashdump-mips.h 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/mips/crashdump-mips.h 2017-10-16 07:01:17.000000000 +0000 @@ -6,12 +6,13 @@ unsigned long max_addr, unsigned long min_base); #ifdef __mips64 #define PAGE_OFFSET 0xa800000000000000ULL +#define MAXMEM 0 #else #define PAGE_OFFSET 0x80000000 +#define MAXMEM 0x80000000 #endif #define __pa(x) ((unsigned long)(X) & 0x7fffffff) -#define MAXMEM 0x80000000 #define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1) #define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2) diff -Nru kexec-tools-2.0.10/kexec/arch/mips/include/arch/options.h kexec-tools-2.0.16/kexec/arch/mips/include/arch/options.h --- kexec-tools-2.0.10/kexec/arch/mips/include/arch/options.h 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/mips/include/arch/options.h 2016-12-20 08:28:23.000000000 +0000 @@ -3,12 +3,19 @@ #define OPT_ARCH_MAX (OPT_MAX+0) #define OPT_APPEND (OPT_ARCH_MAX+0) +#define OPT_DTB (OPT_ARCH_MAX+1) +#define OPT_RAMDISK (OPT_ARCH_MAX+2) /* Options relevant to the architecture (excluding loader-specific ones), * in this case none: */ #define KEXEC_ARCH_OPTIONS \ KEXEC_OPTIONS \ + {"command-line", 1, 0, OPT_APPEND}, \ + {"append", 1, 0, OPT_APPEND}, \ + {"dtb", 1, 0, OPT_DTB }, \ + {"initrd", 1, 0, OPT_RAMDISK }, + #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" @@ -27,9 +34,7 @@ * recognise -- as they now recognise (if not act upon) all possible options. */ #define KEXEC_ALL_OPTIONS \ - KEXEC_ARCH_OPTIONS \ - {"command-line", 1, 0, OPT_APPEND}, \ - {"append", 1, 0, OPT_APPEND}, + KEXEC_ARCH_OPTIONS #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR diff -Nru kexec-tools-2.0.10/kexec/arch/mips/kexec-elf-mips.c kexec-tools-2.0.16/kexec/arch/mips/kexec-elf-mips.c --- kexec-tools-2.0.10/kexec/arch/mips/kexec-elf-mips.c 2015-02-11 23:10:50.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/mips/kexec-elf-mips.c 2016-12-20 08:28:23.000000000 +0000 @@ -29,13 +29,16 @@ #include "kexec-mips.h" #include "crashdump-mips.h" #include +#include "../../fs2dt.h" +#include "../../dt-ops.h" static const int probe_debug = 0; #define BOOTLOADER "kexec" -#define MAX_COMMAND_LINE 256 #define UPSZ(X) _ALIGN_UP(sizeof(X), 4) -static char cmdline_buf[256] = "kexec "; + +#define CMDLINE_PREFIX "kexec " +static char cmdline_buf[COMMAND_LINE_SIZE] = CMDLINE_PREFIX; int elf_mips_probe(const char *buf, off_t len) { @@ -63,50 +66,22 @@ void elf_mips_usage(void) { - printf(" --command-line=STRING Set the kernel command line to " - "STRING.\n" - " --append=STRING Set the kernel command line to " - "STRING.\n"); } int elf_mips_load(int argc, char **argv, const char *buf, off_t len, struct kexec_info *info) { struct mem_ehdr ehdr; - const char *command_line; - int command_line_len; + int command_line_len = 0; char *crash_cmdline; - int opt; int result; unsigned long cmdline_addr; size_t i; - - /* See options.h if adding any more options. */ - static const struct option options[] = { - KEXEC_ARCH_OPTIONS - {"command-line", 1, 0, OPT_APPEND}, - {"append", 1, 0, OPT_APPEND}, - {0, 0, 0, 0}, - }; - - static const char short_options[] = KEXEC_ARCH_OPT_STR "d"; - - command_line = 0; - while ((opt = getopt_long(argc, argv, short_options, - options, 0)) != -1) { - switch (opt) { - default: - /* Ignore core options */ - if (opt < OPT_ARCH_MAX) { - break; - } - case OPT_APPEND: - command_line = optarg; - break; - } - } - - command_line_len = 0; + off_t dtb_length; + char *dtb_buf; + char *initrd_buf = NULL; + unsigned long long kernel_addr = 0, kernel_size = 0; + unsigned long pagesize = getpagesize(); /* Need to append some command line parameters internally in case of * taking crash dumps. @@ -125,8 +100,11 @@ for (i = 0; i < ehdr.e_phnum; i++) { struct mem_phdr *phdr; phdr = &ehdr.e_phdr[i]; - if (phdr->p_type == PT_LOAD) + if (phdr->p_type == PT_LOAD) { phdr->p_paddr = virt_to_phys(phdr->p_paddr); + kernel_addr = phdr->p_paddr; + kernel_size = phdr->p_memsz; + } } /* Load the Elf data */ @@ -136,8 +114,8 @@ info->entry = (void *)virt_to_phys(ehdr.e_entry); - if (command_line) - command_line_len = strlen(command_line) + 1; + if (arch_options.command_line) + command_line_len = strlen(arch_options.command_line) + 1; if (info->kexec_flags & KEXEC_ON_CRASH) { result = load_crashdump_segments(info, crash_cmdline, @@ -148,8 +126,8 @@ } } - if (command_line) - strncat(cmdline_buf, command_line, command_line_len); + if (arch_options.command_line) + strncat(cmdline_buf, arch_options.command_line, command_line_len); if (crash_cmdline) strncat(cmdline_buf, crash_cmdline, sizeof(crash_cmdline) - @@ -163,10 +141,46 @@ else cmdline_addr = 0; + /* MIPS systems that have been converted to use device tree + * passed through UHI will use commandline in the DTB and + * the DTB passed as a separate buffer. Note that + * CMDLINE_PREFIX is skipped here intentionally, as it is + * used only in the legacy method */ + + if (arch_options.dtb_file) { + dtb_buf = slurp_file(arch_options.dtb_file, &dtb_length); + } else { + create_flatten_tree(&dtb_buf, &dtb_length, cmdline_buf + strlen(CMDLINE_PREFIX)); + } + + if (arch_options.initrd_file) { + initrd_buf = slurp_file(arch_options.initrd_file, &initrd_size); + + /* Create initrd entries in dtb - although at this time + * they would not point to the correct location */ + dtb_set_initrd(&dtb_buf, &dtb_length, initrd_buf, initrd_buf + initrd_size); + + initrd_base = add_buffer(info, initrd_buf, initrd_size, + initrd_size, sizeof(void *), + _ALIGN_UP(kernel_addr + kernel_size + dtb_length, + pagesize), 0x0fffffff, 1); + + /* Now that the buffer for initrd is prepared, update the dtb + * with an appropriate location */ + dtb_set_initrd(&dtb_buf, &dtb_length, initrd_base, initrd_base + initrd_size); + } + + + /* This is a legacy method for commandline passing used + * currently by Octeon CPUs only */ add_buffer(info, cmdline_buf, sizeof(cmdline_buf), sizeof(cmdline_buf), sizeof(void *), cmdline_addr, 0x0fffffff, 1); + add_buffer(info, dtb_buf, dtb_length, dtb_length, 0, + _ALIGN_UP(kernel_addr + kernel_size, pagesize), + 0x0fffffff, 1); + return 0; } diff -Nru kexec-tools-2.0.10/kexec/arch/mips/kexec-elf-rel-mips.c kexec-tools-2.0.16/kexec/arch/mips/kexec-elf-rel-mips.c --- kexec-tools-2.0.10/kexec/arch/mips/kexec-elf-rel-mips.c 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/mips/kexec-elf-rel-mips.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/mips/kexec-mips.c kexec-tools-2.0.16/kexec/arch/mips/kexec-mips.c --- kexec-tools-2.0.10/kexec/arch/mips/kexec-mips.c 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/mips/kexec-mips.c 2017-10-18 05:15:24.000000000 +0000 @@ -21,6 +21,10 @@ #include "kexec-mips.h" #include +/* Currently not used but required by top-level fs2dt code */ +off_t initrd_base = 0; +off_t initrd_size = 0; + static struct memory_range memory_range[MAX_MEMORY_RANGES]; /* Return a sorted list of memory ranges. */ @@ -44,7 +48,7 @@ while (fgets(line, sizeof(line), fp) != 0) { if (memory_ranges >= MAX_MEMORY_RANGES) break; - count = sscanf(line, "%Lx-%Lx : %n", &start, &end, &consumed); + count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed); if (count != 2) continue; str = line + consumed; @@ -56,10 +60,16 @@ } else { continue; } - memory_range[memory_ranges].start = start; - memory_range[memory_ranges].end = end; - memory_range[memory_ranges].type = type; - memory_ranges++; + if (memory_ranges > 0 && + memory_range[memory_ranges - 1].end == start && + memory_range[memory_ranges - 1].type == type) { + memory_range[memory_ranges - 1].end = end; + } else { + memory_range[memory_ranges].start = start; + memory_range[memory_ranges].end = end; + memory_range[memory_ranges].type = type; + memory_ranges++; + } } fclose(fp); *range = memory_range; @@ -74,20 +84,48 @@ void arch_usage(void) { -#ifdef __mips64 - fprintf(stderr, " --elf32-core-headers Prepare core headers in " - "ELF32 format\n"); -#endif + printf( + " --command-line=STRING Set the kernel command line to STRING.\n" + " --append=STRING Set the kernel command line to STRING.\n" + " --dtb=FILE Use FILE as the device tree blob.\n" + " --initrd=FILE Use FILE as initial ramdisk.\n" + ); } -#ifdef __mips64 struct arch_options_t arch_options = { - .core_header_type = CORE_TYPE_ELF64 -}; +#ifdef __mips64 + .core_header_type = CORE_TYPE_ELF64, +#else + .core_header_type = CORE_TYPE_ELF32, #endif +}; int arch_process_options(int argc, char **argv) { + static const struct option options[] = { + KEXEC_ARCH_OPTIONS + { 0 }, + }; + static const char short_options[] = KEXEC_ARCH_OPT_STR; + int opt; + + while ((opt = getopt_long(argc, argv, short_options, + options, 0)) != -1) { + switch (opt) { + case OPT_APPEND: + arch_options.command_line = optarg; + break; + case OPT_DTB: + arch_options.dtb_file = optarg; + break; + case OPT_RAMDISK: + arch_options.initrd_file = optarg; + break; + default: + break; + } + } + return 0; } diff -Nru kexec-tools-2.0.10/kexec/arch/mips/kexec-mips.h kexec-tools-2.0.16/kexec/arch/mips/kexec-mips.h --- kexec-tools-2.0.10/kexec/arch/mips/kexec-mips.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/mips/kexec-mips.h 2016-12-20 08:28:23.000000000 +0000 @@ -1,6 +1,11 @@ #ifndef KEXEC_MIPS_H #define KEXEC_MIPS_H +#include + +#define BOOT_BLOCK_VERSION 17 +#define BOOT_BLOCK_LAST_COMP_VERSION 16 + #define MAX_MEMORY_RANGES 64 #define MAX_LINE 160 @@ -13,7 +18,13 @@ void elf_mips_usage(void); struct arch_options_t { - int core_header_type; + char *command_line; + char *dtb_file; + char *initrd_file; + int core_header_type; }; +extern struct memory_ranges usablemem_rgns; +extern off_t initrd_base, initrd_size; + #endif /* KEXEC_MIPS_H */ diff -Nru kexec-tools-2.0.10/kexec/arch/mips/Makefile kexec-tools-2.0.16/kexec/arch/mips/Makefile --- kexec-tools-2.0.10/kexec/arch/mips/Makefile 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/mips/Makefile 2016-12-20 08:28:23.000000000 +0000 @@ -6,6 +6,19 @@ mips_KEXEC_SRCS += kexec/arch/mips/kexec-elf-rel-mips.c mips_KEXEC_SRCS += kexec/arch/mips/crashdump-mips.c +mips_FS2DT = kexec/fs2dt.c +mips_FS2DT_INCLUDE = \ + -include $(srcdir)/kexec/arch/mips/crashdump-mips.h \ + -include $(srcdir)/kexec/arch/mips/kexec-mips.h + +mips_DT_OPS += kexec/dt-ops.c + +include $(srcdir)/kexec/libfdt/Makefile.libfdt + +libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) +mips_CPPFLAGS += -I$(srcdir)/kexec/libfdt +mips_KEXEC_SRCS += $(libfdt_SRCS) + mips_ADD_BUFFER = mips_ADD_SEGMENT = mips_VIRT_TO_PHYS = diff -Nru kexec-tools-2.0.10/kexec/arch/ppc/crashdump-powerpc.c kexec-tools-2.0.16/kexec/arch/ppc/crashdump-powerpc.c --- kexec-tools-2.0.10/kexec/arch/ppc/crashdump-powerpc.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc/crashdump-powerpc.c 2017-08-10 07:28:22.000000000 +0000 @@ -16,6 +16,9 @@ #include "kexec-ppc.h" #include "crashdump-powerpc.h" +#define DEVTREE_CRASHKERNEL_BASE "/proc/device-tree/chosen/linux,crashkernel-base" +#define DEVTREE_CRASHKERNEL_SIZE "/proc/device-tree/chosen/linux,crashkernel-size" + #ifdef CONFIG_PPC64 static struct crash_elf_info elf_info64 = { class: ELFCLASS64, @@ -249,8 +252,12 @@ /* Append str to cmdline */ static void add_cmdline(char *cmdline, char *str) { + int cmdline_size; int cmdlen = strlen(cmdline) + strlen(str); - if (cmdlen > (COMMAND_LINE_SIZE - 1)) + + cmdline_size = (kernel_version() < KERNEL_VERSION(3, 15, 0) ? + 512 : COMMAND_LINE_SIZE); + if (cmdlen > (cmdline_size - 1)) die("Command line overflow\n"); strcat(cmdline, str); } @@ -397,11 +404,28 @@ usablemem_rgns.size, base, size); } +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) +{ + unsigned long long value; + + if (!get_devtree_value(DEVTREE_CRASHKERNEL_BASE, &value)) + *start = value; + else + return -1; + + if (!get_devtree_value(DEVTREE_CRASHKERNEL_SIZE, &value)) + *end = *start + value - 1; + else + return -1; + + return 0; +} + int is_crashkernel_mem_reserved(void) { int fd; - fd = open("/proc/device-tree/chosen/linux,crashkernel-base", O_RDONLY); + fd = open(DEVTREE_CRASHKERNEL_BASE, O_RDONLY); if (fd < 0) return 0; close(fd); diff -Nru kexec-tools-2.0.10/kexec/arch/ppc/crashdump-powerpc.h kexec-tools-2.0.16/kexec/arch/ppc/crashdump-powerpc.h --- kexec-tools-2.0.10/kexec/arch/ppc/crashdump-powerpc.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc/crashdump-powerpc.h 2017-08-10 07:28:22.000000000 +0000 @@ -20,8 +20,6 @@ #define KERNELBASE PAGE_OFFSET #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) -#define COMMAND_LINE_SIZE 512 /* from kernel */ - #ifdef CONFIG_BOOKE /* We don't need backup region in Book E */ #define BACKUP_SRC_START 0x0000 diff -Nru kexec-tools-2.0.10/kexec/arch/ppc/fs2dt.c kexec-tools-2.0.16/kexec/arch/ppc/fs2dt.c --- kexec-tools-2.0.10/kexec/arch/ppc/fs2dt.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc/fs2dt.c 2017-08-10 07:28:22.000000000 +0000 @@ -30,13 +30,13 @@ #include #include "../../kexec.h" #include "kexec-ppc.h" +#include "types.h" #define MAXPATH 1024 /* max path name length */ #define NAMESPACE 16384 /* max bytes for property names */ #define TREEWORDS 65536 /* max 32 bit words for properties */ #define MEMRESERVE 256 /* max number of reserved memory blks */ #define MAX_MEMORY_RANGES 1024 -#define COMMAND_LINE_SIZE 512 /* from kernel */ static char pathname[MAXPATH]; static char propnames[NAMESPACE] = { 0 }; @@ -296,6 +296,8 @@ { char *str1 = (*(struct dirent **)dentry1)->d_name; char *str2 = (*(struct dirent **)dentry2)->d_name; + char *p1, *p2; + int res = 0, max_len; /* * strcmp scans from left to right and fails to idetify for some @@ -303,11 +305,21 @@ * Therefore, we get the wrong sorted order like memory@10000000 and * memory@f000000. */ - if (strchr(str1, '@') && strchr(str2, '@') && - (strlen(str1) > strlen(str2))) - return 1; + if ((p1 = strchr(str1, '@')) && (p2 = strchr(str2, '@'))) { + max_len = max(p1 - str1, p2 - str2); + if ((res = strncmp(str1, str2, max_len)) == 0) { + /* prefix is equal - compare part after '@' by length */ + p1++; p2++; + res = strlen(p1) - strlen(p2); + if (res == 0) + /* equal length, compare by strcmp() */ + res = strcmp(p1,p2); + } + } else { + res = strcmp(str1, str2); + } - return strcmp(str1, str2); + return res; } /* diff -Nru kexec-tools-2.0.10/kexec/arch/ppc/kexec-elf-ppc.c kexec-tools-2.0.16/kexec/arch/ppc/kexec-elf-ppc.c --- kexec-tools-2.0.10/kexec/arch/ppc/kexec-elf-ppc.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc/kexec-elf-ppc.c 2017-03-20 08:13:33.000000000 +0000 @@ -453,7 +453,7 @@ if (!tmp_cmdline) free(command_line); if (error_msg) - die(error_msg); + die("%s", error_msg); return result; } diff -Nru kexec-tools-2.0.10/kexec/arch/ppc/kexec-elf-rel-ppc.c kexec-tools-2.0.16/kexec/arch/ppc/kexec-elf-rel-ppc.c --- kexec-tools-2.0.10/kexec/arch/ppc/kexec-elf-rel-ppc.c 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc/kexec-elf-rel-ppc.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/ppc/kexec-ppc.c kexec-tools-2.0.16/kexec/arch/ppc/kexec-ppc.c --- kexec-tools-2.0.10/kexec/arch/ppc/kexec-ppc.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc/kexec-ppc.c 2017-03-02 09:50:31.000000000 +0000 @@ -423,6 +423,30 @@ return -1; } +/* Return 0 if fname/value valid, -1 otherwise */ +int get_devtree_value(const char *fname, unsigned long long *value) +{ + FILE *file; + char buf[MAXBYTES]; + int n = -1; + + if ((file = fopen(fname, "r"))) { + n = fread(buf, 1, MAXBYTES, file); + fclose(file); + } + + if (n == sizeof(uint32_t)) + *value = ((uint32_t *)buf)[0]; + else if (n == sizeof(uint64_t)) + *value = ((uint64_t *)buf)[0]; + else { + fprintf(stderr, "%s node has invalid size: %d\n", fname, n); + return -1; + } + + return 0; +} + /* Get devtree details and create exclude_range array * Also create usablemem_ranges for KEXEC_ON_CRASH */ diff -Nru kexec-tools-2.0.10/kexec/arch/ppc/kexec-ppc.h kexec-tools-2.0.16/kexec/arch/ppc/kexec-ppc.h --- kexec-tools-2.0.10/kexec/arch/ppc/kexec-ppc.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc/kexec-ppc.h 2017-08-10 07:28:22.000000000 +0000 @@ -6,6 +6,8 @@ #define CORE_TYPE_ELF32 1 #define CORE_TYPE_ELF64 2 +#define COMMAND_LINE_SIZE 2048 /* from kernel */ + extern unsigned char setup_simple_start[]; extern uint32_t setup_simple_size; @@ -75,7 +77,7 @@ extern int init_memory_region_info(void); extern int read_memory_region_limits(int fd, unsigned long long *start, unsigned long long *end); -#define COMMAND_LINE_SIZE 512 /* from kernel */ +extern int get_devtree_value(const char *fname, unsigned long long *pvalue); /*fs2dt*/ void reserve(unsigned long long where, unsigned long long length); diff -Nru kexec-tools-2.0.10/kexec/arch/ppc/kexec-uImage-ppc.c kexec-tools-2.0.16/kexec/arch/ppc/kexec-uImage-ppc.c --- kexec-tools-2.0.10/kexec/arch/ppc/kexec-uImage-ppc.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc/kexec-uImage-ppc.c 2017-03-20 08:13:33.000000000 +0000 @@ -55,7 +55,7 @@ { struct Image_info img; off_t size; - const unsigned char *buf = slurp_file(filename, &size); + const char *buf = slurp_file(filename, &size); int rc; /* Check if this is a uImage RAMDisk */ @@ -306,7 +306,7 @@ if (!tmp_cmdline) free(command_line); if (error_msg) - die(error_msg); + die("%s", error_msg); return ret; } diff -Nru kexec-tools-2.0.10/kexec/arch/ppc/ops.h kexec-tools-2.0.16/kexec/arch/ppc/ops.h --- kexec-tools-2.0.10/kexec/arch/ppc/ops.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc/ops.h 2017-08-10 07:28:22.000000000 +0000 @@ -12,7 +12,6 @@ #define _PPC_BOOT_OPS_H_ #include "types.h" -#define COMMAND_LINE_SIZE 512 #define MAX_PATH_LEN 256 #define MAX_PROP_LEN 256 /* What should this be? */ diff -Nru kexec-tools-2.0.10/kexec/arch/ppc64/crashdump-ppc64.c kexec-tools-2.0.16/kexec/arch/ppc64/crashdump-ppc64.c --- kexec-tools-2.0.10/kexec/arch/ppc64/crashdump-ppc64.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc64/crashdump-ppc64.c 2017-08-30 06:38:07.000000000 +0000 @@ -33,8 +33,12 @@ #include "../../kexec-syscall.h" #include "../../crashdump.h" #include "kexec-ppc64.h" +#include "../../fs2dt.h" #include "crashdump-ppc64.h" +#define DEVTREE_CRASHKERNEL_BASE "/proc/device-tree/chosen/linux,crashkernel-base" +#define DEVTREE_CRASHKERNEL_SIZE "/proc/device-tree/chosen/linux,crashkernel-size" + static struct crash_elf_info elf_info64 = { class: ELFCLASS64, @@ -122,6 +126,7 @@ static int get_dyn_reconf_crash_memory_ranges(void) { uint64_t start, end; + uint64_t startrange, endrange; char fname[128], buf[32]; FILE *file; unsigned int i; @@ -136,6 +141,7 @@ } fseek(file, 4, SEEK_SET); + startrange = endrange = 0; for (i = 0; i < num_of_lmbs; i++) { if ((n = fread(buf, 1, 24, file)) < 0) { perror(fname); @@ -161,12 +167,68 @@ if ((flags & 0x80) || !(flags & 0x8)) continue; - exclude_crash_region(start, end); + if (start != endrange) { + if (startrange != endrange) + exclude_crash_region(startrange, endrange); + startrange = start; + } + endrange = end; } + if (startrange != endrange) + exclude_crash_region(startrange, endrange); + fclose(file); return 0; } +/* + * For a given memory node, check if it is mapped to system RAM or + * to onboard memory on accelerator device like GPU card or such. + */ +static int is_coherent_device_mem(const char *fname) +{ + char fpath[PATH_LEN]; + char buf[32]; + DIR *dmem; + FILE *file; + struct dirent *mentry; + int cnt, ret = 0; + + strcpy(fpath, fname); + if ((dmem = opendir(fpath)) == NULL) { + perror(fpath); + return -1; + } + + while ((mentry = readdir(dmem)) != NULL) { + if (strcmp(mentry->d_name, "compatible")) + continue; + + strcat(fpath, "/compatible"); + if ((file = fopen(fpath, "r")) == NULL) { + perror(fpath); + ret = -1; + break; + } + if ((cnt = fread(buf, 1, 32, file)) < 0) { + perror(fpath); + fclose(file); + ret = -1; + break; + } + if (!strncmp(buf, "ibm,coherent-device-memory", 26)) { + fclose(file); + ret = 1; + break; + } + fclose(file); + } + + closedir(dmem); + return ret; +} + + /* Reads the appropriate file and retrieves the SYSTEM RAM regions for whom to * create Elf headers. Keeping it separate from get_memory_ranges() as * requirements are different in the case of normal kexec and crashdumps. @@ -182,12 +244,12 @@ { char device_tree[256] = "/proc/device-tree/"; - char fname[256]; + char fname[PATH_LEN]; char buf[MAXBYTES]; DIR *dir, *dmem; FILE *file; struct dirent *dentry, *mentry; - int i, n, crash_rng_len = 0; + int n, ret, crash_rng_len = 0; unsigned long long start, end; int page_size; @@ -226,6 +288,19 @@ continue; strcpy(fname, device_tree); strcat(fname, dentry->d_name); + + ret = is_coherent_device_mem(fname); + if (ret == -1) { + closedir(dir); + goto err; + } else if (ret == 1) { + /* + * Avoid adding this memory region as it is not + * mapped to system RAM. + */ + continue; + } + if ((dmem = opendir(fname)) == NULL) { perror(fname); closedir(dir); @@ -367,7 +442,7 @@ static int add_cmdline_param(char *cmdline, uint64_t addr, char *cmdstr, char *byte) { - int cmdlen, len, align = 1024; + int cmdline_size, cmdlen, len, align = 1024; char str[COMMAND_LINE_SIZE], *ptr; /* Passing in =xxxK / =xxxM format. Saves space required in cmdline.*/ @@ -388,7 +463,9 @@ strcat(str, byte); len = strlen(str); cmdlen = strlen(cmdline) + len; - if (cmdlen > (COMMAND_LINE_SIZE - 1)) + cmdline_size = (kernel_version() < KERNEL_VERSION(3, 15, 0) ? + 512 : COMMAND_LINE_SIZE); + if (cmdlen > (cmdline_size - 1)) die("Command line overflow\n"); strcat(cmdline, str); dbgprintf("Command line after adding elfcorehdr: %s\n", cmdline); @@ -515,11 +592,28 @@ usablemem_rgns.size, base, size); } +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) +{ + unsigned long long value; + + if (!get_devtree_value(DEVTREE_CRASHKERNEL_BASE, &value)) + *start = value; + else + return -1; + + if (!get_devtree_value(DEVTREE_CRASHKERNEL_SIZE, &value)) + *end = *start + value - 1; + else + return -1; + + return 0; +} + int is_crashkernel_mem_reserved(void) { int fd; - fd = open("/proc/device-tree/chosen/linux,crashkernel-base", O_RDONLY); + fd = open(DEVTREE_CRASHKERNEL_BASE, O_RDONLY); if (fd < 0) return 0; close(fd); diff -Nru kexec-tools-2.0.10/kexec/arch/ppc64/crashdump-ppc64.h kexec-tools-2.0.16/kexec/arch/ppc64/crashdump-ppc64.h --- kexec-tools-2.0.10/kexec/arch/ppc64/crashdump-ppc64.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc64/crashdump-ppc64.h 2017-08-10 07:28:22.000000000 +0000 @@ -16,7 +16,7 @@ #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) #define MAXMEM (-KERNELBASE-VMALLOCBASE) -#define COMMAND_LINE_SIZE 512 /* from kernel */ +#define COMMAND_LINE_SIZE 2048 /* from kernel */ /* Backup Region, First 64K of System RAM. */ #define BACKUP_SRC_START 0x0000 #define BACKUP_SRC_END 0xffff diff -Nru kexec-tools-2.0.10/kexec/arch/ppc64/fdt.c kexec-tools-2.0.16/kexec/arch/ppc64/fdt.c --- kexec-tools-2.0.10/kexec/arch/ppc64/fdt.c 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc64/fdt.c 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,78 @@ +/* + * ppc64 fdt fixups + * + * Copyright 2015 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation (version 2 of the License). + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +/* + * Let the kernel know it booted from kexec, as some things (e.g. + * secondary CPU release) may work differently. + */ +static int fixup_kexec_prop(void *fdt) +{ + int err, nodeoffset; + + nodeoffset = fdt_subnode_offset(fdt, 0, "chosen"); + if (nodeoffset < 0) + nodeoffset = fdt_add_subnode(fdt, 0, "chosen"); + if (nodeoffset < 0) { + printf("%s: add /chosen %s\n", __func__, + fdt_strerror(nodeoffset)); + return -1; + } + + err = fdt_setprop(fdt, nodeoffset, "linux,booted-from-kexec", + NULL, 0); + if (err < 0) { + printf("%s: couldn't write linux,booted-from-kexec: %s\n", + __func__, fdt_strerror(err)); + return -1; + } + + return 0; +} + + +/* + * For now, assume that the added content fits in the file. + * This should be the case when flattening from /proc/device-tree, + * and when passing in a dtb, dtc can be told to add padding. + */ +int fixup_dt(char **fdt, off_t *size) +{ + int ret; + + *size += 4096; + *fdt = realloc(*fdt, *size); + if (!*fdt) { + fprintf(stderr, "%s: out of memory\n", __func__); + return -1; + } + + ret = fdt_open_into(*fdt, *fdt, *size); + if (ret < 0) { + fprintf(stderr, "%s: fdt_open_into: %s\n", __func__, + fdt_strerror(ret)); + return -1; + } + + ret = fixup_kexec_prop(*fdt); + if (ret < 0) + return ret; + + return 0; +} diff -Nru kexec-tools-2.0.10/kexec/arch/ppc64/include/arch/fdt.h kexec-tools-2.0.16/kexec/arch/ppc64/include/arch/fdt.h --- kexec-tools-2.0.10/kexec/arch/ppc64/include/arch/fdt.h 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc64/include/arch/fdt.h 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,8 @@ +#ifndef KEXEC_ARCH_PPC64_FDT +#define KEXEC_ARCH_PPC64_FDT + +#include + +int fixup_dt(char **fdt, off_t *size); + +#endif diff -Nru kexec-tools-2.0.10/kexec/arch/ppc64/include/arch/options.h kexec-tools-2.0.16/kexec/arch/ppc64/include/arch/options.h --- kexec-tools-2.0.10/kexec/arch/ppc64/include/arch/options.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc64/include/arch/options.h 2016-12-09 09:42:06.000000000 +0000 @@ -2,7 +2,8 @@ #define KEXEC_ARCH_PPC64_OPTIONS_H #define OPT_ELF64_CORE (OPT_MAX+0) -#define OPT_ARCH_MAX (OPT_MAX+1) +#define OPT_DT_NO_OLD_ROOT (OPT_MAX+1) +#define OPT_ARCH_MAX (OPT_MAX+2) /* All 'local' loader options: */ #define OPT_APPEND (OPT_ARCH_MAX+0) @@ -14,6 +15,7 @@ #define KEXEC_ARCH_OPTIONS \ KEXEC_OPTIONS \ { "elf64-core-headers", 0, 0, OPT_ELF64_CORE }, \ + { "dt-no-old-root", 0, 0, OPT_DT_NO_OLD_ROOT }, \ #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" diff -Nru kexec-tools-2.0.10/kexec/arch/ppc64/kexec-elf-ppc64.c kexec-tools-2.0.16/kexec/arch/ppc64/kexec-elf-ppc64.c --- kexec-tools-2.0.10/kexec/arch/ppc64/kexec-elf-ppc64.c 2015-02-09 05:53:22.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc64/kexec-elf-ppc64.c 2016-12-20 08:28:23.000000000 +0000 @@ -37,6 +37,8 @@ #include "kexec-ppc64.h" #include "../../fs2dt.h" #include "crashdump-ppc64.h" +#include +#include #include uint64_t initrd_base, initrd_size; @@ -97,7 +99,6 @@ struct mem_ehdr ehdr; char *cmdline, *modified_cmdline = NULL; const char *devicetreeblob; - int cmdline_len, modified_cmdline_len; uint64_t max_addr, hole_addr; char *seg_buf = NULL; off_t seg_size = 0; @@ -107,7 +108,6 @@ uint64_t *rsvmap_ptr; struct bootblock *bb_ptr; #endif - int i; int result, opt; uint64_t my_kernel, my_dt_offset; uint64_t my_opal_base = 0, my_opal_entry = 0; @@ -162,10 +162,7 @@ } } - cmdline_len = 0; - if (cmdline) - cmdline_len = strlen(cmdline) + 1; - else + if (!cmdline) fprintf(stdout, "Warning: append= option is not passed. Using the first kernel root partition\n"); if (ramdisk && reuse_initrd) @@ -181,7 +178,6 @@ strncpy(modified_cmdline, cmdline, COMMAND_LINE_SIZE); modified_cmdline[COMMAND_LINE_SIZE - 1] = '\0'; } - modified_cmdline_len = strlen(modified_cmdline); } /* Parse the Elf file */ @@ -219,7 +215,6 @@ return -1; /* Use new command line. */ cmdline = modified_cmdline; - cmdline_len = strlen(modified_cmdline) + 1; } /* Add v2wrap to the current image */ @@ -249,6 +244,11 @@ /* create from fs2dt */ create_flatten_tree(&seg_buf, &seg_size, cmdline); } + + result = fixup_dt(&seg_buf, &seg_size); + if (result < 0) + return result; + my_dt_offset = add_buffer(info, seg_buf, seg_size, seg_size, 0, 0, max_addr, -1); diff -Nru kexec-tools-2.0.10/kexec/arch/ppc64/kexec-elf-rel-ppc64.c kexec-tools-2.0.16/kexec/arch/ppc64/kexec-elf-rel-ppc64.c --- kexec-tools-2.0.10/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc64/kexec-elf-rel-ppc64.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/ppc64/kexec-ppc64.c kexec-tools-2.0.16/kexec/arch/ppc64/kexec-ppc64.c --- kexec-tools-2.0.10/kexec/arch/ppc64/kexec-ppc64.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc64/kexec-ppc64.c 2017-08-04 11:10:10.000000000 +0000 @@ -38,7 +38,7 @@ static struct memory_range *exclude_range = NULL; static struct memory_range *memory_range = NULL; static struct memory_range *base_memory_range = NULL; -static uint64_t rmo_top; +static uint64_t rma_top; uint64_t memory_max = 0; uint64_t memory_limit; static int nr_memory_ranges, nr_exclude_ranges; @@ -356,12 +356,36 @@ *range_index = i; } +/* Return 0 if fname/value valid, -1 otherwise */ +int get_devtree_value(const char *fname, unsigned long long *value) +{ + FILE *file; + char buf[MAXBYTES]; + int n = -1; + + if ((file = fopen(fname, "r"))) { + n = fread(buf, 1, MAXBYTES, file); + fclose(file); + } + + if (n == sizeof(uint32_t)) + *value = ((uint32_t *)buf)[0]; + else if (n == sizeof(uint64_t)) + *value = ((uint64_t *)buf)[0]; + else { + fprintf(stderr, "%s node has invalid size: %d\n", fname, n); + return -1; + } + + return 0; +} + /* Get devtree details and create exclude_range array * Also create usablemem_ranges for KEXEC_ON_CRASH */ static int get_devtree_details(unsigned long kexec_flags) { - uint64_t rmo_base; + uint64_t rma_base = -1, base; uint64_t tce_base; unsigned int tce_size; uint64_t htab_base, htab_size; @@ -672,10 +696,13 @@ perror(fname); goto error_openfile; } - rmo_base = be64_to_cpu(((uint64_t *)buf)[0]); - rmo_top = rmo_base + be64_to_cpu(((uint64_t *)buf)[1]); - if (rmo_top > 0x30000000UL) - rmo_top = 0x30000000UL; + base = be64_to_cpu(((uint64_t *)buf)[0]); + if (base < rma_base) { + rma_base = base; + rma_top = base + be64_to_cpu(((uint64_t *)buf)[1]); + if (rma_top > 0x30000000UL) + rma_top = 0x30000000UL; + } fclose(file); closedir(cdir); @@ -787,14 +814,14 @@ j++; if (j >= max_memory_ranges) realloc_memory_ranges(); - /* Limit the end to rmo_top */ - if (memory_range[j-1].start >= rmo_top) { + /* Limit the end to rma_top */ + if (memory_range[j-1].start >= rma_top) { j--; break; } - if ((memory_range[j-1].start < rmo_top) && - (memory_range[j-1].end >= rmo_top)) { - memory_range[j-1].end = rmo_top; + if ((memory_range[j-1].start < rma_top) && + (memory_range[j-1].end >= rma_top)) { + memory_range[j-1].end = rma_top; break; } continue; @@ -809,14 +836,14 @@ j++; if (j >= max_memory_ranges) realloc_memory_ranges(); - /* Limit range to rmo_top */ - if (memory_range[j-1].start >= rmo_top) { + /* Limit range to rma_top */ + if (memory_range[j-1].start >= rma_top) { j--; break; } - if ((memory_range[j-1].start < rmo_top) && - (memory_range[j-1].end >= rmo_top)) { - memory_range[j-1].end = rmo_top; + if ((memory_range[j-1].start < rma_top) && + (memory_range[j-1].end >= rma_top)) { + memory_range[j-1].end = rma_top; break; } } @@ -869,6 +896,8 @@ void arch_usage(void) { fprintf(stderr, " --elf64-core-headers Prepare core headers in ELF64 format\n"); + fprintf(stderr, " --dt-no-old-root Do not reuse old kernel root= param.\n" \ + " while creating flatten device tree.\n"); } struct arch_options_t arch_options = { @@ -895,6 +924,9 @@ case OPT_ELF64_CORE: arch_options.core_header_type = CORE_TYPE_ELF64; break; + case OPT_DT_NO_OLD_ROOT: + dt_no_old_root = 1; + break; } } /* Reset getopt for the next pass; called in other source modules */ diff -Nru kexec-tools-2.0.10/kexec/arch/ppc64/kexec-ppc64.h kexec-tools-2.0.16/kexec/arch/ppc64/kexec-ppc64.h --- kexec-tools-2.0.10/kexec/arch/ppc64/kexec-ppc64.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc64/kexec-ppc64.h 2017-08-28 13:33:13.000000000 +0000 @@ -1,6 +1,7 @@ #ifndef KEXEC_PPC64_H #define KEXEC_PPC64_H +#define PATH_LEN 256 #define MAXBYTES 128 #define MAX_LINE 160 #define CORE_TYPE_ELF32 1 @@ -14,6 +15,8 @@ #define HAVE_DYNAMIC_MEMORY #define NEED_RESERVE_DTB +extern int get_devtree_value(const char *fname, unsigned long long *pvalue); + int setup_memory_ranges(unsigned long kexec_flags); int elf_ppc64_probe(const char *buf, off_t len); diff -Nru kexec-tools-2.0.10/kexec/arch/ppc64/Makefile kexec-tools-2.0.16/kexec/arch/ppc64/Makefile --- kexec-tools-2.0.10/kexec/arch/ppc64/Makefile 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/ppc64/Makefile 2016-12-20 08:28:23.000000000 +0000 @@ -1,11 +1,15 @@ # # kexec ppc64 (linux booting linux) # +include $(srcdir)/kexec/libfdt/Makefile.libfdt + ppc64_KEXEC_SRCS = kexec/arch/ppc64/kexec-elf-rel-ppc64.c ppc64_KEXEC_SRCS += kexec/arch/ppc64/kexec-zImage-ppc64.c ppc64_KEXEC_SRCS += kexec/arch/ppc64/kexec-elf-ppc64.c ppc64_KEXEC_SRCS += kexec/arch/ppc64/kexec-ppc64.c ppc64_KEXEC_SRCS += kexec/arch/ppc64/crashdump-ppc64.c +ppc64_KEXEC_SRCS += kexec/arch/ppc64/fdt.c +ppc64_KEXEC_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) ppc64_ARCH_REUSE_INITRD = @@ -13,7 +17,10 @@ ppc64_FS2DT_INCLUDE = -include $(srcdir)/kexec/arch/ppc64/crashdump-ppc64.h \ -include $(srcdir)/kexec/arch/ppc64/kexec-ppc64.h +ppc64_CPPFLAGS = -I$(srcdir)/kexec/libfdt + dist += kexec/arch/ppc64/Makefile $(ppc64_KEXEC_SRCS) \ kexec/arch/ppc64/kexec-ppc64.h kexec/arch/ppc64/crashdump-ppc64.h \ + kexec/arch/ppc64/include/arch/fdt.h \ kexec/arch/ppc64/include/arch/options.h diff -Nru kexec-tools-2.0.10/kexec/arch/s390/kexec-elf-rel-s390.c kexec-tools-2.0.16/kexec/arch/s390/kexec-elf-rel-s390.c --- kexec-tools-2.0.10/kexec/arch/s390/kexec-elf-rel-s390.c 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/s390/kexec-elf-rel-s390.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/s390/kexec-image.c kexec-tools-2.0.16/kexec/arch/s390/kexec-image.c --- kexec-tools-2.0.10/kexec/arch/s390/kexec-image.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/s390/kexec-image.c 2016-12-09 09:42:06.000000000 +0000 @@ -101,7 +101,7 @@ * we load the ramdisk directly behind the image with 1 MiB alignment. */ if (ramdisk) { - rd_buffer = slurp_file(ramdisk, &ramdisk_len); + rd_buffer = slurp_file_mmap(ramdisk, &ramdisk_len); if (rd_buffer == NULL) { fprintf(stderr, "Could not read ramdisk.\n"); return -1; diff -Nru kexec-tools-2.0.10/kexec/arch/s390/kexec-s390.c kexec-tools-2.0.16/kexec/arch/s390/kexec-s390.c --- kexec-tools-2.0.10/kexec/arch/s390/kexec-s390.c 2011-10-31 06:39:34.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/s390/kexec-s390.c 2017-03-14 09:23:02.000000000 +0000 @@ -170,7 +170,7 @@ if (current_range == MAX_MEMORY_RANGES) break; - sscanf(line,"%Lx-%Lx : %n", &start, &end, &cons); + sscanf(line,"%llx-%llx : %n", &start, &end, &cons); str = line+cons; if ((memcmp(str, sys_ram, strlen(sys_ram)) == 0) || ((memcmp(str, crash_kernel, strlen(crash_kernel)) == 0) && @@ -262,3 +262,8 @@ return parse_iomem_single("Crash kernel\n", &start, &end) == 0 ? (start != end) : 0; } + +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) +{ + return parse_iomem_single("Crash kernel\n", start, end); +} diff -Nru kexec-tools-2.0.10/kexec/arch/sh/crashdump-sh.c kexec-tools-2.0.16/kexec/arch/sh/crashdump-sh.c --- kexec-tools-2.0.10/kexec/arch/sh/crashdump-sh.c 2015-02-25 04:41:32.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/sh/crashdump-sh.c 2017-03-02 09:50:51.000000000 +0000 @@ -178,3 +178,8 @@ return parse_iomem_single("Crash kernel\n", &start, &end) == 0 ? (start != end) : 0; } + +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end) +{ + return parse_iomem_single("Crash kernel\n", start, end); +} diff -Nru kexec-tools-2.0.10/kexec/arch/sh/kexec-elf-rel-sh.c kexec-tools-2.0.16/kexec/arch/sh/kexec-elf-rel-sh.c --- kexec-tools-2.0.10/kexec/arch/sh/kexec-elf-rel-sh.c 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/sh/kexec-elf-rel-sh.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/x86_64/kexec-elf-rel-x86_64.c kexec-tools-2.0.16/kexec/arch/x86_64/kexec-elf-rel-x86_64.c --- kexec-tools-2.0.10/kexec/arch/x86_64/kexec-elf-rel-x86_64.c 2015-05-01 01:13:09.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/x86_64/kexec-elf-rel-x86_64.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/arch/x86_64/kexec-elf-x86_64.c kexec-tools-2.0.16/kexec/arch/x86_64/kexec-elf-x86_64.c --- kexec-tools-2.0.10/kexec/arch/x86_64/kexec-elf-x86_64.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/arch/x86_64/kexec-elf-x86_64.c 2017-03-14 13:38:32.000000000 +0000 @@ -99,7 +99,7 @@ #define ARG_STYLE_NONE 2 int opt; int result = 0; - char *error_msg = NULL; + const char *error_msg = NULL; /* See options.h and add any new options there too! */ static const struct option options[] = { @@ -276,6 +276,6 @@ free(command_line); free(modified_cmdline); if (error_msg) - die(error_msg); + die("%s", error_msg); return result; } diff -Nru kexec-tools-2.0.10/kexec/crashdump.c kexec-tools-2.0.16/kexec/crashdump.c --- kexec-tools-2.0.10/kexec/crashdump.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/crashdump.c 2017-03-14 09:23:02.000000000 +0000 @@ -98,7 +98,7 @@ } if (!fgets(line, sizeof(line), fp)) die("Cannot parse %s: %s\n", crash_notes, strerror(errno)); - count = sscanf(line, "%Lx", &temp); + count = sscanf(line, "%llx", &temp); if (count != 1) die("Cannot parse %s: %s\n", crash_notes, strerror(errno)); *addr = (uint64_t) temp; @@ -112,7 +112,7 @@ if (!fgets(line, sizeof(line), fp)) die("Cannot parse %s: %s\n", crash_notes_size, strerror(errno)); - count = sscanf(line, "%Lu", &temp); + count = sscanf(line, "%llu", &temp); if (count != 1) die("Cannot parse %s: %s\n", crash_notes_size, strerror(errno)); @@ -120,7 +120,7 @@ fclose(fp); } - dbgprintf("%s: crash_notes addr = %Lx, size = %Lu\n", __FUNCTION__, + dbgprintf("%s: crash_notes addr = %llx, size = %llu\n", __FUNCTION__, (unsigned long long)*addr, (unsigned long long)*len); return 0; @@ -141,7 +141,7 @@ if (!fgets(line, sizeof(line), fp)) die("Cannot parse %s: %s\n", kdump_info, strerror(errno)); - count = sscanf(line, "%Lx %Lx", &temp, &temp2); + count = sscanf(line, "%llx %llx", &temp, &temp2); if (count != 2) die("Cannot parse %s: %s\n", kdump_info, strerror(errno)); diff -Nru kexec-tools-2.0.10/kexec/crashdump-elf.c kexec-tools-2.0.16/kexec/crashdump-elf.c --- kexec-tools-2.0.10/kexec/crashdump-elf.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/crashdump-elf.c 2016-12-09 09:42:06.000000000 +0000 @@ -141,11 +141,12 @@ count_cpu = nr_cpus; for (i = 0; count_cpu > 0; i++) { - if (get_note_info(i, ¬es_addr, ¬es_len) < 0) { - /* This cpu is not present. Skip it. */ - continue; - } + int ret; + + ret = get_note_info(i, ¬es_addr, ¬es_len); count_cpu--; + if (ret < 0) /* This cpu is not present. Skip it. */ + continue; phdr = (PHDR *) bufp; bufp += sizeof(PHDR); diff -Nru kexec-tools-2.0.10/kexec/crashdump.h kexec-tools-2.0.16/kexec/crashdump.h --- kexec-tools-2.0.10/kexec/crashdump.h 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/crashdump.h 2017-03-24 06:43:00.000000000 +0000 @@ -1,15 +1,14 @@ #ifndef CRASHDUMP_H #define CRASHDUMP_H -int get_crashkernel_region(uint64_t *start, uint64_t *end); extern int get_crash_notes_per_cpu(int cpu, uint64_t *addr, uint64_t *len); extern int get_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len); extern int get_xen_vmcoreinfo(uint64_t *addr, uint64_t *len); /* Need to find a better way to determine per cpu notes section size. */ #define MAX_NOTE_BYTES 1024 -/* Expecting ELF headers to fit in 32K. Increase it if you need more. */ -#define KCORE_ELF_HEADERS_SIZE 32768 +/* Expecting ELF headers to fit in 64K. Increase it if you need more. */ +#define KCORE_ELF_HEADERS_SIZE 65536 /* The address of the ELF header is passed to the secondary kernel * using the kernel command line option memmap=nnn. * The smallest unit the kernel accepts is in kilobytes, @@ -55,7 +54,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 -Nru kexec-tools-2.0.10/kexec/dt-ops.c kexec-tools-2.0.16/kexec/dt-ops.c --- kexec-tools-2.0.10/kexec/dt-ops.c 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/dt-ops.c 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include +#include + +#include "kexec.h" +#include "dt-ops.h" + +static const char n_chosen[] = "/chosen"; + +static const char p_bootargs[] = "bootargs"; +static const char p_initrd_start[] = "linux,initrd-start"; +static const char p_initrd_end[] = "linux,initrd-end"; + +int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end) +{ + int result; + uint64_t value; + + dbgprintf("%s: start %jd, end %jd, size %jd (%jd KiB)\n", + __func__, (intmax_t)start, (intmax_t)end, + (intmax_t)(end - start), + (intmax_t)(end - start) / 1024); + + value = cpu_to_fdt64(start); + + result = dtb_set_property(dtb, dtb_size, n_chosen, p_initrd_start, + &value, sizeof(value)); + + if (result) + return result; + + value = cpu_to_fdt64(end); + + result = dtb_set_property(dtb, dtb_size, n_chosen, p_initrd_end, + &value, sizeof(value)); + + if (result) { + dtb_delete_property(*dtb, n_chosen, p_initrd_start); + return result; + } + + return 0; +} + +int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line) +{ + return dtb_set_property(dtb, dtb_size, n_chosen, p_bootargs, + command_line, strlen(command_line) + 1); +} + +int dtb_set_property(char **dtb, off_t *dtb_size, const char *node, + const char *prop, const void *value, int value_len) +{ + int result; + int nodeoffset; + void *new_dtb; + int new_size; + + value_len = FDT_TAGALIGN(value_len); + + new_size = FDT_TAGALIGN(*dtb_size + fdt_node_len(node) + + fdt_prop_len(prop, value_len)); + + new_dtb = malloc(new_size); + + if (!new_dtb) { + dbgprintf("%s: malloc failed\n", __func__); + return -ENOMEM; + } + + result = fdt_open_into(*dtb, new_dtb, new_size); + + if (result) { + dbgprintf("%s: fdt_open_into failed: %s\n", __func__, + fdt_strerror(result)); + goto on_error; + } + + nodeoffset = fdt_path_offset(new_dtb, node); + + if (nodeoffset == -FDT_ERR_NOTFOUND) { + result = fdt_add_subnode(new_dtb, nodeoffset, node); + + if (result) { + dbgprintf("%s: fdt_add_subnode failed: %s\n", __func__, + fdt_strerror(result)); + goto on_error; + } + } else if (nodeoffset < 0) { + dbgprintf("%s: fdt_path_offset failed: %s\n", __func__, + fdt_strerror(nodeoffset)); + goto on_error; + } + + result = fdt_setprop(new_dtb, nodeoffset, prop, value, value_len); + + if (result) { + dbgprintf("%s: fdt_setprop failed: %s\n", __func__, + fdt_strerror(result)); + goto on_error; + } + + /* + * Can't call free on dtb since dtb may have been mmaped by + * slurp_file(). + */ + + result = fdt_pack(new_dtb); + + if (result) + dbgprintf("%s: Unable to pack device tree: %s\n", __func__, + fdt_strerror(result)); + + *dtb = new_dtb; + *dtb_size = fdt_totalsize(*dtb); + + return 0; + +on_error: + free(new_dtb); + return result; +} + +int dtb_delete_property(char *dtb, const char *node, const char *prop) +{ + int result; + int nodeoffset = fdt_path_offset(dtb, node); + + if (nodeoffset < 0) { + dbgprintf("%s: fdt_path_offset failed: %s\n", __func__, + fdt_strerror(nodeoffset)); + return nodeoffset; + } + + result = fdt_delprop(dtb, nodeoffset, prop); + + if (result) + dbgprintf("%s: fdt_delprop failed: %s\n", __func__, + fdt_strerror(nodeoffset)); + + return result; +} diff -Nru kexec-tools-2.0.10/kexec/dt-ops.h kexec-tools-2.0.16/kexec/dt-ops.h --- kexec-tools-2.0.10/kexec/dt-ops.h 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/dt-ops.h 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,13 @@ +#if !defined(KEXEC_DT_OPS_H) +#define KEXEC_DT_OPS_H + +#include + +int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end); +int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line); +int dtb_set_property(char **dtb, off_t *dtb_size, const char *node, + const char *prop, const void *value, int value_len); + +int dtb_delete_property(char *dtb, const char *node, const char *prop); + +#endif diff -Nru kexec-tools-2.0.10/kexec/firmware_memmap.c kexec-tools-2.0.16/kexec/firmware_memmap.c --- kexec-tools-2.0.10/kexec/firmware_memmap.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/firmware_memmap.c 2017-05-22 11:43:04.000000000 +0000 @@ -164,10 +164,18 @@ range->type = RANGE_RESERVED; else if (strcmp(type, "reserved") == 0) range->type = RANGE_RESERVED; + else if (strcmp(type, "Reserved") == 0) + range->type = RANGE_RESERVED; + else if (strcmp(type, "Unknown E820 type") == 0) + range->type = RANGE_RESERVED; else if (strcmp(type, "ACPI Non-volatile Storage") == 0) range->type = RANGE_ACPI_NVS; else if (strcmp(type, "Uncached RAM") == 0) range->type = RANGE_UNCACHED; + else if (strcmp(type, "Persistent Memory (legacy)") == 0) + range->type = RANGE_PRAM; + else if (strcmp(type, "Persistent Memory") == 0) + range->type = RANGE_PMEM; else { fprintf(stderr, "Unknown type (%s) while parsing %s. Please " "report this as bug. Using RANGE_RESERVED now.\n", diff -Nru kexec-tools-2.0.10/kexec/fs2dt.c kexec-tools-2.0.16/kexec/fs2dt.c --- kexec-tools-2.0.10/kexec/fs2dt.c 2015-02-18 21:27:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/fs2dt.c 2016-12-20 08:28:23.000000000 +0000 @@ -39,7 +39,7 @@ #define MEMRESERVE 256 /* max number of reserved memory blocks */ #define MEM_RANGE_CHUNK_SZ 2048 /* Initial num dwords for mem ranges */ -static char pathname[MAXPATH], *pathstart; +static char pathname[MAXPATH]; static char propnames[NAMESPACE] = { 0 }; static unsigned *dt_base, *dt; static unsigned int dt_cur_size; @@ -53,6 +53,7 @@ /* Used for enabling printing message from purgatory code * Only has implemented for PPC64 */ int my_debug; +int dt_no_old_root; /* This provides the behaviour of hte existing ppc64 implementation */ static void pad_structure_block(size_t len) { @@ -511,6 +512,39 @@ return strcmp(str1, str2); } +/* grab root= from the old command line */ +static void dt_copy_old_root_param(void) +{ + FILE *fp; + char filename[MAXPATH]; + char *last_cmdline = NULL; + char *p, *old_param; + size_t len = 0; + + strcpy(filename, pathname); + strcat(filename, "bootargs"); + fp = fopen(filename, "r"); + if (!fp) + return; + + if (getline(&last_cmdline, &len, fp) == -1) + die("unable to read %s\n", filename); + + p = strstr(last_cmdline, "root="); + if (p) { + old_param = strtok(p, " "); + len = strlen(local_cmdline); + if (len != 0) + strcat(local_cmdline, " "); + strcat(local_cmdline, old_param); + } + + if (last_cmdline) + free(last_cmdline); + + fclose(fp); +} + /* * put a node (directory) in the property structure. first properties * then children. @@ -545,7 +579,8 @@ strcpy((void *)dt, *basename ? basename : ""); dt += ((plen + 4)/4); - strcat(pathname, "/"); + if (*basename) + strcat(pathname, "/"); dn = pathname + strlen(pathname); putprops(dn, namelist, numlist); @@ -579,8 +614,11 @@ reserve(initrd_base, initrd_size); } - /* Add cmdline to the second kernel. Check to see if the new - * cmdline has a root=. If not, use the old root= cmdline. */ + /* + * Add cmdline to the second kernel. Use the old root= cmdline if there + * is no root= in the new command line and there's no --dt-no-old-root + * option being used. + */ if (!strcmp(basename,"chosen/")) { size_t result; size_t cmd_len = 0; @@ -598,30 +636,9 @@ param = strstr(local_cmdline, "root="); } - /* ... if not, grab root= from the old command line */ - if (!param) { - FILE *fp; - char *last_cmdline = NULL; - char *old_param; - - strcpy(filename, pathname); - strcat(filename, "bootargs"); - fp = fopen(filename, "r"); - if (fp) { - if (getline(&last_cmdline, &cmd_len, fp) == -1) - die("unable to read %s\n", filename); - - param = strstr(last_cmdline, "root="); - if (param) { - old_param = strtok(param, " "); - if (cmd_len != 0) - strcat(local_cmdline, " "); - strcat(local_cmdline, old_param); - } - } - if (last_cmdline) - free(last_cmdline); - } + if (!param && !dt_no_old_root) + dt_copy_old_root_param(); + strcat(local_cmdline, " "); cmd_len = strlen(local_cmdline); cmd_len = cmd_len + 1; @@ -642,15 +659,19 @@ * code can print 'I'm in purgatory' message. Currently only * pseries/hvcterminal is supported. */ - snprintf(filename, MAXPATH, "%slinux,stdout-path", pathname); + snprintf(filename, MAXPATH, "%sstdout-path", pathname); fd = open(filename, O_RDONLY); if (fd == -1) { - printf("Unable to find %s, printing from purgatory is diabled\n", - filename); - goto no_debug; + snprintf(filename, MAXPATH, "%slinux,stdout-path", pathname); + fd = open(filename, O_RDONLY); + if (fd == -1) { + printf("Unable to find %s[linux,]stdout-path, printing from purgatory is disabled\n", + pathname); + goto no_debug; + } } if (fstat(fd, &statbuf)) { - printf("Unable to stat %s, printing from purgatory is diabled\n", + printf("Unable to stat %s, printing from purgatory is disabled\n", filename); close(fd); goto no_debug; @@ -666,19 +687,19 @@ result = read(fd, buff, statbuf.st_size); close(fd); if (result <= 0) { - printf("Unable to read %s, printing from purgatory is diabled\n", + printf("Unable to read %s, printing from purgatory is disabled\n", filename); goto no_debug; } snprintf(filename, MAXPATH, "/proc/device-tree/%s/compatible", buff); fd = open(filename, O_RDONLY); if (fd == -1) { - printf("Unable to find %s printing from purgatory is diabled\n", + printf("Unable to find %s printing from purgatory is disabled\n", filename); goto no_debug; } if (fstat(fd, &statbuf)) { - printf("Unable to stat %s printing from purgatory is diabled\n", + printf("Unable to stat %s printing from purgatory is disabled\n", filename); close(fd); goto no_debug; @@ -788,8 +809,6 @@ { strcpy(pathname, "/proc/device-tree/"); - pathstart = pathname + strlen(pathname); - dt_cur_size = INIT_TREE_WORDS; dt_base = malloc(dt_cur_size*4); if (!dt_base) { diff -Nru kexec-tools-2.0.10/kexec/fs2dt.h kexec-tools-2.0.16/kexec/fs2dt.h --- kexec-tools-2.0.10/kexec/fs2dt.h 2013-11-19 01:05:49.000000000 +0000 +++ kexec-tools-2.0.16/kexec/fs2dt.h 2016-12-09 09:42:06.000000000 +0000 @@ -31,6 +31,7 @@ /* Used for enabling printing message from purgatory code * Only has implemented for PPC64 */ int my_debug; +extern int dt_no_old_root; void reserve(unsigned long long where, unsigned long long length); void create_flatten_tree(char **, off_t *, const char *); diff -Nru kexec-tools-2.0.10/kexec/ifdown.c kexec-tools-2.0.16/kexec/ifdown.c --- kexec-tools-2.0.10/kexec/ifdown.c 2011-10-02 22:56:38.000000000 +0000 +++ kexec-tools-2.0.16/kexec/ifdown.c 2016-12-20 08:28:23.000000000 +0000 @@ -1,6 +1,6 @@ /* - * ifdown.c Find all network interfaces on the system and - * shut them down. + * ifdown.c Find all network interfaces on the system and + * shut them down. * */ char *v_ifdown = "@(#)ifdown.c 1.11 02-Jun-1998 miquels@cistron.nl"; @@ -20,10 +20,10 @@ #include /* - * First, we find all shaper devices and down them. Then we - * down all real interfaces. This is because the comment in the - * shaper driver says "if you down the shaper device before the - * attached inerface your computer will follow". + * First, we find all shaper devices and down them. Then we + * down all real interfaces. This is because the comment in the + * shaper driver says "if you down the shaper device before the + * attached inerface your computer will follow". */ int ifdown(void) { @@ -34,13 +34,13 @@ if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "ifdown: "); perror("socket"); - return -1; + goto error; } if ((ifa = if_nameindex()) == NULL) { fprintf(stderr, "ifdown: "); perror("if_nameindex"); - return -1; + goto error; } for (shaper = 1; shaper >= 0; shaper--) { @@ -57,18 +57,22 @@ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { fprintf(stderr, "ifdown: shutdown "); perror(ifp->if_name); - return -1; + goto error; } ifr.ifr_flags &= ~(IFF_UP); if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) { fprintf(stderr, "ifdown: shutdown "); perror(ifp->if_name); - return -1; + goto error; } } } - close(fd); + close(fd); return 0; + +error: + close(fd); + return -1; } diff -Nru kexec-tools-2.0.10/kexec/kexec.8 kexec-tools-2.0.16/kexec/kexec.8 --- kexec-tools-2.0.10/kexec/kexec.8 2015-04-15 01:07:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/kexec.8 2017-03-02 09:45:46.000000000 +0000 @@ -107,6 +107,12 @@ .B \-d\ (\-\-debug) Enable debugging messages. .TP +.B \-S\ (\-\-status) +Return 0 if the type (by default crash) is loaded. Can be used in conjuction +with -l or -p to toggle the type. Note this option supersedes other options +and it will +.BR not\ load\ or\ unload\ the\ kernel. +.TP .B \-e\ (\-\-exec) Run the currently loaded kernel. Note that it will reboot into the loaded kernel without calling shutdown(8). .TP @@ -173,6 +179,9 @@ .TP .BI \-\-reuseinitrd Reuse initrd from first boot. +.TP +.BI \-\-print-ckr-size +Print crash kernel region size, if available. .SH SUPPORTED KERNEL FILE TYPES AND OPTIONS diff -Nru kexec-tools-2.0.10/kexec/kexec.c kexec-tools-2.0.16/kexec/kexec.c --- kexec-tools-2.0.10/kexec/kexec.c 2015-04-15 01:07:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/kexec.c 2017-03-02 09:45:46.000000000 +0000 @@ -26,9 +26,12 @@ #include #include #include +#include +#include #include #include #include +#include #include #include #ifndef _O_BINARY @@ -48,6 +51,9 @@ #include "kexec-lzma.h" #include +#define KEXEC_LOADED_PATH "/sys/kernel/kexec_loaded" +#define KEXEC_CRASH_LOADED_PATH "/sys/kernel/kexec_crash_loaded" + unsigned long long mem_min = 0; unsigned long long mem_max = ULONG_MAX; static unsigned long kexec_flags = 0; @@ -514,7 +520,8 @@ return buf; } -char *slurp_file(const char *filename, off_t *r_size) +static char *slurp_file_generic(const char *filename, off_t *r_size, + int use_mmap) { int fd; char *buf; @@ -552,12 +559,24 @@ if (err < 0) die("Can not seek to the begin of file %s: %s\n", filename, strerror(errno)); + buf = slurp_fd(fd, filename, size, &nread); + } else if (S_ISBLK(stats.st_mode)) { + err = ioctl(fd, BLKGETSIZE64, &size); + if (err < 0) + die("Can't retrieve size of block device %s: %s\n", + filename, strerror(errno)); + buf = slurp_fd(fd, filename, size, &nread); } else { size = stats.st_size; + if (use_mmap) { + buf = mmap(NULL, size, PROT_READ|PROT_WRITE, + MAP_PRIVATE, fd, 0); + nread = size; + } else { + buf = slurp_fd(fd, filename, size, &nread); + } } - - buf = slurp_fd(fd, filename, size, &nread); - if (!buf) + if ((use_mmap && (buf == MAP_FAILED)) || (!use_mmap && (buf == NULL))) die("Cannot read %s", filename); if (nread != size) @@ -567,6 +586,23 @@ return buf; } +/* + * Read file into malloced buffer. + */ +char *slurp_file(const char *filename, off_t *r_size) +{ + return slurp_file_generic(filename, r_size, 0); +} + +/* + * Map "normal" file or read "character device" into malloced buffer. + * You must not use free, realloc, etc. for the returned buffer. + */ +char *slurp_file_mmap(const char *filename, off_t *r_size) +{ + return slurp_file_generic(filename, r_size, 1); +} + /* This functions reads either specified number of bytes from the file or lesser if EOF is met. */ @@ -674,8 +710,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) { @@ -857,8 +893,6 @@ return -1; } -static int kexec_loaded(void); - static int load_jump_back_helper_image(unsigned long kexec_flags, void *entry) { int result; @@ -869,6 +903,40 @@ return result; } +static int kexec_loaded(const char *file) +{ + long ret = -1; + FILE *fp; + char *p; + char line[3]; + + /* No way to tell if an image is loaded under Xen, assume it is. */ + if (xen_present()) + return 1; + + fp = fopen(file, "r"); + if (fp == NULL) + return -1; + + p = fgets(line, sizeof(line), fp); + fclose(fp); + + if (p == NULL) + return -1; + + ret = strtol(line, &p, 10); + + /* Too long */ + if (ret > INT_MAX) + return -1; + + /* No digits were found */ + if (p == line) + return -1; + + return (int)ret; +} + /* * Jump back to the original kernel */ @@ -876,7 +944,7 @@ { int result; - if (kexec_loaded()) { + if (kexec_loaded(KEXEC_LOADED_PATH)) { fprintf(stderr, "There is kexec kernel loaded, make sure " "you are in kexeced kernel.\n"); return -1; @@ -897,7 +965,7 @@ static void version(void) { - printf(PACKAGE_STRING " released " PACKAGE_DATE "\n"); + printf(PACKAGE_STRING "\n"); } void usage(void) @@ -927,6 +995,7 @@ " --mem-max= Specify the highest memory address to\n" " load code into.\n" " --reuseinitrd Reuse initrd from first boot.\n" + " --print-ckr-size Print crash kernel region size.\n" " --load-preserve-context Load the new kernel and preserve\n" " context of current kernel during kexec.\n" " --load-jump-back-helper Load a helper image to jump back\n" @@ -936,7 +1005,8 @@ " preserve context)\n" " to original kernel.\n" " -s, --kexec-file-syscall Use file based syscall for kexec operation\n" - " -d, --debug Enable debugging to help spot a failure.\n" + " -d, --debug Enable debugging to help spot a failure.\n" + " -S, --status Return 0 if the type (by default crash) is loaded.\n" "\n" "Supported kernel file types and options: \n"); for (i = 0; i < file_types; i++) { @@ -948,40 +1018,30 @@ printf("\n"); } -static int kexec_loaded(void) +static int k_status(unsigned long kexec_flags) { - long ret = -1; - FILE *fp; - char *p; - char line[3]; - - /* No way to tell if an image is loaded under Xen, assume it is. */ - if (xen_present()) - return 1; - - fp = fopen("/sys/kernel/kexec_loaded", "r"); - if (fp == NULL) - return -1; - - p = fgets(line, sizeof(line), fp); - fclose(fp); - - if (p == NULL) - return -1; - - ret = strtol(line, &p, 10); - - /* Too long */ - if (ret > INT_MAX) - return -1; + int result; + long native_arch; - /* No digits were found */ - if (p == line) + /* set the arch */ + native_arch = physical_arch(); + if (native_arch < 0) { return -1; + } + kexec_flags |= native_arch; - return (int)ret; + if (xen_present()) + result = xen_kexec_status(kexec_flags); + else { + if (kexec_flags & KEXEC_ON_CRASH) + result = kexec_loaded(KEXEC_CRASH_LOADED_PATH); + else + result = kexec_loaded(KEXEC_LOADED_PATH); + } + return result; } + /* * Remove parameter from a kernel command line. Helper function by get_command_line(). */ @@ -1159,6 +1219,18 @@ return ret; } +static void print_crashkernel_region_size(void) +{ + uint64_t start = 0, end = 0; + + if (is_crashkernel_mem_reserved() && + get_crash_kernel_load_range(&start, &end)) { + fprintf(stderr, "get_crash_kernel_load_range() failed.\n"); + return; + } + + printf("%lu\n", (start != end) ? (end - start + 1) : 0UL); +} int main(int argc, char *argv[]) { @@ -1171,6 +1243,7 @@ int do_unload = 0; int do_reuse_initrd = 0; int do_kexec_file_syscall = 0; + int do_status = 0; void *entry = 0; char *type = 0; char *endptr; @@ -1312,6 +1385,12 @@ case OPT_KEXEC_FILE_SYSCALL: /* We already parsed it. Nothing to do. */ break; + case OPT_STATUS: + do_status = 1; + break; + case OPT_PRINT_CKR_SIZE: + print_crashkernel_region_size(); + return 0; default: break; } @@ -1322,6 +1401,20 @@ if (skip_sync) do_sync = 0; + if (do_status) { + if (kexec_flags == 0) + kexec_flags = KEXEC_ON_CRASH; + do_load = 0; + do_reuse_initrd = 0; + do_unload = 0; + do_load = 0; + do_shutdown = 0; + do_sync = 0; + do_ifdown = 0; + do_exec = 0; + do_load_jump_back_helper = 0; + } + if (do_load && (kexec_flags & KEXEC_ON_CRASH) && !is_crashkernel_mem_reserved()) { die("Memory for crashkernel is not reserved\n" @@ -1359,7 +1452,9 @@ check_reuse_initrd(); arch_reuse_initrd(); } - + if (do_status) { + result = k_status(kexec_flags); + } if (do_unload) { if (do_kexec_file_syscall) result = kexec_file_unload(kexec_file_flags); @@ -1375,7 +1470,7 @@ kexec_flags, entry); } /* Don't shutdown unless there is something to reboot to! */ - if ((result == 0) && (do_shutdown || do_exec) && !kexec_loaded()) { + if ((result == 0) && (do_shutdown || do_exec) && !kexec_loaded(KEXEC_LOADED_PATH)) { die("Nothing has been loaded!\n"); } if ((result == 0) && do_shutdown) { diff -Nru kexec-tools-2.0.10/kexec/kexec-elf.c kexec-tools-2.0.16/kexec/kexec-elf.c --- kexec-tools-2.0.10/kexec/kexec-elf.c 2013-11-19 01:05:49.000000000 +0000 +++ kexec-tools-2.0.16/kexec/kexec-elf.c 2017-03-13 08:57:11.000000000 +0000 @@ -432,7 +432,8 @@ } return -1; } - if ((phdr->p_paddr + phdr->p_memsz) < phdr->p_paddr) { + if (phdr->p_paddr != (unsigned long long)-1 && + (phdr->p_paddr + phdr->p_memsz) < phdr->p_paddr) { /* The memory address wraps */ if (probe_debug) { fprintf(stderr, "ELF address wrap around\n"); @@ -720,6 +721,14 @@ desc = note + note_size; note_size += _ALIGN(hdr.n_descsz, 4); + if (((note+note_size) > note_end) || + ((note+note_size) < note_start)) { + /* Something is very wrong here ! Most likely the note + * header is invalid */ + fprintf(stderr, "ELF Note corrupted !\n"); + return -1; + } + if ((hdr.n_namesz != 0) && (name[hdr.n_namesz -1] != '\0')) { /* If note name string is not null terminated, just * warn user about it and continue processing. This diff -Nru kexec-tools-2.0.10/kexec/kexec-elf.h kexec-tools-2.0.16/kexec/kexec-elf.h --- kexec-tools-2.0.10/kexec/kexec-elf.h 2013-11-19 01:05:49.000000000 +0000 +++ kexec-tools-2.0.16/kexec/kexec-elf.h 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/kexec-elf-rel.c kexec-tools-2.0.16/kexec/kexec-elf-rel.c --- kexec-tools-2.0.10/kexec/kexec-elf-rel.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/kexec-elf-rel.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/kexec.h kexec-tools-2.0.16/kexec/kexec.h --- kexec-tools-2.0.10/kexec/kexec.h 2015-04-15 01:05:59.000000000 +0000 +++ kexec-tools-2.0.16/kexec/kexec.h 2017-05-22 11:33:20.000000000 +0000 @@ -136,10 +136,13 @@ #define RANGE_ACPI 2 #define RANGE_ACPI_NVS 3 #define RANGE_UNCACHED 4 +#define RANGE_PMEM 6 +#define RANGE_PRAM 11 }; struct memory_ranges { unsigned int size; + unsigned int max_size; struct memory_range *ranges; }; @@ -216,13 +219,15 @@ #define OPT_TYPE 't' #define OPT_PANIC 'p' #define OPT_KEXEC_FILE_SYSCALL 's' +#define OPT_STATUS 'S' #define OPT_MEM_MIN 256 #define OPT_MEM_MAX 257 #define OPT_REUSE_INITRD 258 #define OPT_LOAD_PRESERVE_CONTEXT 259 #define OPT_LOAD_JUMP_BACK_HELPER 260 #define OPT_ENTRY 261 -#define OPT_MAX 262 +#define OPT_PRINT_CKR_SIZE 262 +#define OPT_MAX 263 #define KEXEC_OPTIONS \ { "help", 0, 0, OPT_HELP }, \ { "version", 0, 0, OPT_VERSION }, \ @@ -242,8 +247,10 @@ { "reuseinitrd", 0, 0, OPT_REUSE_INITRD }, \ { "kexec-file-syscall", 0, 0, OPT_KEXEC_FILE_SYSCALL }, \ { "debug", 0, 0, OPT_DEBUG }, \ + { "status", 0, 0, OPT_STATUS }, \ + { "print-ckr-size", 0, 0, OPT_PRINT_CKR_SIZE }, \ -#define KEXEC_OPT_STR "h?vdfxyluet:ps" +#define KEXEC_OPT_STR "h?vdfxyluet:psS" extern void dbgprint_mem_range(const char *prefix, struct memory_range *mr, int nr_mr); extern void die(const char *fmt, ...) @@ -251,6 +258,7 @@ extern void *xmalloc(size_t size); extern void *xrealloc(void *ptr, size_t size); extern char *slurp_file(const char *filename, off_t *r_size); +extern char *slurp_file_mmap(const char *filename, off_t *r_size); extern char *slurp_file_len(const char *filename, off_t size, off_t *nread); extern char *slurp_decompress_file(const char *filename, off_t *r_size); extern unsigned long virt_to_phys(unsigned long addr); @@ -286,7 +294,7 @@ int arch_compat_trampoline(struct kexec_info *info); void arch_update_purgatory(struct kexec_info *info); int is_crashkernel_mem_reserved(void); -int get_max_crash_kernel_limit(uint64_t *start, uint64_t *end); +int get_crash_kernel_load_range(uint64_t *start, uint64_t *end); char *get_command_line(void); int kexec_iomem_for_each_line(char *match, @@ -307,5 +315,8 @@ int xen_kexec_load(struct kexec_info *info); int xen_kexec_unload(uint64_t kexec_flags); void xen_kexec_exec(void); +int xen_kexec_status(uint64_t kexec_flags); + +extern unsigned long long get_kernel_sym(const char *text); #endif /* KEXEC_H */ diff -Nru kexec-tools-2.0.10/kexec/kexec-iomem.c kexec-tools-2.0.16/kexec/kexec-iomem.c --- kexec-tools-2.0.10/kexec/kexec-iomem.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/kexec-iomem.c 2017-05-22 11:31:03.000000000 +0000 @@ -18,6 +18,9 @@ * Iterate over each line in the file returned by proc_iomem(). If match is * NULL or if the line matches with our match-pattern then call the * callback if non-NULL. + * If match is NULL, callback should return a negative if error. + * Otherwise the interation goes on, incrementing nr but only if callback + * returns 0 (matched). * * Return the number of lines matched. */ @@ -37,24 +40,26 @@ char *str; int consumed; int count; - int nr = 0; + int nr = 0, ret; fp = fopen(iomem, "r"); if (!fp) die("Cannot open %s\n", iomem); while(fgets(line, sizeof(line), fp) != 0) { - count = sscanf(line, "%Lx-%Lx : %n", &start, &end, &consumed); + count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed); if (count != 2) continue; str = line + consumed; size = end - start + 1; if (!match || memcmp(str, match, strlen(match)) == 0) { - if (callback - && callback(data, nr, str, start, size) < 0) { - break; + if (callback) { + ret = callback(data, nr, str, start, size); + if (ret < 0) + break; + else if (ret == 0) + nr++; } - nr++; } } diff -Nru kexec-tools-2.0.10/kexec/kexec-syscall.h kexec-tools-2.0.16/kexec/kexec-syscall.h --- kexec-tools-2.0.10/kexec/kexec-syscall.h 2015-05-01 01:13:09.000000000 +0000 +++ kexec-tools-2.0.16/kexec/kexec-syscall.h 2017-01-24 13:38:40.000000000 +0000 @@ -39,8 +39,8 @@ #ifdef __s390__ #define __NR_kexec_load 277 #endif -#ifdef __arm__ -#define __NR_kexec_load __NR_SYSCALL_BASE + 347 +#if defined(__arm__) || defined(__arm64__) +#define __NR_kexec_load __NR_SYSCALL_BASE + 347 #endif #if defined(__mips__) #define __NR_kexec_load 4311 @@ -48,6 +48,9 @@ #ifdef __m68k__ #define __NR_kexec_load 313 #endif +#ifdef __alpha__ +#define __NR_kexec_load 448 +#endif #ifndef __NR_kexec_load #error Unknown processor architecture. Needs a kexec_load syscall number. #endif @@ -108,6 +111,7 @@ #define KEXEC_ARCH_PPC64 (21 << 16) #define KEXEC_ARCH_IA_64 (50 << 16) #define KEXEC_ARCH_ARM (40 << 16) +#define KEXEC_ARCH_ARM64 (183 << 16) #define KEXEC_ARCH_S390 (22 << 16) #define KEXEC_ARCH_SH (42 << 16) #define KEXEC_ARCH_MIPS_LE (10 << 16) @@ -153,5 +157,8 @@ #ifdef __m68k__ #define KEXEC_ARCH_NATIVE KEXEC_ARCH_68K #endif +#if defined(__arm64__) +#define KEXEC_ARCH_NATIVE KEXEC_ARCH_ARM64 +#endif #endif /* KEXEC_SYSCALL_H */ diff -Nru kexec-tools-2.0.10/kexec/kexec-uImage.c kexec-tools-2.0.16/kexec/kexec-uImage.c --- kexec-tools-2.0.10/kexec/kexec-uImage.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/kexec-uImage.c 2017-03-13 09:01:36.000000000 +0000 @@ -24,7 +24,7 @@ * * Returns 0 if this is not a uImage */ -int uImage_probe(const unsigned char *buf, off_t len, unsigned int arch) +int uImage_probe(const char *buf, off_t len, unsigned int arch) { struct image_header header; #ifdef HAVE_LIBZ @@ -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 @@ -108,7 +109,7 @@ * 1 - If the image is not a uImage. */ -int uImage_probe_kernel(const unsigned char *buf, off_t len, unsigned int arch) +int uImage_probe_kernel(const char *buf, off_t len, unsigned int arch) { int type = uImage_probe(buf, len, arch); if (type < 0) @@ -117,7 +118,7 @@ return !(type == IH_TYPE_KERNEL || type == IH_TYPE_KERNEL_NOLOAD); } -int uImage_probe_ramdisk(const unsigned char *buf, off_t len, unsigned int arch) +int uImage_probe_ramdisk(const char *buf, off_t len, unsigned int arch) { int type = uImage_probe(buf, len, arch); @@ -135,7 +136,7 @@ #define COMMENT 0x10 /* bit 4 set: file comment present */ #define RESERVED 0xE0 /* bits 5..7: reserved */ -static int uImage_gz_load(const unsigned char *buf, off_t len, +static int uImage_gz_load(const char *buf, off_t len, struct Image_info *image) { int ret; @@ -209,9 +210,9 @@ return -1; } + uncomp_buf = new_buf; strm.next_out = uncomp_buf + mem_alloc - inc_buf; strm.avail_out = inc_buf; - uncomp_buf = new_buf; } else { printf("Error during decompression %d\n", ret); return -1; @@ -219,7 +220,7 @@ } while (1); inflateEnd(&strm); - image->buf = uncomp_buf; + image->buf = (char *)uncomp_buf; image->len = mem_alloc - strm.avail_out; return 0; } @@ -231,11 +232,11 @@ } #endif -int uImage_load(const unsigned char *buf, off_t len, struct Image_info *image) +int uImage_load(const char *buf, off_t len, struct Image_info *image) { const struct image_header *header = (const struct image_header *)buf; - const unsigned char *img_buf = buf + sizeof(struct image_header); - off_t img_len = header->ih_size; + const char *img_buf = buf + sizeof(struct image_header); + off_t img_len = be32_to_cpu(header->ih_size); /* * Prevent loading a modified image. diff -Nru kexec-tools-2.0.10/kexec/kexec-xen.c kexec-tools-2.0.16/kexec/kexec-xen.c --- kexec-tools-2.0.10/kexec/kexec-xen.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/kexec-xen.c 2017-01-26 10:20:53.000000000 +0000 @@ -105,6 +105,27 @@ return ret; } +int xen_kexec_status(uint64_t kexec_flags) +{ + xc_interface *xch; + uint8_t type; + int ret = -1; + +#ifdef HAVE_KEXEC_CMD_STATUS + xch = xc_interface_open(NULL, NULL, 0); + if (!xch) + return -1; + + type = (kexec_flags & KEXEC_ON_CRASH) ? KEXEC_TYPE_CRASH : KEXEC_TYPE_DEFAULT; + + ret = xc_kexec_status(xch, type); + + xc_interface_close(xch); +#endif + + return ret; +} + void xen_kexec_exec(void) { xc_interface *xch; @@ -129,6 +150,11 @@ { return -1; } + +int xen_kexec_status(uint64_t kexec_flags) +{ + return -1; +} void xen_kexec_exec(void) { diff -Nru kexec-tools-2.0.10/kexec/Makefile kexec-tools-2.0.16/kexec/Makefile --- kexec-tools-2.0.10/kexec/Makefile 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/kexec/Makefile 2017-05-22 11:33:20.000000000 +0000 @@ -26,6 +26,7 @@ KEXEC_SRCS_base += kexec/lzma.c KEXEC_SRCS_base += kexec/zlib.c KEXEC_SRCS_base += kexec/kexec-xen.c +KEXEC_SRCS_base += kexec/symbols.c KEXEC_GENERATED_SRCS += $(PURGATORY_HEX_C) @@ -69,8 +70,17 @@ $(ARCH)_FS2DT = KEXEC_SRCS += $($(ARCH)_FS2DT) +dist += kexec/mem_regions.c kexec/mem_regions.h +$(ARCH)_MEM_REGIONS = +KEXEC_SRCS += $($(ARCH)_MEM_REGIONS) + +dist += kexec/dt-ops.c kexec/dt-ops.h +$(ARCH)_DT_OPS = +KEXEC_SRCS += $($(ARCH)_DT_OPS) + include $(srcdir)/kexec/arch/alpha/Makefile include $(srcdir)/kexec/arch/arm/Makefile +include $(srcdir)/kexec/arch/arm64/Makefile include $(srcdir)/kexec/arch/i386/Makefile include $(srcdir)/kexec/arch/ia64/Makefile include $(srcdir)/kexec/arch/m68k/Makefile diff -Nru kexec-tools-2.0.10/kexec/mem_regions.c kexec-tools-2.0.16/kexec/mem_regions.c --- kexec-tools-2.0.10/kexec/mem_regions.c 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/mem_regions.c 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,127 @@ +#include + +#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 -Nru kexec-tools-2.0.10/kexec/mem_regions.h kexec-tools-2.0.16/kexec/mem_regions.h --- kexec-tools-2.0.10/kexec/mem_regions.h 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/mem_regions.h 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/phys_to_virt.c kexec-tools-2.0.16/kexec/phys_to_virt.c --- kexec-tools-2.0.10/kexec/phys_to_virt.c 2011-10-11 13:04:50.000000000 +0000 +++ kexec-tools-2.0.16/kexec/phys_to_virt.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec/symbols.c kexec-tools-2.0.16/kexec/symbols.c --- kexec-tools-2.0.10/kexec/symbols.c 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/kexec/symbols.c 2017-05-22 11:33:20.000000000 +0000 @@ -0,0 +1,34 @@ +#include +#include +#include "kexec.h" + +/* Retrieve kernel symbol virtual address from /proc/kallsyms */ +unsigned long long get_kernel_sym(const char *symbol) +{ + const char *kallsyms = "/proc/kallsyms"; + char sym[128]; + char line[128]; + FILE *fp; + unsigned long long vaddr; + char type; + + 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, "%llx %c %s", &vaddr, &type, sym) != 3) + continue; + if (strcmp(sym, symbol) == 0) { + dbgprintf("kernel symbol %s vaddr = %16llx\n", + symbol, vaddr); + return vaddr; + } + } + + dbgprintf("Cannot get kernel %s symbol address\n", symbol); + + return 0; +} diff -Nru kexec-tools-2.0.10/kexec/zlib.c kexec-tools-2.0.16/kexec/zlib.c --- kexec-tools-2.0.10/kexec/zlib.c 2015-02-09 06:00:12.000000000 +0000 +++ kexec-tools-2.0.16/kexec/zlib.c 2016-12-20 08:28:23.000000000 +0000 @@ -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 -Nru kexec-tools-2.0.10/kexec-tools.spec kexec-tools-2.0.16/kexec-tools.spec --- kexec-tools-2.0.10/kexec-tools.spec 2015-06-25 10:14:23.000000000 +0000 +++ kexec-tools-2.0.16/kexec-tools.spec 2017-11-20 09:17:13.000000000 +0000 @@ -1,6 +1,6 @@ Summary: Load one kernel from another Name: kexec-tools -Version: 2.0.10 +Version: 2.0.16 Release: 0 License: GPL Group: Development/Tools diff -Nru kexec-tools-2.0.10/purgatory/arch/arm64/entry.S kexec-tools-2.0.16/purgatory/arch/arm64/entry.S --- kexec-tools-2.0.10/purgatory/arch/arm64/entry.S 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/purgatory/arch/arm64/entry.S 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,51 @@ +/* + * ARM64 purgatory. + */ + +.macro size, sym:req + .size \sym, . - \sym +.endm + +.text + +.globl purgatory_start +purgatory_start: + + adr x19, .Lstack + mov sp, x19 + + bl purgatory + + /* Start new image. */ + ldr x17, arm64_kernel_entry + ldr x0, arm64_dtb_addr + mov x1, xzr + mov x2, xzr + mov x3, xzr + br x17 + +size purgatory_start + +.ltorg + +.align 4 + .rept 256 + .quad 0 + .endr +.Lstack: + +.data + +.align 3 + +.globl arm64_kernel_entry +arm64_kernel_entry: + .quad 0 +size arm64_kernel_entry + +.globl arm64_dtb_addr +arm64_dtb_addr: + .quad 0 +size arm64_dtb_addr + +.end \ No newline at end of file diff -Nru kexec-tools-2.0.10/purgatory/arch/arm64/Makefile kexec-tools-2.0.16/purgatory/arch/arm64/Makefile --- kexec-tools-2.0.10/purgatory/arch/arm64/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/purgatory/arch/arm64/Makefile 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,18 @@ + +arm64_PURGATORY_EXTRA_CFLAGS = \ + -mcmodel=large \ + -fno-stack-protector \ + -fno-asynchronous-unwind-tables \ + -Wundef \ + -Werror-implicit-function-declaration \ + -Wdeclaration-after-statement \ + -Werror=implicit-int \ + -Werror=strict-prototypes + +arm64_PURGATORY_SRCS += \ + purgatory/arch/arm64/entry.S \ + purgatory/arch/arm64/purgatory-arm64.c + +dist += \ + $(arm64_PURGATORY_SRCS) \ + purgatory/arch/arm64/Makefile diff -Nru kexec-tools-2.0.10/purgatory/arch/arm64/purgatory-arm64.c kexec-tools-2.0.16/purgatory/arch/arm64/purgatory-arm64.c --- kexec-tools-2.0.10/purgatory/arch/arm64/purgatory-arm64.c 1970-01-01 00:00:00.000000000 +0000 +++ kexec-tools-2.0.16/purgatory/arch/arm64/purgatory-arm64.c 2016-12-20 08:28:23.000000000 +0000 @@ -0,0 +1,19 @@ +/* + * ARM64 purgatory. + */ + +#include +#include + +void putchar(int ch) +{ + /* Nothing for now */ +} + +void post_verification_setup_arch(void) +{ +} + +void setup_arch(void) +{ +} diff -Nru kexec-tools-2.0.10/purgatory/arch/ia64/Makefile kexec-tools-2.0.16/purgatory/arch/ia64/Makefile --- kexec-tools-2.0.10/purgatory/arch/ia64/Makefile 2010-07-29 09:22:16.000000000 +0000 +++ kexec-tools-2.0.16/purgatory/arch/ia64/Makefile 2016-12-20 08:28:23.000000000 +0000 @@ -8,6 +8,10 @@ ia64_PURGATORY_EXTRA_CFLAGS = -ffixed-r28 +# sha256.c needs to be compiled without optimization, else +# purgatory fails to execute on ia64. +ia64_PURGATORY_SHA256_CFLAGS = -O0 + dist += purgatory/arch/ia64/Makefile $(ia64_PURGATORY_SRCS) \ purgatory/arch/ia64/io.h purgatory/arch/ia64/purgatory-ia64.h diff -Nru kexec-tools-2.0.10/purgatory/arch/ppc64/v2wrap.S kexec-tools-2.0.16/purgatory/arch/ppc64/v2wrap.S --- kexec-tools-2.0.10/purgatory/arch/ppc64/v2wrap.S 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/purgatory/arch/ppc64/v2wrap.S 2016-12-09 09:42:06.000000000 +0000 @@ -114,10 +114,24 @@ LOADADDR(6,run_at_load) # the load flag lwz 7,0(6) # possibly patched by kexec-elf-ppc64 stw 7,0x5c(4) # and patch it into the kernel - li 5,0 # r5 will be 0 for kernel - mtctr 4 # prepare branch too mr 3,16 # restore dt address - # skip cache flush, do we care? + mfmsr 5 + andi. 10,5,1 # test MSR_LE + bne little_endian + li 5,0 # r5 will be 0 for kernel + mtctr 4 # prepare branch to bctr # start kernel + +little_endian: # book3s-only + mtsrr0 4 # prepare branch to + + clrrdi 5,5,1 # clear MSR_LE + mtsrr1 5 + + li 5,0 # r5 will be 0 for kernel + + # skip cache flush, do we care? + + rfid # update MSR and start kernel diff -Nru kexec-tools-2.0.10/purgatory/Makefile kexec-tools-2.0.16/purgatory/Makefile --- kexec-tools-2.0.10/purgatory/Makefile 2015-04-30 05:05:17.000000000 +0000 +++ kexec-tools-2.0.16/purgatory/Makefile 2017-01-31 11:23:48.000000000 +0000 @@ -19,6 +19,7 @@ include $(srcdir)/purgatory/arch/alpha/Makefile include $(srcdir)/purgatory/arch/arm/Makefile +include $(srcdir)/purgatory/arch/arm64/Makefile include $(srcdir)/purgatory/arch/i386/Makefile include $(srcdir)/purgatory/arch/ia64/Makefile include $(srcdir)/purgatory/arch/mips/Makefile @@ -33,13 +34,11 @@ PURGATORY_OBJS = $(call objify, $(PURGATORY_SRCS)) purgatory/sha256.o PURGATORY_DEPS = $(call depify, $(PURGATORY_OBJS)) -clean += $(PURGATORY_OBJS) $(PURGATORY_DEPS) $(PURGATORY) +clean += $(PURGATORY_OBJS) $(PURGATORY_DEPS) $(PURGATORY) $(PURGATORY_MAP) $(PURGATORY).sym -include $(PURGATORY_DEPS) -# sha256.c needs to be compiled without optimization, else -# purgatory fails to execute on ia64. -purgatory/sha256.o: CFLAGS += -O0 +purgatory/sha256.o: CFLAGS += -O2 $($(ARCH)_PURGATORY_SHA256_CFLAGS) purgatory/sha256.o: $(srcdir)/util_lib/sha256.c mkdir -p $(@D) diff -Nru kexec-tools-2.0.10/vmcore-dmesg/vmcore-dmesg.c kexec-tools-2.0.16/vmcore-dmesg/vmcore-dmesg.c --- kexec-tools-2.0.10/vmcore-dmesg/vmcore-dmesg.c 2014-10-14 04:58:06.000000000 +0000 +++ kexec-tools-2.0.16/vmcore-dmesg/vmcore-dmesg.c 2017-11-09 01:20:56.000000000 +0000 @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 600 +#define _GNU_SOURCE #define _LARGEFILE_SOURCE 1 #define _FILE_OFFSET_BITS 64 #include @@ -540,6 +541,12 @@ exit(53); } + /* + * To collect full dmesg including the part before `dmesg -c` is useful + * for later debugging. Use same logic as what crash utility is using. + */ + logged_chars = log_end < log_buf_len ? log_end : log_buf_len; + write_to_stdout(buf + (log_buf_len - logged_chars), logged_chars); } @@ -558,53 +565,12 @@ return(file64_to_cpu(*(uint64_t *)(ptr + offset))); } -/* human readable text of the record */ -static char *log_text(char *msg) -{ - return msg + log_sz; -} - -/* get record by index; idx must point to valid msg */ -static char *log_from_idx(char *log_buf, uint32_t idx) -{ - char *msg = log_buf + idx; - - /* - * A length == 0 record is the end of buffer marker. Wrap around and - * read the message at the start of the buffer. - */ - if (!struct_val_u16(msg, log_offset_len)) - return log_buf; - return msg; -} - -/* get next record; idx must point to valid msg */ -static uint32_t log_next(char *log_buf, uint32_t idx) -{ - char *msg = log_buf + idx; - uint16_t len; - - /* length == 0 indicates the end of the buffer; wrap */ - /* - * A length == 0 record is the end of buffer marker. Wrap around and - * read the message at the start of the buffer as *this* one, and - * return the one after that. - */ - len = struct_val_u16(msg, log_offset_len); - if (!len) { - msg = log_buf; - return struct_val_u16(msg, log_offset_len); - } - return idx + len; -} - /* Read headers of log records and dump accordingly */ static void dump_dmesg_structured(int fd) { #define OUT_BUF_SIZE 4096 uint64_t log_buf, log_buf_offset, ts_nsec; uint32_t log_first_idx, log_next_idx, current_idx, len = 0, i; - int log_buf_len; char *buf, out_buf[OUT_BUF_SIZE]; ssize_t ret; char *msg; @@ -652,34 +618,33 @@ } log_buf = read_file_pointer(fd, vaddr_to_offset(log_buf_vaddr)); - log_buf_len = read_file_s32(fd, vaddr_to_offset(log_buf_len_vaddr)); log_first_idx = read_file_u32(fd, vaddr_to_offset(log_first_idx_vaddr)); log_next_idx = read_file_u32(fd, vaddr_to_offset(log_next_idx_vaddr)); log_buf_offset = vaddr_to_offset(log_buf); - buf = calloc(1, log_buf_len); + buf = calloc(1, log_sz); if (!buf) { - fprintf(stderr, "Failed to malloc %d bytes for the logbuf:" - " %s\n", log_buf_len, strerror(errno)); + fprintf(stderr, "Failed to malloc %" PRId64 " bytes for the log:" + " %s\n", log_sz, strerror(errno)); exit(64); } - ret = pread(fd, buf, log_buf_len, log_buf_offset); - if (ret != log_buf_len) { - fprintf(stderr, "Failed to read log buffer of size %d bytes:" - " %s\n", log_buf_len, strerror(errno)); - exit(65); - } - /* Parse records and write out data at standard output */ current_idx = log_first_idx; len = 0; while (current_idx != log_next_idx) { - msg = log_from_idx(buf, current_idx); - ts_nsec = struct_val_u64(msg, log_offset_ts_nsec); + uint16_t loglen; + + ret = pread(fd, buf, log_sz, log_buf_offset + current_idx); + if (ret != log_sz) { + fprintf(stderr, "Failed to read log of size %" PRId64 " bytes:" + " %s\n", log_sz, strerror(errno)); + exit(65); + } + ts_nsec = struct_val_u64(buf, log_offset_ts_nsec); imaxdiv_sec = imaxdiv(ts_nsec, 1000000000); imaxdiv_usec = imaxdiv(imaxdiv_sec.rem, 1000); @@ -688,9 +653,22 @@ (long long unsigned int)imaxdiv_usec.quot); /* escape non-printable characters */ - text_len = struct_val_u16(msg, log_offset_text_len); + text_len = struct_val_u16(buf, log_offset_text_len); + msg = calloc(1, text_len); + if (!msg) { + fprintf(stderr, "Failed to malloc %u bytes for log text:" + " %s\n", text_len, strerror(errno)); + exit(64); + } + + ret = pread(fd, msg, text_len, log_buf_offset + current_idx + log_sz); + if (ret != text_len) { + fprintf(stderr, "Failed to read log text of size %u bytes:" + " %s\n", text_len, strerror(errno)); + exit(65); + } for (i = 0; i < text_len; i++) { - unsigned char c = log_text(msg)[i]; + unsigned char c = msg[i]; if (!isprint(c) && !isspace(c)) len += sprintf(out_buf + len, "\\x%02x", c); @@ -704,11 +682,19 @@ } out_buf[len++] = '\n'; - - /* Move to next record */ - current_idx = log_next(buf, current_idx); + free(msg); + /* + * A length == 0 record is the end of buffer marker. Wrap around + * and read the message at the start of the buffer. + */ + loglen = struct_val_u16(buf, log_offset_len); + if (!loglen) + current_idx = log_first_idx; + else + /* Move to next record */ + current_idx += loglen; } - + free(buf); if (len) write_to_stdout(out_buf, len); }