mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Command line used: $ shfmt --space-redirects --case-indent --simplify --func-next-line --write mk-s390image 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>
219 lines
4.8 KiB
Bash
Executable File
219 lines
4.8 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 -f -- "$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
|
|
if [ ! -r "$i" ]; then
|
|
echo "$cmd: File $i cannot be read, no read permission" >&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
|