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