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