├── .github └── workflows │ └── build.yml ├── .gitignore ├── AUTHORS ├── COPYING ├── INSTALL ├── Makefile.in ├── News ├── TODO ├── bootstrap ├── config ├── config.guess ├── config.sub └── install-sh ├── configure.ac ├── doc ├── Makefile ├── linux-i386-boot.txt ├── linux-i386-zero-page.txt ├── mpc85xx.txt ├── multiboot.html └── nbi-spec.txt ├── include ├── Makefile ├── boot │ ├── beoboot.h │ ├── elf_boot.h │ └── linuxbios_tables.h ├── elf.h ├── image.h ├── kexec-pe-zboot.h ├── kexec-uImage.h ├── pe.h ├── unused.h └── x86 │ ├── mb_header.h │ ├── mb_info.h │ ├── multiboot2.h │ └── x86-linux.h ├── kexec-tools.spec.in ├── kexec ├── .gitignore ├── Makefile ├── add_buffer.c ├── add_segment.c ├── arch │ ├── alpha │ │ ├── Makefile │ │ └── include │ │ │ └── arch │ │ │ └── options.h │ ├── arm │ │ ├── Makefile │ │ ├── crashdump-arm.c │ │ ├── crashdump-arm.h │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── iomem.h │ │ ├── kexec-arm.c │ │ ├── kexec-arm.h │ │ ├── kexec-elf-rel-arm.c │ │ ├── kexec-uImage-arm.c │ │ ├── kexec-zImage-arm.c │ │ ├── phys_to_virt.c │ │ └── phys_to_virt.h │ ├── arm64 │ │ ├── Makefile │ │ ├── crashdump-arm64.c │ │ ├── crashdump-arm64.h │ │ ├── image-header.h │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── iomem.h │ │ ├── kexec-arm64.c │ │ ├── kexec-arm64.h │ │ ├── kexec-elf-arm64.c │ │ ├── kexec-image-arm64.c │ │ ├── kexec-uImage-arm64.c │ │ └── kexec-vmlinuz-arm64.c │ ├── cris │ │ ├── Makefile │ │ ├── cris-setup-simple.S │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── kexec-cris.c │ │ ├── kexec-cris.h │ │ ├── kexec-elf-cris.c │ │ └── kexec-elf-rel-cris.c │ ├── hppa │ │ ├── Makefile │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── kexec-elf-hppa.c │ │ ├── kexec-elf-rel-hppa.c │ │ ├── kexec-hppa.c │ │ └── kexec-hppa.h │ ├── i386 │ │ ├── Makefile │ │ ├── crashdump-x86.c │ │ ├── crashdump-x86.h │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── kexec-beoboot-x86.c │ │ ├── kexec-bzImage.c │ │ ├── kexec-elf-rel-x86.c │ │ ├── kexec-elf-x86.c │ │ ├── kexec-mb2-x86.c │ │ ├── kexec-multiboot-x86.c │ │ ├── kexec-nbi.c │ │ ├── kexec-x86-common.c │ │ ├── kexec-x86.c │ │ ├── kexec-x86.h │ │ ├── x86-linux-setup.c │ │ └── x86-linux-setup.h │ ├── ia64 │ │ ├── Makefile │ │ ├── crashdump-ia64.c │ │ ├── crashdump-ia64.h │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── kexec-elf-ia64.c │ │ ├── kexec-elf-rel-ia64.c │ │ ├── kexec-ia64.c │ │ ├── kexec-ia64.h │ │ └── kexec-iomem.c │ ├── loongarch │ │ ├── Makefile │ │ ├── crashdump-loongarch.c │ │ ├── crashdump-loongarch.h │ │ ├── image-header.h │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── iomem.h │ │ ├── kexec-elf-loongarch.c │ │ ├── kexec-elf-rel-loongarch.c │ │ ├── kexec-loongarch.c │ │ ├── kexec-loongarch.h │ │ ├── kexec-pei-loongarch.c │ │ └── kexec-pez-loongarch.c │ ├── m68k │ │ ├── Makefile │ │ ├── bootinfo.c │ │ ├── bootinfo.h │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── kexec-elf-m68k.c │ │ ├── kexec-elf-rel-m68k.c │ │ ├── kexec-m68k.c │ │ └── kexec-m68k.h │ ├── mips │ │ ├── Makefile │ │ ├── crashdump-mips.c │ │ ├── crashdump-mips.h │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── kexec-elf-mips.c │ │ ├── kexec-elf-rel-mips.c │ │ ├── kexec-mips.c │ │ └── kexec-mips.h │ ├── ppc │ │ ├── Makefile │ │ ├── crashdump-powerpc.c │ │ ├── crashdump-powerpc.h │ │ ├── fixup_dtb.c │ │ ├── fixup_dtb.h │ │ ├── fs2dt.c │ │ ├── include │ │ │ ├── arch │ │ │ │ └── options.h │ │ │ ├── page.h │ │ │ └── types.h │ │ ├── kexec-dol-ppc.c │ │ ├── kexec-elf-ppc.c │ │ ├── kexec-elf-rel-ppc.c │ │ ├── kexec-ppc.c │ │ ├── kexec-ppc.h │ │ ├── kexec-uImage-ppc.c │ │ ├── libfdt-wrapper.c │ │ ├── ops.h │ │ ├── ppc-setup-dol.S │ │ ├── ppc-setup-simple.S │ │ └── ppc_asm.h │ ├── ppc64 │ │ ├── Makefile │ │ ├── crashdump-ppc64.c │ │ ├── crashdump-ppc64.h │ │ ├── fdt.c │ │ ├── include │ │ │ └── arch │ │ │ │ ├── fdt.h │ │ │ │ └── options.h │ │ ├── kexec-elf-ppc64.c │ │ ├── kexec-elf-rel-ppc64.c │ │ ├── kexec-ppc64.c │ │ ├── kexec-ppc64.h │ │ └── kexec-zImage-ppc64.c │ ├── riscv │ │ ├── Makefile │ │ ├── crashdump-riscv.c │ │ ├── image-header.h │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── iomem.h │ │ ├── kexec-elf-riscv.c │ │ ├── kexec-image-riscv.c │ │ ├── kexec-riscv.c │ │ └── kexec-riscv.h │ ├── s390 │ │ ├── Makefile │ │ ├── crashdump-s390.c │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── kexec-elf-rel-s390.c │ │ ├── kexec-image.c │ │ ├── kexec-s390.c │ │ └── kexec-s390.h │ ├── sh │ │ ├── Makefile │ │ ├── crashdump-sh.c │ │ ├── crashdump-sh.h │ │ ├── include │ │ │ └── arch │ │ │ │ └── options.h │ │ ├── kexec-elf-rel-sh.c │ │ ├── kexec-elf-sh.c │ │ ├── kexec-netbsd-sh.c │ │ ├── kexec-sh.c │ │ ├── kexec-sh.h │ │ ├── kexec-uImage-sh.c │ │ ├── kexec-zImage-sh.c │ │ └── netbsd_booter.S │ └── x86_64 │ │ ├── Makefile │ │ ├── include │ │ └── arch │ │ │ └── options.h │ │ ├── kexec-bzImage64.c │ │ ├── kexec-elf-rel-x86_64.c │ │ ├── kexec-elf-x86_64.c │ │ ├── kexec-x86_64.c │ │ └── kexec-x86_64.h ├── arch_reuse_initrd.c ├── crashdump-elf.c ├── crashdump-xen.c ├── crashdump.c ├── crashdump.h ├── dt-ops.c ├── dt-ops.h ├── firmware_memmap.c ├── firmware_memmap.h ├── fs2dt.c ├── fs2dt.h ├── ifdown.c ├── kexec-elf-boot.c ├── kexec-elf-boot.h ├── kexec-elf-core.c ├── kexec-elf-exec.c ├── kexec-elf-rel.c ├── kexec-elf.c ├── kexec-elf.h ├── kexec-iomem.c ├── kexec-lzma.h ├── kexec-pe-zboot.c ├── kexec-sha256.h ├── kexec-syscall.h ├── kexec-uImage.c ├── kexec-uki.c ├── kexec-xen.c ├── kexec-xen.h ├── kexec-zlib.h ├── kexec-zstd.h ├── kexec.8 ├── kexec.c ├── kexec.h ├── libfdt │ ├── Makefile.libfdt │ ├── TODO │ ├── fdt.c │ ├── fdt.h │ ├── fdt_ro.c │ ├── fdt_rw.c │ ├── fdt_strerror.c │ ├── fdt_sw.c │ ├── fdt_wip.c │ ├── libfdt.h │ ├── libfdt_env.h │ └── libfdt_internal.h ├── lzma.c ├── mem_regions.c ├── mem_regions.h ├── phys_arch.c ├── phys_to_virt.c ├── proc_iomem.c ├── symbols.c ├── virt_to_phys.c ├── zlib.c └── zstd.c ├── kexec_test ├── Makefile ├── kexec_test.S ├── kexec_test16.S └── x86-setup-legacy-pic.S ├── purgatory ├── Makefile ├── arch │ ├── alpha │ │ └── Makefile │ ├── arm │ │ └── Makefile │ ├── arm64 │ │ ├── Makefile │ │ ├── entry.S │ │ └── purgatory-arm64.c │ ├── i386 │ │ ├── Makefile │ │ ├── compat_x86_64.S │ │ ├── console-x86.c │ │ ├── crashdump_backup.c │ │ ├── entry32-16-debug.S │ │ ├── entry32-16.S │ │ ├── entry32.S │ │ ├── include │ │ │ └── arch │ │ │ │ ├── debug.h │ │ │ │ └── io.h │ │ ├── pic.c │ │ ├── purgatory-x86.c │ │ ├── purgatory-x86.h │ │ ├── setup-x86.S │ │ ├── stack.S │ │ └── vga.c │ ├── ia64 │ │ ├── Makefile │ │ ├── console-ia64.c │ │ ├── entry.S │ │ ├── io.h │ │ ├── purgatory-ia64.c │ │ ├── purgatory-ia64.h │ │ └── vga.c │ ├── loongarch │ │ ├── Makefile │ │ ├── console-loongarch.c │ │ ├── purgatory-loongarch.c │ │ └── purgatory-loongarch.h │ ├── mips │ │ ├── Makefile │ │ ├── console-mips.c │ │ ├── purgatory-mips.c │ │ └── purgatory-mips.h │ ├── ppc │ │ ├── Makefile │ │ ├── console-ppc.c │ │ ├── misc.S │ │ ├── ppc_asm.h │ │ ├── purgatory-ppc.c │ │ ├── purgatory-ppc.h │ │ └── v2wrap_32.S │ ├── ppc64 │ │ ├── Makefile │ │ ├── console-ppc64.c │ │ ├── crashdump_backup.c │ │ ├── hvCall.S │ │ ├── hvCall.h │ │ ├── misc.S │ │ ├── ppc64_asm.h │ │ ├── purgatory-ppc64.c │ │ ├── purgatory-ppc64.h │ │ └── v2wrap.S │ ├── riscv │ │ └── Makefile │ ├── s390 │ │ ├── Makefile │ │ ├── console-s390.c │ │ ├── purgatory-s390.c │ │ └── setup-s390.S │ ├── sh │ │ └── Makefile │ └── x86_64 │ │ ├── Makefile │ │ ├── entry64-32.S │ │ ├── entry64.S │ │ ├── include │ │ └── arch │ │ │ ├── debug.h │ │ │ └── io.h │ │ ├── purgatory-x86_64.c │ │ ├── purgatory-x86_64.h │ │ ├── setup-x86_64.S │ │ └── stack.S ├── include │ ├── purgatory.h │ └── string.h ├── printf.c ├── purgatory.c └── string.c ├── util ├── Makefile └── bin-to-hex.c ├── util_lib ├── Makefile ├── compute_ip_checksum.c ├── elf_info.c ├── include │ ├── elf_info.h │ ├── ip_checksum.h │ └── sha256.h └── sha256.c └── vmcore-dmesg ├── Makefile ├── vmcore-dmesg.8 └── vmcore-dmesg.c /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: push 4 | 5 | jobs: 6 | build: 7 | name: Build 8 | runs-on: ubuntu-24.04 9 | strategy: 10 | matrix: 11 | arch: 12 | - arm 13 | - arm64 14 | - hppa 15 | - i686 16 | - m68k 17 | - mips 18 | - mipsel 19 | - powerpc 20 | - powerpc64 21 | - powerpc64le 22 | - riscv64 23 | - sh4 24 | - s390x 25 | - x86_64-x32 26 | include: 27 | - arch: x86_64 28 | - arch: x86_64 29 | libxen: libxen 30 | steps: 31 | - name: Checkout 32 | uses: actions/checkout@v4 33 | 34 | - name: Set Environment 35 | env: 36 | LIBXEN: ${{ matrix.libxen }} 37 | ARCH: ${{ matrix.arch }} 38 | run: | 39 | case $LIBXEN in 40 | libxen) EXTRA_PKGS+=" libxen-dev" ;; 41 | esac 42 | 43 | case $ARCH in 44 | arm) GNU_ARCH="arm-linux-gnueabi" ;; 45 | arm64) GNU_ARCH="aarch64-linux-gnu" ;; 46 | x86_64) ;; 47 | x86_64-x32) GNU_ARCH="x86_64-linux-gnux32" 48 | CROSS_COMPILER_PKG="gcc-x86-64-linux-gnux32" ;; 49 | *) GNU_ARCH="$ARCH-linux-gnu" ;; 50 | esac 51 | 52 | if [ -n "$GNU_ARCH" ]; then 53 | if [ -z "$CROSS_COMPILER_PKG" ]; then 54 | CROSS_COMPILER_PKG="gcc-$GNU_ARCH" 55 | fi 56 | EXTRA_PKGS+=" $CROSS_COMPILER_PKG" 57 | CONFIG_FLAGS+=" --host=$GNU_ARCH" 58 | fi 59 | 60 | echo "EXTRA_PKGS=$EXTRA_PKGS" >> $GITHUB_ENV 61 | echo "CONFIG_FLAGS=$CONFIG_FLAGS" >> $GITHUB_ENV 62 | 63 | - name: Install Dependencies 64 | if: env.EXTRA_PKGS != '' 65 | run: | 66 | sudo apt-get update 67 | sudo apt-get -q=2 install ${{ env.EXTRA_PKGS }} 68 | 69 | - name: Build 70 | run: | 71 | ./bootstrap 72 | ./configure ${{ env.CONFIG_FLAGS }} 73 | make -j"$(nproc)" distcheck \ 74 | DISTCHECK_CONFIGURE_FLAGS="${{ env.CONFIG_FLAGS }}" 75 | 76 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # Normal rules 3 | # 4 | *~ 5 | *.a 6 | *.d 7 | *.o 8 | *.ro 9 | 10 | # generated files 11 | /Makefile 12 | /autom4te.cache/ 13 | /bin/ 14 | /build/ 15 | /config.log 16 | /config.status 17 | /configure 18 | /include/config.h.in 19 | /include/config.h 20 | /purgatory/purgatory.map 21 | /purgatory/purgatory.ro.sym 22 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Eric Biederman 2 | Albert Herranz 3 | Jesse Barnes 4 | Khalid Aziz 5 | Hariprasad Nellitheertha 6 | Tim Deegan 7 | And others... 8 | 9 | Currently maintained by 10 | P: Simon Horman 11 | M: horms@verge.net.au 12 | L: kexec@lists.infradead.org 13 | 14 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | 4 | 5 | Checkout from git 6 | ----------------- 7 | 8 | If you use the tarball, you can just skip that section. If you checked out the 9 | kexec-tools from git repository, you have to build the Autoconf-generated 10 | file yourself with running 11 | 12 | ./bootstrap 13 | 14 | You have to install "autoconf" for that. After that, you should have a file 15 | called "configure" in the top-level directory of kexec-tools, and you can 16 | continue with the next step. 17 | 18 | 19 | General 20 | ------- 21 | 22 | You should check first if your favourite Linux distribution doesn't offer a 23 | package. If that package is recent enough, you should consider using that 24 | package instead. 25 | 26 | However, if you want to install kexec-tools from sources 27 | 28 | (1) Run ./configure [--prefix=/usr/local] [options]... 29 | e.g. 30 | 31 | ./configure --prefix=/usr/local 32 | 33 | For a full list of options run 34 | 35 | ./configure --help 36 | 37 | (2) Run make 38 | 39 | make 40 | 41 | (3) To install kexec-tools 42 | After following the above instructions to build-kexec tools, run 43 | 44 | make install 45 | 46 | 47 | Static compilation 48 | ------------------ 49 | 50 | To compile kexec-tools statically (i.e., independent of libraries that are 51 | present on the system), use 52 | 53 | LDFLAGS=-static ./configure 54 | 55 | instead. 56 | 57 | 58 | Cross compilation 59 | ----------------- 60 | 61 | Because kexec is also used in the embedded world, cross-compilation is 62 | supported. You cannot only set "CC", "LD", "CCFLAGS" and "LDFLAGS" environment 63 | variables for the ./configure call as usual, you can also set 64 | 65 | TARGET_CC -- the C compiler used for files that should run on the 66 | target 67 | TARGET_CCFLAGS -- compilation flags for $TARGET_CC 68 | TARGET_LD -- linker used for files that should run on the 69 | target 70 | 71 | Because the build process also requires files that must be executed during the 72 | build, you also need a host compiler, only the target compiler is not enough. 73 | 74 | BUILD_CC -- the C compiler used for files that should run on the 75 | host (the system that builds the kexec-tools) 76 | BUILD_CFLAGS -- compilation flags for $BUILD_CC 77 | 78 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - x86 handle x86 vmlinux parameter header allocation issues. 2 | There is a bug where it can get stomped but the current code 3 | does not allow us much flexibility in what we do with it. 4 | - Restore enough state that DOS/arbitrary BIOS calls can be run on some 5 | platforms. Currently disk-related calls are quite likely to blow up. 6 | - x86 filling in other kernel parameters. 7 | - Merge reboot via kexec functionality into /sbin/reboot 8 | - Improve the documentation 9 | - Add support for loading a boot sector 10 | - Autobuilding of initramfs 11 | ### 12 | -------------------------------------------------------------------------------- /bootstrap: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # bootstrap -- Use this script to create generated files from the CVS dist 3 | # Copyright (C) 2000 Gary V. Vaughan 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2, or (at your option) 8 | # any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | 19 | ## @start 1 20 | #! /bin/sh 21 | 22 | set -x 23 | aclocal -I config 24 | autoheader 25 | autoconf 26 | 27 | ## @end 1 28 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | dist += doc/Makefile \ 2 | doc/linux-i386-boot.txt \ 3 | doc/linux-i386-zero-page.txt \ 4 | doc/multiboot.html \ 5 | doc/nbi-spec.txt 6 | -------------------------------------------------------------------------------- /include/Makefile: -------------------------------------------------------------------------------- 1 | dist += include/Makefile \ 2 | include/config.h \ 3 | include/config.h.in \ 4 | include/kexec-pe-zboot.h \ 5 | include/kexec-uImage.h \ 6 | include/x86/x86-linux.h \ 7 | include/x86/mb_info.h \ 8 | include/x86/mb_header.h \ 9 | include/x86/multiboot2.h \ 10 | include/elf.h \ 11 | include/pe.h \ 12 | include/image.h \ 13 | include/unused.h \ 14 | include/boot/linuxbios_tables.h \ 15 | include/boot/beoboot.h \ 16 | include/boot/elf_boot.h 17 | -------------------------------------------------------------------------------- /include/boot/beoboot.h: -------------------------------------------------------------------------------- 1 | 2 | /*--- Boot image definitions ---------------------------------------*/ 3 | struct beoboot_header { 4 | char magic[4]; 5 | uint8_t arch; 6 | uint8_t flags; 7 | uint16_t cmdline_size;/* length of command line (including null) */ 8 | /* The alpha chunk is a backward compatibility hack. The original 9 | * assumption was that integer sizes didn't matter because we 10 | * would never mix architectures. x86_64 + i386 broke that 11 | * assumption. It's fixed for that combination and the future. 12 | * However, alpha needs a little hack now... */ 13 | #ifdef __alpha__ 14 | unsigned long kernel_size; 15 | unsigned long initrd_size; 16 | #else 17 | uint32_t kernel_size; 18 | uint32_t initrd_size; 19 | #endif 20 | }; 21 | #define BEOBOOT_MAGIC "BeoB" 22 | #define BEOBOOT_ARCH_I386 1 23 | #define BEOBOOT_ARCH_ALPHA 2 24 | #define BEOBOOT_ARCH_PPC 3 25 | #define BEOBOOT_ARCH_PPC64 4 26 | #if defined(__i386__) || defined(__x86_64__) 27 | #define BEOBOOT_ARCH BEOBOOT_ARCH_I386 28 | #elif defined(__alpha__) 29 | #define BEOBOOT_ARCH BEOBOOT_ARCH_ALPHA 30 | #elif defined(powerpc) 31 | #define BEOBOOT_ARCH BEOBOOT_ARCH_PPC 32 | #elif defined(__powerpc64__) 33 | #define BEOBOOT_ARCH BEOBOOT_ARCH_PPC64 34 | #else 35 | #error Unsupported architecture. 36 | #endif 37 | #define BEOBOOT_INITRD_PRESENT 1 38 | /*------------------------------------------------------------------*/ 39 | 40 | -------------------------------------------------------------------------------- /include/boot/linuxbios_tables.h: -------------------------------------------------------------------------------- 1 | #ifndef LINUXBIOS_TABLES_H 2 | #define LINUXBIOS_TABLES_H 3 | 4 | #include 5 | 6 | /* The linuxbios table information is for conveying information 7 | * from the firmware to the loaded OS image. Primarily this 8 | * is expected to be information that cannot be discovered by 9 | * other means, such as quering the hardware directly. 10 | * 11 | * All of the information should be Position Independent Data. 12 | * That is it should be safe to relocated any of the information 13 | * without it's meaning/correctnes changing. For table that 14 | * can reasonably be used on multiple architectures the data 15 | * size should be fixed. This should ease the transition between 16 | * 32 bit and 64 bit architectures etc. 17 | * 18 | * The completeness test for the information in this table is: 19 | * - Can all of the hardware be detected? 20 | * - Are the per motherboard constants available? 21 | * - Is there enough to allow a kernel to run that was written before 22 | * a particular motherboard is constructed? (Assuming the kernel 23 | * has drivers for all of the hardware but it does not have 24 | * assumptions on how the hardware is connected together). 25 | * 26 | * With this test it should be straight forward to determine if a 27 | * table entry is required or not. This should remove much of the 28 | * long term compatibility burden as table entries which are 29 | * irrelevant or have been replaced by better alternatives may be 30 | * dropped. Of course it is polite and expidite to include extra 31 | * table entries and be backwards compatible, but it is not required. 32 | */ 33 | 34 | 35 | struct lb_header 36 | { 37 | uint8_t signature[4]; /* LBIO */ 38 | uint32_t header_bytes; 39 | uint32_t header_checksum; 40 | uint32_t table_bytes; 41 | uint32_t table_checksum; 42 | uint32_t table_entries; 43 | }; 44 | 45 | /* Every entry in the boot enviroment list will correspond to a boot 46 | * info record. Encoding both type and size. The type is obviously 47 | * so you can tell what it is. The size allows you to skip that 48 | * boot enviroment record if you don't know what it easy. This allows 49 | * forward compatibility with records not yet defined. 50 | */ 51 | struct lb_record { 52 | uint32_t tag; /* tag ID */ 53 | uint32_t size; /* size of record (in bytes) */ 54 | }; 55 | 56 | #define LB_TAG_UNUSED 0x0000 57 | 58 | #define LB_TAG_MEMORY 0x0001 59 | 60 | struct lb_memory_range { 61 | uint64_t start; 62 | uint64_t size; 63 | uint32_t type; 64 | #define LB_MEM_RAM 1 65 | #define LB_MEM_RESERVED 2 66 | 67 | }; 68 | 69 | struct lb_memory { 70 | uint32_t tag; 71 | uint32_t size; 72 | struct lb_memory_range map[0]; 73 | }; 74 | 75 | #define LB_TAG_HWRPB 0x0002 76 | struct lb_hwrpb { 77 | uint32_t tag; 78 | uint32_t size; 79 | uint64_t hwrpb; 80 | }; 81 | 82 | #endif /* LINUXBIOS_TABLES_H */ 83 | -------------------------------------------------------------------------------- /include/kexec-pe-zboot.h: -------------------------------------------------------------------------------- 1 | #ifndef __KEXEC_PE_ZBOOT_H__ 2 | #define __KEXEC_PE_ZBOOT_H__ 3 | 4 | /* see drivers/firmware/efi/libstub/zboot-header.S */ 5 | struct linux_pe_zboot_header { 6 | uint32_t mz_magic; 7 | uint32_t image_type; 8 | uint32_t payload_offset; 9 | uint32_t payload_size; 10 | uint32_t reserved[2]; 11 | uint32_t compress_type; 12 | }; 13 | 14 | int pez_prepare(const char *crude_buf, off_t buf_sz, int *kernel_fd, 15 | off_t *kernel_size); 16 | #endif 17 | -------------------------------------------------------------------------------- /include/kexec-uImage.h: -------------------------------------------------------------------------------- 1 | #ifndef __KEXEC_UIMAGE_H__ 2 | #define __KEXEC_UIMAGE_H__ 3 | 4 | struct Image_info { 5 | const char *buf; 6 | off_t len; 7 | unsigned int base; 8 | unsigned int ep; 9 | }; 10 | 11 | int uImage_probe(const char *buf, off_t len, unsigned int arch); 12 | int uImage_probe_kernel(const char *buf, off_t len, unsigned int arch); 13 | int uImage_probe_ramdisk(const char *buf, off_t len, unsigned int arch); 14 | int uImage_load(const char *buf, off_t len, struct Image_info *info); 15 | #endif 16 | -------------------------------------------------------------------------------- /include/unused.h: -------------------------------------------------------------------------------- 1 | #ifndef UNUSED_H 2 | #define UNUSED_H 3 | 4 | /* http://sourcefrog.net/weblog/software/languages/C/unused.html */ 5 | 6 | #ifdef UNUSED 7 | #elif defined(__GNUC__) 8 | # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) 9 | #elif defined(__LCLINT__) 10 | # define UNUSED(x) /*@unused@*/ x 11 | #else 12 | # define UNUSED(x) x 13 | #endif 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /kexec-tools.spec.in: -------------------------------------------------------------------------------- 1 | Summary: Load one kernel from another 2 | Name: kexec-tools 3 | Version: 4 | Release: 0 5 | License: GPL 6 | Group: Development/Tools 7 | Source0:%{name}-%{version}.tar.gz 8 | Packager: Eric Biederman 9 | BuildRoot: %{_tmppath}/%{name} 10 | 11 | %description 12 | /sbin/kexec is a user space utility for loading another kernel 13 | and asking the currently running kernel to do something with it. 14 | A currently running kernel may be asked to start the loaded 15 | kernel on reboot, or to start the loaded kernel after it panics. 16 | 17 | The panic case is useful for having an intact kernel for writing 18 | crash dumps. But other uses may be imagined. 19 | 20 | %prep 21 | %setup -q -n %{name}-%{version} 22 | 23 | %build 24 | %configure 25 | make 26 | 27 | %install 28 | make install DESTDIR=${RPM_BUILD_ROOT} 29 | 30 | %files 31 | %defattr(-,root,root) 32 | %{_sbindir}/kexec 33 | %{_sbindir}/vmcore-dmesg 34 | %doc News 35 | %doc COPYING 36 | %doc TODO 37 | %{_mandir}/man8/kexec.8.gz 38 | %{_mandir}/man8/vmcore-dmesg.8.gz 39 | 40 | %changelog 41 | * Tue Dec 16 2004 Eric Biederman 42 | - kexec-tools initialy packaged as an rpm. 43 | -------------------------------------------------------------------------------- /kexec/.gitignore: -------------------------------------------------------------------------------- 1 | purgatory.c 2 | -------------------------------------------------------------------------------- /kexec/add_buffer.c: -------------------------------------------------------------------------------- 1 | #include "kexec.h" 2 | 3 | unsigned long add_buffer(struct kexec_info *info, 4 | const void *buf, 5 | unsigned long bufsz, 6 | unsigned long memsz, 7 | unsigned long buf_align, 8 | unsigned long buf_min, 9 | unsigned long buf_max, 10 | int buf_end) 11 | { 12 | return add_buffer_virt(info, buf, bufsz, memsz, buf_align, 13 | buf_min, buf_max, buf_end); 14 | } 15 | -------------------------------------------------------------------------------- /kexec/add_segment.c: -------------------------------------------------------------------------------- 1 | #include "kexec.h" 2 | 3 | void add_segment(struct kexec_info *info, 4 | const void *buf, size_t bufsz, 5 | unsigned long base, size_t memsz) 6 | { 7 | return add_segment_phys_virt(info, buf, bufsz, base, memsz, 0); 8 | } 9 | -------------------------------------------------------------------------------- /kexec/arch/alpha/Makefile: -------------------------------------------------------------------------------- 1 | alpha_KEXEC_SRCS= 2 | dist += kexec/arch/alpha/Makefile kexec/arch/alpha/include/arch/options.h 3 | $(alpha_KEXEC_SRCS) 4 | 5 | -------------------------------------------------------------------------------- /kexec/arch/alpha/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_ALPHA_OPTIONS_H 2 | #define KEXEC_ARCH_ALPHA_OPTIONS_H 3 | 4 | #define OPT_ARCH_MAX (OPT_MAX+0) 5 | 6 | /* Options relevant to the architecture (excluding loader-specific ones), 7 | * in this case none: 8 | */ 9 | #define KEXEC_ARCH_OPTIONS \ 10 | KEXEC_OPTIONS \ 11 | 12 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 13 | 14 | /* See the other architectures for details of these; Alpha has no 15 | * loader-specific options yet. 16 | */ 17 | #define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS 18 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR 19 | 20 | #endif /* KEXEC_ARCH_ALPHA_OPTIONS_H */ 21 | -------------------------------------------------------------------------------- /kexec/arch/arm/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec arm (linux booting linux) 3 | # 4 | include $(srcdir)/kexec/libfdt/Makefile.libfdt 5 | 6 | arm_FS2DT = kexec/fs2dt.c 7 | arm_FS2DT_INCLUDE = -include $(srcdir)/kexec/arch/arm/crashdump-arm.h \ 8 | -include $(srcdir)/kexec/arch/arm/kexec-arm.h 9 | 10 | arm_MEM_REGIONS = kexec/mem_regions.c 11 | 12 | arm_KEXEC_SRCS= kexec/arch/arm/kexec-elf-rel-arm.c 13 | arm_KEXEC_SRCS+= kexec/arch/arm/kexec-zImage-arm.c 14 | arm_KEXEC_SRCS+= kexec/arch/arm/kexec-uImage-arm.c 15 | arm_KEXEC_SRCS+= kexec/arch/arm/kexec-arm.c 16 | arm_KEXEC_SRCS+= kexec/arch/arm/crashdump-arm.c 17 | arm_KEXEC_SRCS+= kexec/fs2dt.c 18 | 19 | libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) 20 | 21 | arm_CPPFLAGS = -I$(srcdir)/kexec/libfdt 22 | 23 | # We want 64-bit file IO for kdump to work correctly on LPAE systems 24 | arm_CPPFLAGS += -D_FILE_OFFSET_BITS=64 25 | 26 | arm_KEXEC_SRCS += $(libfdt_SRCS) 27 | 28 | arm_UIMAGE = kexec/kexec-uImage.c 29 | arm_PHYS_TO_VIRT = kexec/arch/arm/phys_to_virt.c 30 | 31 | dist += kexec/arch/arm/Makefile $(arm_KEXEC_SRCS) $(arm_PHYS_TO_VIRT) \ 32 | kexec/arch/arm/iomem.h kexec/arch/arm/phys_to_virt.h \ 33 | kexec/arch/arm/crashdump-arm.h kexec/arch/arm/kexec-arm.h \ 34 | kexec/arch/arm/include/arch/options.h 35 | -------------------------------------------------------------------------------- /kexec/arch/arm/crashdump-arm.h: -------------------------------------------------------------------------------- 1 | #ifndef CRASHDUMP_ARM_H 2 | #define CRASHDUMP_ARM_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define COMMAND_LINE_SIZE 1024 9 | #define DEFAULT_PAGE_OFFSET (0xc0000000) 10 | #define KVBASE_MASK (0x1ffffff) 11 | #define CRASH_MAX_MEMORY_RANGES 32 12 | #define ARM_MAX_VIRTUAL UINT32_MAX 13 | 14 | 15 | extern struct memory_ranges usablemem_rgns; 16 | extern struct memory_range crash_kernel_mem; 17 | extern struct memory_range elfcorehdr_mem; 18 | 19 | struct kexec_info; 20 | 21 | extern int load_crashdump_segments(struct kexec_info *, char *); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif /* CRASHDUMP_ARM_H */ 28 | -------------------------------------------------------------------------------- /kexec/arch/arm/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_ARM_OPTIONS_H 2 | #define KEXEC_ARCH_ARM_OPTIONS_H 3 | 4 | #define OPT_DT_NO_OLD_ROOT (OPT_MAX+0) 5 | #define OPT_ARCH_MAX (OPT_MAX+1) 6 | 7 | #define OPT_DTB (OPT_ARCH_MAX+0) 8 | #define OPT_ATAGS (OPT_ARCH_MAX+1) 9 | #define OPT_IMAGE_SIZE (OPT_ARCH_MAX+2) 10 | #define OPT_PAGE_OFFSET (OPT_ARCH_MAX+3) 11 | #define OPT_APPEND (OPT_ARCH_MAX+4) 12 | #define OPT_RAMDISK (OPT_ARCH_MAX+5) 13 | 14 | /* Options relevant to the architecture (excluding loader-specific ones), 15 | * in this case none: 16 | */ 17 | #define KEXEC_ARCH_OPTIONS \ 18 | KEXEC_OPTIONS \ 19 | { "dt-no-old-root", 0, 0, OPT_DT_NO_OLD_ROOT }, \ 20 | 21 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 22 | 23 | /* The following two #defines list ALL of the options added by all of the 24 | * architecture's loaders. 25 | * o main() uses this complete list to scan for its options, ignoring 26 | * arch-specific/loader-specific ones. 27 | * o Then, arch_process_options() uses this complete list to scan for its 28 | * options, ignoring general/loader-specific ones. 29 | * o Then, the file_type[n].load re-scans for options, using 30 | * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. 31 | * Any unrecognised options cause an error here. 32 | * 33 | * This is done so that main()'s/arch_process_options()'s getopt_long() calls 34 | * don't choose a kernel filename from random arguments to options they don't 35 | * recognise -- as they now recognise (if not act upon) all possible options. 36 | */ 37 | #define KEXEC_ALL_OPTIONS \ 38 | KEXEC_ARCH_OPTIONS \ 39 | { "command-line", 1, 0, OPT_APPEND }, \ 40 | { "append", 1, 0, OPT_APPEND }, \ 41 | { "initrd", 1, 0, OPT_RAMDISK }, \ 42 | { "ramdisk", 1, 0, OPT_RAMDISK }, \ 43 | { "dtb", 1, 0, OPT_DTB }, \ 44 | { "atags", 0, 0, OPT_ATAGS }, \ 45 | { "image-size", 1, 0, OPT_IMAGE_SIZE }, \ 46 | { "page-offset", 1, 0, OPT_PAGE_OFFSET }, 47 | 48 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR "" 49 | 50 | extern unsigned int kexec_arm_image_size; 51 | 52 | #endif /* KEXEC_ARCH_ARM_OPTIONS_H */ 53 | -------------------------------------------------------------------------------- /kexec/arch/arm/iomem.h: -------------------------------------------------------------------------------- 1 | #ifndef IOMEM_H 2 | #define IOMEM_H 3 | 4 | #define SYSTEM_RAM "System RAM\n" 5 | #define SYSTEM_RAM_BOOT "System RAM (boot alias)\n" 6 | #define CRASH_KERNEL "Crash kernel\n" 7 | #define CRASH_KERNEL_BOOT "Crash kernel (boot alias)\n" 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /kexec/arch/arm/kexec-arm.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARM_H 2 | #define KEXEC_ARM_H 3 | 4 | #include 5 | 6 | #define SYSFS_FDT "/sys/firmware/fdt" 7 | #define BOOT_BLOCK_VERSION 17 8 | #define BOOT_BLOCK_LAST_COMP_VERSION 16 9 | 10 | extern off_t initrd_base, initrd_size; 11 | 12 | int zImage_arm_probe(const char *buf, off_t len); 13 | int zImage_arm_load(int argc, char **argv, const char *buf, off_t len, 14 | struct kexec_info *info); 15 | void zImage_arm_usage(void); 16 | 17 | int uImage_arm_probe(const char *buf, off_t len); 18 | int uImage_arm_load(int argc, char **argv, const char *buf, off_t len, 19 | struct kexec_info *info); 20 | extern int have_sysfs_fdt(void); 21 | 22 | #endif /* KEXEC_ARM_H */ 23 | -------------------------------------------------------------------------------- /kexec/arch/arm/kexec-elf-rel-arm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../kexec.h" 4 | #include "../../kexec-elf.h" 5 | 6 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 7 | { 8 | if (ehdr->ei_data != ELFDATA2MSB) { 9 | return 0; 10 | } 11 | if (ehdr->ei_class != ELFCLASS32) { 12 | return 0; 13 | } 14 | if (ehdr->e_machine != EM_ARM) 15 | { 16 | return 0; 17 | } 18 | return 1; 19 | } 20 | 21 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 22 | struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, 23 | unsigned long address, unsigned long value) 24 | { 25 | switch(r_type) { 26 | case R_ARM_ABS32: 27 | *((uint32_t *)location) += value; 28 | break; 29 | case R_ARM_REL32: 30 | *((uint32_t *)location) += value - address; 31 | break; 32 | default: 33 | die("Unknown rel relocation: %lu\n", r_type); 34 | break; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kexec/arch/arm/kexec-uImage-arm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * uImage support added by Marc Andre Tanner 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../../kexec.h" 10 | #include "kexec-arm.h" 11 | 12 | int uImage_arm_probe(const char *buf, off_t len) 13 | { 14 | return uImage_probe_kernel(buf, len, IH_ARCH_ARM); 15 | } 16 | 17 | int uImage_arm_load(int argc, char **argv, const char *buf, off_t len, 18 | struct kexec_info *info) 19 | { 20 | return zImage_arm_load(argc, argv, buf + sizeof(struct image_header), 21 | len - sizeof(struct image_header), info); 22 | } 23 | -------------------------------------------------------------------------------- /kexec/arch/arm/phys_to_virt.c: -------------------------------------------------------------------------------- 1 | #include "../../kexec.h" 2 | #include "../../crashdump.h" 3 | #include "phys_to_virt.h" 4 | 5 | uint64_t phys_offset; 6 | 7 | /** 8 | * phys_to_virt() - translate physical address to virtual address 9 | * @paddr: physical address to translate 10 | * 11 | * For ARM we have following equation to translate from virtual address to 12 | * physical: 13 | * paddr = vaddr - PAGE_OFFSET + PHYS_OFFSET 14 | * 15 | * See also: 16 | * http://lists.arm.linux.org.uk/lurker/message/20010723.185051.94ce743c.en.html 17 | */ 18 | unsigned long 19 | phys_to_virt(struct crash_elf_info *elf_info, unsigned long long paddr) 20 | { 21 | return paddr + elf_info->page_offset - phys_offset; 22 | } 23 | -------------------------------------------------------------------------------- /kexec/arch/arm/phys_to_virt.h: -------------------------------------------------------------------------------- 1 | #ifndef PHYS_TO_VIRT_H 2 | #define PHYS_TO_VIRT_H 3 | 4 | #include 5 | 6 | extern uint64_t phys_offset; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /kexec/arch/arm64/Makefile: -------------------------------------------------------------------------------- 1 | 2 | arm64_FS2DT += kexec/fs2dt.c 3 | arm64_FS2DT_INCLUDE += \ 4 | -include $(srcdir)/kexec/arch/arm64/crashdump-arm64.h \ 5 | -include $(srcdir)/kexec/arch/arm64/kexec-arm64.h 6 | 7 | arm64_DT_OPS += kexec/dt-ops.c 8 | 9 | arm64_MEM_REGIONS = kexec/mem_regions.c 10 | 11 | arm64_CPPFLAGS += -I $(srcdir)/kexec/ 12 | 13 | arm64_KEXEC_SRCS += \ 14 | kexec/arch/arm64/crashdump-arm64.c \ 15 | kexec/arch/arm64/kexec-arm64.c \ 16 | kexec/arch/arm64/kexec-elf-arm64.c \ 17 | kexec/arch/arm64/kexec-uImage-arm64.c \ 18 | kexec/arch/arm64/kexec-image-arm64.c \ 19 | kexec/arch/arm64/kexec-vmlinuz-arm64.c 20 | 21 | arm64_UIMAGE = kexec/kexec-uImage.c 22 | 23 | arm64_ARCH_REUSE_INITRD = 24 | arm64_ADD_SEGMENT = 25 | arm64_VIRT_TO_PHYS = 26 | arm64_PHYS_TO_VIRT = 27 | 28 | dist += $(arm64_KEXEC_SRCS) \ 29 | kexec/arch/arm64/include/arch/options.h \ 30 | kexec/arch/arm64/crashdump-arm64.h \ 31 | kexec/arch/arm64/image-header.h \ 32 | kexec/arch/arm64/iomem.h \ 33 | kexec/arch/arm64/kexec-arm64.h \ 34 | kexec/arch/arm64/Makefile 35 | 36 | ifdef HAVE_LIBFDT 37 | 38 | LIBS += -lfdt 39 | 40 | else 41 | 42 | include $(srcdir)/kexec/libfdt/Makefile.libfdt 43 | 44 | libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) 45 | 46 | arm64_CPPFLAGS += -I$(srcdir)/kexec/libfdt 47 | 48 | arm64_KEXEC_SRCS += $(libfdt_SRCS) 49 | 50 | endif 51 | -------------------------------------------------------------------------------- /kexec/arch/arm64/crashdump-arm64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ARM64 crashdump. 3 | * 4 | * Copyright (c) 2014-2017 Linaro Limited 5 | * Author: AKASHI Takahiro 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License version 2 as 9 | * published by the Free Software Foundation. 10 | */ 11 | 12 | #ifndef CRASHDUMP_ARM64_H 13 | #define CRASHDUMP_ARM64_H 14 | 15 | #include "kexec.h" 16 | 17 | #define CRASH_MAX_MEMORY_RANGES 32768 18 | 19 | /* crash dump kernel support at most two regions, low_region and high region. */ 20 | #define CRASH_MAX_RESERVED_RANGES 2 21 | 22 | extern struct memory_ranges usablemem_rgns; 23 | extern struct memory_range crash_reserved_mem[]; 24 | extern struct memory_range elfcorehdr_mem; 25 | 26 | extern int load_crashdump_segments(struct kexec_info *info); 27 | extern void fixup_elf_addrs(struct mem_ehdr *ehdr); 28 | 29 | #endif /* CRASHDUMP_ARM64_H */ 30 | -------------------------------------------------------------------------------- /kexec/arch/arm64/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #if !defined(KEXEC_ARCH_ARM64_OPTIONS_H) 2 | #define KEXEC_ARCH_ARM64_OPTIONS_H 3 | 4 | #define OPT_APPEND ((OPT_MAX)+0) 5 | #define OPT_DTB ((OPT_MAX)+1) 6 | #define OPT_INITRD ((OPT_MAX)+2) 7 | #define OPT_REUSE_CMDLINE ((OPT_MAX)+3) 8 | #define OPT_SERIAL ((OPT_MAX)+4) 9 | #define OPT_ARCH_MAX ((OPT_MAX)+5) 10 | 11 | #define KEXEC_ARCH_OPTIONS \ 12 | KEXEC_OPTIONS \ 13 | { "append", 1, NULL, OPT_APPEND }, \ 14 | { "command-line", 1, NULL, OPT_APPEND }, \ 15 | { "dtb", 1, NULL, OPT_DTB }, \ 16 | { "initrd", 1, NULL, OPT_INITRD }, \ 17 | { "serial", 1, NULL, OPT_SERIAL }, \ 18 | { "ramdisk", 1, NULL, OPT_INITRD }, \ 19 | { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \ 20 | 21 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */ 22 | #define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS 23 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR 24 | 25 | static const char arm64_opts_usage[] __attribute__ ((unused)) = 26 | " --append=STRING Set the kernel command line to STRING.\n" 27 | " --command-line=STRING Set the kernel command line to STRING.\n" 28 | " --dtb=FILE Use FILE as the device tree blob.\n" 29 | " --initrd=FILE Use FILE as the kernel initial ramdisk.\n" 30 | " --serial=STRING Name of console used for purgatory printing. (e.g. ttyAMA0)\n" 31 | " --ramdisk=FILE Use FILE as the kernel initial ramdisk.\n" 32 | " --reuse-cmdline Use kernel command line from running system.\n"; 33 | 34 | struct arm64_opts { 35 | const char *command_line; 36 | const char *dtb; 37 | const char *initrd; 38 | const char *console; 39 | }; 40 | 41 | extern struct arm64_opts arm64_opts; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /kexec/arch/arm64/iomem.h: -------------------------------------------------------------------------------- 1 | #ifndef IOMEM_H 2 | #define IOMEM_H 3 | 4 | #define SYSTEM_RAM "System RAM\n" 5 | #define KERNEL_CODE "Kernel code\n" 6 | #define KERNEL_DATA "Kernel data\n" 7 | #define CRASH_KERNEL "Crash kernel\n" 8 | #define IOMEM_RESERVED "reserved\n" 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kexec/arch/arm64/kexec-arm64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ARM64 kexec. 3 | */ 4 | 5 | #if !defined(KEXEC_ARM64_H) 6 | #define KEXEC_ARM64_H 7 | 8 | #include 9 | #include 10 | 11 | #include "image-header.h" 12 | #include "kexec.h" 13 | 14 | #define KEXEC_SEGMENT_MAX 64 15 | 16 | #define BOOT_BLOCK_VERSION 17 17 | #define BOOT_BLOCK_LAST_COMP_VERSION 16 18 | #define COMMAND_LINE_SIZE 2048 /* from kernel */ 19 | 20 | #define KiB(x) ((x) * 1024UL) 21 | #define MiB(x) (KiB(x) * 1024UL) 22 | #define GiB(x) (MiB(x) * 1024UL) 23 | 24 | #define ULONGLONG_MAX (~0ULL) 25 | 26 | /* 27 | * Incorrect address 28 | */ 29 | #define NOT_KV_ADDR (0x0) 30 | #define NOT_PADDR (ULONGLONG_MAX) 31 | 32 | int elf_arm64_probe(const char *kernel_buf, off_t kernel_size); 33 | int elf_arm64_load(int argc, char **argv, const char *kernel_buf, 34 | off_t kernel_size, struct kexec_info *info); 35 | void elf_arm64_usage(void); 36 | 37 | int image_arm64_probe(const char *kernel_buf, off_t kernel_size); 38 | int image_arm64_load(int argc, char **argv, const char *kernel_buf, 39 | off_t kernel_size, struct kexec_info *info); 40 | void image_arm64_usage(void); 41 | 42 | int uImage_arm64_probe(const char *buf, off_t len); 43 | int uImage_arm64_load(int argc, char **argv, const char *buf, off_t len, 44 | struct kexec_info *info); 45 | void uImage_arm64_usage(void); 46 | 47 | int pez_arm64_probe(const char *kernel_buf, off_t kernel_size); 48 | int pez_arm64_load(int argc, char **argv, const char *buf, off_t len, 49 | struct kexec_info *info); 50 | void pez_arm64_usage(void); 51 | 52 | 53 | extern off_t initrd_base; 54 | extern off_t initrd_size; 55 | 56 | /** 57 | * struct arm64_mem - Memory layout info. 58 | */ 59 | 60 | struct arm64_mem { 61 | int64_t phys_offset; 62 | uint64_t text_offset; 63 | uint64_t image_size; 64 | uint64_t vp_offset; 65 | }; 66 | 67 | #define arm64_mem_ngv UINT64_MAX 68 | extern struct arm64_mem arm64_mem; 69 | 70 | uint64_t get_phys_offset(void); 71 | uint64_t get_vp_offset(void); 72 | int get_page_offset(unsigned long *offset); 73 | 74 | static inline void reset_vp_offset(void) 75 | { 76 | arm64_mem.vp_offset = arm64_mem_ngv; 77 | } 78 | 79 | int arm64_process_image_header(const struct arm64_image_header *h); 80 | unsigned long arm64_locate_kernel_segment(struct kexec_info *info); 81 | int arm64_load_other_segments(struct kexec_info *info, 82 | unsigned long image_base); 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /kexec/arch/arm64/kexec-uImage-arm64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * uImage support added by David Woodhouse 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../../kexec.h" 10 | #include "kexec-arm64.h" 11 | 12 | int uImage_arm64_probe(const char *buf, off_t len) 13 | { 14 | int ret; 15 | 16 | ret = uImage_probe_kernel(buf, len, IH_ARCH_ARM64); 17 | 18 | /* 0 - valid uImage. 19 | * -1 - uImage is corrupted. 20 | * 1 - image is not a uImage. 21 | */ 22 | if (!ret) 23 | return 0; 24 | else 25 | return -1; 26 | } 27 | 28 | int uImage_arm64_load(int argc, char **argv, const char *buf, off_t len, 29 | struct kexec_info *info) 30 | { 31 | struct Image_info img; 32 | int ret; 33 | 34 | if (info->file_mode) { 35 | fprintf(stderr, 36 | "uImage is not supported in kexec_file\n"); 37 | 38 | return EFAILED; 39 | } 40 | 41 | ret = uImage_load(buf, len, &img); 42 | if (ret) 43 | return ret; 44 | 45 | return image_arm64_load(argc, argv, img.buf, img.len, info); 46 | } 47 | 48 | void uImage_arm64_usage(void) 49 | { 50 | printf( 51 | " An ARM64 U-boot uImage file, compressed or not, big or little endian.\n\n"); 52 | } 53 | -------------------------------------------------------------------------------- /kexec/arch/cris/Makefile: -------------------------------------------------------------------------------- 1 | cris_KEXEC_SRCS = kexec/arch/cris/kexec-cris.c 2 | cris_KEXEC_SRCS += kexec/arch/cris/kexec-elf-cris.c 3 | cris_KEXEC_SRCS += kexec/arch/cris/cris-setup-simple.S 4 | cris_KEXEC_SRCS += kexec/arch/cris/kexec-elf-rel-cris.c 5 | 6 | cris_ADD_BUFFER = 7 | cris_ADD_SEGMENT = 8 | cris_VIRT_TO_PHYS = 9 | 10 | dist += kexec/arch/cris/Makefile $(cris_KEXEC_SRCS) \ 11 | kexec/arch/cris/kexec-cris.h \ 12 | kexec/arch/cris/include/arch/options.h 13 | 14 | -------------------------------------------------------------------------------- /kexec/arch/cris/cris-setup-simple.S: -------------------------------------------------------------------------------- 1 | /* 2 | * cris-setup-simple.S - code to execute before stepping into the new kernel. 3 | * Copyright (C) 2008 AXIS Communications AB 4 | * Written by Edgar E. Iglesias 5 | * 6 | * This source code is licensed under the GNU General Public License, 7 | * Version 2. See the file COPYING for more details. 8 | */ 9 | 10 | .data 11 | .globl cris_trampoline 12 | cris_trampoline: 13 | .balign 4 14 | lapc cris_regframe, $sp 15 | moveq 0, $r0 16 | move $r0, $pid 17 | 18 | movem [$sp+], $r14 19 | jump $r0 20 | nop 21 | 22 | .globl cris_regframe 23 | cris_regframe: 24 | .balign 4 25 | .fill 16, 4, 0 26 | cris_trampoline_end: 27 | 28 | .globl cris_trampoline_size 29 | cris_trampoline_size: 30 | .long cris_trampoline_end - cris_trampoline 31 | 32 | -------------------------------------------------------------------------------- /kexec/arch/cris/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_CRIS_OPTIONS_H 2 | #define KEXEC_ARCH_CRIS_OPTIONS_H 3 | 4 | #define OPT_ARCH_MAX (OPT_MAX+0) 5 | #define OPT_APPEND (OPT_ARCH_MAX+0) 6 | 7 | /* Options relevant to the architecture (excluding loader-specific ones), 8 | * in this case none: 9 | */ 10 | #define KEXEC_ARCH_OPTIONS \ 11 | KEXEC_OPTIONS \ 12 | 13 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 14 | 15 | /* The following two #defines list ALL of the options added by all of the 16 | * architecture's loaders. 17 | * o main() uses this complete list to scan for its options, ignoring 18 | * arch-specific/loader-specific ones. 19 | * o Then, arch_process_options() uses this complete list to scan for its 20 | * options, ignoring general/loader-specific ones. 21 | * o Then, the file_type[n].load re-scans for options, using 22 | * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. 23 | * Any unrecognised options cause an error here. 24 | * 25 | * This is done so that main()'s/arch_process_options()'s getopt_long() calls 26 | * don't choose a kernel filename from random arguments to options they don't 27 | * recognise -- as they now recognise (if not act upon) all possible options. 28 | */ 29 | #define KEXEC_ALL_OPTIONS \ 30 | KEXEC_ARCH_OPTIONS \ 31 | {"append", 1, 0, OPT_APPEND}, 32 | 33 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR 34 | 35 | #endif /* KEXEC_ARCH_CRIS_OPTIONS_H */ 36 | -------------------------------------------------------------------------------- /kexec/arch/cris/kexec-cris.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_CRIS_H 2 | #define KEXEC_CRIS_H 3 | 4 | int elf_cris_probe(const char *buf, off_t len); 5 | int elf_cris_load(int argc, char **argv, const char *buf, off_t len, 6 | struct kexec_info *info); 7 | void elf_cris_usage(void); 8 | 9 | #endif /* KEXEC_CRIS_H */ 10 | -------------------------------------------------------------------------------- /kexec/arch/cris/kexec-elf-rel-cris.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec-elf-rel-cris.c - kexec Elf relocation routines 3 | * Copyright (C) 2008 AXIS Communications AB 4 | * Written by Edgar E. Iglesias 5 | * 6 | * derived from ../ppc/kexec-elf-rel-ppc.c 7 | * Copyright (C) 2004 Albert Herranz 8 | * 9 | * This source code is licensed under the GNU General Public License, 10 | * Version 2. See the file COPYING for more details. 11 | */ 12 | 13 | #include 14 | #include 15 | #include "../../kexec.h" 16 | #include "../../kexec-elf.h" 17 | 18 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 19 | { 20 | if (ehdr->ei_data != ELFDATA2MSB) { 21 | return 0; 22 | } 23 | if (ehdr->ei_class != ELFCLASS32) { 24 | return 0; 25 | } 26 | if (ehdr->e_machine != EM_CRIS) { 27 | return 0; 28 | } 29 | return 1; 30 | } 31 | 32 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 33 | struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, 34 | unsigned long address, unsigned long value) 35 | { 36 | switch(r_type) { 37 | 38 | default: 39 | die("Unknown rela relocation: %lu\n", r_type); 40 | break; 41 | } 42 | return; 43 | } 44 | -------------------------------------------------------------------------------- /kexec/arch/hppa/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec hppa (linux booting linux) 3 | # 4 | hppa_KEXEC_SRCS = kexec/arch/hppa/kexec-hppa.c 5 | hppa_KEXEC_SRCS += kexec/arch/hppa/kexec-elf-hppa.c 6 | hppa_KEXEC_SRCS += kexec/arch/hppa/kexec-elf-rel-hppa.c 7 | 8 | hppa_ADD_SEGMENT = 9 | hppa_VIRT_TO_PHYS = 10 | 11 | dist += kexec/arch/hppa/Makefile $(hppa_KEXEC_SRCS) \ 12 | kexec/arch/hppa/kexec-hppa.h \ 13 | kexec/arch/hppa/include/arch/options.h 14 | -------------------------------------------------------------------------------- /kexec/arch/hppa/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_HPPA_OPTIONS_H 2 | #define KEXEC_ARCH_HPPA_OPTIONS_H 3 | 4 | #define OPT_ARCH_MAX (OPT_MAX+0) 5 | 6 | #define KEXEC_ARCH_OPTIONS \ 7 | KEXEC_OPTIONS 8 | 9 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 10 | 11 | #define KEXEC_ALL_OPTIONS \ 12 | KEXEC_ARCH_OPTIONS \ 13 | { "command-line", 1, 0, OPT_APPEND }, \ 14 | { "reuse-cmdline", 0, 0, OPT_REUSE_CMDLINE }, \ 15 | { "append", 1, 0, OPT_APPEND }, \ 16 | { "initrd", 1, 0, OPT_RAMDISK }, \ 17 | { "ramdisk", 1, 0, OPT_RAMDISK }, 18 | 19 | 20 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR "" 21 | 22 | /* See the other architectures for details of these; HPPA has no 23 | * loader-specific options yet. 24 | */ 25 | #define OPT_ARCH_MAX (OPT_MAX+0) 26 | 27 | #define OPT_APPEND (OPT_ARCH_MAX+0) 28 | #define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1) 29 | #define OPT_RAMDISK (OPT_ARCH_MAX+2) 30 | 31 | #define MAX_MEMORY_RANGES 16 32 | #endif /* KEXEC_ARCH_HPPA_OPTIONS_H */ 33 | -------------------------------------------------------------------------------- /kexec/arch/hppa/kexec-elf-rel-hppa.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec-elf-rel-hppa.c - kexec Elf relocation routines 3 | * 4 | * Copyright (C) 2019 Sven Schnelle 5 | * 6 | * This source code is licensed under the GNU General Public License, 7 | * Version 2. See the file COPYING for more details. 8 | */ 9 | 10 | #include 11 | #include 12 | #include "../../kexec.h" 13 | #include "../../kexec-elf.h" 14 | 15 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 16 | { 17 | if (ehdr->ei_data != ELFDATA2MSB) 18 | return 0; 19 | if (ehdr->e_machine != EM_PARISC) 20 | return 0; 21 | return 1; 22 | } 23 | 24 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 25 | struct mem_sym *UNUSED(sym), 26 | unsigned long r_type, 27 | void *UNUSED(location), 28 | unsigned long UNUSED(address), 29 | unsigned long UNUSED(value)) 30 | { 31 | switch (r_type) { 32 | default: 33 | die("Unknown rela relocation: %lu\n", r_type); 34 | break; 35 | } 36 | return; 37 | } 38 | -------------------------------------------------------------------------------- /kexec/arch/hppa/kexec-hppa.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_HPPA_H 2 | #define KEXEC_HPPA_H 3 | 4 | int elf_hppa_probe(const char *buf, off_t len); 5 | int elf_hppa_load(int argc, char **argv, const char *buf, off_t len, 6 | struct kexec_info *info); 7 | void elf_hppa_usage(void); 8 | 9 | #endif /* KEXEC_HPPA_H */ 10 | -------------------------------------------------------------------------------- /kexec/arch/i386/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec i386 (linux booting linux) 3 | # 4 | i386_KEXEC_SRCS = kexec/arch/i386/kexec-x86.c 5 | i386_KEXEC_SRCS += kexec/arch/i386/kexec-x86-common.c 6 | i386_KEXEC_SRCS += kexec/arch/i386/kexec-elf-x86.c 7 | i386_KEXEC_SRCS += kexec/arch/i386/kexec-elf-rel-x86.c 8 | i386_KEXEC_SRCS += kexec/arch/i386/kexec-bzImage.c 9 | i386_KEXEC_SRCS += kexec/arch/i386/kexec-multiboot-x86.c 10 | i386_KEXEC_SRCS += kexec/arch/i386/kexec-mb2-x86.c 11 | i386_KEXEC_SRCS += kexec/arch/i386/kexec-beoboot-x86.c 12 | i386_KEXEC_SRCS += kexec/arch/i386/kexec-nbi.c 13 | i386_KEXEC_SRCS += kexec/arch/i386/x86-linux-setup.c 14 | i386_KEXEC_SRCS += kexec/arch/i386/crashdump-x86.c 15 | 16 | dist += kexec/arch/i386/Makefile $(i386_KEXEC_SRCS) \ 17 | kexec/arch/i386/crashdump-x86.h \ 18 | kexec/arch/i386/kexec-x86.h \ 19 | kexec/arch/i386/x86-linux-setup.h \ 20 | kexec/arch/i386/include/arch/options.h 21 | -------------------------------------------------------------------------------- /kexec/arch/i386/crashdump-x86.h: -------------------------------------------------------------------------------- 1 | #ifndef CRASHDUMP_X86_H 2 | #define CRASHDUMP_X86_H 3 | 4 | struct kexec_info; 5 | int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline, 6 | unsigned long max_addr, unsigned long min_base); 7 | 8 | #define X86_PAGE_OFFSET 0xc0000000 9 | #define x86__pa(x) ((unsigned long)(x)-X86_PAGE_OFFSET) 10 | 11 | #define X86__VMALLOC_RESERVE (128 << 20) 12 | #define X86_MAXMEM (-X86_PAGE_OFFSET-X86__VMALLOC_RESERVE) 13 | 14 | #define X86_64__START_KERNEL_map 0xffffffff80000000ULL 15 | #define X86_64_PAGE_OFFSET_PRE_2_6_27 0xffff810000000000ULL 16 | #define X86_64_PAGE_OFFSET_PRE_4_20_0 0xffff880000000000ULL 17 | #define X86_64_PAGE_OFFSET 0xffff888000000000ULL 18 | 19 | #define X86_64_MAXMEM 0x3fffffffffffUL 20 | 21 | /* Kernel text size */ 22 | #define X86_64_KERNEL_TEXT_SIZE (512UL*1024*1024) 23 | 24 | #define CRASH_MAX_MEMMAP_NR 1024 25 | 26 | #define CRASH_MAX_MEMORY_RANGES 32768 27 | 28 | /* Backup Region, First 640K of System RAM. */ 29 | #define BACKUP_SRC_START 0x00000000 30 | #define BACKUP_SRC_END 0x0009ffff 31 | #define BACKUP_SRC_SIZE (BACKUP_SRC_END - BACKUP_SRC_START + 1) 32 | 33 | #endif /* CRASHDUMP_X86_H */ 34 | -------------------------------------------------------------------------------- /kexec/arch/i386/kexec-elf-rel-x86.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../kexec.h" 4 | #include "../../kexec-elf.h" 5 | 6 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 7 | { 8 | if (ehdr->ei_data != ELFDATA2LSB) { 9 | return 0; 10 | } 11 | if (ehdr->ei_class != ELFCLASS32) { 12 | return 0; 13 | } 14 | if ((ehdr->e_machine != EM_386) && (ehdr->e_machine != EM_486)) 15 | { 16 | return 0; 17 | } 18 | return 1; 19 | } 20 | 21 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 22 | struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, 23 | unsigned long address, unsigned long value) 24 | { 25 | switch(r_type) { 26 | case R_386_32: 27 | *((uint32_t *)location) += value; 28 | break; 29 | case R_386_PC32: 30 | *((uint32_t *)location) += value - address; 31 | break; 32 | default: 33 | die("Unknown rel relocation: %lu\n", r_type); 34 | break; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kexec/arch/i386/kexec-x86.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_X86_H 2 | #define KEXEC_X86_H 3 | 4 | #define MAX_MEMORY_RANGES 2048 5 | 6 | enum coretype { 7 | CORE_TYPE_UNDEF = 0, 8 | CORE_TYPE_ELF32 = 1, 9 | CORE_TYPE_ELF64 = 2 10 | }; 11 | 12 | extern unsigned char compat_x86_64[]; 13 | extern uint32_t compat_x86_64_size, compat_x86_64_entry32; 14 | 15 | struct entry32_regs { 16 | uint32_t eax; 17 | uint32_t ebx; 18 | uint32_t ecx; 19 | uint32_t edx; 20 | uint32_t esi; 21 | uint32_t edi; 22 | uint32_t esp; 23 | uint32_t ebp; 24 | uint32_t eip; 25 | }; 26 | 27 | struct entry16_regs { 28 | uint32_t eax; 29 | uint32_t ebx; 30 | uint32_t ecx; 31 | uint32_t edx; 32 | uint32_t esi; 33 | uint32_t edi; 34 | uint32_t esp; 35 | uint32_t ebp; 36 | uint16_t ds; 37 | uint16_t es; 38 | uint16_t ss; 39 | uint16_t fs; 40 | uint16_t gs; 41 | uint16_t ip; 42 | uint16_t cs; 43 | uint16_t pad; 44 | }; 45 | 46 | struct arch_options_t { 47 | uint8_t reset_vga; 48 | uint16_t serial_base; 49 | uint32_t serial_baud; 50 | uint8_t console_vga; 51 | uint8_t console_serial; 52 | enum coretype core_header_type; 53 | uint8_t pass_memmap_cmdline; 54 | uint8_t noefi; 55 | uint8_t reuse_video_type; 56 | }; 57 | 58 | int multiboot_x86_probe(const char *buf, off_t len); 59 | int multiboot_x86_load(int argc, char **argv, const char *buf, off_t len, 60 | struct kexec_info *info); 61 | void multiboot_x86_usage(void); 62 | 63 | int multiboot2_x86_load(int argc, char **argv, const char *buf, off_t len, 64 | struct kexec_info *info); 65 | void multiboot2_x86_usage(void); 66 | int multiboot2_x86_probe(const char *buf, off_t buf_len); 67 | 68 | int elf_x86_probe(const char *buf, off_t len); 69 | int elf_x86_any_probe(const char *buf, off_t len, enum coretype arch); 70 | int elf_x86_load(int argc, char **argv, const char *buf, off_t len, 71 | struct kexec_info *info); 72 | void elf_x86_usage(void); 73 | 74 | int bzImage_probe(const char *buf, off_t len); 75 | int bzImage_load(int argc, char **argv, const char *buf, off_t len, 76 | struct kexec_info *info); 77 | void bzImage_usage(void); 78 | int do_bzImage_load(struct kexec_info *info, 79 | const char *kernel, off_t kernel_len, 80 | const char *command_line, off_t command_line_len, 81 | const char *initrd, off_t initrd_len, 82 | const char *dtb, off_t dtb_len, 83 | int real_mode_entry); 84 | 85 | int beoboot_probe(const char *buf, off_t len); 86 | int beoboot_load(int argc, char **argv, const char *buf, off_t len, 87 | struct kexec_info *info); 88 | void beoboot_usage(void); 89 | 90 | int nbi_probe(const char *buf, off_t len); 91 | int nbi_load(int argc, char **argv, const char *buf, off_t len, 92 | struct kexec_info *info); 93 | void nbi_usage(void); 94 | 95 | extern unsigned xen_e820_to_kexec_type(uint32_t type); 96 | extern uint64_t get_acpi_rsdp(void); 97 | #endif /* KEXEC_X86_H */ 98 | -------------------------------------------------------------------------------- /kexec/arch/i386/x86-linux-setup.h: -------------------------------------------------------------------------------- 1 | #ifndef X86_LINUX_SETUP_H 2 | #define X86_LINUX_SETUP_H 3 | #include 4 | 5 | void init_linux_parameters(struct x86_linux_param_header *real_mode); 6 | void setup_linux_bootloader_parameters_high( 7 | struct kexec_info *info, struct x86_linux_param_header *real_mode, 8 | unsigned long real_mode_base, unsigned long cmdline_offset, 9 | const char *cmdline, off_t cmdline_len, 10 | const char *initrd_buf, off_t initrd_size, int initrd_high); 11 | static inline void setup_linux_bootloader_parameters( 12 | struct kexec_info *info, struct x86_linux_param_header *real_mode, 13 | unsigned long real_mode_base, unsigned long cmdline_offset, 14 | const char *cmdline, off_t cmdline_len, 15 | const char *initrd_buf, off_t initrd_size) 16 | { 17 | setup_linux_bootloader_parameters_high(info, 18 | real_mode, real_mode_base, 19 | cmdline_offset, cmdline, cmdline_len, 20 | initrd_buf, initrd_size, 0); 21 | } 22 | void setup_linux_system_parameters(struct kexec_info *info, 23 | struct x86_linux_param_header *real_mode); 24 | void setup_linux_dtb(struct kexec_info *info, struct x86_linux_param_header *real_mode, 25 | const char *dtb_buf, int dtb_len); 26 | int get_bootparam(void *buf, off_t offset, size_t size); 27 | 28 | 29 | #define SETUP_BASE 0x90000 30 | #define KERN32_BASE 0x100000 /* 1MB */ 31 | #define INITRD_BASE 0x1000000 /* 16MB */ 32 | 33 | /* command line parameter may be appended by purgatory */ 34 | #define PURGATORY_CMDLINE_SIZE 64 35 | extern int bzImage_support_efi_boot; 36 | extern struct arch_options_t arch_options; 37 | 38 | #endif /* X86_LINUX_SETUP_H */ 39 | -------------------------------------------------------------------------------- /kexec/arch/ia64/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec ia64 (linux booting linux) 3 | # 4 | ia64_KEXEC_SRCS = kexec/arch/ia64/kexec-iomem.c 5 | ia64_KEXEC_SRCS += kexec/arch/ia64/kexec-ia64.c 6 | ia64_KEXEC_SRCS += kexec/arch/ia64/kexec-elf-ia64.c 7 | ia64_KEXEC_SRCS += kexec/arch/ia64/kexec-elf-rel-ia64.c 8 | ia64_KEXEC_SRCS += kexec/arch/ia64/crashdump-ia64.c 9 | 10 | ia64_PROC_IOMEM = 11 | 12 | dist += kexec/arch/ia64/Makefile $(ia64_KEXEC_SRCS) \ 13 | kexec/arch/ia64/kexec-ia64.h kexec/arch/ia64/crashdump-ia64.h \ 14 | kexec/arch/ia64/include/arch/options.h 15 | 16 | 17 | -------------------------------------------------------------------------------- /kexec/arch/ia64/crashdump-ia64.h: -------------------------------------------------------------------------------- 1 | #ifndef CRASHDUMP_IA64_H 2 | #define CRASHDUMP_IA64_H 3 | 4 | #define PAGE_OFFSET 0xe000000000000000UL 5 | #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) 6 | extern int load_crashdump_segments(struct kexec_info *info, 7 | struct mem_ehdr *ehdr, unsigned long max_addr, 8 | unsigned long min_base, const char **cmdline); 9 | 10 | #define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1) 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /kexec/arch/ia64/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_IA64_OPTIONS_H 2 | #define KEXEC_ARCH_IA64_OPTIONS_H 3 | 4 | #define OPT_ARCH_MAX (OPT_MAX+0) 5 | #define OPT_APPEND (OPT_ARCH_MAX+0) 6 | #define OPT_RAMDISK (OPT_ARCH_MAX+1) 7 | #define OPT_NOIO (OPT_ARCH_MAX+2) 8 | #define OPT_VMM (OPT_ARCH_MAX+3) 9 | 10 | /* Options relevant to the architecture (excluding loader-specific ones), 11 | * in this case none: 12 | */ 13 | #define KEXEC_ARCH_OPTIONS \ 14 | KEXEC_OPTIONS \ 15 | 16 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 17 | 18 | /* The following two #defines list ALL of the options added by all of the 19 | * architecture's loaders. 20 | * o main() uses this complete list to scan for its options, ignoring 21 | * arch-specific/loader-specific ones. 22 | * o Then, arch_process_options() uses this complete list to scan for its 23 | * options, ignoring general/loader-specific ones. 24 | * o Then, the file_type[n].load re-scans for options, using 25 | * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. 26 | * Any unrecognised options cause an error here. 27 | * 28 | * This is done so that main()'s/arch_process_options()'s getopt_long() calls 29 | * don't choose a kernel filename from random arguments to options they don't 30 | * recognise -- as they now recognise (if not act upon) all possible options. 31 | */ 32 | #define KEXEC_ALL_OPTIONS \ 33 | KEXEC_ARCH_OPTIONS \ 34 | {"command-line", 1, 0, OPT_APPEND}, \ 35 | {"append", 1, 0, OPT_APPEND}, \ 36 | {"initrd", 1, 0, OPT_RAMDISK}, \ 37 | {"noio", 0, 0, OPT_NOIO}, \ 38 | {"vmm", 1, 0, OPT_VMM}, \ 39 | 40 | #define KEXEC_ALL_OPT_STR KEXEC_OPT_STR 41 | 42 | #endif /* KEXEC_ARCH_IA64_OPTIONS_H */ 43 | -------------------------------------------------------------------------------- /kexec/arch/ia64/kexec-ia64.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_IA64_H 2 | #define KEXEC_IA64_H 3 | 4 | extern int max_memory_ranges; 5 | int elf_ia64_probe(const char *buf, off_t len); 6 | int elf_ia64_load(int argc, char **argv, const char *buf, off_t len, 7 | struct kexec_info *info); 8 | void elf_ia64_usage(void); 9 | int update_loaded_segments(struct mem_ehdr *ehdr); 10 | void move_loaded_segments(struct mem_ehdr *ehdr, unsigned long addr); 11 | 12 | #define EFI_PAGE_SIZE (1UL<<12) 13 | #define ELF_PAGE_SIZE (1UL<<16) 14 | #endif /* KEXEC_IA64_H */ 15 | -------------------------------------------------------------------------------- /kexec/arch/ia64/kexec-iomem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../kexec.h" 4 | #include "../../crashdump.h" 5 | 6 | static const char proc_iomem_str[]= "/proc/iomem"; 7 | static const char proc_iomem_machine_str[]= "/proc/iomem_machine"; 8 | 9 | /* 10 | * On IA64 XEN the EFI tables are virtualised. 11 | * For this reason on such systems /proc/iomem_machine is provided, 12 | * which is based on the hypervisor's (machine's) EFI tables. 13 | * If Xen is in use, then /proc/iomem is used for memory regions relating 14 | * to the currently running dom0 kernel, and /proc/iomem_machine is used 15 | * for regions relating to the machine itself or the hypervisor. 16 | * If Xen is not in used, then /proc/iomem used. 17 | */ 18 | const char *proc_iomem(void) 19 | { 20 | if (xen_present()) 21 | return proc_iomem_machine_str; 22 | return proc_iomem_str; 23 | } 24 | -------------------------------------------------------------------------------- /kexec/arch/loongarch/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec loongarch (linux booting linux) 3 | # 4 | loongarch_KEXEC_SRCS = kexec/arch/loongarch/kexec-loongarch.c 5 | loongarch_KEXEC_SRCS += kexec/arch/loongarch/kexec-elf-loongarch.c 6 | loongarch_KEXEC_SRCS += kexec/arch/loongarch/kexec-pei-loongarch.c 7 | loongarch_KEXEC_SRCS += kexec/arch/loongarch/kexec-elf-rel-loongarch.c 8 | loongarch_KEXEC_SRCS += kexec/arch/loongarch/crashdump-loongarch.c 9 | loongarch_KEXEC_SRCS += kexec/arch/loongarch/kexec-pez-loongarch.c 10 | 11 | loongarch_MEM_REGIONS = kexec/mem_regions.c 12 | 13 | loongarch_CPPFLAGS += -I $(srcdir)/kexec/ 14 | 15 | loongarch_ADD_BUFFER = 16 | loongarch_ADD_SEGMENT = 17 | loongarch_VIRT_TO_PHYS = 18 | 19 | dist += kexec/arch/loongarch/Makefile $(loongarch_KEXEC_SRCS) \ 20 | kexec/arch/loongarch/kexec-loongarch.h \ 21 | kexec/arch/loongarch/image-header.h \ 22 | kexec/arch/loongarch/iomem.h \ 23 | kexec/arch/loongarch/crashdump-loongarch.h \ 24 | kexec/arch/loongarch/include/arch/options.h 25 | -------------------------------------------------------------------------------- /kexec/arch/loongarch/crashdump-loongarch.h: -------------------------------------------------------------------------------- 1 | #ifndef CRASHDUMP_LOONGARCH_H 2 | #define CRASHDUMP_LOONGARCH_H 3 | 4 | struct kexec_info; 5 | extern struct memory_ranges usablemem_rgns; 6 | extern struct memory_range crash_reserved_mem[]; 7 | extern struct memory_range elfcorehdr_mem; 8 | 9 | int load_crashdump_segments(struct kexec_info *info); 10 | int is_crashkernel_mem_reserved(void); 11 | void fixup_elf_addrs(struct mem_ehdr *ehdr); 12 | int get_crash_kernel_load_range(uint64_t *start, uint64_t *end); 13 | 14 | #define PAGE_OFFSET 0x9000000000000000ULL 15 | #define MAXMEM 0 16 | 17 | #define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1) 18 | #define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2) 19 | 20 | /* crash dump kernel support at most two regions, low_region and high region. */ 21 | #define CRASH_MAX_RESERVED_RANGES 2 22 | 23 | #define COMMAND_LINE_SIZE 512 24 | 25 | extern struct arch_options_t arch_options; 26 | #endif /* CRASHDUMP_LOONGARCH_H */ 27 | -------------------------------------------------------------------------------- /kexec/arch/loongarch/image-header.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LoongArch binary image header. 3 | */ 4 | 5 | #if !defined(__LOONGARCH_IMAGE_HEADER_H) 6 | #define __LOONGARCH_IMAGE_HEADER_H 7 | 8 | #include 9 | #include 10 | 11 | /** 12 | * struct loongarch_image_header 13 | * 14 | * @pe_sig: Optional PE format 'MZ' signature. 15 | * @reserved_1: Reserved. 16 | * @kernel_entry: Kernel image entry pointer. 17 | * @image_size: An estimated size of the memory image size in LSB byte order. 18 | * @text_offset: The image load offset in LSB byte order. 19 | * @reserved_2: Reserved. 20 | * @reserved_3: Reserved. 21 | * @pe_header: Optional offset to a PE format header. 22 | **/ 23 | 24 | struct loongarch_image_header { 25 | uint8_t pe_sig[2]; 26 | uint16_t reserved_1[3]; 27 | uint64_t kernel_entry; 28 | uint64_t image_size; 29 | uint64_t text_offset; 30 | uint64_t reserved_2[3]; 31 | uint32_t reserved_3; 32 | uint32_t pe_header; 33 | }; 34 | 35 | static const uint8_t loongarch_image_pe_sig[2] = {'M', 'Z'}; 36 | static const uint8_t loongarch_pe_machtype[6] = {'P','E', 0x0, 0x0, 0x64, 0x62}; 37 | 38 | /** 39 | * loongarch_header_check_pe_sig - Helper to check the loongarch image header. 40 | * 41 | * Returns non-zero if 'MZ' signature is found. 42 | */ 43 | 44 | static inline int loongarch_header_check_pe_sig(const struct loongarch_image_header *h) 45 | { 46 | if (!h) 47 | return 0; 48 | 49 | return (h->pe_sig[0] == loongarch_image_pe_sig[0] 50 | && h->pe_sig[1] == loongarch_image_pe_sig[1]); 51 | } 52 | 53 | static inline uint64_t loongarch_header_text_offset( 54 | const struct loongarch_image_header *h) 55 | { 56 | if (!h) 57 | return 0; 58 | 59 | return le64toh(h->text_offset); 60 | } 61 | 62 | static inline uint64_t loongarch_header_image_size( 63 | const struct loongarch_image_header *h) 64 | { 65 | if (!h) 66 | return 0; 67 | 68 | return le64toh(h->image_size); 69 | } 70 | 71 | static inline uint64_t loongarch_header_kernel_entry( 72 | const struct loongarch_image_header *h) 73 | { 74 | if (!h) 75 | return 0; 76 | 77 | return le64toh(h->kernel_entry); 78 | } 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /kexec/arch/loongarch/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_LOONGARCH_OPTIONS_H 2 | #define KEXEC_ARCH_LOONGARCH_OPTIONS_H 3 | 4 | #define OPT_APPEND ((OPT_MAX)+0) 5 | #define OPT_INITRD ((OPT_MAX)+1) 6 | #define OPT_REUSE_CMDLINE ((OPT_MAX)+2) 7 | #define OPT_ARCH_MAX ((OPT_MAX)+3) 8 | 9 | #define KEXEC_ARCH_OPTIONS \ 10 | KEXEC_OPTIONS \ 11 | { "append", 1, NULL, OPT_APPEND }, \ 12 | { "command-line", 1, NULL, OPT_APPEND }, \ 13 | { "initrd", 1, NULL, OPT_INITRD }, \ 14 | { "ramdisk", 1, NULL, OPT_INITRD }, \ 15 | { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \ 16 | 17 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR /* Only accept long arch options. */ 18 | #define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS 19 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR 20 | 21 | static const char loongarch_opts_usage[] __attribute__ ((unused)) = 22 | " --append=STRING Set the kernel command line to STRING.\n" 23 | " --command-line=STRING Set the kernel command line to STRING.\n" 24 | " --initrd=FILE Use FILE as the kernel initial ramdisk.\n" 25 | " --ramdisk=FILE Use FILE as the kernel initial ramdisk.\n" 26 | " --reuse-cmdline Use kernel command line from running system.\n"; 27 | 28 | #endif /* KEXEC_ARCH_LOONGARCH_OPTIONS_H */ 29 | -------------------------------------------------------------------------------- /kexec/arch/loongarch/iomem.h: -------------------------------------------------------------------------------- 1 | #ifndef IOMEM_H 2 | #define IOMEM_H 3 | 4 | #define SYSTEM_RAM "System RAM\n" 5 | #define KERNEL_CODE "Kernel code\n" 6 | #define KERNEL_DATA "Kernel data\n" 7 | #define CRASH_KERNEL "Crash kernel\n" 8 | #define IOMEM_RESERVED "Reserved\n" 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kexec/arch/loongarch/kexec-elf-rel-loongarch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec-elf-rel-loongarch.c - kexec Elf relocation routines 3 | * 4 | * Copyright (C) 2022 Loongson Technology Corporation Limited. 5 | * 6 | * This source code is licensed under the GNU General Public License, 7 | * Version 2. See the file COPYING for more details. 8 | */ 9 | 10 | #include 11 | #include 12 | #include "../../kexec.h" 13 | #include "../../kexec-elf.h" 14 | 15 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 16 | { 17 | if (ehdr->ei_data != ELFDATA2MSB) 18 | return 0; 19 | 20 | if (ehdr->ei_class != ELFCLASS32) 21 | return 0; 22 | 23 | if (ehdr->e_machine != EM_LOONGARCH) 24 | return 0; 25 | 26 | return 1; 27 | } 28 | 29 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 30 | struct mem_sym *UNUSED(sym), 31 | unsigned long r_type, 32 | void *UNUSED(location), 33 | unsigned long UNUSED(address), 34 | unsigned long UNUSED(value)) 35 | { 36 | switch (r_type) { 37 | 38 | default: 39 | die("Unknown rela relocation: %lu\n", r_type); 40 | break; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /kexec/arch/loongarch/kexec-loongarch.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_LOONGARCH_H 2 | #define KEXEC_LOONGARCH_H 3 | 4 | #include 5 | 6 | #include "image-header.h" 7 | 8 | #define BOOT_BLOCK_VERSION 17 9 | #define BOOT_BLOCK_LAST_COMP_VERSION 16 10 | 11 | #define MAX_MEMORY_RANGES 64 12 | #define MAX_LINE 160 13 | 14 | #define CORE_TYPE_ELF64 1 15 | 16 | #define COMMAND_LINE_SIZE 512 17 | 18 | #define KiB(x) ((x) * 1024UL) 19 | #define MiB(x) (KiB(x) * 1024UL) 20 | 21 | int elf_loongarch_probe(const char *kernel_buf, off_t kernel_size); 22 | int elf_loongarch_load(int argc, char **argv, const char *buf, off_t len, 23 | struct kexec_info *info); 24 | void elf_loongarch_usage(void); 25 | 26 | int pei_loongarch_probe(const char *buf, off_t len); 27 | int pei_loongarch_load(int argc, char **argv, const char *buf, off_t len, 28 | struct kexec_info *info); 29 | void pei_loongarch_usage(void); 30 | int pez_loongarch_probe(const char *kernel_buf, off_t kernel_size); 31 | int pez_loongarch_load(int argc, char **argv, const char *buf, off_t len, 32 | struct kexec_info *info); 33 | void pez_loongarch_usage(void); 34 | 35 | int loongarch_process_image_header(const struct loongarch_image_header *h); 36 | 37 | unsigned long loongarch_locate_kernel_segment(struct kexec_info *info); 38 | int loongarch_load_other_segments(struct kexec_info *info, 39 | unsigned long hole_min); 40 | 41 | struct arch_options_t { 42 | char *command_line; 43 | char *initrd_file; 44 | char *dtb; 45 | int core_header_type; 46 | }; 47 | 48 | /** 49 | * struct loongarch_mem - Memory layout info. 50 | */ 51 | 52 | struct loongarch_mem { 53 | uint64_t phys_offset; 54 | uint64_t text_offset; 55 | uint64_t image_size; 56 | }; 57 | 58 | extern struct loongarch_mem loongarch_mem; 59 | 60 | extern struct memory_ranges usablemem_rgns; 61 | extern struct arch_options_t arch_options; 62 | extern off_t initrd_base, initrd_size; 63 | 64 | #endif /* KEXEC_LOONGARCH_H */ 65 | -------------------------------------------------------------------------------- /kexec/arch/loongarch/kexec-pez-loongarch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LoongArch PE compressed Image (vmlinuz, ZBOOT) support. 3 | * Based on arm64 code 4 | */ 5 | 6 | #define _GNU_SOURCE 7 | #include 8 | #include 9 | #include 10 | #include "kexec.h" 11 | #include "kexec-loongarch.h" 12 | #include 13 | #include "arch/options.h" 14 | 15 | static int kernel_fd = -1; 16 | static off_t decompressed_size; 17 | 18 | /* Returns: 19 | * -1 : in case of error/invalid format (not a valid PE+compressed ZBOOT format. 20 | */ 21 | int pez_loongarch_probe(const char *kernel_buf, off_t kernel_size) 22 | { 23 | int ret = -1; 24 | const struct loongarch_image_header *h; 25 | char *buf; 26 | off_t buf_sz; 27 | 28 | buf = (char *)kernel_buf; 29 | buf_sz = kernel_size; 30 | if (!buf) 31 | return -1; 32 | h = (const struct loongarch_image_header *)buf; 33 | 34 | dbgprintf("%s: PROBE.\n", __func__); 35 | if (buf_sz < sizeof(struct loongarch_image_header)) { 36 | dbgprintf("%s: Not large enough to be a PE image.\n", __func__); 37 | return -1; 38 | } 39 | if (!loongarch_header_check_pe_sig(h)) { 40 | dbgprintf("%s: Not an PE image.\n", __func__); 41 | return -1; 42 | } 43 | 44 | if (buf_sz < sizeof(struct loongarch_image_header) + h->pe_header) { 45 | dbgprintf("%s: PE image offset larger than image.\n", __func__); 46 | return -1; 47 | } 48 | 49 | if (memcmp(&buf[h->pe_header], 50 | loongarch_pe_machtype, sizeof(loongarch_pe_machtype))) { 51 | dbgprintf("%s: PE header doesn't match machine type.\n", __func__); 52 | return -1; 53 | } 54 | 55 | ret = pez_prepare(buf, buf_sz, &kernel_fd, &decompressed_size); 56 | 57 | /* Fixme: add sanity check of the decompressed kernel before return */ 58 | return ret; 59 | } 60 | 61 | int pez_loongarch_load(int argc, char **argv, const char *buf, off_t len, 62 | struct kexec_info *info) 63 | { 64 | if (kernel_fd > 0 && decompressed_size > 0) { 65 | char *kbuf; 66 | off_t nread; 67 | 68 | info->kernel_fd = kernel_fd; 69 | /* 70 | * slurp_fd will close kernel_fd, but it is safe here 71 | * due to no kexec_file_load support. 72 | */ 73 | kbuf = slurp_fd(kernel_fd, NULL, decompressed_size, &nread); 74 | if (!kbuf || nread != decompressed_size) { 75 | dbgprintf("%s: slurp_fd failed.\n", __func__); 76 | return -1; 77 | } 78 | return pei_loongarch_load(argc, argv, kbuf, decompressed_size, info); 79 | } 80 | 81 | dbgprintf("%s: wrong kernel file descriptor.\n", __func__); 82 | return -1; 83 | } 84 | 85 | void pez_loongarch_usage(void) 86 | { 87 | printf( 88 | " An LoongArch vmlinuz, PE image of a compressed, little endian.\n" 89 | " kernel, built with ZBOOT enabled.\n\n"); 90 | } 91 | -------------------------------------------------------------------------------- /kexec/arch/m68k/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec m68k (linux booting linux) 3 | # 4 | m68k_KEXEC_SRCS = kexec/arch/m68k/kexec-m68k.c 5 | m68k_KEXEC_SRCS += kexec/arch/m68k/kexec-elf-m68k.c 6 | m68k_KEXEC_SRCS += kexec/arch/m68k/kexec-elf-rel-m68k.c 7 | m68k_KEXEC_SRCS += kexec/arch/m68k/bootinfo.c 8 | 9 | m68k_ADD_SEGMENT = 10 | m68k_VIRT_TO_PHYS = 11 | 12 | dist += kexec/arch/m68k/Makefile $(m68k_KEXEC_SRCS) \ 13 | kexec/arch/m68k/bootinfo.h \ 14 | kexec/arch/m68k/kexec-m68k.h \ 15 | kexec/arch/m68k/include/arch/options.h 16 | -------------------------------------------------------------------------------- /kexec/arch/m68k/bootinfo.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define DEFAULT_BOOTINFO_FILE "/proc/bootinfo" 4 | #define MAX_BOOTINFO_SIZE 1536 5 | 6 | /* New in 6.2's . Remove once 6.2 is baseline version. */ 7 | #ifndef BI_RNG_SEED 8 | #define BI_RNG_SEED 0x0008 9 | #endif 10 | 11 | 12 | /* 13 | * Convenience overlay of several struct bi_record variants 14 | */ 15 | 16 | struct bi_rec { 17 | __be16 tag; 18 | __be16 size; 19 | union { 20 | __be32 data[0]; 21 | /* shorthands for the types we use */ 22 | __be32 machtype; 23 | struct { 24 | __be32 addr; 25 | __be32 size; 26 | } mem_info; 27 | char string[0]; 28 | struct { 29 | __be16 len; 30 | __u8 data[0]; 31 | } rng_seed; 32 | }; 33 | }; 34 | 35 | 36 | /* 37 | * We only support the "new" tagged bootinfo (v2) 38 | */ 39 | 40 | #define SUPPORTED_BOOTINFO_VERSION 2 41 | 42 | 43 | extern const char *bootinfo_file; 44 | 45 | extern void bootinfo_load(void); 46 | extern void bootinfo_print(void); 47 | extern int bootinfo_get_memory_ranges(struct memory_range **range); 48 | extern void bootinfo_set_cmdline(const char *cmdline); 49 | extern void bootinfo_set_ramdisk(unsigned long ramdisk_addr, 50 | unsigned long ramdisk_size); 51 | extern void bootinfo_add_rng_seed(void); 52 | extern void bootinfo_check_bootversion(const struct kexec_info *info); 53 | extern void add_bootinfo(struct kexec_info *info, unsigned long addr); 54 | -------------------------------------------------------------------------------- /kexec/arch/m68k/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_M68K_OPTIONS_H 2 | #define KEXEC_ARCH_M68K_OPTIONS_H 3 | 4 | #define OPT_ARCH_MAX (OPT_MAX+0) 5 | 6 | /* All 'local' loader options: */ 7 | #define OPT_APPEND (OPT_ARCH_MAX+0) 8 | #define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+1) 9 | #define OPT_RAMDISK (OPT_ARCH_MAX+2) 10 | #define OPT_BOOTINFO (OPT_ARCH_MAX+3) 11 | 12 | /* Options relevant to the architecture (excluding loader-specific ones), 13 | * in this case none: 14 | */ 15 | #define KEXEC_ARCH_OPTIONS \ 16 | KEXEC_OPTIONS \ 17 | 18 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 19 | 20 | /* The following two #defines list ALL of the options added by all of the 21 | * architecture's loaders. 22 | * o main() uses this complete list to scan for its options, ignoring 23 | * arch-specific/loader-specific ones. 24 | * o Then, arch_process_options() uses this complete list to scan for its 25 | * options, ignoring general/loader-specific ones. 26 | * o Then, the file_type[n].load re-scans for options, using 27 | * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. 28 | * Any unrecognised options cause an error here. 29 | * 30 | * This is done so that main()'s/arch_process_options()'s getopt_long() calls 31 | * don't choose a kernel filename from random arguments to options they don't 32 | * recognise -- as they now recognise (if not act upon) all possible options. 33 | */ 34 | #define KEXEC_ALL_OPTIONS \ 35 | KEXEC_ARCH_OPTIONS \ 36 | { "command-line", 1, NULL, OPT_APPEND }, \ 37 | { "append", 1, NULL, OPT_APPEND }, \ 38 | { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \ 39 | { "ramdisk", 1, NULL, OPT_RAMDISK }, \ 40 | { "initrd", 1, NULL, OPT_RAMDISK }, \ 41 | { "bootinfo", 1, NULL, OPT_BOOTINFO }, 42 | 43 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR 44 | 45 | #endif /* KEXEC_ARCH_M68K_OPTIONS_H */ 46 | -------------------------------------------------------------------------------- /kexec/arch/m68k/kexec-elf-rel-m68k.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec-elf-rel-m68k.c - kexec Elf relocation routines 3 | * 4 | * Copyright (C) 2013 Geert Uytterhoeven 5 | * 6 | * This source code is licensed under the GNU General Public License, 7 | * Version 2. See the file COPYING for more details. 8 | */ 9 | 10 | #include 11 | #include 12 | #include "../../kexec.h" 13 | #include "../../kexec-elf.h" 14 | 15 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 16 | { 17 | if (ehdr->ei_data != ELFDATA2MSB) 18 | return 0; 19 | if (ehdr->ei_class != ELFCLASS32) 20 | return 0; 21 | if (ehdr->e_machine != EM_68K) 22 | return 0; 23 | return 1; 24 | } 25 | 26 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 27 | struct mem_sym *UNUSED(sym), 28 | unsigned long r_type, 29 | void *UNUSED(location), 30 | unsigned long UNUSED(address), 31 | unsigned long UNUSED(value)) 32 | { 33 | switch (r_type) { 34 | default: 35 | die("Unknown rela relocation: %lu\n", r_type); 36 | break; 37 | } 38 | return; 39 | } 40 | -------------------------------------------------------------------------------- /kexec/arch/m68k/kexec-m68k.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_M68K_H 2 | #define KEXEC_M68K_H 3 | 4 | int elf_m68k_probe(const char *buf, off_t len); 5 | int elf_m68k_load(int argc, char **argv, const char *buf, off_t len, 6 | struct kexec_info *info); 7 | void elf_m68k_usage(void); 8 | 9 | #endif /* KEXEC_M68K_H */ 10 | -------------------------------------------------------------------------------- /kexec/arch/mips/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec mips (linux booting linux) 3 | # 4 | mips_KEXEC_SRCS = kexec/arch/mips/kexec-mips.c 5 | mips_KEXEC_SRCS += kexec/arch/mips/kexec-elf-mips.c 6 | mips_KEXEC_SRCS += kexec/arch/mips/kexec-elf-rel-mips.c 7 | mips_KEXEC_SRCS += kexec/arch/mips/crashdump-mips.c 8 | 9 | mips_FS2DT = kexec/fs2dt.c 10 | mips_FS2DT_INCLUDE = \ 11 | -include $(srcdir)/kexec/arch/mips/crashdump-mips.h \ 12 | -include $(srcdir)/kexec/arch/mips/kexec-mips.h 13 | 14 | mips_DT_OPS += kexec/dt-ops.c 15 | 16 | mips_MEM_REGIONS = kexec/mem_regions.c 17 | 18 | include $(srcdir)/kexec/libfdt/Makefile.libfdt 19 | 20 | libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) 21 | mips_CPPFLAGS += -I$(srcdir)/kexec/libfdt 22 | mips_KEXEC_SRCS += $(libfdt_SRCS) 23 | 24 | mips_ADD_BUFFER = 25 | mips_ADD_SEGMENT = 26 | mips_VIRT_TO_PHYS = 27 | 28 | dist += kexec/arch/mips/Makefile $(mips_KEXEC_SRCS) \ 29 | kexec/arch/mips/kexec-mips.h \ 30 | kexec/arch/mips/crashdump-mips.h \ 31 | kexec/arch/mips/include/arch/options.h 32 | -------------------------------------------------------------------------------- /kexec/arch/mips/crashdump-mips.h: -------------------------------------------------------------------------------- 1 | #ifndef CRASHDUMP_MIPS_H 2 | #define CRASHDUMP_MIPS_H 3 | 4 | struct kexec_info; 5 | int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline, 6 | unsigned long max_addr, unsigned long min_base); 7 | #ifdef __mips64 8 | #define PAGE_OFFSET 0xa800000000000000ULL 9 | #define MAXMEM 0 10 | #else 11 | #define PAGE_OFFSET 0x80000000 12 | #define MAXMEM 0x80000000 13 | #endif 14 | #define __pa(x) ((unsigned long)(X) & 0x7fffffff) 15 | 16 | #define LOONGSON_PAGE_OFFSET 0xffffffff80000000ULL 17 | #define OCTEON_PAGE_OFFSET 0x8000000000000000ULL 18 | 19 | #define CRASH_MAX_MEMMAP_NR (KEXEC_MAX_SEGMENTS + 1) 20 | #define CRASH_MAX_MEMORY_RANGES (MAX_MEMORY_RANGES + 2) 21 | 22 | #define COMMAND_LINE_SIZE 512 23 | 24 | /* Backup Region, First 1M of System RAM. */ 25 | #define BACKUP_SRC_START 0x00000000 26 | #define BACKUP_SRC_END 0x000fffff 27 | #define BACKUP_SRC_SIZE (BACKUP_SRC_END - BACKUP_SRC_START + 1) 28 | 29 | extern struct arch_options_t arch_options; 30 | #endif /* CRASHDUMP_MIPS_H */ 31 | -------------------------------------------------------------------------------- /kexec/arch/mips/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_MIPS_OPTIONS_H 2 | #define KEXEC_ARCH_MIPS_OPTIONS_H 3 | 4 | #define OPT_ARCH_MAX (OPT_MAX+0) 5 | #define OPT_APPEND (OPT_ARCH_MAX+0) 6 | #define OPT_DTB (OPT_ARCH_MAX+1) 7 | #define OPT_RAMDISK (OPT_ARCH_MAX+2) 8 | #define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+3) 9 | 10 | /* Options relevant to the architecture (excluding loader-specific ones), 11 | * in this case none: 12 | */ 13 | #define KEXEC_ARCH_OPTIONS \ 14 | KEXEC_OPTIONS \ 15 | {"command-line", 1, 0, OPT_APPEND}, \ 16 | {"append", 1, 0, OPT_APPEND}, \ 17 | {"dtb", 1, 0, OPT_DTB }, \ 18 | {"initrd", 1, 0, OPT_RAMDISK }, \ 19 | { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, 20 | 21 | 22 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 23 | 24 | /* The following two #defines list ALL of the options added by all of the 25 | * architecture's loaders. 26 | * o main() uses this complete list to scan for its options, ignoring 27 | * arch-specific/loader-specific ones. 28 | * o Then, arch_process_options() uses this complete list to scan for its 29 | * options, ignoring general/loader-specific ones. 30 | * o Then, the file_type[n].load re-scans for options, using 31 | * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. 32 | * Any unrecognised options cause an error here. 33 | * 34 | * This is done so that main()'s/arch_process_options()'s getopt_long() calls 35 | * don't choose a kernel filename from random arguments to options they don't 36 | * recognise -- as they now recognise (if not act upon) all possible options. 37 | */ 38 | #define KEXEC_ALL_OPTIONS \ 39 | KEXEC_ARCH_OPTIONS 40 | 41 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR 42 | 43 | #endif /* KEXEC_ARCH_MIPS_OPTIONS_H */ 44 | -------------------------------------------------------------------------------- /kexec/arch/mips/kexec-elf-rel-mips.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec-elf-rel-mips.c - kexec Elf relocation routines 3 | * Copyright (C) 2007 Francesco Chiechi, Alessandro Rubini 4 | * Copyright (C) 2007 Tvblob s.r.l. 5 | * 6 | * derived from ../ppc/kexec-elf-rel-ppc.c 7 | * Copyright (C) 2004 Albert Herranz 8 | * 9 | * This source code is licensed under the GNU General Public License, 10 | * Version 2. See the file COPYING for more details. 11 | */ 12 | 13 | #include 14 | #include 15 | #include "../../kexec.h" 16 | #include "../../kexec-elf.h" 17 | 18 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 19 | { 20 | if (ehdr->ei_data != ELFDATA2MSB) { 21 | return 0; 22 | } 23 | if (ehdr->ei_class != ELFCLASS32) { 24 | return 0; 25 | } 26 | if (ehdr->e_machine != EM_MIPS) { 27 | return 0; 28 | } 29 | return 1; 30 | } 31 | 32 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 33 | struct mem_sym *UNUSED(sym), 34 | unsigned long r_type, 35 | void *UNUSED(location), 36 | unsigned long UNUSED(address), 37 | unsigned long UNUSED(value)) 38 | { 39 | switch(r_type) { 40 | 41 | default: 42 | die("Unknown rela relocation: %lu\n", r_type); 43 | break; 44 | } 45 | return; 46 | } 47 | -------------------------------------------------------------------------------- /kexec/arch/mips/kexec-mips.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_MIPS_H 2 | #define KEXEC_MIPS_H 3 | 4 | #include 5 | 6 | #define BOOT_BLOCK_VERSION 17 7 | #define BOOT_BLOCK_LAST_COMP_VERSION 16 8 | 9 | #define MAX_MEMORY_RANGES 64 10 | #define MAX_LINE 160 11 | 12 | #define CORE_TYPE_ELF32 1 13 | #define CORE_TYPE_ELF64 2 14 | 15 | int elf_mips_probe(const char *buf, off_t len); 16 | int elf_mips_load(int argc, char **argv, const char *buf, off_t len, 17 | struct kexec_info *info); 18 | void elf_mips_usage(void); 19 | 20 | struct arch_options_t { 21 | char *command_line; 22 | char *dtb_file; 23 | char *initrd_file; 24 | int core_header_type; 25 | }; 26 | 27 | extern struct memory_ranges usablemem_rgns; 28 | extern off_t initrd_base, initrd_size; 29 | 30 | #endif /* KEXEC_MIPS_H */ 31 | -------------------------------------------------------------------------------- /kexec/arch/ppc/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec ppc (linux booting linux) 3 | # 4 | include $(srcdir)/kexec/libfdt/Makefile.libfdt 5 | 6 | ppc_KEXEC_SRCS = kexec/arch/ppc/kexec-ppc.c 7 | ppc_KEXEC_SRCS += kexec/arch/ppc/kexec-elf-ppc.c 8 | ppc_KEXEC_SRCS += kexec/arch/ppc/kexec-elf-rel-ppc.c 9 | ppc_KEXEC_SRCS += kexec/arch/ppc/kexec-dol-ppc.c 10 | ppc_KEXEC_SRCS += kexec/arch/ppc/kexec-uImage-ppc.c 11 | ppc_KEXEC_SRCS += kexec/arch/ppc/ppc-setup-simple.S 12 | ppc_KEXEC_SRCS += kexec/arch/ppc/ppc-setup-dol.S 13 | ppc_KEXEC_SRCS += kexec/arch/ppc/fixup_dtb.c 14 | ppc_KEXEC_SRCS += kexec/arch/ppc/fs2dt.c 15 | ppc_KEXEC_SRCS += kexec/arch/ppc/crashdump-powerpc.c 16 | 17 | ppc_UIMAGE = kexec/kexec-uImage.c 18 | 19 | ppc_libfdt_SRCS = kexec/arch/ppc/libfdt-wrapper.c 20 | libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) 21 | ppc_ARCH_REUSE_INITRD = 22 | 23 | ppc_CPPFLAGS = -I$(srcdir)/kexec/libfdt 24 | 25 | ppc_KEXEC_SRCS += $(libfdt_SRCS) $(ppc_libfdt_SRCS) 26 | 27 | ppc_ASFLAGS = -Wa,--noexecstack 28 | 29 | dist += kexec/arch/ppc/Makefile $(ppc_KEXEC_SRCS) \ 30 | kexec/arch/ppc/crashdump-powerpc.h kexec/arch/ppc/fixup_dtb.h \ 31 | kexec/arch/ppc/kexec-ppc.h kexec/arch/ppc/ops.h \ 32 | kexec/arch/ppc/ppc_asm.h \ 33 | kexec/arch/ppc/include/page.h kexec/arch/ppc/include/types.h \ 34 | kexec/arch/ppc/include/arch/options.h 35 | -------------------------------------------------------------------------------- /kexec/arch/ppc/crashdump-powerpc.h: -------------------------------------------------------------------------------- 1 | #ifndef CRASHDUMP_POWERPC_H 2 | #define CRASHDUMP_POWERPC_H 3 | 4 | struct kexec_info; 5 | int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline, 6 | unsigned long max_addr, unsigned long min_base); 7 | void add_usable_mem_rgns(unsigned long long base, unsigned long long size); 8 | 9 | extern struct arch_options_t arch_options; 10 | 11 | #ifdef CONFIG_PPC64 12 | #define PAGE_OFFSET 0xC000000000000000UL 13 | #define VMALLOCBASE 0xD000000000000000UL 14 | #define MAXMEM (-KERNELBASE-VMALLOCBASE) 15 | #else 16 | #define PAGE_OFFSET 0xC0000000 17 | #define MAXMEM 0x30000000 /* Use CONFIG_LOWMEM_SIZE from kernel */ 18 | #endif 19 | 20 | #define KERNELBASE PAGE_OFFSET 21 | #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) 22 | 23 | #ifdef CONFIG_BOOKE 24 | /* We don't need backup region in Book E */ 25 | #define BACKUP_SRC_START 0x0000 26 | #define BACKUP_SRC_END 0x0000 27 | #define BACKUP_SRC_SIZE 0x0000 28 | #else 29 | /* Backup Region, First 64K of System RAM. */ 30 | #define BACKUP_SRC_START 0x0000 31 | #define BACKUP_SRC_END 0xffff 32 | #define BACKUP_SRC_SIZE (BACKUP_SRC_END - BACKUP_SRC_START + 1) 33 | #endif 34 | 35 | #define KDUMP_BACKUP_LIMIT BACKUP_SRC_SIZE 36 | 37 | extern unsigned long long crash_base; 38 | extern unsigned long long crash_size; 39 | extern unsigned int rtas_base; 40 | extern unsigned int rtas_size; 41 | extern uint64_t opal_base; 42 | extern uint64_t opal_size; 43 | extern uint64_t memory_limit; 44 | 45 | #endif /* CRASHDUMP_POWERPC_H */ 46 | -------------------------------------------------------------------------------- /kexec/arch/ppc/fixup_dtb.h: -------------------------------------------------------------------------------- 1 | #ifndef __FIXUP_DTB_H 2 | #define __FIXUP_DTB_H 3 | 4 | char *fixup_dtb_init(struct kexec_info *info, char *blob_buf, off_t *blob_size, 5 | unsigned long hole_addr, unsigned long *dtb_addr); 6 | 7 | char *fixup_dtb_finalize(struct kexec_info *info, char *blob_buf, off_t *blob_size, 8 | char *nodes[], char *cmdline); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kexec/arch/ppc/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_PPC_OPTIONS_H 2 | #define KEXEC_ARCH_PPC_OPTIONS_H 3 | 4 | #define OPT_ARCH_MAX (OPT_MAX+0) 5 | 6 | /* All 'local' loader options: */ 7 | #define OPT_APPEND (OPT_ARCH_MAX+0) 8 | #define OPT_GAMECUBE (OPT_ARCH_MAX+1) 9 | #define OPT_DTB (OPT_ARCH_MAX+2) 10 | #define OPT_NODES (OPT_ARCH_MAX+3) 11 | #define OPT_RAMDISK (OPT_ARCH_MAX+4) 12 | 13 | /* Options relevant to the architecture (excluding loader-specific ones), 14 | * in this case none: 15 | */ 16 | #define KEXEC_ARCH_OPTIONS \ 17 | KEXEC_OPTIONS \ 18 | 19 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 20 | 21 | /* The following two #defines list ALL of the options added by all of the 22 | * architecture's loaders. 23 | * o main() uses this complete list to scan for its options, ignoring 24 | * arch-specific/loader-specific ones. 25 | * o Then, arch_process_options() uses this complete list to scan for its 26 | * options, ignoring general/loader-specific ones. 27 | * o Then, the file_type[n].load re-scans for options, using 28 | * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. 29 | * Any unrecognised options cause an error here. 30 | * 31 | * This is done so that main()'s/arch_process_options()'s getopt_long() calls 32 | * don't choose a kernel filename from random arguments to options they don't 33 | * recognise -- as they now recognise (if not act upon) all possible options. 34 | */ 35 | #define KEXEC_ALL_OPTIONS \ 36 | KEXEC_ARCH_OPTIONS \ 37 | {"command-line", 1, 0, OPT_APPEND},\ 38 | {"append", 1, 0, OPT_APPEND},\ 39 | {"ramdisk", 1, 0, OPT_APPEND},\ 40 | {"initrd", 1, 0, OPT_APPEND},\ 41 | {"gamecube", 1, 0, OPT_GAMECUBE},\ 42 | {"dtb", 1, 0, OPT_DTB},\ 43 | {"reuse-node", 1, 0, OPT_NODES}, 44 | 45 | #define KEXEC_ALL_OPT_STR KEXEC_OPT_STR 46 | 47 | #endif /* KEXEC_ARCH_PPC_OPTIONS_H */ 48 | -------------------------------------------------------------------------------- /kexec/arch/ppc/include/page.h: -------------------------------------------------------------------------------- 1 | #ifndef _PPC_BOOT_PAGE_H 2 | #define _PPC_BOOT_PAGE_H 3 | /* 4 | * Copyright (C) 2001 PPC64 Team, IBM Corp 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; either version 9 | * 2 of the License, or (at your option) any later version. 10 | */ 11 | 12 | #ifdef __ASSEMBLY__ 13 | #define ASM_CONST(x) x 14 | #else 15 | #define __ASM_CONST(x) x##UL 16 | #define ASM_CONST(x) __ASM_CONST(x) 17 | #endif 18 | 19 | /* PAGE_SHIFT determines the page size */ 20 | #define PAGE_SHIFT 12 21 | #define PAGE_SIZE (ASM_CONST(1) << PAGE_SHIFT) 22 | #define PAGE_MASK (~(PAGE_SIZE-1)) 23 | 24 | /* to align the pointer to the (next) page boundary */ 25 | #define PAGE_ALIGN(addr) (((addr)+((PAGE_SIZE)-1))&(~((PAGE_SIZE)-1))) 26 | 27 | #endif /* _PPC_BOOT_PAGE_H */ 28 | -------------------------------------------------------------------------------- /kexec/arch/ppc/include/types.h: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_H_ 2 | #define _TYPES_H_ 3 | 4 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 5 | 6 | typedef unsigned char u8; 7 | typedef unsigned short u16; 8 | typedef unsigned int u32; 9 | typedef unsigned long long u64; 10 | typedef signed char s8; 11 | typedef short s16; 12 | typedef int s32; 13 | typedef long long s64; 14 | 15 | #define min(x,y) ({ \ 16 | typeof(x) _x = (x); \ 17 | typeof(y) _y = (y); \ 18 | (void) (&_x == &_y); \ 19 | _x < _y ? _x : _y; }) 20 | 21 | #define max(x,y) ({ \ 22 | typeof(x) _x = (x); \ 23 | typeof(y) _y = (y); \ 24 | (void) (&_x == &_y); \ 25 | _x > _y ? _x : _y; }) 26 | 27 | #endif /* _TYPES_H_ */ 28 | -------------------------------------------------------------------------------- /kexec/arch/ppc/kexec-elf-rel-ppc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../kexec.h" 4 | #include "../../kexec-elf.h" 5 | 6 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 7 | { 8 | if (ehdr->ei_data != ELFDATA2MSB) { 9 | return 0; 10 | } 11 | if (ehdr->ei_class != ELFCLASS32) { 12 | return 0; 13 | } 14 | if (ehdr->e_machine != EM_PPC) { 15 | return 0; 16 | } 17 | return 1; 18 | } 19 | 20 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 21 | struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, 22 | unsigned long address, unsigned long value) 23 | { 24 | switch(r_type) { 25 | case R_PPC_ADDR32: 26 | /* Simply set it */ 27 | *(uint32_t *)location = value; 28 | break; 29 | 30 | case R_PPC_ADDR16_LO: 31 | /* Low half of the symbol */ 32 | *(uint16_t *)location = value; 33 | break; 34 | 35 | case R_PPC_ADDR16_HI: 36 | *(uint16_t *)location = (value>>16) & 0xffff; 37 | break; 38 | 39 | case R_PPC_ADDR16_HA: 40 | /* Sign-adjusted lower 16 bits: PPC ELF ABI says: 41 | (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF. 42 | This is the same, only sane. 43 | */ 44 | *(uint16_t *)location = (value + 0x8000) >> 16; 45 | break; 46 | 47 | case R_PPC_REL24: 48 | if ((int)(value - address) < -0x02000000 49 | || (int)(value - address) >= 0x02000000) 50 | { 51 | die("Symbol more than 16MiB away"); 52 | } 53 | /* Only replace bits 2 through 26 */ 54 | *(uint32_t *)location 55 | = (*(uint32_t *)location & ~0x03fffffc) 56 | | ((value - address) 57 | & 0x03fffffc); 58 | break; 59 | 60 | case R_PPC_REL32: 61 | /* 32-bit relative jump. */ 62 | *(uint32_t *)location = value - address; 63 | break; 64 | default: 65 | die("Unknown rela relocation: %lu\n", r_type); 66 | break; 67 | } 68 | return; 69 | } 70 | -------------------------------------------------------------------------------- /kexec/arch/ppc/kexec-ppc.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_PPC_H 2 | #define KEXEC_PPC_H 3 | 4 | #define MAXBYTES 128 5 | #define MAX_LINE 160 6 | #define CORE_TYPE_ELF32 1 7 | #define CORE_TYPE_ELF64 2 8 | 9 | #define COMMAND_LINE_SIZE 2048 /* from kernel */ 10 | 11 | extern unsigned char setup_simple_start[]; 12 | extern uint32_t setup_simple_size; 13 | 14 | extern struct { 15 | uint32_t spr8; 16 | } setup_simple_regs; 17 | 18 | extern unsigned char setup_dol_start[]; 19 | extern uint32_t setup_dol_size; 20 | extern uint64_t rmo_top; 21 | 22 | extern struct { 23 | uint32_t spr8; 24 | } setup_dol_regs; 25 | 26 | #define SIZE_16M (16*1024*1024UL) 27 | 28 | int elf_ppc_probe(const char *buf, off_t len); 29 | int elf_ppc_load(int argc, char **argv, const char *buf, off_t len, 30 | struct kexec_info *info); 31 | void elf_ppc_usage(void); 32 | 33 | int uImage_ppc_probe(const char *buf, off_t len); 34 | int uImage_ppc_load(int argc, char **argv, const char *buf, off_t len, 35 | struct kexec_info *info); 36 | void uImage_ppc_usage(void); 37 | 38 | int dol_ppc_probe(const char *buf, off_t len); 39 | int dol_ppc_load(int argc, char **argv, const char *buf, off_t len, 40 | struct kexec_info *info); 41 | void dol_ppc_usage(void); 42 | 43 | /* 44 | * During inital setup the kernel does not map the whole memory but a part of 45 | * it. On Book-E that is 64MiB, 601 24MiB or 256MiB (if possible). 46 | */ 47 | #define KERNEL_ACCESS_TOP (24 * 1024 * 1024) 48 | 49 | /* boot block version 17 as defined by the linux kernel */ 50 | struct bootblock { 51 | unsigned magic, 52 | totalsize, 53 | off_dt_struct, 54 | off_dt_strings, 55 | off_mem_rsvmap, 56 | version, 57 | last_comp_version, 58 | boot_physid, 59 | dt_strings_size, 60 | dt_struct_size; 61 | }; 62 | 63 | typedef struct mem_rgns { 64 | unsigned int size; 65 | struct memory_range *ranges; 66 | } mem_rgns_t; 67 | extern mem_rgns_t usablemem_rgns; 68 | extern int max_memory_ranges; 69 | extern unsigned long long crash_base, crash_size; 70 | extern unsigned long long initrd_base, initrd_size; 71 | extern unsigned long long ramdisk_base, ramdisk_size; 72 | extern unsigned char reuse_initrd; 73 | extern const char *ramdisk; 74 | 75 | /* Method to parse the memory/reg nodes in device-tree */ 76 | extern unsigned long dt_address_cells, dt_size_cells; 77 | extern int init_memory_region_info(void); 78 | extern int read_memory_region_limits(int fd, unsigned long long *start, 79 | unsigned long long *end); 80 | extern int get_devtree_value(const char *fname, unsigned long long *pvalue); 81 | /*fs2dt*/ 82 | void reserve(unsigned long long where, unsigned long long length); 83 | 84 | /* Defined kexec-uImage-ppc.c */ 85 | extern char* slurp_ramdisk_ppc(const char *filename, off_t *r_size); 86 | #endif /* KEXEC_PPC_H */ 87 | -------------------------------------------------------------------------------- /kexec/arch/ppc/ppc-setup-simple.S: -------------------------------------------------------------------------------- 1 | /* 2 | * ppc-setup-simple.S - (hopefully) setup for simple embedded platforms 3 | * Copyright (C) 2004 Albert Herranz 4 | * 5 | * This source code is licensed under the GNU General Public License, 6 | * Version 2. See the file COPYING for more details. 7 | */ 8 | 9 | /* 10 | * Only suitable for platforms booting with MMU turned off. 11 | * -- Albert Herranz 12 | */ 13 | 14 | #include "ppc_asm.h" 15 | 16 | .data 17 | .globl setup_simple_start 18 | setup_simple_start: 19 | 20 | /* should perform here any required setup */ 21 | 22 | RELOC_SYM(setup_simple_regs) 23 | mr r9, r3 24 | lwz r5, spr8 - setup_simple_regs(r9) 25 | 26 | mtlr r5 27 | blr 28 | 29 | .balign 4 30 | .globl setup_simple_regs 31 | setup_simple_regs: 32 | spr8: .long 0x00000000 33 | 34 | setup_simple_end: 35 | 36 | .globl setup_simple_size 37 | setup_simple_size: 38 | .long setup_simple_end - setup_simple_start 39 | 40 | -------------------------------------------------------------------------------- /kexec/arch/ppc64/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec ppc64 (linux booting linux) 3 | # 4 | include $(srcdir)/kexec/libfdt/Makefile.libfdt 5 | 6 | ppc64_KEXEC_SRCS = kexec/arch/ppc64/kexec-elf-rel-ppc64.c 7 | ppc64_KEXEC_SRCS += kexec/arch/ppc64/kexec-zImage-ppc64.c 8 | ppc64_KEXEC_SRCS += kexec/arch/ppc64/kexec-elf-ppc64.c 9 | ppc64_KEXEC_SRCS += kexec/arch/ppc64/kexec-ppc64.c 10 | ppc64_KEXEC_SRCS += kexec/arch/ppc64/crashdump-ppc64.c 11 | ppc64_KEXEC_SRCS += kexec/arch/ppc64/fdt.c 12 | ppc64_KEXEC_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) 13 | 14 | ppc64_ARCH_REUSE_INITRD = 15 | 16 | ppc64_FS2DT = kexec/fs2dt.c 17 | ppc64_FS2DT_INCLUDE = -include $(srcdir)/kexec/arch/ppc64/crashdump-ppc64.h \ 18 | -include $(srcdir)/kexec/arch/ppc64/kexec-ppc64.h 19 | 20 | ppc64_CPPFLAGS = -I$(srcdir)/kexec/libfdt 21 | 22 | dist += kexec/arch/ppc64/Makefile $(ppc64_KEXEC_SRCS) \ 23 | kexec/arch/ppc64/kexec-ppc64.h kexec/arch/ppc64/crashdump-ppc64.h \ 24 | kexec/arch/ppc64/include/arch/fdt.h \ 25 | kexec/arch/ppc64/include/arch/options.h 26 | 27 | -------------------------------------------------------------------------------- /kexec/arch/ppc64/crashdump-ppc64.h: -------------------------------------------------------------------------------- 1 | #ifndef CRASHDUMP_PPC64_H 2 | #define CRASHDUMP_PPC64_H 3 | 4 | #include 5 | #include 6 | 7 | struct kexec_info; 8 | int load_crashdump_segments(struct kexec_info *info, char *mod_cmdline, 9 | uint64_t max_addr, unsigned long min_base); 10 | void add_usable_mem_rgns(unsigned long long base, unsigned long long size); 11 | 12 | #define PAGE_OFFSET 0xC000000000000000ULL 13 | #define KERNELBASE PAGE_OFFSET 14 | #define VMALLOCBASE 0xD000000000000000ULL 15 | 16 | #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) 17 | #define MAXMEM (-(unsigned long)(KERNELBASE-VMALLOCBASE)) 18 | 19 | #define COMMAND_LINE_SIZE 2048 /* from kernel */ 20 | /* Backup Region, First 64K of System RAM. */ 21 | #define BACKUP_SRC_START 0x0000 22 | #define BACKUP_SRC_END 0xffff 23 | #define BACKUP_SRC_SIZE (BACKUP_SRC_END - BACKUP_SRC_START + 1) 24 | 25 | #define KDUMP_BACKUP_LIMIT BACKUP_SRC_SIZE 26 | 27 | #define KERNEL_RUN_AT_ZERO_MAGIC 0x72756e30 /* "run0" */ 28 | 29 | extern uint64_t crash_base; 30 | extern uint64_t crash_size; 31 | extern uint64_t memory_limit; 32 | extern unsigned int rtas_base; 33 | extern unsigned int rtas_size; 34 | extern uint64_t opal_base; 35 | extern uint64_t opal_size; 36 | 37 | /* 38 | * In case of ibm,dynamic-memory-v2 property, this is the number of LMB 39 | * sets where each set represents a group of sequential LMB entries. In 40 | * case of ibm,dynamic-memory property, the number of LMB sets is nothing 41 | * but the total number of LMB entries. 42 | */ 43 | extern unsigned int num_of_lmb_sets; 44 | extern unsigned int is_dyn_mem_v2; 45 | extern uint64_t lmb_size; 46 | 47 | #define LMB_ENTRY_SIZE 24 48 | #define DRCONF_ADDR (is_dyn_mem_v2 ? 4 : 0) 49 | #define DRCONF_FLAGS 20 50 | 51 | #endif /* CRASHDUMP_PPC64_H */ 52 | -------------------------------------------------------------------------------- /kexec/arch/ppc64/include/arch/fdt.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_PPC64_FDT 2 | #define KEXEC_ARCH_PPC64_FDT 3 | 4 | #include 5 | 6 | int fixup_dt(char **fdt, off_t *size, unsigned long kexec_flags); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /kexec/arch/ppc64/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_PPC64_OPTIONS_H 2 | #define KEXEC_ARCH_PPC64_OPTIONS_H 3 | 4 | #define OPT_ELF64_CORE (OPT_MAX+0) 5 | #define OPT_DT_NO_OLD_ROOT (OPT_MAX+1) 6 | #define OPT_ARCH_MAX (OPT_MAX+2) 7 | 8 | /* All 'local' loader options: */ 9 | #define OPT_APPEND (OPT_ARCH_MAX+0) 10 | #define OPT_RAMDISK (OPT_ARCH_MAX+1) 11 | #define OPT_DEVICETREEBLOB (OPT_ARCH_MAX+2) 12 | #define OPT_ARGS_IGNORE (OPT_ARCH_MAX+3) 13 | #define OPT_REUSE_CMDLINE (OPT_ARCH_MAX+4) 14 | 15 | /* Options relevant to the architecture (excluding loader-specific ones): */ 16 | #define KEXEC_ARCH_OPTIONS \ 17 | KEXEC_OPTIONS \ 18 | { "elf64-core-headers", 0, 0, OPT_ELF64_CORE }, \ 19 | { "dt-no-old-root", 0, 0, OPT_DT_NO_OLD_ROOT }, \ 20 | 21 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 22 | 23 | /* The following two #defines list ALL of the options added by all of the 24 | * architecture's loaders. 25 | * o main() uses this complete list to scan for its options, ignoring 26 | * arch-specific/loader-specific ones. 27 | * o Then, arch_process_options() uses this complete list to scan for its 28 | * options, ignoring general/loader-specific ones. 29 | * o Then, the file_type[n].load re-scans for options, using 30 | * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. 31 | * Any unrecognised options cause an error here. 32 | * 33 | * This is done so that main()'s/arch_process_options()'s getopt_long() calls 34 | * don't choose a kernel filename from random arguments to options they don't 35 | * recognise -- as they now recognise (if not act upon) all possible options. 36 | */ 37 | #define KEXEC_ALL_OPTIONS \ 38 | KEXEC_ARCH_OPTIONS \ 39 | { "command-line", 1, NULL, OPT_APPEND }, \ 40 | { "append", 1, NULL, OPT_APPEND }, \ 41 | { "ramdisk", 1, NULL, OPT_RAMDISK }, \ 42 | { "initrd", 1, NULL, OPT_RAMDISK }, \ 43 | { "devicetreeblob", 1, NULL, OPT_DEVICETREEBLOB }, \ 44 | { "dtb", 1, NULL, OPT_DEVICETREEBLOB }, \ 45 | { "args-linux", 0, NULL, OPT_ARGS_IGNORE }, \ 46 | { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, 47 | 48 | #define KEXEC_ALL_OPT_STR KEXEC_OPT_STR 49 | 50 | 51 | #endif /* KEXEC_ARCH_PPC64_OPTIONS_H */ 52 | -------------------------------------------------------------------------------- /kexec/arch/ppc64/kexec-ppc64.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_PPC64_H 2 | #define KEXEC_PPC64_H 3 | 4 | #define PATH_LEN 256 5 | #define MAXBYTES 128 6 | #define MAX_LINE 160 7 | #define CORE_TYPE_ELF32 1 8 | #define CORE_TYPE_ELF64 2 9 | 10 | #define BOOT_BLOCK_VERSION 17 11 | #define BOOT_BLOCK_LAST_COMP_VERSION 17 12 | #if (BOOT_BLOCK_VERSION < 16) 13 | # define NEED_STRUCTURE_BLOCK_EXTRA_PAD 14 | #endif 15 | #define HAVE_DYNAMIC_MEMORY 16 | #define NEED_RESERVE_DTB 17 | 18 | extern int get_devtree_value(const char *fname, unsigned long long *pvalue); 19 | 20 | int setup_memory_ranges(unsigned long kexec_flags); 21 | 22 | int elf_ppc64_probe(const char *buf, off_t len); 23 | int elf_ppc64_load(int argc, char **argv, const char *buf, off_t len, 24 | struct kexec_info *info); 25 | void elf_ppc64_usage(void); 26 | 27 | struct mem_ehdr; 28 | unsigned long my_r2(const struct mem_ehdr *ehdr); 29 | 30 | extern uint64_t initrd_base, initrd_size; 31 | extern int max_memory_ranges; 32 | extern unsigned char reuse_initrd; 33 | 34 | struct arch_options_t { 35 | int core_header_type; 36 | }; 37 | 38 | typedef struct mem_rgns { 39 | unsigned int size; 40 | struct memory_range *ranges; 41 | } mem_rgns_t; 42 | 43 | extern mem_rgns_t usablemem_rgns; 44 | 45 | #endif /* KEXEC_PPC64_H */ 46 | -------------------------------------------------------------------------------- /kexec/arch/riscv/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec riscv 3 | # 4 | riscv_KEXEC_SRCS = kexec/arch/riscv/crashdump-riscv.c 5 | riscv_KEXEC_SRCS += kexec/arch/riscv/kexec-elf-riscv.c 6 | riscv_KEXEC_SRCS += kexec/arch/riscv/kexec-image-riscv.c 7 | riscv_KEXEC_SRCS += kexec/arch/riscv/kexec-riscv.c 8 | 9 | riscv_DT_OPS += kexec/dt-ops.c 10 | 11 | riscv_MEM_REGIONS = kexec/mem_regions.c 12 | 13 | riscv_ARCH_REUSE_INITRD = 14 | 15 | riscv_CPPFLAGS += -I $(srcdir)/kexec/ 16 | 17 | dist += $(riscv_KEXEC_SRCS) \ 18 | kexec/arch/riscv/image-header.h \ 19 | kexec/arch/riscv/include/arch/options.h \ 20 | kexec/arch/riscv/iomem.h \ 21 | kexec/arch/riscv/kexec-riscv.h \ 22 | kexec/arch/riscv/Makefile 23 | 24 | ifdef HAVE_LIBFDT 25 | 26 | LIBS += -lfdt 27 | 28 | else 29 | 30 | include $(srcdir)/kexec/libfdt/Makefile.libfdt 31 | 32 | libfdt_SRCS += $(LIBFDT_SRCS:%=kexec/libfdt/%) 33 | 34 | riscv_CPPFLAGS += -I$(srcdir)/kexec/libfdt 35 | 36 | riscv_KEXEC_SRCS += $(libfdt_SRCS) 37 | 38 | endif 39 | -------------------------------------------------------------------------------- /kexec/arch/riscv/image-header.h: -------------------------------------------------------------------------------- 1 | /* 2 | * RISCV64 binary image header. 3 | * token from arm64/image-header.h 4 | */ 5 | 6 | #if !defined(__RISCV_IMAGE_HEADER_H) 7 | #define __RISCV_IMAGE_HEADER_H 8 | 9 | #include 10 | #include 11 | 12 | /** 13 | * struct riscv_image_header - riscv kernel image header. 14 | * 15 | **/ 16 | struct riscv_image_header { 17 | uint32_t code0; 18 | uint32_t code1; 19 | uint64_t text_offset; 20 | uint64_t image_size; 21 | uint64_t flags; 22 | uint32_t version; 23 | uint32_t res1; 24 | uint64_t res2; 25 | uint64_t magic; 26 | uint32_t magic2; 27 | uint32_t res3; 28 | }; 29 | 30 | #define RISCV_IMAGE_MAGIC 0x5643534952 31 | #define RISCV_IMAGE_MAGIC2 0x05435352 32 | 33 | #define RISCV_HEADER_VERSION_MAJOR 0 34 | #define RISCV_HEADER_VERSION_MINOR 2 35 | 36 | #define RISCV_HEADER_VERSION (RISCV_HEADER_VERSION_MAJOR << 16 | \ 37 | RISCV_HEADER_VERSION_MINOR) 38 | 39 | 40 | static const uint64_t riscv_image_flag_be = (1UL << 0); 41 | 42 | /** 43 | * riscv_header_check_magic - Helper to check the riscv image header. 44 | * 45 | * Returns non-zero if header is OK. 46 | */ 47 | 48 | static inline int riscv_header_check_magic(const struct riscv_image_header *h) 49 | { 50 | if (!h) 51 | return 0; 52 | 53 | return (h->version >= RISCV_HEADER_VERSION && h->magic2 == RISCV_IMAGE_MAGIC2); 54 | } 55 | 56 | /** 57 | * riscv_header_check_endiannes - Helper to check the riscv image header. 58 | * 59 | * Returns non-zero if the image was built as big endian. 60 | */ 61 | 62 | static inline int riscv_header_check_endiannes(const struct riscv_image_header *h) 63 | { 64 | if (!h) 65 | return 0; 66 | 67 | return (le64toh(h->flags) & riscv_image_flag_be) >> 0; 68 | } 69 | 70 | 71 | 72 | static inline uint64_t riscv_header_text_offset(const struct riscv_image_header *h) 73 | { 74 | if (!h) 75 | return 0; 76 | 77 | return le64toh(h->text_offset); 78 | } 79 | 80 | static inline uint64_t riscv_header_image_size(const struct riscv_image_header *h) 81 | { 82 | if (!h) 83 | return 0; 84 | 85 | return le64toh(h->image_size); 86 | } 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /kexec/arch/riscv/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_RISCV_OPTIONS_H 2 | #define KEXEC_ARCH_RISCV_OPTIONS_H 3 | 4 | #define OPT_APPEND ((OPT_MAX)+0) 5 | #define OPT_DTB ((OPT_MAX)+1) 6 | #define OPT_INITRD ((OPT_MAX)+2) 7 | #define OPT_CMDLINE ((OPT_MAX)+3) 8 | #define OPT_REUSE_CMDLINE ((OPT_MAX)+4) 9 | #define OPT_ARCH_MAX ((OPT_MAX)+5) 10 | 11 | /* Options relevant to the architecture (excluding loader-specific ones), 12 | * in this case none: 13 | */ 14 | #define KEXEC_ARCH_OPTIONS \ 15 | KEXEC_OPTIONS \ 16 | { "append", 1, 0, OPT_APPEND}, \ 17 | { "dtb", 1, 0, OPT_DTB }, \ 18 | { "initrd", 1, 0, OPT_INITRD }, \ 19 | { "command-line", 1, 0, OPT_CMDLINE}, \ 20 | { "reuse-cmdline", 0, NULL, OPT_REUSE_CMDLINE }, \ 21 | 22 | 23 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 24 | 25 | /* The following two #defines list ALL of the options added by all of the 26 | * architecture's loaders. 27 | * o main() uses this complete list to scan for its options, ignoring 28 | * arch-specific/loader-specific ones. 29 | * o Then, arch_process_options() uses this complete list to scan for its 30 | * options, ignoring general/loader-specific ones. 31 | * o Then, the file_type[n].load re-scans for options, using 32 | * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. 33 | * Any unrecognised options cause an error here. 34 | * 35 | * This is done so that main()'s/arch_process_options()'s getopt_long() calls 36 | * don't choose a kernel filename from random arguments to options they don't 37 | * recognise -- as they now recognise (if not act upon) all possible options. 38 | */ 39 | #define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS 40 | 41 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR 42 | 43 | #endif /* KEXEC_ARCH_RISCV_OPTIONS_H */ 44 | -------------------------------------------------------------------------------- /kexec/arch/riscv/iomem.h: -------------------------------------------------------------------------------- 1 | #ifndef IOMEM_H 2 | #define IOMEM_H 3 | 4 | #define SYSTEM_RAM "System RAM\n" 5 | #define KERNEL_CODE "Kernel code\n" 6 | #define KERNEL_DATA "Kernel data\n" 7 | #define CRASH_KERNEL "Crash kernel\n" 8 | #define IOMEM_RESERVED "Reserved\n" 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /kexec/arch/riscv/kexec-image-riscv.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * RISC-V kexec binary image support. 4 | * 5 | * Author: Song Shuai 6 | */ 7 | 8 | #define _GNU_SOURCE 9 | 10 | #include 11 | #include 12 | #include 13 | #include "image-header.h" 14 | #include "kexec.h" 15 | #include "kexec-riscv.h" 16 | #include "kexec-syscall.h" 17 | #include "arch/options.h" 18 | 19 | int image_riscv_probe(const char *kernel_buf, off_t kernel_size) 20 | { 21 | const struct riscv_image_header *h; 22 | 23 | if (kernel_size < sizeof(struct riscv_image_header)) { 24 | dbgprintf("%s: No riscv image header.\n", __func__); 25 | return -1; 26 | } 27 | 28 | h = (const struct riscv_image_header *)(kernel_buf); 29 | 30 | if (!riscv_header_check_magic(h)) { 31 | dbgprintf("%s: Bad riscv image header.\n", __func__); 32 | return -1; 33 | } 34 | 35 | return 0; 36 | } 37 | 38 | int image_riscv_load(int argc, char **argv, const char *kernel_buf, 39 | off_t kernel_size, struct kexec_info *info) 40 | { 41 | const struct riscv_image_header *h; 42 | unsigned long text_offset, image_size; 43 | off_t new_base_addr = 0; 44 | 45 | int ret; 46 | 47 | if (info->file_mode) { 48 | return prepare_kexec_file_options(info); 49 | } 50 | 51 | h = (const struct riscv_image_header *)(kernel_buf); 52 | 53 | /* Check header */ 54 | if (!h->image_size){ 55 | dbgprintf("Kernel image size is NULL\n"); 56 | ret = EFAILED; 57 | goto exit; 58 | } 59 | 60 | if(riscv_header_check_endiannes(h)){ 61 | dbgprintf("Kernel image was built as big endian\n"); 62 | ret = EFAILED; 63 | goto exit; 64 | } 65 | 66 | text_offset = riscv_header_text_offset(h); 67 | image_size = riscv_header_image_size(h); 68 | 69 | /* Setup the entry and segments */ 70 | 71 | ret = riscv_find_pbase(info, &new_base_addr, image_size, text_offset); 72 | if (ret < 0) { 73 | fprintf(stderr, "Could not find a memory region for the " 74 | "provided Image\n"); 75 | goto exit; 76 | } 77 | 78 | info->entry = (void *) new_base_addr; 79 | dbgprintf("Entry point for the Image: 0x%lX\n", new_base_addr); 80 | 81 | add_segment(info, kernel_buf, kernel_size, new_base_addr, image_size); 82 | 83 | ret = load_extra_segments(info, text_offset, image_size, ULONG_MAX); 84 | exit: 85 | if (ret) 86 | fprintf(stderr, "kexec: load failed.\n"); 87 | return ret; 88 | } 89 | 90 | void image_riscv_usage(void) 91 | { 92 | printf( 93 | " An RISC-V binary image, uncompressed, little endian.\n" 94 | " Typically an Image file.\n\n"); 95 | } 96 | -------------------------------------------------------------------------------- /kexec/arch/riscv/kexec-riscv.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 */ 2 | /* 3 | * Copyright (C) 2019 FORTH-ICS/CARV 4 | * Nick Kossifidis 5 | */ 6 | 7 | /* 8 | * Kernel should be aligned to the nearest 9 | * hugepage (2MB for RV64, 4MB for RV32). 10 | */ 11 | 12 | #if __riscv_xlen == 64 13 | #define KERNEL_ALIGN 0x200000 14 | #else 15 | #define KERNEL_ALIGN 0x400000 16 | #endif 17 | 18 | struct fdt_image { 19 | char *buf; 20 | off_t size; 21 | }; 22 | 23 | struct riscv_opts { 24 | char *cmdline; 25 | char *fdt_path; 26 | char *initrd_path; 27 | uint64_t initrd_start; 28 | uint64_t initrd_end; 29 | struct fdt_image *fdt; 30 | }; 31 | 32 | /* crashdump-riscv.c */ 33 | extern struct memory_range elfcorehdr_mem; 34 | int load_elfcorehdr(struct kexec_info *info); 35 | 36 | /* kexec-riscv.c */ 37 | int prepare_kexec_file_options(struct kexec_info *info); 38 | int load_extra_segments(struct kexec_info *info, uint64_t kernel_base, 39 | uint64_t kernel_size, uint64_t max_addr); 40 | int riscv_find_pbase(struct kexec_info *info, off_t *addr, 41 | off_t size, off_t align); 42 | 43 | /* kexec-elf-riscv.c */ 44 | int elf_riscv_probe(const char *buf, off_t len); 45 | void elf_riscv_usage(void); 46 | int elf_riscv_load(int argc, char **argv, const char *buf, off_t len, 47 | struct kexec_info *info); 48 | 49 | /* kexec-image-riscv.c */ 50 | int image_riscv_probe(const char *buf, off_t len); 51 | void image_riscv_usage(void); 52 | int image_riscv_load(int argc, char **argv, const char *buf, off_t len, 53 | struct kexec_info *info); 54 | -------------------------------------------------------------------------------- /kexec/arch/s390/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec s390 (linux booting linux) 3 | # 4 | s390_KEXEC_SRCS = kexec/arch/s390/kexec-s390.c 5 | s390_KEXEC_SRCS += kexec/arch/s390/kexec-image.c 6 | s390_KEXEC_SRCS += kexec/arch/s390/kexec-elf-rel-s390.c 7 | s390_KEXEC_SRCS += kexec/arch/s390/crashdump-s390.c 8 | 9 | dist += kexec/arch/s390/Makefile $(s390_KEXEC_SRCS) \ 10 | kexec/arch/s390/kexec-s390.h \ 11 | kexec/arch/s390/include/arch/options.h 12 | -------------------------------------------------------------------------------- /kexec/arch/s390/crashdump-s390.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec/arch/s390/crashdump-s390.c 3 | * 4 | * Copyright IBM Corp. 2011 5 | * 6 | * Author(s): Michael Holzheu 7 | */ 8 | 9 | #ifdef __s390x__ 10 | #define _GNU_SOURCE 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "../../kexec.h" 17 | #include "../../kexec-syscall.h" 18 | #include "../../kexec/crashdump.h" 19 | #include "kexec-s390.h" 20 | 21 | /* 22 | * Create ELF core header 23 | */ 24 | static int create_elf_header(struct kexec_info *info, unsigned long crash_base, 25 | unsigned long crash_end) 26 | { 27 | #ifdef WITH_ELF_HEADER 28 | static struct memory_range crash_memory_range[MAX_MEMORY_RANGES]; 29 | unsigned long elfcorehdr, elfcorehdr_size, bufsz; 30 | struct crash_elf_info elf_info; 31 | char str[COMMAND_LINESIZE]; 32 | int ranges; 33 | void *tmp; 34 | 35 | memset(&elf_info, 0, sizeof(elf_info)); 36 | 37 | elf_info.data = ELFDATA2MSB; 38 | elf_info.machine = EM_S390; 39 | elf_info.class = ELFCLASS64; 40 | elf_info.get_note_info = get_crash_notes_per_cpu; 41 | 42 | if (get_memory_ranges_s390(crash_memory_range, &ranges, 0)) 43 | return -1; 44 | 45 | if (crash_create_elf64_headers(info, &elf_info, crash_memory_range, 46 | ranges, &tmp, &bufsz, 47 | ELF_CORE_HEADER_ALIGN)) 48 | return -1; 49 | 50 | elfcorehdr = add_buffer(info, tmp, bufsz, bufsz, 1024, 51 | crash_base, crash_end, -1); 52 | elfcorehdr_size = bufsz; 53 | snprintf(str, sizeof(str), " elfcorehdr=%ld@%ldK\n", 54 | elfcorehdr_size, elfcorehdr / 1024); 55 | if (command_line_add(info, str)) 56 | return -1; 57 | #endif 58 | return 0; 59 | } 60 | 61 | /* 62 | * Load additional segments for kdump kernel 63 | */ 64 | int load_crashdump_segments(struct kexec_info *info, unsigned long crash_base, 65 | unsigned long crash_end) 66 | { 67 | unsigned long crash_size = crash_size = crash_end - crash_base + 1; 68 | 69 | if (create_elf_header(info, crash_base, crash_end)) 70 | return -1; 71 | elf_rel_build_load(info, &info->rhdr, (const char *) purgatory, 72 | purgatory_size, crash_base + 0x2000, 73 | crash_base + 0x10000, -1, 0); 74 | elf_rel_set_symbol(&info->rhdr, "crash_base", &crash_base, 75 | sizeof(crash_base)); 76 | elf_rel_set_symbol(&info->rhdr, "crash_size", &crash_size, 77 | sizeof(crash_size)); 78 | info->entry = (void *) elf_rel_get_addr(&info->rhdr, "purgatory_start"); 79 | return 0; 80 | } 81 | #else 82 | /* 83 | * kdump is not available for s390 84 | */ 85 | int load_crashdump_segments(struct kexec_info *info, unsigned long crash_base, 86 | unsigned long crash_end) 87 | { 88 | return -1; 89 | } 90 | #endif 91 | -------------------------------------------------------------------------------- /kexec/arch/s390/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_S390_OPTIONS_H 2 | #define KEXEC_ARCH_S390_OPTIONS_H 3 | 4 | #define OPT_ARCH_MAX (OPT_MAX+0) 5 | #define OPT_APPEND (OPT_MAX+0) 6 | #define OPT_RAMDISK (OPT_MAX+1) 7 | #define OPT_REUSE_CMDLINE (OPT_MAX+2) 8 | 9 | /* Options relevant to the architecture (excluding loader-specific ones), 10 | * in this case none: 11 | */ 12 | #define KEXEC_ARCH_OPTIONS \ 13 | KEXEC_OPTIONS \ 14 | 15 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 16 | 17 | /* The following two #defines list ALL of the options added by all of the 18 | * architecture's loaders. 19 | * o main() uses this complete list to scan for its options, ignoring 20 | * arch-specific/loader-specific ones. 21 | * o Then, arch_process_options() uses this complete list to scan for its 22 | * options, ignoring general/loader-specific ones. 23 | * o Then, the file_type[n].load re-scans for options, using 24 | * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. 25 | * Any unrecognised options cause an error here. 26 | * 27 | * This is done so that main()'s/arch_process_options()'s getopt_long() calls 28 | * don't choose a kernel filename from random arguments to options they don't 29 | * recognise -- as they now recognise (if not act upon) all possible options. 30 | */ 31 | #define KEXEC_ALL_OPTIONS \ 32 | KEXEC_ARCH_OPTIONS \ 33 | {"command-line", 1, 0, OPT_APPEND}, \ 34 | {"append", 1, 0, OPT_APPEND}, \ 35 | {"initrd", 1, 0, OPT_RAMDISK}, \ 36 | {"reuse-cmdline", 0, 0, OPT_REUSE_CMDLINE }, 37 | 38 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR 39 | 40 | #endif /* KEXEC_ARCH_S390_OPTIONS_H */ 41 | -------------------------------------------------------------------------------- /kexec/arch/s390/kexec-elf-rel-s390.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec/arch/s390/kexec-elf-rel-s390.c 3 | * 4 | * Copyright IBM Corp. 2005,2011 5 | * 6 | * Author(s): Heiko Carstens 7 | * 8 | */ 9 | 10 | #include 11 | #include 12 | #include "../../kexec.h" 13 | #include "../../kexec-elf.h" 14 | 15 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 16 | { 17 | if (ehdr->ei_data != ELFDATA2MSB) 18 | return 0; 19 | if (ehdr->ei_class != ELFCLASS64) 20 | return 0; 21 | if (ehdr->e_machine != EM_S390) 22 | return 0; 23 | return 1; 24 | } 25 | 26 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 27 | struct mem_sym *UNUSED(sym), 28 | unsigned long r_type, 29 | void *loc, 30 | unsigned long address, 31 | unsigned long val) 32 | { 33 | switch (r_type) { 34 | case R_390_8: /* Direct 8 bit. */ 35 | case R_390_12: /* Direct 12 bit. */ 36 | case R_390_16: /* Direct 16 bit. */ 37 | case R_390_20: /* Direct 20 bit. */ 38 | case R_390_32: /* Direct 32 bit. */ 39 | case R_390_64: /* Direct 64 bit. */ 40 | if (r_type == R_390_8) 41 | *(unsigned char *) loc = val; 42 | else if (r_type == R_390_12) 43 | *(unsigned short *) loc = (val & 0xfff) | 44 | (*(unsigned short *) loc & 0xf000); 45 | else if (r_type == R_390_16) 46 | *(unsigned short *) loc = val; 47 | else if (r_type == R_390_20) 48 | *(unsigned int *) loc = 49 | (*(unsigned int *) loc & 0xf00000ff) | 50 | (val & 0xfff) << 16 | (val & 0xff000) >> 4; 51 | else if (r_type == R_390_32) 52 | *(unsigned int *) loc = val; 53 | else if (r_type == R_390_64) 54 | *(unsigned long *) loc = val; 55 | break; 56 | case R_390_PC16: /* PC relative 16 bit. */ 57 | case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */ 58 | case R_390_PC32DBL: /* PC relative 32 bit shifted by 1. */ 59 | case R_390_PLT32DBL: /* 32 bit PC rel. PLT shifted by 1. */ 60 | case R_390_PC32: /* PC relative 32 bit. */ 61 | case R_390_PC64: /* PC relative 64 bit. */ 62 | val -= address; 63 | if (r_type == R_390_PC16) 64 | *(unsigned short *) loc = val; 65 | else if (r_type == R_390_PC16DBL) 66 | *(unsigned short *) loc = val >> 1; 67 | else if (r_type == R_390_PC32DBL || r_type == R_390_PLT32DBL) 68 | *(unsigned int *) loc = val >> 1; 69 | else if (r_type == R_390_PC32) 70 | *(unsigned int *) loc = val; 71 | else if (r_type == R_390_PC64) 72 | *(unsigned long *) loc = val; 73 | break; 74 | default: 75 | die("Unknown rela relocation: 0x%lx 0x%lx\n", r_type, address); 76 | break; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /kexec/arch/s390/kexec-s390.h: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec/arch/s390/kexec-s390.h 3 | * 4 | * (C) Copyright IBM Corp. 2005 5 | * 6 | * Author(s): Rolf Adelsberger 7 | * 8 | */ 9 | 10 | #ifndef KEXEC_S390_H 11 | #define KEXEC_S390_H 12 | 13 | #define IMAGE_READ_OFFSET 0x10000 14 | 15 | #define RAMDISK_ORIGIN_ADDR 0x800000 16 | #define INITRD_START_OFFS 0x408 17 | #define INITRD_SIZE_OFFS 0x410 18 | #define OLDMEM_BASE_OFFS 0x418 19 | #define OLDMEM_SIZE_OFFS 0x420 20 | #define MAX_COMMAND_LINESIZE_OFFS 0x430 21 | #define COMMAND_LINE_OFFS 0x480 22 | #define LEGACY_COMMAND_LINESIZE 896 23 | #define MAX_MEMORY_RANGES 1024 24 | 25 | #define MAX(x, y) ((x) > (y) ? (x) : (y)) 26 | #define MIN(x, y) ((x) < (y) ? (x) : (y)) 27 | 28 | extern int image_s390_load(int, char **, const char *, off_t, struct kexec_info *); 29 | extern int image_s390_probe(const char *, off_t); 30 | extern void image_s390_usage(void); 31 | extern int load_crashdump_segments(struct kexec_info *info, 32 | unsigned long crash_base, 33 | unsigned long crash_end); 34 | extern int get_memory_ranges_s390(struct memory_range range[], int *ranges, 35 | int with_crashk); 36 | extern int command_line_add(struct kexec_info *info, const char *str); 37 | 38 | #endif /* KEXEC_S390_H */ 39 | -------------------------------------------------------------------------------- /kexec/arch/sh/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec sh (linux booting linux) 3 | # 4 | sh_KEXEC_SRCS += kexec/arch/sh/kexec-sh.c 5 | sh_KEXEC_SRCS += kexec/arch/sh/kexec-uImage-sh.c 6 | sh_KEXEC_SRCS += kexec/arch/sh/kexec-zImage-sh.c 7 | sh_KEXEC_SRCS += kexec/arch/sh/kexec-netbsd-sh.c 8 | sh_KEXEC_SRCS += kexec/arch/sh/kexec-elf-sh.c 9 | sh_KEXEC_SRCS += kexec/arch/sh/kexec-elf-rel-sh.c 10 | sh_KEXEC_SRCS += kexec/arch/sh/netbsd_booter.S 11 | sh_KEXEC_SRCS += kexec/arch/sh/crashdump-sh.c 12 | 13 | sh_UIMAGE = kexec/kexec-uImage.c 14 | 15 | sh_ADD_BUFFER = 16 | sh_ADD_SEGMENT = 17 | sh_VIRT_TO_PHYS = 18 | 19 | dist += kexec/arch/sh/Makefile $(sh_KEXEC_SRCS) \ 20 | kexec/arch/sh/kexec-sh.h \ 21 | kexec/arch/sh/crashdump-sh.h \ 22 | kexec/arch/sh/include/arch/options.h 23 | -------------------------------------------------------------------------------- /kexec/arch/sh/crashdump-sh.h: -------------------------------------------------------------------------------- 1 | #ifndef CRASHDUMP_SH_H 2 | #define CRASHDUMP_SH_H 3 | 4 | struct kexec_info; 5 | int load_crashdump_segments(struct kexec_info *info, char* mod_cmdline); 6 | 7 | #define PAGE_OFFSET 0x80000000 8 | 9 | #endif /* CRASHDUMP_SH_H */ 10 | -------------------------------------------------------------------------------- /kexec/arch/sh/include/arch/options.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ARCH_SH_OPTIONS_H 2 | #define KEXEC_ARCH_SH_OPTIONS_H 3 | 4 | #define OPT_ARCH_MAX (OPT_MAX+0) 5 | #define OPT_APPEND (OPT_ARCH_MAX+1) 6 | #define OPT_EMPTYZERO (OPT_ARCH_MAX+2) 7 | #define OPT_NBSD_HOWTO (OPT_ARCH_MAX+3) 8 | #define OPT_NBSD_MROOT (OPT_ARCH_MAX+4) 9 | 10 | /* Options relevant to the architecture (excluding loader-specific ones): */ 11 | #define KEXEC_ARCH_OPTIONS \ 12 | KEXEC_OPTIONS \ 13 | {"command-line", 1, 0, OPT_APPEND}, \ 14 | {"append", 1, 0, OPT_APPEND}, \ 15 | {"empty-zero", 1, 0, OPT_APPEND}, \ 16 | {"howto", 1, 0, OPT_NBSD_HOWTO}, \ 17 | {"miniroot", 1, 0, OPT_NBSD_MROOT}, 18 | /* These options seem to be loader-specific rather than superh-specific, so 19 | * ought to be moved to KEXEC_ALL_OPTIONS below and parsed in the relevant 20 | * loader, e.g. kexec-netbsd-sh.c 21 | */ 22 | 23 | #define KEXEC_ARCH_OPT_STR KEXEC_OPT_STR "" 24 | 25 | /* The following two #defines list ALL of the options added by all of the 26 | * architecture's loaders. 27 | * o main() uses this complete list to scan for its options, ignoring 28 | * arch-specific/loader-specific ones. 29 | * o Then, arch_process_options() uses this complete list to scan for its 30 | * options, ignoring general/loader-specific ones. 31 | * o Then, the file_type[n].load re-scans for options, using 32 | * KEXEC_ARCH_OPTIONS plus its loader-specific options subset. 33 | * Any unrecognised options cause an error here. 34 | * 35 | * This is done so that main()'s/arch_process_options()'s getopt_long() calls 36 | * don't choose a kernel filename from random arguments to options they don't 37 | * recognise -- as they now recognise (if not act upon) all possible options. 38 | */ 39 | #define KEXEC_ALL_OPTIONS KEXEC_ARCH_OPTIONS 40 | #define KEXEC_ALL_OPT_STR KEXEC_ARCH_OPT_STR 41 | 42 | #endif /* KEXEC_ARCH_SH_OPTIONS_H */ 43 | -------------------------------------------------------------------------------- /kexec/arch/sh/kexec-elf-rel-sh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec-elf-rel-sh.c - ELF relocations for SuperH 3 | * Copyright (C) 2008 Paul Mundt 4 | * 5 | * Based on the SHcompact module loader (arch/sh/kernel/module.c) in the 6 | * Linux kernel, which is written by: 7 | * 8 | * Copyright (C) 2003 - 2008 Kaz Kojima & Paul Mundt 9 | * 10 | * This source code is licensed under the GNU General Public License, 11 | * Version 2. See the file COPYING for more details. 12 | */ 13 | #include 14 | #include 15 | #include "../../kexec.h" 16 | #include "../../kexec-elf.h" 17 | 18 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 19 | { 20 | /* Intentionally don't bother with endianness validation, it's 21 | * configurable */ 22 | 23 | if (ehdr->ei_class != ELFCLASS32) 24 | return 0; 25 | if (ehdr->e_machine != EM_SH) 26 | return 0; 27 | 28 | return 1; 29 | } 30 | 31 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 32 | struct mem_sym *UNUSED(sym), unsigned long r_type, void *orig_loc, 33 | unsigned long UNUSED(address), unsigned long relocation) 34 | { 35 | uint32_t *location = orig_loc; 36 | uint32_t value; 37 | 38 | switch (r_type) { 39 | case R_SH_DIR32: 40 | value = get_unaligned(location); 41 | value += relocation; 42 | put_unaligned(value, location); 43 | break; 44 | case R_SH_REL32: 45 | relocation = (relocation - (uint32_t)location); 46 | value = get_unaligned(location); 47 | value += relocation; 48 | put_unaligned(value, location); 49 | break; 50 | default: 51 | die("Unknown rela relocation: %lu\n", r_type); 52 | break; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /kexec/arch/sh/kexec-sh.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_SH_H 2 | #define KEXEC_SH_H 3 | 4 | #define COMMAND_LINE_SIZE 2048 5 | 6 | int uImage_sh_probe(const char *buf, off_t len); 7 | int uImage_sh_load(int argc, char **argv, const char *buf, off_t len, 8 | struct kexec_info *info); 9 | 10 | int zImage_sh_probe(const char *buf, off_t len); 11 | int zImage_sh_load(int argc, char **argv, const char *buf, off_t len, 12 | struct kexec_info *info); 13 | void zImage_sh_usage(void); 14 | 15 | int elf_sh_probe(const char *buf, off_t len); 16 | int elf_sh_load(int argc, char **argv, const char *buf, off_t len, 17 | struct kexec_info *info); 18 | void elf_sh_usage(void); 19 | 20 | int netbsd_sh_probe(const char *buf, off_t len); 21 | int netbsd_sh_load(int argc, char **argv, const char *buf, off_t len, 22 | struct kexec_info *info); 23 | void netbsd_sh_usage(void); 24 | 25 | char *get_append(void); 26 | void kexec_sh_setup_zero_page(char *zero_page_buf, size_t zero_page_size, 27 | char *cmd_line); 28 | 29 | #endif /* KEXEC_SH_H */ 30 | -------------------------------------------------------------------------------- /kexec/arch/sh/kexec-uImage-sh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * uImage support added by Marc Andre Tanner 3 | * 4 | * Cloned from ARM by Paul Mundt, 2009. 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "../../kexec.h" 12 | #include "kexec-sh.h" 13 | 14 | int uImage_sh_probe(const char *buf, off_t len) 15 | { 16 | return uImage_probe_kernel(buf, len, IH_ARCH_SH); 17 | } 18 | 19 | int uImage_sh_load(int argc, char **argv, const char *buf, off_t len, 20 | struct kexec_info *info) 21 | { 22 | return zImage_sh_load(argc, argv, buf + sizeof(struct image_header), 23 | len - sizeof(struct image_header), info); 24 | } 25 | -------------------------------------------------------------------------------- /kexec/arch/sh/netbsd_booter.S: -------------------------------------------------------------------------------- 1 | .globl netbsd_booter 2 | netbsd_booter: 3 | mov.l ccr,r0 4 | mov #0,r1 5 | mov.l r1,@r0 6 | nop 7 | nop 8 | nop 9 | nop 10 | nop 11 | nop 12 | nop 13 | nop 14 | nop 15 | nop 16 | mova netbsd_start,r0 17 | mov.l @r0,r1 18 | add #4,r0 19 | mov.l @r0,r4 ! howto 20 | add #4,r0 21 | mov r0,r5 ! bootinfo 22 | jmp @r1 23 | nop 24 | nop 25 | nop 26 | .align 4 27 | ccr: .long 0xff00001c 28 | 29 | .align 8 30 | netbsd_start: 31 | .long 0x8c001000 32 | .long 0x200 ! howto 33 | .long 0 ! bootinfo 34 | .long 0 ! bootinfo 35 | .long 0 ! bootinfo 36 | .long 0 ! bootinfo 37 | .long 0 ! bootinfo 38 | .long 0 ! bootinfo 39 | .long 0 ! bootinfo 40 | .long 0 ! bootinfo 41 | .long 0 ! bootinfo 42 | .long 0 ! bootinfo 43 | .long 0 ! bootinfo 44 | .long 0 ! bootinfo 45 | .long 0 ! bootinfo 46 | .long 0 ! bootinfo 47 | 48 | -------------------------------------------------------------------------------- /kexec/arch/x86_64/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec x86_64 (linux booting linux) 3 | # 4 | x86_64_KEXEC_SRCS = kexec/arch/i386/kexec-elf-x86.c 5 | x86_64_KEXEC_SRCS += kexec/arch/i386/kexec-bzImage.c 6 | x86_64_KEXEC_SRCS += kexec/arch/i386/kexec-multiboot-x86.c 7 | x86_64_KEXEC_SRCS += kexec/arch/i386/kexec-mb2-x86.c 8 | x86_64_KEXEC_SRCS += kexec/arch/i386/kexec-beoboot-x86.c 9 | x86_64_KEXEC_SRCS += kexec/arch/i386/kexec-nbi.c 10 | x86_64_KEXEC_SRCS += kexec/arch/i386/x86-linux-setup.c 11 | x86_64_KEXEC_SRCS += kexec/arch/i386/kexec-x86-common.c 12 | x86_64_KEXEC_SRCS += kexec/arch/i386/crashdump-x86.c 13 | 14 | x86_64_KEXEC_SRCS_native = kexec/arch/x86_64/kexec-x86_64.c 15 | x86_64_KEXEC_SRCS_native += kexec/arch/x86_64/kexec-elf-x86_64.c 16 | x86_64_KEXEC_SRCS_native += kexec/arch/x86_64/kexec-elf-rel-x86_64.c 17 | x86_64_KEXEC_SRCS_native += kexec/arch/x86_64/kexec-bzImage64.c 18 | 19 | x86_64_KEXEC_SRCS += $(x86_64_KEXEC_SRCS_native) 20 | 21 | # Don't add sources in i386/ to dist, as i386/Makefile adds them 22 | dist += kexec/arch/x86_64/Makefile $(x86_64_KEXEC_SRCS_native) \ 23 | kexec/arch/x86_64/kexec-x86_64.h \ 24 | kexec/arch/x86_64/include/arch/options.h 25 | -------------------------------------------------------------------------------- /kexec/arch/x86_64/include/arch/options.h: -------------------------------------------------------------------------------- 1 | ../../../i386/include/arch/options.h -------------------------------------------------------------------------------- /kexec/arch/x86_64/kexec-elf-rel-x86_64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../../kexec.h" 4 | #include "../../kexec-elf.h" 5 | 6 | int machine_verify_elf_rel(struct mem_ehdr *ehdr) 7 | { 8 | if (ehdr->ei_data != ELFDATA2LSB) { 9 | return 0; 10 | } 11 | if (ehdr->ei_class != ELFCLASS64 && 12 | ehdr->ei_class != ELFCLASS32) { /* x32 */ 13 | return 0; 14 | } 15 | if (ehdr->e_machine != EM_X86_64) { 16 | return 0; 17 | } 18 | return 1; 19 | } 20 | 21 | static const char *reloc_name(unsigned long r_type) 22 | { 23 | static const char *r_name[] = { 24 | "R_X86_64_NONE", 25 | "R_X86_64_64", 26 | "R_X86_64_PC32", 27 | "R_X86_64_GOT32", 28 | "R_X86_64_PLT32", 29 | "R_X86_64_COPY", 30 | "R_X86_64_GLOB_DAT", 31 | "R_X86_64_JUMP_SLOT", 32 | "R_X86_64_RELATIVE", 33 | "R_X86_64_GOTPCREL", 34 | "R_X86_64_32", 35 | "R_X86_64_32S", 36 | "R_X86_64_16", 37 | "R_X86_64_PC16", 38 | "R_X86_64_8", 39 | "R_X86_64_PC8", 40 | "R_X86_64_DTPMOD64", 41 | "R_X86_64_DTPOFF64", 42 | "R_X86_64_TPOFF64", 43 | "R_X86_64_TLSGD", 44 | "R_X86_64_TLSLD", 45 | "R_X86_64_DTPOFF32", 46 | "R_X86_64_GOTTPOFF", 47 | "R_X86_64_TPOFF32", 48 | }; 49 | static char buf[100]; 50 | const char *name; 51 | if (r_type < (sizeof(r_name)/sizeof(r_name[0]))){ 52 | name = r_name[r_type]; 53 | } 54 | else { 55 | sprintf(buf, "R_X86_64_%lu", r_type); 56 | name = buf; 57 | } 58 | return name; 59 | } 60 | 61 | void machine_apply_elf_rel(struct mem_ehdr *UNUSED(ehdr), 62 | struct mem_sym *UNUSED(sym), unsigned long r_type, void *location, 63 | unsigned long address, unsigned long value) 64 | { 65 | dbgprintf("%s\n", reloc_name(r_type)); 66 | switch(r_type) { 67 | case R_X86_64_NONE: 68 | break; 69 | case R_X86_64_64: 70 | *(uint64_t *)location = value; 71 | break; 72 | case R_X86_64_32: 73 | *(uint32_t *)location = value; 74 | if (value != *(uint32_t *)location) 75 | goto overflow; 76 | break; 77 | case R_X86_64_32S: 78 | *(uint32_t *)location = value; 79 | if ((int64_t)value != *(int32_t *)location) 80 | goto overflow; 81 | break; 82 | case R_X86_64_PC32: 83 | case R_X86_64_PLT32: 84 | *(uint32_t *)location = value - address; 85 | break; 86 | default: 87 | die("Unhandled rela relocation: %s\n", reloc_name(r_type)); 88 | break; 89 | } 90 | return; 91 | overflow: 92 | die("overflow in relocation type %s val %lx\n", 93 | reloc_name(r_type), value); 94 | } 95 | -------------------------------------------------------------------------------- /kexec/arch/x86_64/kexec-x86_64.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_X86_64_H 2 | #define KEXEC_X86_64_H 3 | 4 | #include "../i386/kexec-x86.h" 5 | 6 | struct entry64_regs { 7 | uint64_t rax; 8 | uint64_t rbx; 9 | uint64_t rcx; 10 | uint64_t rdx; 11 | uint64_t rsi; 12 | uint64_t rdi; 13 | uint64_t rsp; 14 | uint64_t rbp; 15 | uint64_t r8; 16 | uint64_t r9; 17 | uint64_t r10; 18 | uint64_t r11; 19 | uint64_t r12; 20 | uint64_t r13; 21 | uint64_t r14; 22 | uint64_t r15; 23 | uint64_t rip; 24 | }; 25 | 26 | int elf_x86_64_probe(const char *buf, off_t len); 27 | int elf_x86_64_load(int argc, char **argv, const char *buf, off_t len, 28 | struct kexec_info *info); 29 | void elf_x86_64_usage(void); 30 | 31 | int bzImage64_probe(const char *buf, off_t len); 32 | int bzImage64_load(int argc, char **argv, const char *buf, off_t len, 33 | struct kexec_info *info); 34 | void bzImage64_usage(void); 35 | 36 | int multiboot2_x86_load(int argc, char **argv, const char *buf, off_t len, 37 | struct kexec_info *info); 38 | void multiboot2_x86_usage(void); 39 | int multiboot2_x86_probe(const char *buf, off_t buf_len); 40 | 41 | #endif /* KEXEC_X86_64_H */ 42 | -------------------------------------------------------------------------------- /kexec/arch_reuse_initrd.c: -------------------------------------------------------------------------------- 1 | #include "kexec.h" 2 | 3 | unsigned char reuse_initrd = 0; 4 | 5 | void arch_reuse_initrd(void) 6 | { 7 | die("--reuseinitrd not implemented on this architecture\n"); 8 | } 9 | -------------------------------------------------------------------------------- /kexec/crashdump.h: -------------------------------------------------------------------------------- 1 | #ifndef CRASHDUMP_H 2 | #define CRASHDUMP_H 3 | 4 | extern int get_crash_notes_per_cpu(int cpu, uint64_t *addr, uint64_t *len); 5 | extern int get_kernel_vmcoreinfo(uint64_t *addr, uint64_t *len); 6 | extern int get_xen_vmcoreinfo(uint64_t *addr, uint64_t *len); 7 | 8 | /* Need to find a better way to determine per cpu notes section size. */ 9 | #define MAX_NOTE_BYTES 1024 10 | /* Expecting ELF headers to fit in 64K. Increase it if you need more. */ 11 | #define KCORE_ELF_HEADERS_SIZE 65536 12 | /* The address of the ELF header is passed to the secondary kernel 13 | * using the kernel command line option memmap=nnn. 14 | * The smallest unit the kernel accepts is in kilobytes, 15 | * so we need to make sure the ELF header is aligned to 1024. 16 | */ 17 | #define ELF_CORE_HEADER_ALIGN 1024 18 | 19 | /* structure passed to crash_create_elf32/64_headers() */ 20 | 21 | struct crash_elf_info { 22 | unsigned long class; 23 | unsigned long data; 24 | unsigned long machine; 25 | 26 | unsigned long long page_offset; 27 | unsigned long long kern_vaddr_start; 28 | unsigned long long kern_paddr_start; 29 | unsigned long kern_size; 30 | unsigned long lowmem_limit; 31 | 32 | int (*get_note_info)(int cpu, uint64_t *addr, uint64_t *len); 33 | }; 34 | 35 | typedef int(*crash_create_elf_headers_func)(struct kexec_info *info, 36 | struct crash_elf_info *elf_info, 37 | struct memory_range *range, 38 | int ranges, 39 | void **buf, unsigned long *size, 40 | unsigned long align); 41 | 42 | int crash_create_elf32_headers(struct kexec_info *info, 43 | struct crash_elf_info *elf_info, 44 | struct memory_range *range, int ranges, 45 | void **buf, unsigned long *size, 46 | unsigned long align); 47 | 48 | int crash_create_elf64_headers(struct kexec_info *info, 49 | struct crash_elf_info *elf_info, 50 | struct memory_range *range, int ranges, 51 | void **buf, unsigned long *size, 52 | unsigned long align); 53 | 54 | unsigned long crash_architecture(struct crash_elf_info *elf_info); 55 | 56 | unsigned long phys_to_virt(struct crash_elf_info *elf_info, 57 | unsigned long long paddr); 58 | 59 | unsigned long xen_architecture(struct crash_elf_info *elf_info); 60 | int xen_get_nr_phys_cpus(void); 61 | int xen_get_note(int cpu, uint64_t *addr, uint64_t *len); 62 | int xen_get_crashkernel_region(uint64_t *start, uint64_t *end); 63 | 64 | #endif /* CRASHDUMP_H */ 65 | -------------------------------------------------------------------------------- /kexec/dt-ops.h: -------------------------------------------------------------------------------- 1 | #if !defined(KEXEC_DT_OPS_H) 2 | #define KEXEC_DT_OPS_H 3 | 4 | #include 5 | 6 | int dtb_set_initrd(char **dtb, off_t *dtb_size, off_t start, off_t end); 7 | void dtb_clear_initrd(char **dtb, off_t *dtb_size); 8 | int dtb_set_bootargs(char **dtb, off_t *dtb_size, const char *command_line); 9 | int dtb_set_property(char **dtb, off_t *dtb_size, const char *node, 10 | const char *prop, const void *value, int value_len); 11 | 12 | int dtb_delete_property(char *dtb, const char *node, const char *prop); 13 | 14 | void dtb_extract_int_property(uint64_t *val, const void *buf, uint32_t cells); 15 | void dtb_fill_int_property(void *buf, uint64_t val, uint32_t cells); 16 | int dtb_add_range_property(char **dtb, off_t *dtb_size, uint64_t start, uint64_t end, 17 | const char *node, const char* parent); 18 | int dtb_get_memory_ranges(char *dtb, struct memory_ranges *mem_ranges, 19 | struct memory_ranges *extra_ranges); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /kexec/fs2dt.h: -------------------------------------------------------------------------------- 1 | #ifndef FS2DT_H 2 | #define FS2DT_H 3 | 4 | #if (BOOT_BLOCK_VERSION != 2 && BOOT_BLOCK_VERSION != 17) 5 | #error Please add or correct definition of BOOT_BLOCK_VERSION 6 | #endif 7 | 8 | /* boot block as defined by the linux kernel */ 9 | struct bootblock { 10 | unsigned magic; 11 | unsigned totalsize; 12 | unsigned off_dt_struct; 13 | unsigned off_dt_strings; 14 | unsigned off_mem_rsvmap; 15 | unsigned version; 16 | unsigned last_comp_version; 17 | #if (BOOT_BLOCK_VERSION >= 2) 18 | /* version 2 fields below */ 19 | unsigned boot_physid; 20 | /* version 3 fields below */ 21 | unsigned dt_strings_size; 22 | #if (BOOT_BLOCK_VERSION >= 17) 23 | /* version 17 fields below */ 24 | unsigned dt_struct_size; 25 | #endif 26 | #endif 27 | }; 28 | 29 | extern struct bootblock bb[1]; 30 | 31 | /* Used for enabling printing message from purgatory code 32 | * Only has implemented for PPC64 */ 33 | extern int my_debug; 34 | extern int dt_no_old_root; 35 | 36 | void reserve(unsigned long long where, unsigned long long length); 37 | void create_flatten_tree(char **, off_t *, const char *); 38 | 39 | #endif /* KEXEC_H */ 40 | -------------------------------------------------------------------------------- /kexec/ifdown.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ifdown.c Find all network interfaces on the system and 3 | * shut them down. 4 | * 5 | */ 6 | char *v_ifdown = "@(#)ifdown.c 1.11 02-Jun-1998 miquels@cistron.nl"; 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | /* 23 | * First, we find all shaper devices and down them. Then we 24 | * down all real interfaces. This is because the comment in the 25 | * shaper driver says "if you down the shaper device before the 26 | * attached inerface your computer will follow". 27 | */ 28 | int ifdown(void) 29 | { 30 | struct if_nameindex *ifa, *ifp; 31 | struct ifreq ifr; 32 | int fd, shaper; 33 | 34 | if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 35 | fprintf(stderr, "ifdown: "); 36 | perror("socket"); 37 | goto error; 38 | } 39 | 40 | if ((ifa = if_nameindex()) == NULL) { 41 | fprintf(stderr, "ifdown: "); 42 | perror("if_nameindex"); 43 | goto error; 44 | } 45 | 46 | for (shaper = 1; shaper >= 0; shaper--) { 47 | for (ifp = ifa; ifp->if_index; ifp++) { 48 | 49 | if ((strncmp(ifp->if_name, "shaper", 6) == 0) 50 | != shaper) continue; 51 | if (strcmp(ifp->if_name, "lo") == 0) 52 | continue; 53 | if (strchr(ifp->if_name, ':') != NULL) 54 | continue; 55 | 56 | strncpy(ifr.ifr_name, ifp->if_name, IFNAMSIZ-1); 57 | ifr.ifr_name[IFNAMSIZ-1] = 0; 58 | if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { 59 | fprintf(stderr, "ifdown: shutdown "); 60 | perror(ifp->if_name); 61 | goto error; 62 | } 63 | ifr.ifr_flags &= ~(IFF_UP); 64 | if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) { 65 | fprintf(stderr, "ifdown: shutdown "); 66 | perror(ifp->if_name); 67 | goto error; 68 | } 69 | 70 | } 71 | } 72 | 73 | close(fd); 74 | return 0; 75 | 76 | error: 77 | close(fd); 78 | return -1; 79 | } 80 | -------------------------------------------------------------------------------- /kexec/kexec-elf-boot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec: Linux boots Linux 3 | * 4 | * Copyright (C) 2003-2005 Eric Biederman (ebiederm@xmission.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation (version 2 of the License). 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | #define _GNU_SOURCE 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "kexec.h" 30 | #include "kexec-elf.h" 31 | #include "kexec-elf-boot.h" 32 | 33 | 34 | #define UPSZ(X) _ALIGN_UP(sizeof(X), 4) 35 | 36 | static struct boot_notes { 37 | Elf_Bhdr hdr; 38 | Elf_Nhdr bl_hdr; 39 | unsigned char bl_desc[UPSZ(BOOTLOADER)]; 40 | Elf_Nhdr blv_hdr; 41 | unsigned char blv_desc[UPSZ(BOOTLOADER_VERSION)]; 42 | Elf_Nhdr cmd_hdr; 43 | unsigned char command_line[0]; 44 | } boot_notes = { 45 | .hdr = { 46 | .b_signature = ELF_BOOT_MAGIC, 47 | .b_size = sizeof(boot_notes), 48 | .b_checksum = 0, 49 | .b_records = 3, 50 | }, 51 | .bl_hdr = { 52 | .n_namesz = 0, 53 | .n_descsz = sizeof(BOOTLOADER), 54 | .n_type = EBN_BOOTLOADER_NAME, 55 | }, 56 | .bl_desc = BOOTLOADER, 57 | .blv_hdr = { 58 | .n_namesz = 0, 59 | .n_descsz = sizeof(BOOTLOADER_VERSION), 60 | .n_type = EBN_BOOTLOADER_VERSION, 61 | }, 62 | .blv_desc = BOOTLOADER_VERSION, 63 | .cmd_hdr = { 64 | .n_namesz = 0, 65 | .n_descsz = 0, 66 | .n_type = EBN_COMMAND_LINE, 67 | }, 68 | }; 69 | 70 | unsigned long elf_boot_notes( 71 | struct kexec_info *info, unsigned long max_addr, 72 | const char *cmdline, int cmdline_len) 73 | { 74 | unsigned long note_bytes; 75 | unsigned long note_base; 76 | struct boot_notes *notes; 77 | note_bytes = sizeof(*notes) + _ALIGN(cmdline_len, 4); 78 | notes = xmalloc(note_bytes); 79 | memcpy(notes, &boot_notes, sizeof(boot_notes)); 80 | memcpy(notes->command_line, cmdline, cmdline_len); 81 | notes->hdr.b_size = note_bytes; 82 | notes->cmd_hdr.n_descsz = cmdline_len; 83 | notes->hdr.b_checksum = compute_ip_checksum(notes, note_bytes); 84 | 85 | note_base = add_buffer(info, notes, note_bytes, note_bytes, 86 | 4, 0, max_addr, 1); 87 | 88 | return note_base; 89 | } 90 | -------------------------------------------------------------------------------- /kexec/kexec-elf-boot.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_ELF_BOOT_H 2 | #define KEXEC_ELF_BOOT_H 3 | 4 | unsigned long elf_boot_notes( 5 | struct kexec_info *info, unsigned long max_addr, 6 | const char *cmdline, int cmdline_len); 7 | 8 | #endif /* KEXEC_ELF_BOOT_H */ 9 | -------------------------------------------------------------------------------- /kexec/kexec-elf-core.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "elf.h" 6 | #include "kexec-elf.h" 7 | 8 | 9 | int build_elf_core_info(const char *buf, off_t len, struct mem_ehdr *ehdr, 10 | uint32_t flags) 11 | { 12 | int result; 13 | result = build_elf_info(buf, len, ehdr, flags); 14 | if (result < 0) { 15 | return result; 16 | } 17 | if ((ehdr->e_type != ET_CORE)) { 18 | /* not an ELF Core */ 19 | fprintf(stderr, "Not ELF type ET_CORE\n"); 20 | return -1; 21 | } 22 | if (!ehdr->e_phdr) { 23 | /* No program header */ 24 | fprintf(stderr, "No ELF program header\n"); 25 | return -1; 26 | } 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /kexec/kexec-iomem.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "kexec.h" 13 | #include "crashdump.h" 14 | 15 | /* 16 | * kexec_iomem_for_each_line() 17 | * 18 | * Iterate over each line in the file returned by proc_iomem(). If match is 19 | * NULL or if the line matches with our match-pattern then call the 20 | * callback if non-NULL. 21 | * If match is NULL, callback should return a negative if error. 22 | * Otherwise the interation goes on, incrementing nr but only if callback 23 | * returns 0 (matched). 24 | * 25 | * Return the number of lines matched. 26 | */ 27 | 28 | int kexec_iomem_for_each_line(char *match, 29 | int (*callback)(void *data, 30 | int nr, 31 | char *str, 32 | unsigned long long base, 33 | unsigned long long length), 34 | void *data) 35 | { 36 | const char *iomem = proc_iomem(); 37 | char line[MAX_LINE]; 38 | FILE *fp; 39 | unsigned long long start, end, size; 40 | char *str; 41 | int consumed; 42 | int count; 43 | int nr = 0, ret; 44 | 45 | if (!callback) 46 | return nr; 47 | 48 | fp = fopen(iomem, "r"); 49 | if (!fp) 50 | die("Cannot open %s\n", iomem); 51 | 52 | while(fgets(line, sizeof(line), fp) != 0) { 53 | count = sscanf(line, "%llx-%llx : %n", &start, &end, &consumed); 54 | if (count != 2) 55 | continue; 56 | str = line + consumed; 57 | size = end - start + 1; 58 | if (!match || memcmp(str, match, strlen(match)) == 0) { 59 | ret = callback(data, nr, str, start, size); 60 | if (ret < 0) 61 | break; 62 | else if (ret == 0) 63 | nr++; 64 | } 65 | } 66 | 67 | fclose(fp); 68 | 69 | return nr; 70 | } 71 | 72 | static int kexec_iomem_single_callback(void *data, int nr, 73 | char *UNUSED(str), 74 | unsigned long long base, 75 | unsigned long long length) 76 | { 77 | struct memory_range *range = data; 78 | 79 | if (nr == 0) { 80 | range->start = base; 81 | range->end = base + length - 1; 82 | } 83 | 84 | return 0; 85 | } 86 | 87 | int parse_iomem_single(char *str, uint64_t *start, uint64_t *end) 88 | { 89 | struct memory_range range; 90 | int ret; 91 | 92 | memset(&range, 0, sizeof(range)); 93 | 94 | ret = kexec_iomem_for_each_line(str, 95 | kexec_iomem_single_callback, &range); 96 | 97 | if (ret == 1) { 98 | if (start) 99 | *start = range.start; 100 | if (end) 101 | *end = range.end; 102 | 103 | ret = 0; 104 | } 105 | else 106 | ret = -1; 107 | 108 | return ret; 109 | } 110 | -------------------------------------------------------------------------------- /kexec/kexec-lzma.h: -------------------------------------------------------------------------------- 1 | #ifndef __KEXEC_LZMA_H 2 | #define __KEXEC_LZMA_H 3 | 4 | #include 5 | 6 | char *lzma_decompress_file(const char *filename, off_t *r_size); 7 | 8 | #endif /* __KEXEC_LZMA_H */ 9 | -------------------------------------------------------------------------------- /kexec/kexec-sha256.h: -------------------------------------------------------------------------------- 1 | #ifndef KEXEC_SHA256_H 2 | #define KEXEC_SHA256_H 3 | 4 | struct sha256_region { 5 | uint64_t start; 6 | uint64_t len; 7 | }; 8 | 9 | #define SHA256_REGIONS 16 10 | 11 | #endif /* KEXEC_SHA256_H */ 12 | -------------------------------------------------------------------------------- /kexec/kexec-zlib.h: -------------------------------------------------------------------------------- 1 | #ifndef __KEXEC_ZLIB_H 2 | #define __KEXEC_ZLIB_H 3 | 4 | #include 5 | #include 6 | 7 | #include "config.h" 8 | 9 | int is_zlib_file(const char *filename, off_t *r_size); 10 | char *zlib_decompress_file(const char *filename, off_t *r_size); 11 | #endif /* __KEXEC_ZLIB_H */ 12 | -------------------------------------------------------------------------------- /kexec/kexec-zstd.h: -------------------------------------------------------------------------------- 1 | #ifndef __KEXEC_ZSTD_H 2 | #define __KEXEC_ZSTD_H 3 | 4 | #include 5 | 6 | char *zstd_decompress_file(const char *filename, off_t *r_size); 7 | #endif /* __KEXEC_ZSTD_H */ 8 | -------------------------------------------------------------------------------- /kexec/libfdt/Makefile.libfdt: -------------------------------------------------------------------------------- 1 | # Makefile.libfdt 2 | # 3 | # This is not a complete Makefile of itself. Instead, it is designed to 4 | # be easily embeddable into other systems of Makefiles. 5 | # 6 | LIBFDT_INCLUDES = fdt.h libfdt.h 7 | LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c 8 | LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) 9 | 10 | dist += kexec/libfdt/Makefile.libfdt \ 11 | kexec/libfdt/fdt.h kexec/libfdt/libfdt.h \ 12 | kexec/libfdt/libfdt_env.h \ 13 | kexec/libfdt/libfdt_internal.h 14 | -------------------------------------------------------------------------------- /kexec/libfdt/TODO: -------------------------------------------------------------------------------- 1 | - Tree traversal functions 2 | - Graft function 3 | - Complete libfdt.h documenting comments 4 | -------------------------------------------------------------------------------- /kexec/libfdt/fdt.h: -------------------------------------------------------------------------------- 1 | #ifndef _FDT_H 2 | #define _FDT_H 3 | 4 | #ifndef __ASSEMBLY__ 5 | 6 | struct fdt_header { 7 | uint32_t magic; /* magic word FDT_MAGIC */ 8 | uint32_t totalsize; /* total size of DT block */ 9 | uint32_t off_dt_struct; /* offset to structure */ 10 | uint32_t off_dt_strings; /* offset to strings */ 11 | uint32_t off_mem_rsvmap; /* offset to memory reserve map */ 12 | uint32_t version; /* format version */ 13 | uint32_t last_comp_version; /* last compatible version */ 14 | 15 | /* version 2 fields below */ 16 | uint32_t boot_cpuid_phys; /* Which physical CPU id we're 17 | booting on */ 18 | /* version 3 fields below */ 19 | uint32_t size_dt_strings; /* size of the strings block */ 20 | 21 | /* version 17 fields below */ 22 | uint32_t size_dt_struct; /* size of the structure block */ 23 | }; 24 | 25 | struct fdt_reserve_entry { 26 | uint64_t address; 27 | uint64_t size; 28 | }; 29 | 30 | struct fdt_node_header { 31 | uint32_t tag; 32 | char name[0]; 33 | }; 34 | 35 | struct fdt_property { 36 | uint32_t tag; 37 | uint32_t len; 38 | uint32_t nameoff; 39 | char data[0]; 40 | }; 41 | 42 | #endif /* !__ASSEMBLY */ 43 | 44 | #define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ 45 | #define FDT_TAGSIZE sizeof(uint32_t) 46 | 47 | #define FDT_BEGIN_NODE 0x1 /* Start node: full name */ 48 | #define FDT_END_NODE 0x2 /* End node */ 49 | #define FDT_PROP 0x3 /* Property: name off, 50 | size, content */ 51 | #define FDT_NOP 0x4 /* nop */ 52 | #define FDT_END 0x9 53 | 54 | #define FDT_V1_SIZE (7*sizeof(uint32_t)) 55 | #define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t)) 56 | #define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t)) 57 | #define FDT_V16_SIZE FDT_V3_SIZE 58 | #define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t)) 59 | 60 | #endif /* _FDT_H */ 61 | -------------------------------------------------------------------------------- /kexec/libfdt/libfdt_env.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIBFDT_ENV_H 2 | #define _LIBFDT_ENV_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define _B(n) ((unsigned long long)((uint8_t *)&x)[n]) 9 | static inline uint32_t fdt32_to_cpu(uint32_t x) 10 | { 11 | return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3); 12 | } 13 | #define cpu_to_fdt32(x) fdt32_to_cpu(x) 14 | 15 | static inline uint64_t fdt64_to_cpu(uint64_t x) 16 | { 17 | return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32) 18 | | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7); 19 | } 20 | #define cpu_to_fdt64(x) fdt64_to_cpu(x) 21 | #undef _B 22 | 23 | #endif /* _LIBFDT_ENV_H */ 24 | -------------------------------------------------------------------------------- /kexec/mem_regions.h: -------------------------------------------------------------------------------- 1 | #ifndef MEM_REGIONS_H 2 | #define MEM_REGIONS_H 3 | 4 | struct memory_ranges; 5 | struct memory_range; 6 | 7 | void mem_regions_sort(struct memory_ranges *ranges); 8 | 9 | int mem_regions_exclude(struct memory_ranges *ranges, 10 | const struct memory_range *range); 11 | 12 | int mem_regions_add(struct memory_ranges *ranges, unsigned long long base, 13 | unsigned long long length, int type); 14 | 15 | int mem_regions_alloc_and_exclude(struct memory_ranges *ranges, 16 | const struct memory_range *range); 17 | 18 | int mem_regions_alloc_and_add(struct memory_ranges *ranges, 19 | unsigned long long base, 20 | unsigned long long length, int type); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /kexec/phys_arch.c: -------------------------------------------------------------------------------- 1 | #include "kexec.h" 2 | #include 3 | #include 4 | #include 5 | 6 | long physical_arch(void) 7 | { 8 | struct utsname utsname; 9 | int i, result = uname(&utsname); 10 | if (result < 0) { 11 | fprintf(stderr, "uname failed: %s\n", 12 | strerror(errno)); 13 | return -1; 14 | } 15 | 16 | for (i = 0; arches[i].machine; ++i) { 17 | if (strcmp(utsname.machine, arches[i].machine) == 0) 18 | return arches[i].arch; 19 | if ((strcmp(arches[i].machine, "arm") == 0) && 20 | (strncmp(utsname.machine, arches[i].machine, 21 | strlen(arches[i].machine)) == 0)) 22 | return arches[i].arch; 23 | } 24 | 25 | fprintf(stderr, "Unsupported machine type: %s\n", 26 | utsname.machine); 27 | return -1; 28 | } 29 | -------------------------------------------------------------------------------- /kexec/phys_to_virt.c: -------------------------------------------------------------------------------- 1 | #include "kexec.h" 2 | #include "crashdump.h" 3 | 4 | /** 5 | * phys_to_virt() - translate physical address to virtual address 6 | * @paddr: physical address to translate 7 | * 8 | * For most architectures physical address is simply virtual address minus 9 | * PAGE_OFFSET. Architectures that don't follow this convention should provide 10 | * their own implementation. 11 | */ 12 | unsigned long 13 | phys_to_virt(struct crash_elf_info *elf_info, unsigned long long paddr) 14 | { 15 | return paddr + elf_info->page_offset; 16 | } 17 | -------------------------------------------------------------------------------- /kexec/proc_iomem.c: -------------------------------------------------------------------------------- 1 | #include "kexec.h" 2 | 3 | static const char proc_iomem_str[] = "/proc/iomem"; 4 | 5 | /* 6 | * Allow an architecture specific implementation of this 7 | * function to override the location of a file looking a lot 8 | * like /proc/iomem 9 | */ 10 | const char *proc_iomem(void) 11 | { 12 | return proc_iomem_str; 13 | } 14 | -------------------------------------------------------------------------------- /kexec/symbols.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "kexec.h" 4 | 5 | /* Retrieve kernel symbol virtual address from /proc/kallsyms */ 6 | unsigned long long get_kernel_sym(const char *symbol) 7 | { 8 | const char *kallsyms = "/proc/kallsyms"; 9 | char sym[128]; 10 | char line[128]; 11 | FILE *fp; 12 | unsigned long long vaddr; 13 | char type; 14 | 15 | fp = fopen(kallsyms, "r"); 16 | if (!fp) { 17 | fprintf(stderr, "Cannot open %s\n", kallsyms); 18 | return 0; 19 | } 20 | 21 | while (fgets(line, sizeof(line), fp) != NULL) { 22 | if (sscanf(line, "%llx %c %s", &vaddr, &type, sym) != 3) 23 | continue; 24 | if (strcmp(sym, symbol) == 0) { 25 | dbgprintf("kernel symbol %s vaddr = %16llx\n", 26 | symbol, vaddr); 27 | fclose(fp); 28 | return vaddr; 29 | } 30 | } 31 | 32 | dbgprintf("Cannot get kernel %s symbol address\n", symbol); 33 | 34 | fclose(fp); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /kexec/virt_to_phys.c: -------------------------------------------------------------------------------- 1 | #include "kexec.h" 2 | #include 3 | 4 | unsigned long virt_to_phys(unsigned long UNUSED(addr)) 5 | { 6 | abort(); 7 | } 8 | -------------------------------------------------------------------------------- /kexec_test/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # kexec_test Debugging payload to be certain the infrastructure works 3 | # 4 | RELOC:=0x10000 5 | KEXEC_TEST_SRCS:= kexec_test/kexec_test16.S kexec_test/kexec_test.S 6 | 7 | dist += kexec_test/Makefile $(KEXEC_TEST_SRCS) \ 8 | kexec_test/x86-setup-legacy-pic.S 9 | 10 | BUILD_KEXEC_TEST = no 11 | ifeq ($(ARCH),i386) 12 | BUILD_KEXEC_TEST = yes 13 | endif 14 | ifeq ($(ARCH),x86_64) 15 | BUILD_KEXEC_TEST = yes 16 | endif 17 | 18 | ifeq ($(BUILD_KEXEC_TEST),yes) 19 | 20 | KEXEC_TEST_OBJS = $(call objify, $(KEXEC_TEST_SRCS)) 21 | KEXEC_TEST_DEPS = $(call depify, $(KEXEC_TEST_OBJS)) 22 | 23 | KEXEC_TEST = $(PKGLIBDIR)/kexec_test 24 | 25 | clean += $(KEXEC_TEST_OBJS) $(KEXEC_TEST_DEPS) $(KEXEC_TEST) 26 | 27 | -include $(KEXEC_TEST_DEPS) 28 | 29 | $(KEXEC_TEST): CC=$(TARGET_CC) 30 | $(KEXEC_TEST): CPPFLAGS+=-DRELOC=$(RELOC) 31 | $(KEXEC_TEST): ASFLAGS+=-m32 32 | #$(KEXEC_TEST): LDFLAGS=-m32 -Wl,-e -Wl,_start -Wl,-Ttext -Wl,$(RELOC) \ 33 | # -nostartfiles 34 | $(KEXEC_TEST): LDFLAGS=-melf_i386 -e _start -Ttext $(RELOC) 35 | 36 | $(KEXEC_TEST): $(KEXEC_TEST_OBJS) 37 | mkdir -p $(@D) 38 | $(TARGET_LD) $(LDFLAGS) -o $@ $^ 39 | 40 | endif 41 | -------------------------------------------------------------------------------- /kexec_test/x86-setup-legacy-pic.S: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec: Linux boots Linux 3 | * 4 | * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation (version 2 of the License). 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | .text 21 | .code32 22 | setup_legacy_pic: 23 | /* Load the legacy dos settings into the 8259A pic */ 24 | movb $0xff, %al 25 | outb %al, $0x21 /* mask all of 8259A-1 */ 26 | outb %al, $0xa1 /* mask all of 8259A-1 */ 27 | 28 | movb $0x11, %al 29 | outb %al, $0x20 /* ICW1: select 8259A-1 init */ 30 | outb %al, $0x80 /* A short delay */ 31 | movb $0x08, %al 32 | outb %al, $0x21 /* ICW2: 8259A-1 IR0-7 mappend to 0x8-0xf */ 33 | outb %al, $0x80 /* A short delay */ 34 | movb $01, %al 35 | outb %al, $0x21 /* Normal 8086 auto EOI mode */ 36 | outb %al, $0x80 /* A short delay */ 37 | 38 | 39 | movb $0x11, %al 40 | outb %al, $0xA0 /* ICW1: select 8259A-2 init */ 41 | outb %al, $0x80 /* A short delay */ 42 | movb $0x70, %al 43 | outb %al, $0xA1 /* ICW2: 8259A-2 IR0-7 mappend to 0x70-0x77 */ 44 | outb %al, $0x80 /* A short delay */ 45 | movb $01, %al 46 | outb %al, $0xA1 /* Normal 8086 auto EOI mode */ 47 | outb %al, $0x80 /* A short delay */ 48 | 49 | movb $0, %al 50 | outb %al, $0x21 /* Unmask all of 8259A-1 */ 51 | outb %al, $0xa1 /* Unmask all of 8259A-2 */ 52 | 53 | ret 54 | -------------------------------------------------------------------------------- /purgatory/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory (an uncomfortable intermediate state) 3 | # In this case the code that runs between kernels 4 | # 5 | 6 | # There is probably a cleaner way to do this but for now this 7 | # should keep us from accidentially include unsafe library functions 8 | # or headers. 9 | 10 | PURGATORY = purgatory/purgatory.ro 11 | PURGATORY_SRCS = 12 | PURGATORY_SRCS += purgatory/purgatory.c 13 | PURGATORY_SRCS += purgatory/printf.c 14 | PURGATORY_SRCS += purgatory/string.c 15 | PURGATORY_MAP = purgatory/purgatory.map 16 | 17 | dist += purgatory/Makefile $(PURGATORY_SRCS) \ 18 | purgatory/include/purgatory.h purgatory/include/string.h 19 | 20 | include $(srcdir)/purgatory/arch/alpha/Makefile 21 | include $(srcdir)/purgatory/arch/arm/Makefile 22 | include $(srcdir)/purgatory/arch/arm64/Makefile 23 | include $(srcdir)/purgatory/arch/i386/Makefile 24 | include $(srcdir)/purgatory/arch/ia64/Makefile 25 | include $(srcdir)/purgatory/arch/mips/Makefile 26 | include $(srcdir)/purgatory/arch/ppc/Makefile 27 | include $(srcdir)/purgatory/arch/ppc64/Makefile 28 | include $(srcdir)/purgatory/arch/riscv/Makefile 29 | include $(srcdir)/purgatory/arch/s390/Makefile 30 | include $(srcdir)/purgatory/arch/sh/Makefile 31 | include $(srcdir)/purgatory/arch/x86_64/Makefile 32 | include $(srcdir)/purgatory/arch/loongarch/Makefile 33 | 34 | PURGATORY_SRCS+=$($(ARCH)_PURGATORY_SRCS) 35 | 36 | PURGATORY_OBJS = $(call objify, $(PURGATORY_SRCS)) purgatory/sha256.o 37 | PURGATORY_DEPS = $(call depify, $(PURGATORY_OBJS)) 38 | 39 | clean += $(PURGATORY_OBJS) $(PURGATORY_DEPS) $(PURGATORY) $(PURGATORY_MAP) $(PURGATORY).sym 40 | 41 | -include $(PURGATORY_DEPS) 42 | 43 | purgatory/sha256.o: CFLAGS += -O2 $($(ARCH)_PURGATORY_SHA256_CFLAGS) 44 | 45 | purgatory/sha256.o: $(srcdir)/util_lib/sha256.c 46 | mkdir -p $(@D) 47 | $(COMPILE.c) -o $@ $^ 48 | 49 | $(PURGATORY): CC=$(TARGET_CC) 50 | $(PURGATORY): CFLAGS=$(PURGATORY_EXTRA_CFLAGS) \ 51 | $($(ARCH)_PURGATORY_EXTRA_CFLAGS) \ 52 | -Os -fno-builtin -ffreestanding \ 53 | -fno-zero-initialized-in-bss \ 54 | -fno-PIC -fno-PIE -fno-stack-protector -fno-tree-vectorize 55 | 56 | $(PURGATORY): CPPFLAGS=$($(ARCH)_PURGATORY_EXTRA_CFLAGS) \ 57 | -I$(srcdir)/purgatory/include \ 58 | -I$(srcdir)/purgatory/arch/$(ARCH)/include \ 59 | -I$(srcdir)/util_lib/include \ 60 | -I$(srcdir)/include \ 61 | -Iinclude \ 62 | -I$(shell $(CC) -print-file-name=include) 63 | $(PURGATORY): LDFLAGS=$($(ARCH)_PURGATORY_EXTRA_CFLAGS)\ 64 | -Wl,--no-undefined -nostartfiles -nostdlib \ 65 | -nodefaultlibs -e purgatory_start -r \ 66 | -Wl,-Map=$(PURGATORY_MAP) 67 | 68 | $(PURGATORY): $(PURGATORY_OBJS) 69 | $(MKDIR) -p $(@D) 70 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@.sym $^ 71 | # $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) --no-undefined -e purgatory_start -r -o $@ $(PURGATORY_OBJS) $(UTIL_LIB) 72 | $(STRIP) --strip-debug -o $@ $@.sym 73 | 74 | echo:: 75 | @echo "PURGATORY_SRCS $(PURGATORY_SRCS)" 76 | @echo "PURGATORY_DEPS $(PURGATORY_DEPS)" 77 | @echo "PURGATORY_OBJS $(PURGATORY_OBJS)" 78 | -------------------------------------------------------------------------------- /purgatory/arch/alpha/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory alpha 3 | # 4 | 5 | alpha_PURGATORY_SRCS = 6 | 7 | dist += purgatory/arch/alpha/Makefile $(alpha_PURGATORY_SRCS) 8 | 9 | -------------------------------------------------------------------------------- /purgatory/arch/arm/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory arm 3 | # 4 | 5 | arm_PURGATORY_SRCS = 6 | 7 | dist += purgatory/arch/arm/Makefile $(arm_PURGATORY_SRCS) 8 | 9 | 10 | -------------------------------------------------------------------------------- /purgatory/arch/arm64/Makefile: -------------------------------------------------------------------------------- 1 | 2 | arm64_PURGATORY_EXTRA_CFLAGS = \ 3 | -mcmodel=large \ 4 | -fno-PIC \ 5 | -fno-stack-protector \ 6 | -fno-asynchronous-unwind-tables \ 7 | -Wundef \ 8 | -Werror-implicit-function-declaration \ 9 | -Wdeclaration-after-statement \ 10 | -Werror=implicit-int \ 11 | -Werror=strict-prototypes 12 | 13 | arm64_PURGATORY_SRCS += \ 14 | purgatory/arch/arm64/entry.S \ 15 | purgatory/arch/arm64/purgatory-arm64.c 16 | 17 | dist += \ 18 | $(arm64_PURGATORY_SRCS) \ 19 | purgatory/arch/arm64/Makefile 20 | -------------------------------------------------------------------------------- /purgatory/arch/arm64/entry.S: -------------------------------------------------------------------------------- 1 | /* 2 | * ARM64 purgatory. 3 | */ 4 | 5 | .macro size, sym:req 6 | .size \sym, . - \sym 7 | .endm 8 | 9 | .text 10 | 11 | .globl purgatory_start 12 | purgatory_start: 13 | 14 | adr x19, .Lstack 15 | mov sp, x19 16 | 17 | bl purgatory 18 | 19 | /* Start new image. */ 20 | ldr x17, arm64_kernel_entry 21 | ldr x0, arm64_dtb_addr 22 | mov x1, xzr 23 | mov x2, xzr 24 | mov x3, xzr 25 | br x17 26 | 27 | size purgatory_start 28 | 29 | .ltorg 30 | 31 | .align 4 32 | .rept 256 33 | .quad 0 34 | .endr 35 | .Lstack: 36 | 37 | .data 38 | 39 | .align 3 40 | 41 | .globl arm64_kernel_entry 42 | arm64_kernel_entry: 43 | .quad 0 44 | size arm64_kernel_entry 45 | 46 | .globl arm64_dtb_addr 47 | arm64_dtb_addr: 48 | .quad 0 49 | size arm64_dtb_addr 50 | 51 | .end -------------------------------------------------------------------------------- /purgatory/arch/arm64/purgatory-arm64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ARM64 purgatory. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | /* Symbols set by kexec. */ 9 | 10 | uint8_t *arm64_sink __attribute__ ((section ("data"))); 11 | extern void (*arm64_kernel_entry)(uint64_t, uint64_t, uint64_t, uint64_t); 12 | extern uint64_t arm64_dtb_addr; 13 | 14 | void putchar(int ch) 15 | { 16 | if (!arm64_sink) 17 | return; 18 | 19 | *arm64_sink = ch; 20 | 21 | if (ch == '\n') 22 | *arm64_sink = '\r'; 23 | } 24 | 25 | void post_verification_setup_arch(void) 26 | { 27 | printf("purgatory: booting kernel now\n"); 28 | } 29 | 30 | void setup_arch(void) 31 | { 32 | printf("purgatory: entry=%lx\n", (unsigned long)arm64_kernel_entry); 33 | printf("purgatory: dtb=%lx\n", arm64_dtb_addr); 34 | } 35 | -------------------------------------------------------------------------------- /purgatory/arch/i386/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory i386 3 | # 4 | 5 | i386_PURGATORY_SRCS = purgatory/arch/i386/entry32-16.S 6 | i386_PURGATORY_SRCS += purgatory/arch/i386/entry32-16-debug.S 7 | i386_PURGATORY_SRCS += purgatory/arch/i386/entry32.S 8 | i386_PURGATORY_SRCS += purgatory/arch/i386/setup-x86.S 9 | i386_PURGATORY_SRCS += purgatory/arch/i386/stack.S 10 | i386_PURGATORY_SRCS += purgatory/arch/i386/compat_x86_64.S 11 | i386_PURGATORY_SRCS += purgatory/arch/i386/purgatory-x86.c 12 | i386_PURGATORY_SRCS += purgatory/arch/i386/console-x86.c 13 | i386_PURGATORY_SRCS += purgatory/arch/i386/vga.c 14 | i386_PURGATORY_SRCS += purgatory/arch/i386/pic.c 15 | i386_PURGATORY_SRCS += purgatory/arch/i386/crashdump_backup.c 16 | 17 | dist += purgatory/arch/i386/Makefile $(i386_PURGATORY_SRCS) \ 18 | purgatory/arch/i386/purgatory-x86.h \ 19 | purgatory/arch/i386/include/arch/io.h \ 20 | purgatory/arch/i386/include/arch/debug.h 21 | 22 | -------------------------------------------------------------------------------- /purgatory/arch/i386/compat_x86_64.S: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec: Linux boots Linux 3 | * 4 | * Copyright (C) 2003,2004,2005 Eric Biederman (ebiederm@xmission.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation (version 2 of the License). 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | .equ MSR_K6_EFER, 0xC0000080 21 | .equ EFER_LME, 0x00000100 22 | .equ X86_CR4_PAE, 0x00000020 23 | .equ CR0_PG, 0x80000000 24 | 25 | .globl compat_x86_64, compat_x86_64_entry32 26 | .text 27 | .code64 28 | .balign 16 29 | compat_x86_64: 30 | /* Setup a temporary gdt */ 31 | /* This also acts as a serializing instruction ensuring 32 | * my self modifying code works. 33 | */ 34 | lgdt gdt(%rip) 35 | 36 | /* Switch to 32bit compatiblity mode */ 37 | ljmp *lm_exit_addr(%rip) 38 | lm_exit: 39 | .code32 40 | 41 | /* Disable paging */ 42 | movl %cr0, %eax 43 | andl $~CR0_PG, %eax 44 | movl %eax, %cr0 45 | 46 | /* Disable long mode */ 47 | movl $MSR_K6_EFER, %ecx 48 | rdmsr 49 | andl $~EFER_LME, %eax 50 | wrmsr 51 | 52 | /* Disable PAE */ 53 | xorl %eax, %eax 54 | movl %eax, %cr4 55 | 56 | /* load the data segments */ 57 | movl $0x18, %eax /* data segment */ 58 | movl %eax, %ds 59 | movl %eax, %es 60 | movl %eax, %ss 61 | movl %eax, %fs 62 | movl %eax, %gs 63 | 64 | /* set all of the registers to known values */ 65 | /* leave %esp alone */ 66 | 67 | xorl %eax, %eax 68 | xorl %ebx, %ebx 69 | xorl %ecx, %ecx 70 | xorl %edx, %edx 71 | xorl %esi, %esi 72 | xorl %edi, %edi 73 | xorl %ebp, %ebp 74 | 75 | jmp *compat_x86_64_entry32 76 | 77 | .section ".rodata" 78 | .balign 16 79 | gdt: /* 0x00 unusable segment 80 | * 0x08 unused 81 | * so use them as the gdt ptr 82 | */ 83 | .word gdt_end - gdt - 1 84 | # A quad word pointer to the gdt with the high 32bits 0 85 | .long gdt, 0 86 | .word 0, 0, 0 87 | 88 | /* 0x10 4GB flat code segment */ 89 | .word 0xFFFF, 0x0000, 0x9A00, 0x00CF 90 | /* 0x18 4GB flat data segment */ 91 | .word 0xFFFF, 0x0000, 0x9200, 0x00CF 92 | gdt_end: 93 | 94 | lm_exit_addr: 95 | .long lm_exit 96 | .long 0x10 97 | 98 | compat_x86_64_entry32: 99 | .long 0 100 | .size compat_x86_64_entry32, . - compat_x86_64_entry32 101 | -------------------------------------------------------------------------------- /purgatory/arch/i386/crashdump_backup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec: Linux boots Linux 3 | * 4 | * Created by: Vivek goyal (vgoyal@in.ibm.com) 5 | * Copyright (C) IBM Corporation, 2005. All rights reserved 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License as published by 9 | * the Free Software Foundation (version 2 of the License). 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | /* Backup region start gets set after /proc/iomem has been parsed. */ 25 | /* We reuse the same code for x86_64 also so changing backup_start to 26 | unsigned long */ 27 | unsigned long backup_start = 0; 28 | 29 | unsigned long backup_src_start = 0; 30 | unsigned long backup_src_size = 0; 31 | 32 | /* Backup first 640K of memory to backup region as reserved by kexec. 33 | * Assuming first 640K has to be present on i386 machines and no address 34 | * validity checks have to be performed. */ 35 | 36 | void crashdump_backup_memory(void) 37 | { 38 | void *dest, *src; 39 | size_t size; 40 | 41 | src = (void *) backup_src_start; 42 | size = (size_t) backup_src_size; 43 | 44 | if (!size) 45 | return; 46 | 47 | if (backup_start) { 48 | dest = (void *)(backup_start); 49 | memcpy(dest, src, size); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /purgatory/arch/i386/include/arch/io.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_I386_IO_H 2 | #define ARCH_I386_IO_H 3 | 4 | #include 5 | /* Helper functions for directly doing I/O */ 6 | 7 | static inline __attribute__((__always_inline__)) 8 | uint8_t inb(uint16_t port) 9 | { 10 | uint8_t result; 11 | 12 | __asm__ __volatile__ ( 13 | "inb %w1,%0" 14 | :"=a" (result) 15 | :"Nd" (port)); 16 | return result; 17 | } 18 | 19 | static inline __attribute__((__always_inline__)) 20 | uint16_t inw(uint16_t port) 21 | { 22 | uint16_t result; 23 | 24 | __asm__ __volatile__ ( 25 | "inw %w1,%0" 26 | :"=a" (result) 27 | :"Nd" (port)); 28 | return result; 29 | } 30 | 31 | static inline __attribute__((__always_inline__)) 32 | uint32_t inl(uint32_t port) 33 | { 34 | uint32_t result; 35 | 36 | __asm__ __volatile__ ( 37 | "inl %w1,%0" 38 | :"=a" (result) 39 | :"Nd" (port)); 40 | return result; 41 | } 42 | 43 | static inline __attribute__((__always_inline__)) 44 | void outb (uint8_t value, uint16_t port) 45 | { 46 | __asm__ __volatile__ ( 47 | "outb %b0,%w1" 48 | : 49 | :"a" (value), "Nd" (port)); 50 | } 51 | 52 | static inline __attribute__((__always_inline__)) 53 | void outw (uint16_t value, uint16_t port) 54 | { 55 | __asm__ __volatile__ ( 56 | "outw %w0,%w1" 57 | : 58 | :"a" (value), "Nd" (port)); 59 | } 60 | 61 | static inline __attribute__((__always_inline__)) 62 | void outl (uint32_t value, uint16_t port) 63 | { 64 | __asm__ __volatile__ ( 65 | "outl %0,%w1" 66 | : 67 | :"a" (value), "Nd" (port)); 68 | } 69 | 70 | 71 | /* 72 | * readX/writeX() are used to access memory mapped devices. On some 73 | * architectures the memory mapped IO stuff needs to be accessed 74 | * differently. On the x86 architecture, we just read/write the 75 | * memory location directly. 76 | */ 77 | 78 | static inline __attribute__((__always_inline__)) 79 | unsigned char readb(const volatile void *addr) 80 | { 81 | return *(volatile unsigned char *) addr; 82 | } 83 | static inline __attribute__((__always_inline__)) 84 | unsigned short readw(const volatile void *addr) 85 | { 86 | return *(volatile unsigned short *) addr; 87 | } 88 | static inline __attribute__((__always_inline__)) 89 | unsigned int readl(const volatile void *addr) 90 | { 91 | return *(volatile unsigned int *) addr; 92 | } 93 | 94 | static inline __attribute__((__always_inline__)) 95 | void writeb(unsigned char b, volatile void *addr) 96 | { 97 | *(volatile unsigned char *) addr = b; 98 | } 99 | static inline __attribute__((__always_inline__)) 100 | void writew(unsigned short b, volatile void *addr) 101 | { 102 | *(volatile unsigned short *) addr = b; 103 | } 104 | static inline __attribute__((__always_inline__)) 105 | void writel(unsigned int b, volatile void *addr) 106 | { 107 | *(volatile unsigned int *) addr = b; 108 | } 109 | 110 | #endif /* ARCH_I386_IO_H */ 111 | -------------------------------------------------------------------------------- /purgatory/arch/i386/pic.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec: Linux boots Linux 3 | * 4 | * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation (version 2 of the License). 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | #include 20 | #include 21 | #include "purgatory-x86.h" 22 | 23 | 24 | void x86_setup_legacy_pic(void) 25 | { 26 | /* Load the legacy dos settings into the 8259A pic */ 27 | outb(0xff, 0x21); /* mask all of 8259A-1 */ 28 | outb(0xff, 0xa1); /* mask all of 8259A-2 */ 29 | 30 | outb(0x11, 0x20); /* ICW1: select 8259A-1 init */ 31 | outb(0x11, 0x80); /* A short delay */ 32 | 33 | outb(0x08, 0x21); /* ICW2: 8259A-1 IR0-7 mappend to 0x8-0xf */ 34 | outb(0x08, 0x80); /* A short delay */ 35 | 36 | outb(0x01, 0x21); /* Normal 8086 auto EOI mode */ 37 | outb(0x01, 0x80); /* A short delay */ 38 | 39 | outb(0x11, 0xa0); /* ICW1: select 8259A-2 init */ 40 | outb(0x11, 0x80); /* A short delay */ 41 | 42 | outb(0x70, 0xa1); /* ICW2: 8259A-2 IR0-7 mappend to 0x70-0x77 */ 43 | outb(0x70, 0x80); /* A short delay */ 44 | 45 | outb(0x01, 0xa1); /* Normal 8086 auto EOI mode */ 46 | outb(0x01, 0x80); /* A short delay */ 47 | 48 | outb(0x00, 0x21); /* Unmask all of 8259A-1 */ 49 | outb(0x00, 0xa1); /* Unmask all of 8259A-2 */ 50 | } 51 | 52 | -------------------------------------------------------------------------------- /purgatory/arch/i386/purgatory-x86.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "purgatory-x86.h" 4 | 5 | /* 6 | * CPU 7 | * ============================================================================= 8 | */ 9 | 10 | void x86_setup_cpu(void) 11 | { 12 | #if 0 13 | /* This code is only needed for old versions of the kexec kernel patch. 14 | * While it is still a good idea doing this unconditionally breaks 15 | * on older cpus that did not implemented cr4. 16 | * So this code is disabled for now. If this is revisited 17 | * I first need to detect cpuid support and then use cpuid 18 | * to conditionally change newer cpu registers. 19 | */ 20 | /* clear special bits in %cr4 */ 21 | asm volatile( 22 | "movl %0, %%eax\n\t" 23 | "movl %%eax, %%cr4\n\t" 24 | : /* outputs */ 25 | : "r" (0) 26 | ); 27 | #endif 28 | } 29 | 30 | uint8_t reset_vga = 0; 31 | uint8_t legacy_timer = 0; 32 | uint8_t legacy_pic = 0; 33 | uint8_t panic_kernel = 0; 34 | unsigned long jump_back_entry = 0; 35 | char *cmdline_end = 0; 36 | 37 | void setup_arch(void) 38 | { 39 | x86_setup_cpu(); 40 | if (reset_vga) x86_reset_vga(); 41 | if (legacy_pic) x86_setup_legacy_pic(); 42 | /* if (legacy_timer) x86_setup_legacy_timer(); */ 43 | } 44 | 45 | static void x86_setup_jump_back_entry(void) 46 | { 47 | if (cmdline_end) 48 | sprintf(cmdline_end, " kexec_jump_back_entry=0x%x", 49 | jump_back_entry); 50 | } 51 | 52 | /* This function can be used to execute after the SHA256 verification. */ 53 | void post_verification_setup_arch(void) 54 | { 55 | if (panic_kernel) crashdump_backup_memory(); 56 | if (jump_back_entry) x86_setup_jump_back_entry(); 57 | } 58 | -------------------------------------------------------------------------------- /purgatory/arch/i386/purgatory-x86.h: -------------------------------------------------------------------------------- 1 | #ifndef PURGATORY_X86_H 2 | #define PURGATORY_X86_H 3 | 4 | void x86_reset_vga(void); 5 | void x86_setup_legacy_pic(void); 6 | void x86_setup_legacy_timer(void); 7 | void crashdump_backup_memory(void); 8 | 9 | #endif /* PURGATORY_X86_H */ 10 | -------------------------------------------------------------------------------- /purgatory/arch/i386/setup-x86.S: -------------------------------------------------------------------------------- 1 | /* 2 | * purgatory: setup code 3 | * 4 | * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation (version 2 of the License). 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | 21 | #undef i386 22 | 23 | .text 24 | .globl purgatory_start 25 | purgatory_start: 26 | .code32 27 | .arch i386 28 | 29 | /* Load a gdt so I know what the segment registers are */ 30 | lgdt %cs:gdt 31 | 32 | /* load the data segments */ 33 | movl $0x08, %eax /* data segment */ 34 | movl %eax, %ds 35 | movl %eax, %es 36 | movl %eax, %ss 37 | movl %eax, %fs 38 | movl %eax, %gs 39 | 40 | /* load the code segment */ 41 | ljmp $0x10,$1f 42 | 1: 43 | 44 | movl 0(%esp), %eax 45 | movl %eax, jump_back_entry 46 | 47 | /* Setup a stack */ 48 | movl $lstack_end, %esp 49 | 50 | /* Call the C code */ 51 | call purgatory 52 | jmp entry32 53 | 54 | .section ".rodata" 55 | .balign 16 56 | gdt: 57 | /* 0x00 unusable segment so used as the gdt ptr */ 58 | .word gdt_end - gdt - 1 59 | .long gdt 60 | .word 0 61 | 62 | /* 0x8 4GB flat data segment */ 63 | .word 0xFFFF, 0x0000, 0x9200, 0x00CF 64 | 65 | /* 0x10 4GB flat code segment */ 66 | .word 0xFFFF, 0x0000, 0x9A00, 0x00CF 67 | gdt_end: 68 | 69 | /* A stack for the purgatory code */ 70 | .bss 71 | .balign 4096 72 | lstack: 73 | .skip 4096 74 | lstack_end: 75 | 76 | -------------------------------------------------------------------------------- /purgatory/arch/i386/stack.S: -------------------------------------------------------------------------------- 1 | /* 2 | * purgatory: stack 3 | * 4 | * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation (version 2 of the License). 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | /* A stack for the loaded kernel. 21 | * Seperate and in the data section so it can be prepopulated. 22 | */ 23 | .data 24 | .globl stack, stack_end 25 | .globl stack_arg32_1, stack_arg32_2, stack_arg32_3 ,stack_arg32_4 26 | .globl stack_arg32_5, stack_arg32_6, stack_arg32_7 ,stack_arg32_8 27 | .balign 4096 28 | stack: 29 | .skip 4096 - (8*4) 30 | stack_arg32_8: .long 0 ; .size stack_arg32_8, 4 31 | stack_arg32_7: .long 0 ; .size stack_arg32_7, 4 32 | stack_arg32_6: .long 0 ; .size stack_arg32_6, 4 33 | stack_arg32_5: .long 0 ; .size stack_arg32_5, 4 34 | stack_arg32_4: .long 0 ; .size stack_arg32_4, 4 35 | stack_arg32_3: .long 0 ; .size stack_arg32_3, 4 36 | stack_arg32_2: .long 0 ; .size stack_arg32_2, 4 37 | stack_arg32_1: .long 0 ; .size stack_arg32_1, 4 38 | stack_end: 39 | 40 | -------------------------------------------------------------------------------- /purgatory/arch/ia64/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory ia64 3 | # 4 | ia64_PURGATORY_SRCS += purgatory/arch/ia64/entry.S 5 | ia64_PURGATORY_SRCS += purgatory/arch/ia64/purgatory-ia64.c 6 | ia64_PURGATORY_SRCS += purgatory/arch/ia64/console-ia64.c 7 | ia64_PURGATORY_SRCS += purgatory/arch/ia64/vga.c 8 | 9 | ia64_PURGATORY_EXTRA_CFLAGS = -ffixed-r28 10 | 11 | # sha256.c needs to be compiled without optimization, else 12 | # purgatory fails to execute on ia64. 13 | ia64_PURGATORY_SHA256_CFLAGS = -O0 14 | 15 | dist += purgatory/arch/ia64/Makefile $(ia64_PURGATORY_SRCS) \ 16 | purgatory/arch/ia64/io.h purgatory/arch/ia64/purgatory-ia64.h 17 | 18 | -------------------------------------------------------------------------------- /purgatory/arch/ia64/console-ia64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "io.h" 3 | 4 | #define VGABASE UNCACHED(0xb8000) 5 | 6 | /* code based on i386 console code 7 | * TODO add serial support 8 | */ 9 | #define MAX_YPOS 25 10 | #define MAX_XPOS 80 11 | 12 | unsigned long current_ypos = 1, current_xpos = 0; 13 | 14 | static void putchar_vga(int ch) 15 | { 16 | int i, k, j; 17 | 18 | if (current_ypos >= MAX_YPOS) { 19 | /* scroll 1 line up */ 20 | for (k = 1, j = 0; k < MAX_YPOS; k++, j++) { 21 | for (i = 0; i < MAX_XPOS; i++) { 22 | writew(readw(VGABASE + 2*(MAX_XPOS*k + i)), 23 | VGABASE + 2*(MAX_XPOS*j + i)); 24 | } 25 | } 26 | for (i = 0; i < MAX_XPOS; i++) 27 | writew(0x720, VGABASE + 2*(MAX_XPOS*j + i)); 28 | current_ypos = MAX_YPOS-1; 29 | } 30 | if (ch == '\n') { 31 | current_xpos = 0; 32 | current_ypos++; 33 | } else if (ch != '\r') { 34 | writew(((0x7 << 8) | (unsigned short) ch), 35 | VGABASE + 2*(MAX_XPOS*current_ypos + 36 | current_xpos++)); 37 | if (current_xpos >= MAX_XPOS) { 38 | current_xpos = 0; 39 | current_ypos++; 40 | } 41 | } 42 | } 43 | 44 | void putchar(int ch) 45 | { 46 | putchar_vga(ch); 47 | } 48 | -------------------------------------------------------------------------------- /purgatory/arch/ia64/entry.S: -------------------------------------------------------------------------------- 1 | /* 2 | * purgatory: setup code 3 | * 4 | * Copyright (C) 2005-2006 Zou Nan hai (nanhai.zou@intel.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation (version 2 of the License). 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | #define DECLARE_DATA8(name) \ 20 | .global name; \ 21 | .size name, 8; \ 22 | name: data8 0x0 23 | 24 | .global __dummy_efi_function 25 | .align 32 26 | .proc __dummy_efi_function 27 | __dummy_efi_function: 28 | mov r8=r0;; 29 | br.ret.sptk.many rp;; 30 | .global __dummy_efi_function_end 31 | __dummy_efi_function_end: 32 | .endp __dummy_efi_function 33 | 34 | .global purgatory_start 35 | .align 32 36 | .proc purgatory_start 37 | purgatory_start: 38 | movl r2=__gp_value;; 39 | ld8 gp=[r2];; 40 | br.call.sptk.many b0=purgatory 41 | ;; 42 | alloc r2 = ar.pfs, 0, 0, 2, 0 43 | ;; 44 | mov out0=r28 45 | movl out1=__vmcode_base; 46 | br.call.sptk.many b0=ia64_env_setup 47 | movl r10=__kernel_entry;; 48 | ld8 r14=[r10];; 49 | movl r10=__boot_param_base;; 50 | ld8 r28=[r10];; 51 | mov b6=r14;; 52 | mov ar.lc=r0 53 | mov ar.ec=r0 54 | cover;; 55 | invala;; 56 | br.call.sptk.many b0=b6 57 | .endp purgatory_start 58 | 59 | DECLARE_DATA8(__kernel_entry) 60 | DECLARE_DATA8(__vmcode_base) 61 | DECLARE_DATA8(__vmcode_size) 62 | DECLARE_DATA8(__ramdisk_base) 63 | DECLARE_DATA8(__ramdisk_size) 64 | DECLARE_DATA8(__command_line) 65 | DECLARE_DATA8(__command_line_len) 66 | DECLARE_DATA8(__efi_memmap_base) 67 | DECLARE_DATA8(__efi_memmap_size) 68 | DECLARE_DATA8(__boot_param_base) 69 | DECLARE_DATA8(__loaded_segments) 70 | DECLARE_DATA8(__loaded_segments_num) 71 | 72 | DECLARE_DATA8(__gp_value) 73 | DECLARE_DATA8(__noio) 74 | -------------------------------------------------------------------------------- /purgatory/arch/ia64/io.h: -------------------------------------------------------------------------------- 1 | #ifndef IO_H 2 | #define IO_H 3 | #define UNCACHED(x) (void *)((x)|(1UL<<63)) 4 | #define MF() asm volatile ("mf.a" ::: "memory") 5 | #define IO_SPACE_ENCODING(p) ((((p) >> 2) << 12) | (p & 0xfff)) 6 | extern long __noio; 7 | static inline void *io_addr (unsigned long port) 8 | { 9 | unsigned long offset; 10 | unsigned long io_base; 11 | asm volatile ("mov %0=ar.k0":"=r"(io_base)); 12 | offset = IO_SPACE_ENCODING(port); 13 | return UNCACHED(io_base | offset); 14 | } 15 | 16 | static inline unsigned int inb (unsigned long port) 17 | { 18 | volatile unsigned char *addr = io_addr(port); 19 | unsigned char ret = 0; 20 | if (!__noio) { 21 | ret = *addr; 22 | MF(); 23 | } 24 | return ret; 25 | } 26 | 27 | static inline unsigned int inw (unsigned long port) 28 | { 29 | volatile unsigned short *addr = io_addr(port); 30 | unsigned short ret = 0; 31 | 32 | if (!__noio) { 33 | ret = *addr; 34 | MF(); 35 | } 36 | return ret; 37 | } 38 | 39 | static inline unsigned int inl (unsigned long port) 40 | { 41 | volatile unsigned int *addr = io_addr(port); 42 | unsigned int ret ; 43 | if (!__noio) { 44 | ret = *addr; 45 | MF(); 46 | } 47 | return ret; 48 | } 49 | 50 | static inline void outb (unsigned char val, unsigned long port) 51 | { 52 | volatile unsigned char *addr = io_addr(port); 53 | 54 | if (!__noio) { 55 | *addr = val; 56 | MF(); 57 | } 58 | } 59 | 60 | static inline void outw (unsigned short val, unsigned long port) 61 | { 62 | volatile unsigned short *addr = io_addr(port); 63 | 64 | if (!__noio) { 65 | *addr = val; 66 | MF(); 67 | } 68 | } 69 | 70 | static inline void outl (unsigned int val, unsigned long port) 71 | { 72 | volatile unsigned int *addr = io_addr(port); 73 | 74 | if (!__noio) { 75 | *addr = val; 76 | MF(); 77 | } 78 | } 79 | 80 | static inline unsigned char readb(const volatile void *addr) 81 | { 82 | return __noio ? 0 :*(volatile unsigned char *) addr; 83 | } 84 | static inline unsigned short readw(const volatile void *addr) 85 | { 86 | return __noio ? 0 :*(volatile unsigned short *) addr; 87 | } 88 | static inline unsigned int readl(const volatile void *addr) 89 | { 90 | return __noio ? 0 :*(volatile unsigned int *) addr; 91 | } 92 | 93 | static inline void writeb(unsigned char b, volatile void *addr) 94 | { 95 | if (!__noio) 96 | *(volatile unsigned char *) addr = b; 97 | } 98 | static inline void writew(unsigned short b, volatile void *addr) 99 | { 100 | if (!__noio) 101 | *(volatile unsigned short *) addr = b; 102 | } 103 | static inline void writel(unsigned int b, volatile void *addr) 104 | { 105 | if (!__noio) 106 | *(volatile unsigned int *) addr = b; 107 | } 108 | #endif 109 | -------------------------------------------------------------------------------- /purgatory/arch/ia64/purgatory-ia64.h: -------------------------------------------------------------------------------- 1 | #ifndef PURGATORY_IA64_H 2 | #define PURGATORY_IA64_H 3 | 4 | void reset_vga(void); 5 | #endif /* PURGATORY_IA64_H */ 6 | -------------------------------------------------------------------------------- /purgatory/arch/loongarch/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory loongarch 3 | # 4 | 5 | loongarch_PURGATORY_SRCS+= purgatory/arch/loongarch/purgatory-loongarch.c 6 | loongarch_PURGATORY_SRCS+= purgatory/arch/loongarch/console-loongarch.c 7 | 8 | dist += purgatory/arch/loongarch/Makefile $(loongarch_PURGATORY_SRCS) \ 9 | purgatory/arch/loongarch/purgatory-loongarch.h 10 | 11 | -------------------------------------------------------------------------------- /purgatory/arch/loongarch/console-loongarch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "unused.h" 3 | 4 | void putchar(int UNUSED(ch)) 5 | { 6 | /* Nothing for now */ 7 | } 8 | -------------------------------------------------------------------------------- /purgatory/arch/loongarch/purgatory-loongarch.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "purgatory-loongarch.h" 3 | 4 | void setup_arch(void) 5 | { 6 | /* Nothing for now */ 7 | } 8 | -------------------------------------------------------------------------------- /purgatory/arch/loongarch/purgatory-loongarch.h: -------------------------------------------------------------------------------- 1 | #ifndef PURGATORY_LOONGARCH_H 2 | #define PURGATORY_LOONGARCH_H 3 | 4 | /* nothing yet */ 5 | 6 | #endif /* PURGATORY_LOONGARCH_H */ 7 | -------------------------------------------------------------------------------- /purgatory/arch/mips/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory mips 3 | # 4 | 5 | mips_PURGATORY_SRCS+= purgatory/arch/mips/purgatory-mips.c 6 | mips_PURGATORY_SRCS+= purgatory/arch/mips/console-mips.c 7 | 8 | dist += purgatory/arch/mips/Makefile $(mips_PURGATORY_SRCS) \ 9 | purgatory/arch/mips/purgatory-mips.h 10 | 11 | -------------------------------------------------------------------------------- /purgatory/arch/mips/console-mips.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "unused.h" 3 | 4 | void putchar(int UNUSED(ch)) 5 | { 6 | /* Nothing for now */ 7 | } 8 | -------------------------------------------------------------------------------- /purgatory/arch/mips/purgatory-mips.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "purgatory-mips.h" 3 | 4 | void setup_arch(void) 5 | { 6 | /* Nothing for now */ 7 | } 8 | -------------------------------------------------------------------------------- /purgatory/arch/mips/purgatory-mips.h: -------------------------------------------------------------------------------- 1 | #ifndef PURGATORY_MIPSEL_H 2 | #define PURGATORY_MIPSEL_H 3 | 4 | /* nothing yet */ 5 | 6 | #endif /* PURGATORY_MIPSEL_H */ 7 | -------------------------------------------------------------------------------- /purgatory/arch/ppc/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory ppc 3 | # 4 | 5 | ppc_PURGATORY_SRCS += purgatory/arch/ppc/v2wrap_32.S 6 | ppc_PURGATORY_SRCS += purgatory/arch/ppc/misc.S 7 | ppc_PURGATORY_SRCS += purgatory/arch/ppc/purgatory-ppc.c 8 | ppc_PURGATORY_SRCS += purgatory/arch/ppc/console-ppc.c 9 | 10 | ppc_PURGATORY_EXTRA_CFLAGS += -msoft-float 11 | 12 | dist += purgatory/arch/ppc/Makefile $(ppc_PURGATORY_SRCS) \ 13 | purgatory/arch/ppc/purgatory-ppc.h purgatory/arch/ppc/ppc_asm.h 14 | 15 | -------------------------------------------------------------------------------- /purgatory/arch/ppc/console-ppc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "unused.h" 3 | 4 | void putchar(int UNUSED(ch)) 5 | { 6 | /* Nothing for now */ 7 | } 8 | -------------------------------------------------------------------------------- /purgatory/arch/ppc/purgatory-ppc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec: Linux boots Linux 3 | * 4 | * Created by: Mohan Kumar M (mohan@in.ibm.com) 5 | * 6 | * Copyright (C) IBM Corporation, 2005. All rights reserved 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation (version 2 of the License). 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #include 23 | #include "purgatory-ppc.h" 24 | 25 | unsigned int panic_kernel = 0; 26 | unsigned long backup_start = 0; 27 | unsigned long stack = 0; 28 | unsigned long dt_offset = 0; 29 | unsigned long my_thread_ptr = 0; 30 | unsigned long kernel = 0; 31 | 32 | void setup_arch(void) 33 | { 34 | return; 35 | } 36 | 37 | void post_verification_setup_arch(void) 38 | { 39 | #ifndef CONFIG_BOOKE 40 | if (panic_kernel) 41 | crashdump_backup_memory(); 42 | #endif 43 | } 44 | 45 | void crashdump_backup_memory(void) 46 | { 47 | return; 48 | } 49 | -------------------------------------------------------------------------------- /purgatory/arch/ppc/purgatory-ppc.h: -------------------------------------------------------------------------------- 1 | #ifndef PURGATORY_PPC_H 2 | #define PURGATORY_PPC_H 3 | 4 | void crashdump_backup_memory(void); 5 | void post_verification_setup_arch(void); 6 | #endif /* PURGATORY_PPC_H */ 7 | -------------------------------------------------------------------------------- /purgatory/arch/ppc64/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory ppc64 3 | # 4 | 5 | ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/v2wrap.S 6 | ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/hvCall.S 7 | ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/purgatory-ppc64.c 8 | ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/console-ppc64.c 9 | ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/crashdump_backup.c 10 | ppc64_PURGATORY_SRCS += purgatory/arch/ppc64/misc.S 11 | 12 | ppc64_PURGATORY_EXTRA_CFLAGS += -m64 -msoft-float \ 13 | -fno-exceptions 14 | ppc64_PURGATORY_EXTRA_ASFLAGS += -m64 15 | ifeq ($(SUBARCH),BE) 16 | ppc64_PURGATORY_EXTRA_LDFLAGS += -melf64ppc 17 | ppc64_PURGATORY_EXTRA_CFLAGS += -mcall-aixdesc 18 | ppc64_PURGATORY_EXTRA_ASFLAGS += -mcall-aixdesc 19 | else 20 | ppc64_PURGATORY_EXTRA_LDFLAGS += -melf64lppc 21 | ppc64_PURGATORY_EXTRA_CFLAGS += -mlittle-endian 22 | ppc64_PURGATORY_EXTRA_ASFLAGS += -mlittle-endian 23 | endif 24 | 25 | dist += purgatory/arch/ppc64/Makefile $(ppc64_PURGATORY_SRCS) \ 26 | purgatory/arch/ppc64/hvCall.h \ 27 | purgatory/arch/ppc64/ppc64_asm.h \ 28 | purgatory/arch/ppc64/purgatory-ppc64.h 29 | -------------------------------------------------------------------------------- /purgatory/arch/ppc64/console-ppc64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec: Linux boots Linux 3 | * 4 | * Created by: Mohan Kumar M (mohan@in.ibm.com) 5 | * 6 | * Copyright (C) IBM Corporation, 2005. All rights reserved 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation (version 2 of the License). 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #include 23 | #include "hvCall.h" 24 | #include 25 | #include 26 | #include 27 | 28 | extern int debug; 29 | 30 | void putchar(int c) 31 | { 32 | char buff[16] = ""; 33 | unsigned long *lbuf = (unsigned long *)buff; 34 | 35 | if (!debug) /* running on non pseries */ 36 | return; 37 | 38 | if (c == '\n') 39 | putchar('\r'); 40 | 41 | buff[0] = c; 42 | plpar_hcall_norets(H_PUT_TERM_CHAR, 0, 1, 43 | __cpu_to_be64(lbuf[0]), __cpu_to_be64(lbuf[1])); 44 | return; 45 | } 46 | -------------------------------------------------------------------------------- /purgatory/arch/ppc64/crashdump_backup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec: Linux boots Linux 3 | * 4 | * Created by: Mohan Kumar M (mohan@in.ibm.com) 5 | * 6 | * Copyright (C) IBM Corporation, 2005. All rights reserved 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation (version 2 of the License). 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #include 23 | #include 24 | #include "../../../kexec/arch/ppc64/crashdump-ppc64.h" 25 | 26 | extern unsigned long backup_start; 27 | 28 | /* Backup first 32KB of memory to backup region reserved by kexec */ 29 | void crashdump_backup_memory(void) 30 | { 31 | void *dest, *src; 32 | 33 | src = (void *)BACKUP_SRC_START; 34 | 35 | if (backup_start) { 36 | dest = (void *)(backup_start); 37 | memcpy(dest, src, BACKUP_SRC_SIZE); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /purgatory/arch/ppc64/hvCall.S: -------------------------------------------------------------------------------- 1 | /* 2 | * This file contains the generic function to perform a call to the 3 | * pSeries LPAR hypervisor. 4 | * 5 | * Taken from linux/arch/powerpc/platforms/pseries/hvCall.S 6 | * 7 | * This program is free software; you can redistribute it and/or 8 | * modify it under the terms of the GNU General Public License 9 | * as published by the Free Software Foundation; either version 10 | * 2 of the License, or (at your option) any later version. 11 | */ 12 | #include "ppc64_asm.h" 13 | 14 | #define HVSC .long 0x44000022 15 | .text 16 | .machine ppc64 17 | .globl DOTSYM(plpar_hcall_norets) 18 | DOTSYM(plpar_hcall_norets): 19 | or 6,6,6 # medium low priority 20 | mfcr 0 21 | stw 0,8(1) 22 | 23 | HVSC /* invoke the hypervisor */ 24 | 25 | lwz 0,8(1) 26 | mtcrf 0xff,0 27 | blr /* return r3 = status */ 28 | -------------------------------------------------------------------------------- /purgatory/arch/ppc64/hvCall.h: -------------------------------------------------------------------------------- 1 | #ifndef HVCALL_H 2 | #define HVCALL_H 3 | 4 | #define H_PUT_TERM_CHAR 0x58 5 | 6 | long plpar_hcall_norets(unsigned long opcode, ...); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /purgatory/arch/ppc64/ppc64_asm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ppc64_asm.h - common defines for PPC64 assembly parts 3 | * 4 | * This source code is licensed under the GNU General Public License, 5 | * Version 2. See the file COPYING for more details. 6 | */ 7 | 8 | /* 9 | * ABIv1 requires dot symbol while ABIv2 does not. 10 | */ 11 | #if defined(_CALL_ELF) && _CALL_ELF == 2 12 | #define DOTSYM(a) a 13 | #else 14 | #define GLUE(a,b) a##b 15 | #define DOTSYM(a) GLUE(.,a) 16 | #endif 17 | -------------------------------------------------------------------------------- /purgatory/arch/ppc64/purgatory-ppc64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * kexec: Linux boots Linux 3 | * 4 | * Created by: Mohan Kumar M (mohan@in.ibm.com) 5 | * 6 | * Copyright (C) IBM Corporation, 2005. All rights reserved 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation (version 2 of the License). 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 | */ 21 | 22 | #include 23 | #include "purgatory-ppc64.h" 24 | 25 | unsigned int panic_kernel = 0; 26 | unsigned long backup_start = 0; 27 | unsigned long stack = 0; 28 | unsigned long dt_offset = 0; 29 | unsigned long my_toc = 0; 30 | unsigned long kernel = 0; 31 | unsigned int debug = 0; 32 | unsigned long opal_base = 0; 33 | unsigned long opal_entry = 0; 34 | 35 | void setup_arch(void) 36 | { 37 | return; 38 | } 39 | 40 | void post_verification_setup_arch(void) 41 | { 42 | if (panic_kernel) 43 | crashdump_backup_memory(); 44 | } 45 | -------------------------------------------------------------------------------- /purgatory/arch/ppc64/purgatory-ppc64.h: -------------------------------------------------------------------------------- 1 | #ifndef PURGATORY_PPC64_H 2 | #define PURGATORY_PPC64_H 3 | 4 | void crashdump_backup_memory(void); 5 | 6 | #endif /* PURGATORY_PPC64_H */ 7 | -------------------------------------------------------------------------------- /purgatory/arch/riscv/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory riscv 3 | # 4 | 5 | riscv_PURGATORY_SRCS = 6 | 7 | dist += purgatory/arch/riscv/Makefile $(riscv_PURGATORY_SRCS) 8 | -------------------------------------------------------------------------------- /purgatory/arch/s390/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory s390 3 | # 4 | 5 | s390_PURGATORY_SRCS += purgatory/arch/s390/console-s390.c 6 | s390_PURGATORY_SRCS += purgatory/arch/s390/setup-s390.S 7 | s390_PURGATORY_SRCS += purgatory/arch/s390/purgatory-s390.c 8 | 9 | dist += purgatory/arch/s390/Makefile $(s390_PURGATORY_SRCS) 10 | 11 | -------------------------------------------------------------------------------- /purgatory/arch/s390/console-s390.c: -------------------------------------------------------------------------------- 1 | /* 2 | * S390 console code (currently not implemented) 3 | * 4 | * Copyright IBM Corp. 2011 5 | * 6 | * Author(s): Michael Holzheu 7 | */ 8 | 9 | #include 10 | #include "unused.h" 11 | 12 | void putchar(int UNUSED(ch)) 13 | { 14 | } 15 | -------------------------------------------------------------------------------- /purgatory/arch/s390/purgatory-s390.c: -------------------------------------------------------------------------------- 1 | /* 2 | * S390 purgatory 3 | * 4 | * Copyright IBM Corp. 2011 5 | * 6 | * Author(s): Michael Holzheu 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "../../../kexec/kexec-sha256.h" 13 | 14 | #define MIN(x, y) ((x) < (y) ? (x) : (y)) 15 | #define MAX(x, y) ((x) > (y) ? (x) : (y)) 16 | 17 | extern struct sha256_region sha256_regions[SHA256_REGIONS]; 18 | 19 | unsigned long crash_base = (unsigned long) -1; 20 | unsigned long crash_size = (unsigned long) -1; 21 | 22 | /* 23 | * Implement memcpy using the mvcle instruction 24 | */ 25 | static void memcpy_fast(void *target, void *src, unsigned long size) 26 | { 27 | register unsigned long __target asm("2") = (unsigned long) target; 28 | register unsigned long __size1 asm("3") = size; 29 | register unsigned long __src asm("4") = (unsigned long) src; 30 | register unsigned long __size2 asm("5") = size; 31 | 32 | asm volatile ( 33 | "0: mvcle %0,%2,0\n" 34 | " jo 0b\n" 35 | : "+d" (__target), "+d" (__size1), "+d" (__src), "+d" (__size2) 36 | : 37 | : "cc", "memory" 38 | ); 39 | } 40 | 41 | /* 42 | * Swap memory areas 43 | */ 44 | static void memswap(void *addr1, void *addr2, unsigned long size) 45 | { 46 | unsigned long off, copy_len; 47 | static char buf[1024]; 48 | 49 | for (off = 0; off < size; off += sizeof(buf)) { 50 | copy_len = MIN(size - off, sizeof(buf)); 51 | memcpy_fast(buf, (void *) addr2 + off, copy_len); 52 | memcpy_fast(addr2 + off, addr1 + off, copy_len); 53 | memcpy_fast(addr1 + off, buf, copy_len); 54 | } 55 | } 56 | 57 | /* 58 | * Nothing to do 59 | */ 60 | void setup_arch(void) 61 | { 62 | } 63 | 64 | /* 65 | * Do swap of [crash base - crash base + size] with [0 - crash size] 66 | * 67 | * We swap all kexec segments except of purgatory. The rest is copied 68 | * from [0 - crash size] to [crash base - crash base + size]. 69 | * We use [0x2000 - 0x10000] for purgatory. This area is never used 70 | * by s390 Linux kernels. 71 | * 72 | * This functions assumes that the sha256_regions[] is sorted. 73 | */ 74 | void post_verification_setup_arch(void) 75 | { 76 | unsigned long start, len, last = crash_base + 0x10000; 77 | struct sha256_region *ptr, *end; 78 | 79 | end = &sha256_regions[sizeof(sha256_regions)/sizeof(sha256_regions[0])]; 80 | for (ptr = sha256_regions; ptr < end; ptr++) { 81 | if (!ptr->start) 82 | continue; 83 | start = MAX(ptr->start, crash_base + 0x10000); 84 | len = ptr->len - (start - ptr->start); 85 | memcpy_fast((void *) last, (void *) last - crash_base, 86 | start - last); 87 | memswap((void *) start - crash_base, (void *) start, len); 88 | last = start + len; 89 | } 90 | memcpy_fast((void *) last, (void *) last - crash_base, 91 | crash_base + crash_size - last); 92 | memcpy_fast((void *) crash_base, (void *) 0, 0x2000); 93 | } 94 | -------------------------------------------------------------------------------- /purgatory/arch/s390/setup-s390.S: -------------------------------------------------------------------------------- 1 | /* 2 | * Purgatory setup code 3 | * 4 | * Copyright IBM Corp. 2011 5 | * 6 | * Author(s): Michael Holzheu 7 | */ 8 | 9 | .text 10 | .globl purgatory_start 11 | .balign 16 12 | purgatory_start: 13 | #ifdef __s390x__ 14 | larl %r5,gprs_save_area 15 | stmg %r6,%r15,0(%r5) 16 | larl %r15,lstack_end 17 | aghi %r15,-160 18 | 19 | cghi %r2,0 20 | je verify_checksums 21 | 22 | brasl %r14,purgatory 23 | larl %r14,kdump_psw 24 | lpswe 0(%r14) 25 | 26 | verify_checksums: 27 | brasl %r14,verify_sha256_digest 28 | larl %r5,gprs_save_area 29 | lmg %r6,%r15,0(%r5) 30 | br %r14 31 | .section ".data" 32 | .balign 16 33 | kdump_psw: 34 | .quad 0x0000000180000000 35 | .quad 0x0000000000010010 36 | 37 | .bss 38 | gprs_save_area: 39 | .fill 80 40 | 41 | .balign 4096 42 | lstack: 43 | .skip 4096 44 | lstack_end: 45 | #else 46 | 0: j 0 47 | #endif 48 | -------------------------------------------------------------------------------- /purgatory/arch/sh/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory sh 3 | # 4 | 5 | sh_PURGATORY_SRCS = 6 | 7 | dist += purgatory/arch/sh/Makefile $(sh_PURGATORY_SRCS) 8 | 9 | -------------------------------------------------------------------------------- /purgatory/arch/x86_64/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Purgatory x86_64 3 | # 4 | 5 | x86_64_PURGATORY_SRCS_native = purgatory/arch/x86_64/entry64-32.S 6 | x86_64_PURGATORY_SRCS_native += purgatory/arch/x86_64/entry64.S 7 | x86_64_PURGATORY_SRCS_native += purgatory/arch/x86_64/setup-x86_64.S 8 | x86_64_PURGATORY_SRCS_native += purgatory/arch/x86_64/stack.S 9 | x86_64_PURGATORY_SRCS_native += purgatory/arch/x86_64/purgatory-x86_64.c 10 | 11 | x86_64_PURGATORY_SRCS += $(x86_64_PURGATORY_SRCS_native) 12 | 13 | dist += purgatory/arch/x86_64/Makefile $(x86_64_PURGATORY_SRCS_native) \ 14 | purgatory/arch/x86_64/include/arch/io.h \ 15 | purgatory/arch/x86_64/include/arch/debug.h \ 16 | purgatory/arch/x86_64/purgatory-x86_64.h 17 | 18 | # Don't add sources in i386/ to dist, as i386/Makefile adds them 19 | x86_64_PURGATORY_SRCS += purgatory/arch/i386/entry32-16.S 20 | x86_64_PURGATORY_SRCS += purgatory/arch/i386/entry32-16-debug.S 21 | x86_64_PURGATORY_SRCS += purgatory/arch/i386/crashdump_backup.c 22 | x86_64_PURGATORY_SRCS += purgatory/arch/i386/console-x86.c 23 | x86_64_PURGATORY_SRCS += purgatory/arch/i386/vga.c 24 | x86_64_PURGATORY_SRCS += purgatory/arch/i386/pic.c 25 | 26 | ifneq ($(SUBARCH),x32) 27 | x86_64_PURGATORY_EXTRA_CFLAGS = -mcmodel=large -march=x86-64 -mno-mmx -mno-sse -mno-sse2 -mno-avx 28 | endif 29 | -------------------------------------------------------------------------------- /purgatory/arch/x86_64/include/arch/io.h: -------------------------------------------------------------------------------- 1 | #ifndef ARCH_X86_64_IO_H 2 | #define ARCH_X86_64_IO_H 3 | 4 | #include 5 | #include "../../../i386/include/arch/io.h" 6 | 7 | #endif /* ARCH_X86_64_IO_H */ 8 | -------------------------------------------------------------------------------- /purgatory/arch/x86_64/purgatory-x86_64.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "purgatory-x86_64.h" 5 | 6 | uint8_t reset_vga = 0; 7 | uint8_t legacy_pic = 0; 8 | uint8_t panic_kernel = 0; 9 | unsigned long jump_back_entry = 0; 10 | char *cmdline_end = NULL; 11 | 12 | void setup_arch(void) 13 | { 14 | if (reset_vga) x86_reset_vga(); 15 | if (legacy_pic) x86_setup_legacy_pic(); 16 | } 17 | 18 | void x86_setup_jump_back_entry(void) 19 | { 20 | if (cmdline_end) 21 | sprintf(cmdline_end, " kexec_jump_back_entry=0x%lx", 22 | jump_back_entry); 23 | } 24 | 25 | /* This function can be used to execute after the SHA256 verification. */ 26 | void post_verification_setup_arch(void) 27 | { 28 | if (panic_kernel) crashdump_backup_memory(); 29 | if (jump_back_entry) x86_setup_jump_back_entry(); 30 | } 31 | -------------------------------------------------------------------------------- /purgatory/arch/x86_64/purgatory-x86_64.h: -------------------------------------------------------------------------------- 1 | #ifndef PURGATORY_X86_64_H 2 | #define PURGATORY_X86_64_H 3 | #include "../i386/purgatory-x86.h" 4 | #endif /* PURGATORY_X86_64_H */ 5 | -------------------------------------------------------------------------------- /purgatory/arch/x86_64/setup-x86_64.S: -------------------------------------------------------------------------------- 1 | /* 2 | * purgatory: setup code 3 | * 4 | * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation (version 2 of the License). 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | #include "arch/debug.h" 21 | 22 | 23 | #undef i386 24 | 25 | .text 26 | .globl purgatory_start 27 | .balign 16 28 | purgatory_start: 29 | .code64 30 | 31 | /* Load a gdt so I know what the segment registers are */ 32 | lgdt gdt(%rip) 33 | 34 | /* load the data segments */ 35 | movl $0x18, %eax /* data segment */ 36 | movl %eax, %ds 37 | movl %eax, %es 38 | movl %eax, %ss 39 | movl %eax, %fs 40 | movl %eax, %gs 41 | 42 | /* In 64bit mode the code segment is meaningless */ 43 | 44 | movq 0(%rsp), %rax 45 | movq %rax, jump_back_entry(%rip) 46 | 47 | /* Setup a stack */ 48 | leaq lstack_end(%rip), %rsp 49 | 50 | /* Call the C code */ 51 | call purgatory 52 | jmp entry64 53 | 54 | .section ".rodata" 55 | .balign 16 56 | gdt: /* 0x00 unusable segment 57 | * 0x08 unused 58 | * so use them as the gdt ptr 59 | */ 60 | .word gdt_end - gdt - 1 61 | .quad gdt 62 | .word 0, 0, 0 63 | 64 | /* 0x10 4GB flat code segment */ 65 | .word 0xFFFF, 0x0000, 0x9A00, 0x00AF 66 | 67 | /* 0x18 4GB flat data segment */ 68 | .word 0xFFFF, 0x0000, 0x9200, 0x00CF 69 | gdt_end: 70 | 71 | .bss 72 | .balign 4096 73 | lstack: 74 | .skip 4096 75 | lstack_end: 76 | 77 | -------------------------------------------------------------------------------- /purgatory/arch/x86_64/stack.S: -------------------------------------------------------------------------------- 1 | /* 2 | * purgatory: stack 3 | * 4 | * Copyright (C) 2003,2004 Eric Biederman (ebiederm@xmission.com) 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation (version 2 of the License). 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 | */ 19 | 20 | /* A stack for the loaded kernel. 21 | * Seperate and in the data section so it can be prepopulated. 22 | */ 23 | .data 24 | .balign 4096 25 | .globl stack, stack_end 26 | .globl stack_arg32_1, stack_arg32_2, stack_arg32_3 ,stack_arg32_4 27 | .globl stack_arg32_5, stack_arg32_6, stack_arg32_7 ,stack_arg32_8 28 | .globl stack_arg64_1, stack_arg64_2, stack_arg64_3 ,stack_arg64_4 29 | 30 | stack: 31 | .skip 4096 - (8*4) 32 | stack_arg64_4: ; .size stack_arg64_4, 8 33 | stack_arg32_8: .long 0 ; .size stack_arg32_8, 4 34 | stack_arg32_7: .long 0 ; .size stack_arg32_7, 4 35 | stack_arg64_3: ; .size stack_arg64_3, 8 36 | stack_arg32_6: .long 0 ; .size stack_arg32_6, 4 37 | stack_arg32_5: .long 0 ; .size stack_arg32_5, 4 38 | stack_arg64_2: ; .size stack_arg64_2, 8 39 | stack_arg32_4: .long 0 ; .size stack_arg32_4, 4 40 | stack_arg32_3: .long 0 ; .size stack_arg32_3, 4 41 | stack_arg64_1: ; .size stack_arg64_1, 8 42 | stack_arg32_2: .long 0 ; .size stack_arg32_2, 4 43 | stack_arg32_1: .long 0 ; .size stack_arg32_1, 4 44 | stack_end: 45 | -------------------------------------------------------------------------------- /purgatory/include/purgatory.h: -------------------------------------------------------------------------------- 1 | #ifndef PURGATORY_H 2 | #define PURGATORY_H 3 | 4 | void putchar(int ch); 5 | void sprintf(char *buffer, const char *fmt, ...) 6 | __attribute__ ((format (printf, 2, 3))); 7 | void printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); 8 | void setup_arch(void); 9 | void post_verification_setup_arch(void); 10 | 11 | #endif /* PURGATORY_H */ 12 | -------------------------------------------------------------------------------- /purgatory/include/string.h: -------------------------------------------------------------------------------- 1 | #ifndef STRING_H 2 | #define STRING_H 3 | 4 | #include 5 | 6 | size_t strnlen(const char *s, size_t max); 7 | void* memset(void* s, int c, size_t n); 8 | void* memcpy(void *dest, const void *src, size_t len); 9 | int memcmp(void *src1, void *src2, size_t len); 10 | 11 | 12 | #endif /* STRING_H */ 13 | -------------------------------------------------------------------------------- /purgatory/purgatory.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../kexec/kexec-sha256.h" 8 | 9 | struct sha256_region sha256_regions[SHA256_REGIONS] = {}; 10 | sha256_digest_t sha256_digest = { }; 11 | int skip_checks = 0; 12 | 13 | int verify_sha256_digest(void) 14 | { 15 | struct sha256_region *ptr, *end; 16 | sha256_digest_t digest; 17 | size_t i; 18 | sha256_context ctx; 19 | sha256_starts(&ctx); 20 | end = &sha256_regions[sizeof(sha256_regions)/sizeof(sha256_regions[0])]; 21 | for(ptr = sha256_regions; ptr < end; ptr++) { 22 | sha256_update(&ctx, (uint8_t *)((uintptr_t)ptr->start), 23 | ptr->len); 24 | } 25 | sha256_finish(&ctx, digest); 26 | if (memcmp(digest, sha256_digest, sizeof(digest)) != 0) { 27 | printf("sha256 digests do not match :(\n"); 28 | printf(" digest: "); 29 | for(i = 0; i < sizeof(digest); i++) { 30 | printf("%hhx ", digest[i]); 31 | } 32 | printf("\n"); 33 | printf("sha256_digest: "); 34 | for(i = 0; i < sizeof(sha256_digest); i++) { 35 | printf("%hhx ", sha256_digest[i]); 36 | } 37 | printf("\n"); 38 | return 1; 39 | } 40 | return 0; 41 | } 42 | 43 | void purgatory(void) 44 | { 45 | printf("I'm in purgatory\n"); 46 | setup_arch(); 47 | if (!skip_checks && verify_sha256_digest()) { 48 | for(;;) { 49 | /* loop forever */ 50 | } 51 | } 52 | post_verification_setup_arch(); 53 | } 54 | -------------------------------------------------------------------------------- /purgatory/string.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | size_t strnlen(const char *s, size_t max) 5 | { 6 | size_t len = 0; 7 | while(len < max && *s) { 8 | len++; 9 | s++; 10 | } 11 | return len; 12 | } 13 | 14 | void* memset(void* s, int c, size_t n) 15 | { 16 | size_t i; 17 | char *ss = (char*)s; 18 | 19 | for (i=0;i 2 | 3 | int main(int argc, char **argv) 4 | { 5 | int c; 6 | int i; 7 | const char *name = argv[1]; 8 | printf("#include \n"); 9 | printf("const char %s[] = {\n", name); 10 | i = 0; 11 | while((c = getchar()) != EOF) { 12 | if ((i % 16) != 0) { 13 | putchar(' '); 14 | } 15 | printf("0x%02x,", c); 16 | i++; 17 | if ((i %16) == 0) { 18 | putchar('\n'); 19 | } 20 | } 21 | putchar('\n'); 22 | printf("};\n"); 23 | printf("size_t %s_size = sizeof(%s);\n", name, name); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /util_lib/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Utility function library 3 | # 4 | UTIL_LIB_SRCS += 5 | UTIL_LIB_SRCS += util_lib/compute_ip_checksum.c 6 | UTIL_LIB_SRCS += util_lib/elf_info.c 7 | UTIL_LIB_SRCS += util_lib/sha256.c 8 | UTIL_LIB_OBJS =$(call objify, $(UTIL_LIB_SRCS)) 9 | UTIL_LIB_DEPS =$(call depify, $(UTIL_LIB_OBJS)) 10 | UTIL_LIB = libutil.a 11 | 12 | -include $(UTIL_LIB_DEPS) 13 | 14 | dist += util_lib/Makefile $(UTIL_LIB_SRCS) \ 15 | util_lib/include/elf_info.h util_lib/include/sha256.h \ 16 | util_lib/include/ip_checksum.h 17 | clean += $(UTIL_LIB_OBJS) $(UTIL_LIB_DEPS) $(UTIL_LIB) 18 | 19 | $(UTIL_LIB): CPPFLAGS += -I$(srcdir)/util_lib/include 20 | 21 | $(UTIL_LIB): $(UTIL_LIB_OBJS) 22 | @$(MKDIR) -p $(@D) 23 | $(AR) rs $(UTIL_LIB) $(UTIL_LIB_OBJS) 24 | 25 | -------------------------------------------------------------------------------- /util_lib/include/elf_info.h: -------------------------------------------------------------------------------- 1 | #ifndef ELF_INFO_H 2 | #define ELF_INFO_H 3 | 4 | #define _XOPEN_SOURCE 700 5 | #define _GNU_SOURCE 6 | #define _LARGEFILE_SOURCE 1 7 | #define _FILE_OFFSET_BITS 64 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | int get_pt_load(int idx, 27 | unsigned long long *phys_start, 28 | unsigned long long *phys_end, 29 | unsigned long long *virt_start, 30 | unsigned long long *virt_end); 31 | int read_phys_offset_elf_kcore(int fd, long *phys_off); 32 | int read_elf(int fd); 33 | void dump_dmesg(int fd, void (*handler)(char*, unsigned int)); 34 | extern void (*arch_scan_vmcoreinfo)(char *pos); 35 | 36 | #endif /* ELF_INFO_H */ 37 | -------------------------------------------------------------------------------- /util_lib/include/ip_checksum.h: -------------------------------------------------------------------------------- 1 | #ifndef IP_CHECKSUM_H 2 | #define IP_CHECKSUM_H 3 | 4 | unsigned long compute_ip_checksum(void *addr, unsigned long length); 5 | unsigned long add_ip_checksums(unsigned long offset, unsigned long sum, unsigned long new); 6 | unsigned long negate_ip_checksum(unsigned long sum); 7 | 8 | #endif /* IP_CHECKSUM_H */ 9 | -------------------------------------------------------------------------------- /util_lib/include/sha256.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA256_H 2 | #define SHA256_H 3 | 4 | #include 5 | #include 6 | 7 | typedef struct 8 | { 9 | size_t total[2]; 10 | uint32_t state[8]; 11 | uint8_t buffer[64]; 12 | } 13 | sha256_context; 14 | 15 | typedef uint8_t sha256_digest_t[32]; 16 | 17 | void sha256_starts( sha256_context *ctx ); 18 | void sha256_update( sha256_context *ctx, const uint8_t *input, size_t length ); 19 | void sha256_finish( sha256_context *ctx, sha256_digest_t digest ); 20 | 21 | 22 | #endif /* SHA256_H */ 23 | -------------------------------------------------------------------------------- /vmcore-dmesg/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # vmcore-dmesg (reading demsg from vmcore) 3 | # 4 | 5 | VMCORE_DMESG_SRCS:= vmcore-dmesg/vmcore-dmesg.c 6 | 7 | VMCORE_DMESG_OBJS = $(call objify, $(VMCORE_DMESG_SRCS)) 8 | VMCORE_DMESG_DEPS = $(call depify, $(VMCORE_DMESG_OBJS)) 9 | 10 | VMCORE_DMESG = $(SBINDIR)/vmcore-dmesg 11 | VMCORE_DMESG_MANPAGE = $(MANDIR)/man8/vmcore-dmesg.8 12 | 13 | dist += vmcore-dmesg/Makefile $(VMCORE_DMESG_SRCS) vmcore-dmesg/vmcore-dmesg.8 14 | clean += $(VMCORE_DMESG_OBJS) $(VMCORE_DMESG_DEPS) $(VMCORE_DMESG) $(VMCORE_DMESG_MANPAGE) 15 | 16 | -include $(VMCORE_DMESG_DEPS) 17 | 18 | $(VMCORE_DMESG): $(VMCORE_DMESG_OBJS) $(UTIL_LIB) 19 | @$(MKDIR) -p $(@D) 20 | $(LINK.o) -o $@ $^ $(CFLAGS) $(LIBS) 21 | 22 | $(VMCORE_DMESG_MANPAGE): vmcore-dmesg/vmcore-dmesg.8 23 | $(MKDIR) -p $(MANDIR)/man8 24 | cp $^ $(VMCORE_DMESG_MANPAGE) 25 | echo:: 26 | @echo "VMCORE_DMESG_SRCS $(VMCORE_DMESG_SRCS)" 27 | @echo "VMCORE_DMESG_DEPS $(VMCORE_DMESG_DEPS)" 28 | @echo "VMCORE_DMESG_OBJS $(VMCORE_DMESG_OBJS)" 29 | 30 | -------------------------------------------------------------------------------- /vmcore-dmesg/vmcore-dmesg.8: -------------------------------------------------------------------------------- 1 | .\" Hey, EMACS: -*- nroff -*- 2 | .\" First parameter, NAME, should be all caps 3 | .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection 4 | .\" other parameters are allowed: see man(7), man(1) 5 | .TH VMCORE-DMESG 8 "Sep 21, 2020" 6 | .\" Please adjust this date whenever revising the manpage. 7 | .\" 8 | .\" Some roff macros, for reference: 9 | .\" .nh disable hyphenation 10 | .\" .hy enable hyphenation 11 | .\" .ad l left justify 12 | .\" .ad b justify to both left and right margins 13 | .\" .nf disable filling 14 | .\" .fi enable filling 15 | .\" .br insert line break 16 | .\" .sp insert n+1 empty lines 17 | .\" for manpage-specific macros, see man(7) 18 | .SH NAME 19 | vmcore-dmesg 20 | .SH SYNOPSIS 21 | .B vmcore-dmesg 22 | .RI " vmcore" 23 | .SH DESCRIPTION 24 | .PP 25 | .\" TeX users may be more comfortable with the \fB\fP and 26 | .\" \fI\fP escape sequences to invode bold face and italics, 27 | .\" respectively. 28 | \fBvmcore-dmesg\fP extracts the dmesg from a vmcore and write it to 29 | standard out. \fBvmcore-dmesg\fP works against either 30 | \fB/proc/vmcore\fP in a crash dump capture context or a copy 31 | of \fB/proc/vmcore\fP that has been saved for later analysis. A 32 | single build of \fBvmcore-dmesg\fP should work against any linux 33 | vmcore written created on any architecture. 34 | 35 | .\"These programs follow the usual GNU command line syntax, with long 36 | .\"options starting with two dashes (`-'). 37 | .\"A summary of options is included below. 38 | .\"For a complete description, see the Info files. 39 | .SH SEE ALSO 40 | kexec(8) 41 | .SH AUTHOR 42 | vmcore-dmesg was written by Eric Biederman. 43 | -------------------------------------------------------------------------------- /vmcore-dmesg/vmcore-dmesg.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* The 32bit and 64bit note headers make it clear we don't care */ 4 | typedef Elf32_Nhdr Elf_Nhdr; 5 | 6 | extern const char *fname; 7 | 8 | /* stole this macro from kernel printk.c */ 9 | #define LOG_BUF_LEN_MAX (uint32_t)(1U << 31) 10 | 11 | static void write_to_stdout(char *buf, unsigned int nr) 12 | { 13 | ssize_t ret; 14 | static uint32_t n_bytes = 0; 15 | 16 | n_bytes += nr; 17 | if (n_bytes > LOG_BUF_LEN_MAX) { 18 | fprintf(stderr, "The vmcore-dmesg.txt over 2G in size is not supported.\n"); 19 | exit(53); 20 | } 21 | 22 | ret = write(STDOUT_FILENO, buf, nr); 23 | if (ret != nr) { 24 | fprintf(stderr, "Failed to write out the dmesg log buffer!:" 25 | " %s\n", strerror(errno)); 26 | exit(54); 27 | } 28 | } 29 | 30 | static int read_vmcore_dmesg(int fd, void (*handler)(char*, unsigned int)) 31 | { 32 | int ret; 33 | 34 | ret = read_elf(fd); 35 | if (ret > 0) { 36 | fprintf(stderr, "Unable to read ELF information" 37 | " from vmcore\n"); 38 | return ret; 39 | } 40 | 41 | dump_dmesg(fd, handler); 42 | 43 | return 0; 44 | } 45 | 46 | int main(int argc, char **argv) 47 | { 48 | ssize_t ret; 49 | int fd; 50 | 51 | if (argc != 2) { 52 | fprintf(stderr, "usage: %s \n", argv[0]); 53 | return 1; 54 | } 55 | fname = argv[1]; 56 | 57 | fd = open(fname, O_RDONLY); 58 | if (fd < 0) { 59 | fprintf(stderr, "Cannot open %s: %s\n", 60 | fname, strerror(errno)); 61 | return 2; 62 | } 63 | 64 | ret = read_vmcore_dmesg(fd, write_to_stdout); 65 | 66 | close(fd); 67 | 68 | return ret; 69 | } 70 | --------------------------------------------------------------------------------