1f279b49fSH. Peter Anvin (Intel)#!/bin/bash 24366d57aSChangbin Du# 34366d57aSChangbin Du# This file is subject to the terms and conditions of the GNU General Public 44366d57aSChangbin Du# License. See the file "COPYING" in the main directory of this archive 54366d57aSChangbin Du# for more details. 64366d57aSChangbin Du# 74366d57aSChangbin Du# Copyright (C) 2017 by Changbin Du <changbin.du@intel.com> 84366d57aSChangbin Du# 94366d57aSChangbin Du# Adapted from code in arch/x86/boot/Makefile by H. Peter Anvin and others 104366d57aSChangbin Du# 11f279b49fSH. Peter Anvin (Intel)# "make fdimage/fdimage144/fdimage288/hdimage/isoimage" 12f279b49fSH. Peter Anvin (Intel)# script for x86 architecture 134366d57aSChangbin Du# 144366d57aSChangbin Du# Arguments: 154366d57aSChangbin Du# $1 - fdimage format 164366d57aSChangbin Du# $2 - target image file 174366d57aSChangbin Du# $3 - kernel bzImage file 18f279b49fSH. Peter Anvin (Intel)# $4 - mtools configuration file 194366d57aSChangbin Du# $5 - kernel cmdline 20f279b49fSH. Peter Anvin (Intel)# $6+ - initrd image file(s) 21f279b49fSH. Peter Anvin (Intel)# 22f279b49fSH. Peter Anvin (Intel)# This script requires: 23f279b49fSH. Peter Anvin (Intel)# bash 24f279b49fSH. Peter Anvin (Intel)# syslinux 25f279b49fSH. Peter Anvin (Intel)# mtools (for fdimage* and hdimage) 26f279b49fSH. Peter Anvin (Intel)# edk2/OVMF (for hdimage) 27f279b49fSH. Peter Anvin (Intel)# 28f279b49fSH. Peter Anvin (Intel)# Otherwise try to stick to POSIX shell commands... 294366d57aSChangbin Du# 304366d57aSChangbin Du 317980f029SChangbin Du# Use "make V=1" to debug this script 327980f029SChangbin Ducase "${KBUILD_VERBOSE}" in 337980f029SChangbin Du*1*) 347980f029SChangbin Du set -x 357980f029SChangbin Du ;; 367980f029SChangbin Duesac 377980f029SChangbin Du 38f279b49fSH. Peter Anvin (Intel)# Exit the top-level shell with an error 39f279b49fSH. Peter Anvin (Intel)topshell=$$ 40f279b49fSH. Peter Anvin (Intel)trap 'exit 1' USR1 41f279b49fSH. Peter Anvin (Intel)die() { 42f279b49fSH. Peter Anvin (Intel) echo "" 1>&2 43f279b49fSH. Peter Anvin (Intel) echo " *** $*" 1>&2 44f279b49fSH. Peter Anvin (Intel) echo "" 1>&2 45f279b49fSH. Peter Anvin (Intel) kill -USR1 $topshell 46f279b49fSH. Peter Anvin (Intel)} 47f279b49fSH. Peter Anvin (Intel) 48f279b49fSH. Peter Anvin (Intel)# Verify the existence and readability of a file 494366d57aSChangbin Duverify() { 50f279b49fSH. Peter Anvin (Intel) if [ ! -f "$1" -o ! -r "$1" ]; then 51f279b49fSH. Peter Anvin (Intel) die "Missing file: $1" 524366d57aSChangbin Du fi 534366d57aSChangbin Du} 544366d57aSChangbin Du 55f279b49fSH. Peter Anvin (Intel)diskfmt="$1" 56f279b49fSH. Peter Anvin (Intel)FIMAGE="$2" 57f279b49fSH. Peter Anvin (Intel)FBZIMAGE="$3" 58f279b49fSH. Peter Anvin (Intel)MTOOLSRC="$4" 59f279b49fSH. Peter Anvin (Intel)KCMDLINE="$5" 60f279b49fSH. Peter Anvin (Intel)shift 5 # Remaining arguments = initrd files 614366d57aSChangbin Du 62f279b49fSH. Peter Anvin (Intel)export MTOOLSRC 63f279b49fSH. Peter Anvin (Intel) 64f279b49fSH. Peter Anvin (Intel)# common options for dd 65f279b49fSH. Peter Anvin (Intel)dd='dd iflag=fullblock' 664366d57aSChangbin Du 674366d57aSChangbin Du# Make sure the files actually exist 684366d57aSChangbin Duverify "$FBZIMAGE" 694366d57aSChangbin Du 70f279b49fSH. Peter Anvin (Intel)declare -a FDINITRDS 71f279b49fSH. Peter Anvin (Intel)irdpfx=' initrd=' 72f279b49fSH. Peter Anvin (Intel)initrdopts_syslinux='' 73f279b49fSH. Peter Anvin (Intel)initrdopts_efi='' 74f279b49fSH. Peter Anvin (Intel)for f in "$@"; do 75f279b49fSH. Peter Anvin (Intel) if [ -f "$f" -a -r "$f" ]; then 76f279b49fSH. Peter Anvin (Intel) FDINITRDS=("${FDINITRDS[@]}" "$f") 77f279b49fSH. Peter Anvin (Intel) fname="$(basename "$f")" 78f279b49fSH. Peter Anvin (Intel) initrdopts_syslinux="${initrdopts_syslinux}${irdpfx}${fname}" 79f279b49fSH. Peter Anvin (Intel) irdpfx=, 80f279b49fSH. Peter Anvin (Intel) initrdopts_efi="${initrdopts_efi} initrd=${fname}" 81f279b49fSH. Peter Anvin (Intel) fi 82f279b49fSH. Peter Anvin (Intel)done 83f279b49fSH. Peter Anvin (Intel) 84f279b49fSH. Peter Anvin (Intel)# Read a $3-byte littleendian unsigned value at offset $2 from file $1 85f279b49fSH. Peter Anvin (Intel)le() { 86f279b49fSH. Peter Anvin (Intel) local n=0 87f279b49fSH. Peter Anvin (Intel) local m=1 88f279b49fSH. Peter Anvin (Intel) for b in $(od -A n -v -j $2 -N $3 -t u1 "$1"); do 89f279b49fSH. Peter Anvin (Intel) n=$((n + b*m)) 90f279b49fSH. Peter Anvin (Intel) m=$((m * 256)) 91f279b49fSH. Peter Anvin (Intel) done 92f279b49fSH. Peter Anvin (Intel) echo $n 93f279b49fSH. Peter Anvin (Intel)} 94f279b49fSH. Peter Anvin (Intel) 95f279b49fSH. Peter Anvin (Intel)# Get the EFI architecture name such that boot{name}.efi is the default 96f279b49fSH. Peter Anvin (Intel)# boot file name. Returns false with no output if the file is not an 97f279b49fSH. Peter Anvin (Intel)# EFI image or otherwise unknown. 98f279b49fSH. Peter Anvin (Intel)efiarch() { 99f279b49fSH. Peter Anvin (Intel) [ -f "$1" ] || return 100f279b49fSH. Peter Anvin (Intel) [ $(le "$1" 0 2) -eq 23117 ] || return # MZ magic 101f279b49fSH. Peter Anvin (Intel) peoffs=$(le "$1" 60 4) # PE header offset 102f279b49fSH. Peter Anvin (Intel) [ $peoffs -ge 64 ] || return 103f279b49fSH. Peter Anvin (Intel) [ $(le "$1" $peoffs 4) -eq 17744 ] || return # PE magic 104f279b49fSH. Peter Anvin (Intel) case $(le "$1" $((peoffs+4+20)) 2) in # PE type 105f279b49fSH. Peter Anvin (Intel) 267) ;; # PE32 106f279b49fSH. Peter Anvin (Intel) 523) ;; # PE32+ 107f279b49fSH. Peter Anvin (Intel) *) return 1 ;; # Invalid 108f279b49fSH. Peter Anvin (Intel) esac 109f279b49fSH. Peter Anvin (Intel) [ $(le "$1" $((peoffs+4+20+68)) 2) -eq 10 ] || return # EFI app 110f279b49fSH. Peter Anvin (Intel) case $(le "$1" $((peoffs+4)) 2) in # Machine type 111f279b49fSH. Peter Anvin (Intel) 332) echo i386 ;; 112f279b49fSH. Peter Anvin (Intel) 450) echo arm ;; 113f279b49fSH. Peter Anvin (Intel) 512) echo ia64 ;; 114f279b49fSH. Peter Anvin (Intel) 20530) echo riscv32 ;; 115f279b49fSH. Peter Anvin (Intel) 20580) echo riscv64 ;; 116f279b49fSH. Peter Anvin (Intel) 20776) echo riscv128 ;; 117f279b49fSH. Peter Anvin (Intel) 34404) echo x64 ;; 118f279b49fSH. Peter Anvin (Intel) 43620) echo aa64 ;; 119f279b49fSH. Peter Anvin (Intel) esac 120f279b49fSH. Peter Anvin (Intel)} 121f279b49fSH. Peter Anvin (Intel) 122f279b49fSH. Peter Anvin (Intel)# Get the combined sizes in bytes of the files given, counting sparse 123*067595d7SH. Peter Anvin (Intel)# files as full length, and padding each file to cluster size 124*067595d7SH. Peter Anvin (Intel)cluster=16384 125f279b49fSH. Peter Anvin (Intel)filesizes() { 126f279b49fSH. Peter Anvin (Intel) local t=0 127f279b49fSH. Peter Anvin (Intel) local s 128f279b49fSH. Peter Anvin (Intel) for s in $(ls -lnL "$@" 2>/dev/null | awk '/^-/{ print $5; }'); do 129*067595d7SH. Peter Anvin (Intel) t=$((t + ((s+cluster-1)/cluster)*cluster)) 130f279b49fSH. Peter Anvin (Intel) done 131f279b49fSH. Peter Anvin (Intel) echo $t 132f279b49fSH. Peter Anvin (Intel)} 133f279b49fSH. Peter Anvin (Intel) 134f279b49fSH. Peter Anvin (Intel)# Expand directory names which should be in /usr/share into a list 135f279b49fSH. Peter Anvin (Intel)# of possible alternatives 136f279b49fSH. Peter Anvin (Intel)sharedirs() { 137f279b49fSH. Peter Anvin (Intel) local dir file 138f279b49fSH. Peter Anvin (Intel) for dir in /usr/share /usr/lib64 /usr/lib; do 139f279b49fSH. Peter Anvin (Intel) for file; do 140f279b49fSH. Peter Anvin (Intel) echo "$dir/$file" 141f279b49fSH. Peter Anvin (Intel) echo "$dir/${file^^}" 142f279b49fSH. Peter Anvin (Intel) done 143f279b49fSH. Peter Anvin (Intel) done 144f279b49fSH. Peter Anvin (Intel)} 145f279b49fSH. Peter Anvin (Intel)efidirs() { 146f279b49fSH. Peter Anvin (Intel) local dir file 147f279b49fSH. Peter Anvin (Intel) for dir in /usr/share /boot /usr/lib64 /usr/lib; do 148f279b49fSH. Peter Anvin (Intel) for file; do 149f279b49fSH. Peter Anvin (Intel) echo "$dir/$file" 150f279b49fSH. Peter Anvin (Intel) echo "$dir/${file^^}" 151f279b49fSH. Peter Anvin (Intel) done 152f279b49fSH. Peter Anvin (Intel) done 153f279b49fSH. Peter Anvin (Intel)} 154f279b49fSH. Peter Anvin (Intel) 155f279b49fSH. Peter Anvin (Intel)findsyslinux() { 156f279b49fSH. Peter Anvin (Intel) local f="$(find -L $(sharedirs syslinux isolinux) \ 157f279b49fSH. Peter Anvin (Intel) -name "$1" -readable -type f -print -quit 2>/dev/null)" 158f279b49fSH. Peter Anvin (Intel) if [ ! -f "$f" ]; then 159f279b49fSH. Peter Anvin (Intel) die "Need a $1 file, please install syslinux/isolinux." 160f279b49fSH. Peter Anvin (Intel) fi 161f279b49fSH. Peter Anvin (Intel) echo "$f" 162f279b49fSH. Peter Anvin (Intel) return 0 163f279b49fSH. Peter Anvin (Intel)} 164f279b49fSH. Peter Anvin (Intel) 165f279b49fSH. Peter Anvin (Intel)findovmf() { 166f279b49fSH. Peter Anvin (Intel) local arch="$1" 167f279b49fSH. Peter Anvin (Intel) shift 168f279b49fSH. Peter Anvin (Intel) local -a names=(-false) 169f279b49fSH. Peter Anvin (Intel) local name f 170f279b49fSH. Peter Anvin (Intel) for name; do 171f279b49fSH. Peter Anvin (Intel) names=("${names[@]}" -or -iname "$name") 172f279b49fSH. Peter Anvin (Intel) done 173f279b49fSH. Peter Anvin (Intel) for f in $(find -L $(efidirs edk2 ovmf) \ 174f279b49fSH. Peter Anvin (Intel) \( "${names[@]}" \) -readable -type f \ 175f279b49fSH. Peter Anvin (Intel) -print 2>/dev/null); do 176f279b49fSH. Peter Anvin (Intel) if [ "$(efiarch "$f")" = "$arch" ]; then 177f279b49fSH. Peter Anvin (Intel) echo "$f" 178f279b49fSH. Peter Anvin (Intel) return 0 179f279b49fSH. Peter Anvin (Intel) fi 180f279b49fSH. Peter Anvin (Intel) done 181f279b49fSH. Peter Anvin (Intel) die "Need a $1 file for $arch, please install EDK2/OVMF." 182f279b49fSH. Peter Anvin (Intel)} 183f279b49fSH. Peter Anvin (Intel) 184f279b49fSH. Peter Anvin (Intel)do_mcopy() { 185f279b49fSH. Peter Anvin (Intel) if [ ${#FDINITRDS[@]} -gt 0 ]; then 186f279b49fSH. Peter Anvin (Intel) mcopy "${FDINITRDS[@]}" "$1" 187f279b49fSH. Peter Anvin (Intel) fi 188f279b49fSH. Peter Anvin (Intel) if [ -n "$efishell" ]; then 189f279b49fSH. Peter Anvin (Intel) mmd "$1"EFI "$1"EFI/Boot 190f279b49fSH. Peter Anvin (Intel) mcopy "$efishell" "$1"EFI/Boot/boot${kefiarch}.efi 191f279b49fSH. Peter Anvin (Intel) fi 192f279b49fSH. Peter Anvin (Intel) if [ -n "$kefiarch" ]; then 193f279b49fSH. Peter Anvin (Intel) echo linux "$KCMDLINE$initrdopts_efi" | \ 194f279b49fSH. Peter Anvin (Intel) mcopy - "$1"startup.nsh 195f279b49fSH. Peter Anvin (Intel) fi 196f279b49fSH. Peter Anvin (Intel) echo default linux "$KCMDLINE$initrdopts_syslinux" | \ 197f279b49fSH. Peter Anvin (Intel) mcopy - "$1"syslinux.cfg 198f279b49fSH. Peter Anvin (Intel) mcopy "$FBZIMAGE" "$1"linux 199f279b49fSH. Peter Anvin (Intel)} 200f279b49fSH. Peter Anvin (Intel) 2014366d57aSChangbin Dugenbzdisk() { 202f79ce87fSChangbin Du verify "$MTOOLSRC" 203f279b49fSH. Peter Anvin (Intel) mformat -v 'LINUX_BOOT' a: 204f279b49fSH. Peter Anvin (Intel) syslinux "$FIMAGE" 205f279b49fSH. Peter Anvin (Intel) do_mcopy a: 2064366d57aSChangbin Du} 2074366d57aSChangbin Du 2084366d57aSChangbin Dugenfdimage144() { 209f79ce87fSChangbin Du verify "$MTOOLSRC" 210f279b49fSH. Peter Anvin (Intel) $dd if=/dev/zero of="$FIMAGE" bs=1024 count=1440 2>/dev/null 211f279b49fSH. Peter Anvin (Intel) mformat -v 'LINUX_BOOT' v: 212f279b49fSH. Peter Anvin (Intel) syslinux "$FIMAGE" 213f279b49fSH. Peter Anvin (Intel) do_mcopy v: 2144366d57aSChangbin Du} 2154366d57aSChangbin Du 2164366d57aSChangbin Dugenfdimage288() { 217f79ce87fSChangbin Du verify "$MTOOLSRC" 218f279b49fSH. Peter Anvin (Intel) $dd if=/dev/zero of="$FIMAGE" bs=1024 count=2880 2>/dev/null 219f279b49fSH. Peter Anvin (Intel) mformat -v 'LINUX_BOOT' w: 220f279b49fSH. Peter Anvin (Intel) syslinux "$FIMAGE" 221f279b49fSH. Peter Anvin (Intel) do_mcopy w: 222f279b49fSH. Peter Anvin (Intel)} 223f279b49fSH. Peter Anvin (Intel) 224f279b49fSH. Peter Anvin (Intel)genhdimage() { 225f279b49fSH. Peter Anvin (Intel) verify "$MTOOLSRC" 226f279b49fSH. Peter Anvin (Intel) mbr="$(findsyslinux mbr.bin)" 227f279b49fSH. Peter Anvin (Intel) kefiarch="$(efiarch "$FBZIMAGE")" 228f279b49fSH. Peter Anvin (Intel) if [ -n "$kefiarch" ]; then 229f279b49fSH. Peter Anvin (Intel) # The efishell provides command line handling 230f279b49fSH. Peter Anvin (Intel) efishell="$(findovmf $kefiarch shell.efi shell${kefiarch}.efi)" 231f279b49fSH. Peter Anvin (Intel) ptype='-T 0xef' # EFI system partition, no GPT 2324366d57aSChangbin Du fi 233f279b49fSH. Peter Anvin (Intel) sizes=$(filesizes "$FBZIMAGE" "${FDINITRDS[@]}" "$efishell") 234*067595d7SH. Peter Anvin (Intel) # Allow 1% + 2 MiB for filesystem and partition table overhead, 235*067595d7SH. Peter Anvin (Intel) # syslinux, and config files; this is probably excessive... 236f279b49fSH. Peter Anvin (Intel) megs=$(((sizes + sizes/100 + 2*1024*1024 - 1)/(1024*1024))) 237f279b49fSH. Peter Anvin (Intel) $dd if=/dev/zero of="$FIMAGE" bs=$((1024*1024)) count=$megs 2>/dev/null 238*067595d7SH. Peter Anvin (Intel) mpartition -I -c -s 32 -h 64 $ptype -b 64 -a p: 239f279b49fSH. Peter Anvin (Intel) $dd if="$mbr" of="$FIMAGE" bs=440 count=1 conv=notrunc 2>/dev/null 240*067595d7SH. Peter Anvin (Intel) mformat -v 'LINUX_BOOT' -s 32 -h 64 -c $((cluster/512)) -t $megs h: 241*067595d7SH. Peter Anvin (Intel) syslinux --offset $((64*512)) "$FIMAGE" 242f279b49fSH. Peter Anvin (Intel) do_mcopy h: 2434366d57aSChangbin Du} 2444366d57aSChangbin Du 2455f0e3fe6SMatthew Wilcoxgeniso() { 246f279b49fSH. Peter Anvin (Intel) tmp_dir="$(dirname "$FIMAGE")/isoimage" 247f279b49fSH. Peter Anvin (Intel) rm -rf "$tmp_dir" 248f279b49fSH. Peter Anvin (Intel) mkdir "$tmp_dir" 249f279b49fSH. Peter Anvin (Intel) isolinux=$(findsyslinux isolinux.bin) 250f279b49fSH. Peter Anvin (Intel) ldlinux=$(findsyslinux ldlinux.c32) 251f279b49fSH. Peter Anvin (Intel) cp "$isolinux" "$ldlinux" "$tmp_dir" 252f279b49fSH. Peter Anvin (Intel) cp "$FBZIMAGE" "$tmp_dir"/linux 253f279b49fSH. Peter Anvin (Intel) echo default linux "$KCMDLINE" > "$tmp_dir"/isolinux.cfg 254f279b49fSH. Peter Anvin (Intel) cp "${FDINITRDS[@]}" "$tmp_dir"/ 255f279b49fSH. Peter Anvin (Intel) genisoimage -J -r -appid 'LINUX_BOOT' -input-charset=utf-8 \ 256f279b49fSH. Peter Anvin (Intel) -quiet -o "$FIMAGE" -b isolinux.bin \ 257f279b49fSH. Peter Anvin (Intel) -c boot.cat -no-emul-boot -boot-load-size 4 \ 258f279b49fSH. Peter Anvin (Intel) -boot-info-table "$tmp_dir" 259f279b49fSH. Peter Anvin (Intel) isohybrid "$FIMAGE" 2>/dev/null || true 260f279b49fSH. Peter Anvin (Intel) rm -rf "$tmp_dir" 2614366d57aSChangbin Du} 2624366d57aSChangbin Du 263f279b49fSH. Peter Anvin (Intel)rm -f "$FIMAGE" 264f279b49fSH. Peter Anvin (Intel) 265f279b49fSH. Peter Anvin (Intel)case "$diskfmt" in 2664366d57aSChangbin Du bzdisk) genbzdisk;; 2674366d57aSChangbin Du fdimage144) genfdimage144;; 2684366d57aSChangbin Du fdimage288) genfdimage288;; 269f279b49fSH. Peter Anvin (Intel) hdimage) genhdimage;; 2705f0e3fe6SMatthew Wilcox isoimage) geniso;; 271f279b49fSH. Peter Anvin (Intel) *) die "Unknown image format: $diskfmt";; 2724366d57aSChangbin Duesac 273