mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Since Linux commit 5ecb2da660ab ("s390: support command lines longer
than 896 bytes") the s390x kernel supports longer command lines than 896
bytes. The indication of the maximum size is stored in a new field at
address 0x10430, older kernels without the support store a value of 0
there so in that case fallback to the old maximum length of 896.
In addition, use the checked size as limit to copy in the 'dd' call.
This prevents Linux kernel corruption in case the parmline has changed
in between.
Fixes: https://github.com/ibm-s390-linux/s390-tools/issues/194
Reviewed-by: Jan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
209 lines
4.6 KiB
Bash
Executable File
209 lines
4.6 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# netboot - PXE-style boot for KVM on s390
|
|
#
|
|
# Sample script to build a single s390 boot image consisting of
|
|
# kernel, an initial ramdisk and kernel parameters from
|
|
# individual components. Note that bash is required to run this script!
|
|
#
|
|
# Sample invocation:
|
|
#
|
|
# ./mk-s390image /boot/image -r /boot/initrd image
|
|
#
|
|
# The resulting image can be used to build a bootable
|
|
# ISO or as firmware image for KVM.
|
|
#
|
|
# Copyright IBM Corp. 2017
|
|
#
|
|
# s390-tools is free software; you can redistribute it and/or modify
|
|
# it under the terms of the MIT license. See LICENSE for details.
|
|
|
|
# Offsets
|
|
OFFS_INITRD_START_BYTES=66568
|
|
OFFS_INITRD_SIZE_BYTES=66576
|
|
OFFS_COMMANDLINE_MAX_SIZE_BYTES=66608
|
|
OFFS_COMMANDLINE_BYTES=66688
|
|
LEGACY_MAX_PARMFILE_SIZE=896
|
|
|
|
# Variables
|
|
cmd=$(basename -- "$0")
|
|
kernel=
|
|
ramdisk=
|
|
parmfile=
|
|
image=
|
|
binval=
|
|
success=no
|
|
|
|
# Cleanup on exit
|
|
# shellcheck disable=SC2317
|
|
cleanup()
|
|
{
|
|
if [ -n "$binval" ]
|
|
then
|
|
rm -f -- "$binval"
|
|
fi
|
|
if [ -n "$image" ] && [ "$success" = no ]
|
|
then
|
|
rm -- "$image"
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
# Usage
|
|
usage()
|
|
{
|
|
cat <<-EOF
|
|
Usage: $cmd KERNEL BOOT_IMAGE [-r RAMDISK] [-p PARMFILE]
|
|
|
|
Build an s390 image BOOT_IMAGE suitable for CD/tape/network boot or as a
|
|
KVM firmware image using a stripped Linux kernel file KERNEL.
|
|
|
|
OPTIONS
|
|
-p Use PARMFILE with kernel parameters in the image
|
|
-r Include RAMDISK in the image
|
|
-h Print this help, then exit
|
|
-v Print version information, then exit
|
|
EOF
|
|
}
|
|
|
|
printversion()
|
|
{
|
|
cat <<-EOD
|
|
$cmd: version %S390_TOOLS_VERSION%
|
|
Copyright IBM Corp. 2017
|
|
EOD
|
|
}
|
|
|
|
# Convert decimal number to big endian doubleword
|
|
dec2be64()
|
|
{
|
|
local num=$1
|
|
local b
|
|
local i
|
|
for i in $(seq 1 8)
|
|
do
|
|
b="\\x$(printf '%x' "$((num % 256))")$b"
|
|
num=$((num / 256)) || true
|
|
done
|
|
printf '%b' "$b"
|
|
}
|
|
|
|
max_kernel_cmdline_size()
|
|
{
|
|
local __kernel=$1 size v
|
|
|
|
size_be="$(od -A n -j "${OFFS_COMMANDLINE_MAX_SIZE_BYTES}" -N 8 -t uL -- "$__kernel")"
|
|
# If little endian then swap bytes
|
|
if (("$(printf '\1' | od -dAn)" == 1)); then
|
|
v="$(printf '%016x0' "$size_be")"
|
|
size="0x${v:14:2}${v:12:2}${v:10:2}${v:8:2}${v:6:2}${v:4:2}${v:2:2}${v:0:2}"
|
|
else
|
|
size="$size_be"
|
|
fi
|
|
if ((size == 0)); then
|
|
size="${LEGACY_MAX_PARMFILE_SIZE}"
|
|
fi
|
|
# Use arithmetic expression to remove leading and trailing whitespace.
|
|
printf '%s' "$((size))"
|
|
}
|
|
|
|
# Do the image build
|
|
dobuild()
|
|
{
|
|
local i
|
|
local kernel_size
|
|
local ramdisk_size
|
|
local ramdisk_offset
|
|
local parmfile_size
|
|
# check whether all specified files exist
|
|
for i in $kernel $ramdisk $parmfile
|
|
do
|
|
if [ ! -f "$i" ]
|
|
then
|
|
echo "$cmd: File $i not found" >&2
|
|
return 1
|
|
fi
|
|
done
|
|
if ! file -b -- "$(readlink -f -- "$kernel")" | grep "Linux S390" > /dev/null
|
|
then
|
|
echo "$cmd: Unrecognized file format for $kernel" >&2
|
|
return 1
|
|
fi
|
|
|
|
# from now on we SHOULD only fail on disk shortage
|
|
# or file permissions, let the shell handle that
|
|
set -e
|
|
|
|
# copy over kernel padded with zeroes to page boundary
|
|
dd if="$kernel" of="$image" bs=4096 conv=sync status=none
|
|
|
|
# append ramdisk if specified
|
|
if [ "$ramdisk" != "" ]
|
|
then
|
|
ramdisk_size=$(du -b -L -- "$ramdisk" | cut -f1)
|
|
# shellcheck disable=SC2034
|
|
kernel_size=$(du -b -L -- "$kernel" | cut -f1)
|
|
ramdisk_offset=$(du -b -L -- "$image" | cut -f1)
|
|
cat -- "$ramdisk" >> "$image"
|
|
binval=$(mktemp)
|
|
dec2be64 "$ramdisk_offset" > "$binval"
|
|
dd seek=$OFFS_INITRD_START_BYTES if="$binval" of="$image" bs=1 \
|
|
count=8 conv=notrunc status=none
|
|
dec2be64 "$ramdisk_size" > "$binval"
|
|
dd seek=$OFFS_INITRD_SIZE_BYTES if="$binval" of="$image" bs=1 \
|
|
count=8 conv=notrunc status=none
|
|
fi
|
|
|
|
# set cmdline
|
|
if [ "$parmfile" != "" ]
|
|
then
|
|
max_parmfile_size=$(max_kernel_cmdline_size "$kernel")
|
|
parmfile_size=$(du -b -L -- "$parmfile" | cut -f1)
|
|
if (( parmfile_size <= max_parmfile_size ));
|
|
then
|
|
# Clear any previous parameters
|
|
dd seek=$OFFS_COMMANDLINE_BYTES bs=1 count="$max_parmfile_size" \
|
|
if=/dev/zero of="$image" conv=notrunc status=none
|
|
dd seek=$OFFS_COMMANDLINE_BYTES bs=1 count="$parmfile_size" \
|
|
if="$parmfile" of="$image" conv=notrunc status=none
|
|
else
|
|
echo "$cmd: Size $parmfile_size of $parmfile exceeds command line limit of $max_parmfile_size bytes" >&2
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# we've done it
|
|
success=yes
|
|
}
|
|
|
|
# check args and build
|
|
# shellcheck disable=SC2086,SC2048
|
|
if args=$(getopt "r:p:hv" $*)
|
|
then
|
|
# shellcheck disable=SC2086
|
|
set -- $args
|
|
while [ "$1" != "" ]
|
|
do
|
|
case $1 in
|
|
-r) ramdisk=$2; shift 2;;
|
|
-p) parmfile=$2; shift 2;;
|
|
-h) usage; exit 0;;
|
|
-v) printversion; exit 0;;
|
|
--) shift; break;;
|
|
*) echo "$cmd: Unexpected argument $1, exiting..." >&2; exit 1;;
|
|
esac
|
|
done
|
|
fi
|
|
|
|
if [ $# = 2 ]
|
|
then
|
|
kernel=$1
|
|
image=$2
|
|
dobuild
|
|
exit 0
|
|
fi
|
|
|
|
# something wasn't right
|
|
usage >&2
|
|
exit 1
|