Commit f279b49f authored by H. Peter Anvin (Intel)'s avatar H. Peter Anvin (Intel) Committed by Ingo Molnar

x86/boot: Modernize genimage script; hdimage+EFI support

The image generation scripts in arch/x86/boot are pretty out of date,
except for the isoimage target. Update and clean up the
genimage.sh script, and make it support an arbitrary number of
initramfs files in the image.

Add a "hdimage" target, which can be booted by either BIOS or
EFI (if the kernel is compiled with the EFI stub.) For EFI to be able
to pass the command line to the kernel, we need the EFI shell, but the
firmware builtin EFI shell, if it even exists, is pretty much always
the last resort boot option, so search for OVMF or EDK2 and explicitly
include a copy of the EFI shell.

To make this all work, use bash features in the script.  Furthermore,
this version of the script makes use of some mtools features,
especially mpartition, that might not exist in very old version of
mtools, but given all the other dependencies on this script this
doesn't seem such a big deal.

Finally, put a volume label ("LINUX_BOOT") on all generated images.
Signed-off-by: default avatarH. Peter Anvin (Intel) <hpa@zytor.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/20210510082840.628372-1-hpa@zytor.com
parent 6efb943b
...@@ -256,7 +256,7 @@ drivers-$(CONFIG_FB) += arch/x86/video/ ...@@ -256,7 +256,7 @@ drivers-$(CONFIG_FB) += arch/x86/video/
boot := arch/x86/boot boot := arch/x86/boot
BOOT_TARGETS = bzdisk fdimage fdimage144 fdimage288 isoimage BOOT_TARGETS = bzdisk fdimage fdimage144 fdimage288 hdimage isoimage
PHONY += bzImage $(BOOT_TARGETS) PHONY += bzImage $(BOOT_TARGETS)
...@@ -314,8 +314,9 @@ define archhelp ...@@ -314,8 +314,9 @@ define archhelp
echo ' fdimage - Create 1.4MB boot floppy image (arch/x86/boot/fdimage)' echo ' fdimage - Create 1.4MB boot floppy image (arch/x86/boot/fdimage)'
echo ' fdimage144 - Create 1.4MB boot floppy image (arch/x86/boot/fdimage)' echo ' fdimage144 - Create 1.4MB boot floppy image (arch/x86/boot/fdimage)'
echo ' fdimage288 - Create 2.8MB boot floppy image (arch/x86/boot/fdimage)' echo ' fdimage288 - Create 2.8MB boot floppy image (arch/x86/boot/fdimage)'
echo ' hdimage - Create a BIOS/EFI hard disk image (arch/x86/boot/hdimage)'
echo ' isoimage - Create a boot CD-ROM image (arch/x86/boot/image.iso)' echo ' isoimage - Create a boot CD-ROM image (arch/x86/boot/image.iso)'
echo ' bzdisk/fdimage*/isoimage also accept:' echo ' bzdisk/fdimage*/hdimage/isoimage also accept:'
echo ' FDARGS="..." arguments for the booted kernel' echo ' FDARGS="..." arguments for the booted kernel'
echo ' FDINITRD=file initrd for the booted kernel' echo ' FDINITRD=file initrd for the booted kernel'
echo '' echo ''
......
...@@ -11,3 +11,4 @@ setup.elf ...@@ -11,3 +11,4 @@ setup.elf
fdimage fdimage
mtools.conf mtools.conf
image.iso image.iso
hdimage
...@@ -29,7 +29,7 @@ KCOV_INSTRUMENT := n ...@@ -29,7 +29,7 @@ KCOV_INSTRUMENT := n
SVGA_MODE := -DSVGA_MODE=NORMAL_VGA SVGA_MODE := -DSVGA_MODE=NORMAL_VGA
targets := vmlinux.bin setup.bin setup.elf bzImage targets := vmlinux.bin setup.bin setup.elf bzImage
targets += fdimage fdimage144 fdimage288 image.iso mtools.conf targets += fdimage fdimage144 fdimage288 image.iso hdimage
subdir- := compressed subdir- := compressed
setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpuflags.o cpucheck.o setup-y += a20.o bioscall.o cmdline.o copy.o cpu.o cpuflags.o cpucheck.o
...@@ -115,47 +115,49 @@ $(obj)/compressed/vmlinux: FORCE ...@@ -115,47 +115,49 @@ $(obj)/compressed/vmlinux: FORCE
$(Q)$(MAKE) $(build)=$(obj)/compressed $@ $(Q)$(MAKE) $(build)=$(obj)/compressed $@
# Set this if you want to pass append arguments to the # Set this if you want to pass append arguments to the
# bzdisk/fdimage/isoimage kernel # bzdisk/fdimage/hdimage/isoimage kernel
FDARGS = FDARGS =
# Set this if you want an initrd included with the # Set this if you want one or more initrds included in the image
# bzdisk/fdimage/isoimage kernel
FDINITRD = FDINITRD =
image_cmdline = default linux $(FDARGS) $(if $(FDINITRD),initrd=initrd.img,) imgdeps = $(obj)/bzImage $(obj)/mtools.conf $(src)/genimage.sh
$(obj)/mtools.conf: $(src)/mtools.conf.in $(obj)/mtools.conf: $(src)/mtools.conf.in
sed -e 's|@OBJ@|$(obj)|g' < $< > $@ sed -e 's|@OBJ@|$(obj)|g' < $< > $@
targets += mtools.conf
# genimage.sh requires bash, but it also has a bunch of other
# external dependencies.
quiet_cmd_genimage = GENIMAGE $3 quiet_cmd_genimage = GENIMAGE $3
cmd_genimage = sh $(srctree)/$(src)/genimage.sh $2 $3 $(obj)/bzImage \ cmd_genimage = $(BASH) $(srctree)/$(src)/genimage.sh $2 $3 $(obj)/bzImage \
$(obj)/mtools.conf '$(image_cmdline)' $(FDINITRD) $(obj)/mtools.conf '$(FDARGS)' $(FDINITRD)
PHONY += bzdisk fdimage fdimage144 fdimage288 isoimage bzlilo install PHONY += bzdisk fdimage fdimage144 fdimage288 hdimage isoimage install
# This requires write access to /dev/fd0 # This requires write access to /dev/fd0
bzdisk: $(obj)/bzImage $(obj)/mtools.conf # All images require syslinux to be installed; hdimage also requires
# EDK2/OVMF if the kernel is compiled with the EFI stub.
bzdisk: $(imgdeps)
$(call cmd,genimage,bzdisk,/dev/fd0) $(call cmd,genimage,bzdisk,/dev/fd0)
# These require being root or having syslinux 2.02 or higher installed fdimage fdimage144: $(imgdeps)
fdimage fdimage144: $(obj)/bzImage $(obj)/mtools.conf
$(call cmd,genimage,fdimage144,$(obj)/fdimage) $(call cmd,genimage,fdimage144,$(obj)/fdimage)
@$(kecho) 'Kernel: $(obj)/fdimage is ready' @$(kecho) 'Kernel: $(obj)/fdimage is ready'
fdimage288: $(obj)/bzImage $(obj)/mtools.conf fdimage288: $(imgdeps)
$(call cmd,genimage,fdimage288,$(obj)/fdimage) $(call cmd,genimage,fdimage288,$(obj)/fdimage)
@$(kecho) 'Kernel: $(obj)/fdimage is ready' @$(kecho) 'Kernel: $(obj)/fdimage is ready'
isoimage: $(obj)/bzImage hdimage: $(imgdeps)
$(call cmd,genimage,hdimage,$(obj)/hdimage)
@$(kecho) 'Kernel: $(obj)/hdimage is ready'
isoimage: $(imgdeps)
$(call cmd,genimage,isoimage,$(obj)/image.iso) $(call cmd,genimage,isoimage,$(obj)/image.iso)
@$(kecho) 'Kernel: $(obj)/image.iso is ready' @$(kecho) 'Kernel: $(obj)/image.iso is ready'
bzlilo:
if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
cat $(obj)/bzImage > $(INSTALL_PATH)/vmlinuz
cp System.map $(INSTALL_PATH)/
if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
install: install:
sh $(srctree)/$(src)/install.sh $(KERNELRELEASE) $(obj)/bzImage \ $(CONFIG_SHELL) $(srctree)/$(src)/install.sh \
$(KERNELRELEASE) $(obj)/bzImage \
System.map "$(INSTALL_PATH)" System.map "$(INSTALL_PATH)"
#!/bin/sh #!/bin/bash
# #
# This file is subject to the terms and conditions of the GNU General Public # This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive # License. See the file "COPYING" in the main directory of this archive
...@@ -8,15 +8,24 @@ ...@@ -8,15 +8,24 @@
# #
# Adapted from code in arch/x86/boot/Makefile by H. Peter Anvin and others # Adapted from code in arch/x86/boot/Makefile by H. Peter Anvin and others
# #
# "make fdimage/fdimage144/fdimage288/isoimage" script for x86 architecture # "make fdimage/fdimage144/fdimage288/hdimage/isoimage"
# script for x86 architecture
# #
# Arguments: # Arguments:
# $1 - fdimage format # $1 - fdimage format
# $2 - target image file # $2 - target image file
# $3 - kernel bzImage file # $3 - kernel bzImage file
# $4 - mtool configuration file # $4 - mtools configuration file
# $5 - kernel cmdline # $5 - kernel cmdline
# $6 - inird image file # $6+ - initrd image file(s)
#
# This script requires:
# bash
# syslinux
# mtools (for fdimage* and hdimage)
# edk2/OVMF (for hdimage)
#
# Otherwise try to stick to POSIX shell commands...
# #
# Use "make V=1" to debug this script # Use "make V=1" to debug this script
...@@ -26,105 +35,237 @@ case "${KBUILD_VERBOSE}" in ...@@ -26,105 +35,237 @@ case "${KBUILD_VERBOSE}" in
;; ;;
esac esac
verify () { # Exit the top-level shell with an error
if [ ! -f "$1" ]; then topshell=$$
echo "" 1>&2 trap 'exit 1' USR1
echo " *** Missing file: $1" 1>&2 die() {
echo "" 1>&2 echo "" 1>&2
exit 1 echo " *** $*" 1>&2
echo "" 1>&2
kill -USR1 $topshell
}
# Verify the existence and readability of a file
verify() {
if [ ! -f "$1" -o ! -r "$1" ]; then
die "Missing file: $1"
fi fi
} }
diskfmt="$1"
FIMAGE="$2"
FBZIMAGE="$3"
MTOOLSRC="$4"
KCMDLINE="$5"
shift 5 # Remaining arguments = initrd files
export MTOOLSRC
export MTOOLSRC=$4 # common options for dd
FIMAGE=$2 dd='dd iflag=fullblock'
FBZIMAGE=$3
KCMDLINE=$5
FDINITRD=$6
# Make sure the files actually exist # Make sure the files actually exist
verify "$FBZIMAGE" verify "$FBZIMAGE"
genbzdisk() { declare -a FDINITRDS
verify "$MTOOLSRC" irdpfx=' initrd='
mformat a: initrdopts_syslinux=''
syslinux $FIMAGE initrdopts_efi=''
echo "$KCMDLINE" | mcopy - a:syslinux.cfg for f in "$@"; do
if [ -f "$FDINITRD" ] ; then if [ -f "$f" -a -r "$f" ]; then
mcopy "$FDINITRD" a:initrd.img FDINITRDS=("${FDINITRDS[@]}" "$f")
fname="$(basename "$f")"
initrdopts_syslinux="${initrdopts_syslinux}${irdpfx}${fname}"
irdpfx=,
initrdopts_efi="${initrdopts_efi} initrd=${fname}"
fi fi
mcopy $FBZIMAGE a:linux done
# Read a $3-byte littleendian unsigned value at offset $2 from file $1
le() {
local n=0
local m=1
for b in $(od -A n -v -j $2 -N $3 -t u1 "$1"); do
n=$((n + b*m))
m=$((m * 256))
done
echo $n
} }
genfdimage144() { # Get the EFI architecture name such that boot{name}.efi is the default
verify "$MTOOLSRC" # boot file name. Returns false with no output if the file is not an
dd if=/dev/zero of=$FIMAGE bs=1024 count=1440 2> /dev/null # EFI image or otherwise unknown.
mformat v: efiarch() {
syslinux $FIMAGE [ -f "$1" ] || return
echo "$KCMDLINE" | mcopy - v:syslinux.cfg [ $(le "$1" 0 2) -eq 23117 ] || return # MZ magic
if [ -f "$FDINITRD" ] ; then peoffs=$(le "$1" 60 4) # PE header offset
mcopy "$FDINITRD" v:initrd.img [ $peoffs -ge 64 ] || return
fi [ $(le "$1" $peoffs 4) -eq 17744 ] || return # PE magic
mcopy $FBZIMAGE v:linux case $(le "$1" $((peoffs+4+20)) 2) in # PE type
267) ;; # PE32
523) ;; # PE32+
*) return 1 ;; # Invalid
esac
[ $(le "$1" $((peoffs+4+20+68)) 2) -eq 10 ] || return # EFI app
case $(le "$1" $((peoffs+4)) 2) in # Machine type
332) echo i386 ;;
450) echo arm ;;
512) echo ia64 ;;
20530) echo riscv32 ;;
20580) echo riscv64 ;;
20776) echo riscv128 ;;
34404) echo x64 ;;
43620) echo aa64 ;;
esac
} }
genfdimage288() { # Get the combined sizes in bytes of the files given, counting sparse
verify "$MTOOLSRC" # files as full length, and padding each file to a 4K block size
dd if=/dev/zero of=$FIMAGE bs=1024 count=2880 2> /dev/null filesizes() {
mformat w: local t=0
syslinux $FIMAGE local s
echo "$KCMDLINE" | mcopy - W:syslinux.cfg for s in $(ls -lnL "$@" 2>/dev/null | awk '/^-/{ print $5; }'); do
if [ -f "$FDINITRD" ] ; then t=$((t + ((s+4095)/4096)*4096))
mcopy "$FDINITRD" w:initrd.img done
fi echo $t
mcopy $FBZIMAGE w:linux
} }
geniso() { # Expand directory names which should be in /usr/share into a list
tmp_dir=`dirname $FIMAGE`/isoimage # of possible alternatives
rm -rf $tmp_dir sharedirs() {
mkdir $tmp_dir local dir file
for i in lib lib64 share ; do for dir in /usr/share /usr/lib64 /usr/lib; do
for j in syslinux ISOLINUX ; do for file; do
if [ -f /usr/$i/$j/isolinux.bin ] ; then echo "$dir/$file"
isolinux=/usr/$i/$j/isolinux.bin echo "$dir/${file^^}"
fi
done done
for j in syslinux syslinux/modules/bios ; do done
if [ -f /usr/$i/$j/ldlinux.c32 ]; then }
ldlinux=/usr/$i/$j/ldlinux.c32 efidirs() {
fi local dir file
for dir in /usr/share /boot /usr/lib64 /usr/lib; do
for file; do
echo "$dir/$file"
echo "$dir/${file^^}"
done done
if [ -n "$isolinux" -a -n "$ldlinux" ] ; then done
break }
findsyslinux() {
local f="$(find -L $(sharedirs syslinux isolinux) \
-name "$1" -readable -type f -print -quit 2>/dev/null)"
if [ ! -f "$f" ]; then
die "Need a $1 file, please install syslinux/isolinux."
fi
echo "$f"
return 0
}
findovmf() {
local arch="$1"
shift
local -a names=(-false)
local name f
for name; do
names=("${names[@]}" -or -iname "$name")
done
for f in $(find -L $(efidirs edk2 ovmf) \
\( "${names[@]}" \) -readable -type f \
-print 2>/dev/null); do
if [ "$(efiarch "$f")" = "$arch" ]; then
echo "$f"
return 0
fi fi
done done
if [ -z "$isolinux" ] ; then die "Need a $1 file for $arch, please install EDK2/OVMF."
echo 'Need an isolinux.bin file, please install syslinux/isolinux.' }
exit 1
do_mcopy() {
if [ ${#FDINITRDS[@]} -gt 0 ]; then
mcopy "${FDINITRDS[@]}" "$1"
fi
if [ -n "$efishell" ]; then
mmd "$1"EFI "$1"EFI/Boot
mcopy "$efishell" "$1"EFI/Boot/boot${kefiarch}.efi
fi fi
if [ -z "$ldlinux" ] ; then if [ -n "$kefiarch" ]; then
echo 'Need an ldlinux.c32 file, please install syslinux/isolinux.' echo linux "$KCMDLINE$initrdopts_efi" | \
exit 1 mcopy - "$1"startup.nsh
fi fi
cp $isolinux $tmp_dir echo default linux "$KCMDLINE$initrdopts_syslinux" | \
cp $ldlinux $tmp_dir mcopy - "$1"syslinux.cfg
cp $FBZIMAGE $tmp_dir/linux mcopy "$FBZIMAGE" "$1"linux
echo "$KCMDLINE" > $tmp_dir/isolinux.cfg }
if [ -f "$FDINITRD" ] ; then
cp "$FDINITRD" $tmp_dir/initrd.img genbzdisk() {
verify "$MTOOLSRC"
mformat -v 'LINUX_BOOT' a:
syslinux "$FIMAGE"
do_mcopy a:
}
genfdimage144() {
verify "$MTOOLSRC"
$dd if=/dev/zero of="$FIMAGE" bs=1024 count=1440 2>/dev/null
mformat -v 'LINUX_BOOT' v:
syslinux "$FIMAGE"
do_mcopy v:
}
genfdimage288() {
verify "$MTOOLSRC"
$dd if=/dev/zero of="$FIMAGE" bs=1024 count=2880 2>/dev/null
mformat -v 'LINUX_BOOT' w:
syslinux "$FIMAGE"
do_mcopy w:
}
genhdimage() {
verify "$MTOOLSRC"
mbr="$(findsyslinux mbr.bin)"
kefiarch="$(efiarch "$FBZIMAGE")"
if [ -n "$kefiarch" ]; then
# The efishell provides command line handling
efishell="$(findovmf $kefiarch shell.efi shell${kefiarch}.efi)"
ptype='-T 0xef' # EFI system partition, no GPT
fi fi
genisoimage -J -r -input-charset=utf-8 -quiet -o $FIMAGE \ sizes=$(filesizes "$FBZIMAGE" "${FDINITRDS[@]}" "$efishell")
-b isolinux.bin -c boot.cat -no-emul-boot -boot-load-size 4 \ # Allow 1% + 1 MiB for filesystem and partition table overhead,
-boot-info-table $tmp_dir # syslinux, and config files
isohybrid $FIMAGE 2>/dev/null || true megs=$(((sizes + sizes/100 + 2*1024*1024 - 1)/(1024*1024)))
rm -rf $tmp_dir $dd if=/dev/zero of="$FIMAGE" bs=$((1024*1024)) count=$megs 2>/dev/null
mpartition -I -c -s 32 -h 64 -t $megs $ptype -b 512 -a h:
$dd if="$mbr" of="$FIMAGE" bs=440 count=1 conv=notrunc 2>/dev/null
mformat -v 'LINUX_BOOT' -s 32 -h 64 -t $megs h:
syslinux --offset $((512*512)) "$FIMAGE"
do_mcopy h:
}
geniso() {
tmp_dir="$(dirname "$FIMAGE")/isoimage"
rm -rf "$tmp_dir"
mkdir "$tmp_dir"
isolinux=$(findsyslinux isolinux.bin)
ldlinux=$(findsyslinux ldlinux.c32)
cp "$isolinux" "$ldlinux" "$tmp_dir"
cp "$FBZIMAGE" "$tmp_dir"/linux
echo default linux "$KCMDLINE" > "$tmp_dir"/isolinux.cfg
cp "${FDINITRDS[@]}" "$tmp_dir"/
genisoimage -J -r -appid 'LINUX_BOOT' -input-charset=utf-8 \
-quiet -o "$FIMAGE" -b isolinux.bin \
-c boot.cat -no-emul-boot -boot-load-size 4 \
-boot-info-table "$tmp_dir"
isohybrid "$FIMAGE" 2>/dev/null || true
rm -rf "$tmp_dir"
} }
case $1 in rm -f "$FIMAGE"
case "$diskfmt" in
bzdisk) genbzdisk;; bzdisk) genbzdisk;;
fdimage144) genfdimage144;; fdimage144) genfdimage144;;
fdimage288) genfdimage288;; fdimage288) genfdimage288;;
hdimage) genhdimage;;
isoimage) geniso;; isoimage) geniso;;
*) echo 'Unknown image format'; exit 1; *) die "Unknown image format: $diskfmt";;
esac esac
...@@ -14,4 +14,7 @@ drive v: ...@@ -14,4 +14,7 @@ drive v:
drive w: drive w:
file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter
# Hard disk
drive h:
file="@OBJ@/hdimage" partition=1 mformat_only
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment