123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- #!/bin/bash
- #
- # 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
- # for more details.
- #
- # Copyright (C) 2017 by Changbin Du <[email protected]>
- #
- # Adapted from code in arch/x86/boot/Makefile by H. Peter Anvin and others
- #
- # "make fdimage/fdimage144/fdimage288/hdimage/isoimage"
- # script for x86 architecture
- #
- # Arguments:
- # $1 - fdimage format
- # $2 - target image file
- # $3 - kernel bzImage file
- # $4 - mtools configuration file
- # $5 - kernel cmdline
- # $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
- case "${KBUILD_VERBOSE}" in
- *1*)
- set -x
- ;;
- esac
- # Exit the top-level shell with an error
- topshell=$$
- trap 'exit 1' USR1
- die() {
- echo "" 1>&2
- 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
- }
- diskfmt="$1"
- FIMAGE="$2"
- FBZIMAGE="$3"
- MTOOLSRC="$4"
- KCMDLINE="$5"
- shift 5 # Remaining arguments = initrd files
- export MTOOLSRC
- # common options for dd
- dd='dd iflag=fullblock'
- # Make sure the files actually exist
- verify "$FBZIMAGE"
- declare -a FDINITRDS
- irdpfx=' initrd='
- initrdopts_syslinux=''
- initrdopts_efi=''
- for f in "$@"; do
- if [ -f "$f" -a -r "$f" ]; then
- FDINITRDS=("${FDINITRDS[@]}" "$f")
- fname="$(basename "$f")"
- initrdopts_syslinux="${initrdopts_syslinux}${irdpfx}${fname}"
- irdpfx=,
- initrdopts_efi="${initrdopts_efi} initrd=${fname}"
- fi
- 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
- }
- # Get the EFI architecture name such that boot{name}.efi is the default
- # boot file name. Returns false with no output if the file is not an
- # EFI image or otherwise unknown.
- efiarch() {
- [ -f "$1" ] || return
- [ $(le "$1" 0 2) -eq 23117 ] || return # MZ magic
- peoffs=$(le "$1" 60 4) # PE header offset
- [ $peoffs -ge 64 ] || return
- [ $(le "$1" $peoffs 4) -eq 17744 ] || return # PE magic
- 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
- }
- # Get the combined sizes in bytes of the files given, counting sparse
- # files as full length, and padding each file to cluster size
- cluster=16384
- filesizes() {
- local t=0
- local s
- for s in $(ls -lnL "$@" 2>/dev/null | awk '/^-/{ print $5; }'); do
- t=$((t + ((s+cluster-1)/cluster)*cluster))
- done
- echo $t
- }
- # Expand directory names which should be in /usr/share into a list
- # of possible alternatives
- sharedirs() {
- local dir file
- for dir in /usr/share /usr/lib64 /usr/lib; do
- for file; do
- echo "$dir/$file"
- echo "$dir/${file^^}"
- done
- done
- }
- efidirs() {
- 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
- }
- 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
- done
- die "Need a $1 file for $arch, please install EDK2/OVMF."
- }
- 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
- if [ -n "$kefiarch" ]; then
- echo linux "$KCMDLINE$initrdopts_efi" | \
- mcopy - "$1"startup.nsh
- fi
- echo default linux "$KCMDLINE$initrdopts_syslinux" | \
- mcopy - "$1"syslinux.cfg
- mcopy "$FBZIMAGE" "$1"linux
- }
- 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
- sizes=$(filesizes "$FBZIMAGE" "${FDINITRDS[@]}" "$efishell")
- # Allow 1% + 2 MiB for filesystem and partition table overhead,
- # syslinux, and config files; this is probably excessive...
- megs=$(((sizes + sizes/100 + 2*1024*1024 - 1)/(1024*1024)))
- $dd if=/dev/zero of="$FIMAGE" bs=$((1024*1024)) count=$megs 2>/dev/null
- mpartition -I -c -s 32 -h 64 $ptype -b 64 -a p:
- $dd if="$mbr" of="$FIMAGE" bs=440 count=1 conv=notrunc 2>/dev/null
- mformat -v 'LINUX_BOOT' -s 32 -h 64 -c $((cluster/512)) -t $megs h:
- syslinux --offset $((64*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"
- }
- rm -f "$FIMAGE"
- case "$diskfmt" in
- bzdisk) genbzdisk;;
- fdimage144) genfdimage144;;
- fdimage288) genfdimage288;;
- hdimage) genhdimage;;
- isoimage) geniso;;
- *) die "Unknown image format: $diskfmt";;
- esac
|