forked from aguslr/multibootusb
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmakeUSB.sh
More file actions
executable file
·416 lines (373 loc) · 9.47 KB
/
makeUSB.sh
File metadata and controls
executable file
·416 lines (373 loc) · 9.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
#!/bin/sh
# Description: Script to prepare multiboot USB drive
# Exit if any variable is not set
set -o nounset
# show line number when execute by bash -x makeUSB.sh
export PS4=' +\t $BASH_SOURCE:$LINENO: ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
# Exit if any return code is not zero
set -e
# Defaults
scriptname=$(basename "$0")
hybrid=0
eficonfig=0
interactive=0
data_part=2
data_fmt="vfat"
efi_mnt="/mnt/MBU-EFI/"
data_mnt="/mnt/MBU-DATA/"
log_file="/dev/null"
# Show usage
showUsage() {
cat <<- EOF
Script to prepare multiboot USB drive
Usage: $scriptname [options] device [fs-type]
device Device to modify (e.g. /dev/sdb)
fs-type Filesystem type for the data partition [ext3|ext4|vfat|ntfs]
-b, --hybrid Create a hybrid MBR
-e, --efi Enable EFI compatibility
-i, --interactive Launch gdisk to create a hybrid MBR
-l, --log Save debug information to log
-h, --help Display this message
EOF
}
# Clean up when exiting
cleanUp() {
# Unmount everything
umount --force "$efi_mnt" 2>/dev/null || true
umount --force "$data_mnt" 2>/dev/null || true
# Delete mountpoints
[ -d "$efi_mnt" ] && rmdir "$efi_mnt"
[ -d "$data_mnt" ] && rmdir "$data_mnt"
# Exit
exit "${1-0}"
}
# Trap kill signals (SIGHUP, SIGINT, SIGTERM) to do some cleanup and exit
trap 'cleanUp' 1 2 15
# Check arguments
[ $# -eq 0 ] && showUsage && exit 0
while [ "$#" -gt 0 ]; do
case "$1" in
# Show help
-h|--help)
showUsage
exit 0
;;
-b|--hybrid)
hybrid=1
shift
;;
-e|--efi)
eficonfig=1
data_part=3
shift
;;
-i|--interactive)
interactive=1
shift
;;
-l|--log)
log_file="${scriptname%.*}.log"
printf '' "$log_file"
shift
;;
/dev/*)
if [ -b "$1" ]; then
usb_dev="$1"
else
printf '%s: %s is not a valid device.\n' "$scriptname" "$1" >&2
cleanUp 1
fi
shift
;;
*)
data_fmt="$1"
shift
;;
esac
done
# Check for root
if [ "$(id -u)" -ne 0 ]; then
printf '%s: This script must be run as root.\n' "$scriptname" >&2
cleanUp 2
fi
# Check for required arguments
if [ ! "$usb_dev" ]; then
printf '%s: No device was provided.\n' "$scriptname" >&2
showUsage
cleanUp 1
fi
# Check for required binaries
command -v sgdisk >/dev/null || cleanUp 3
command -v dd >/dev/null || cleanUp 3
command -v mkfs.${data_fmt} >/dev/null || cleanUp 3
command -v mount >/dev/null || cleanUp 3
command -v wget >/dev/null || cleanUp 3
command -v gunzip >/dev/null || cleanUp 3
command -v tar >/dev/null || cleanUp 3
# Check for GRUB installation binary
grub_cmd=$(command -v grub-install) \
|| grub_cmd=$(command -v grub2-install) \
|| cleanUp 3
# Unmount device
umount --force ${usb_dev}* 2>/dev/null || true
# Confirm the device
read -r -p "Are you sure you want to use $usb_dev? [y/N] " answer1
case "$answer1" in
[yY][eE][sS]|[yY])
read -r -p "THIS WILL DELETE ALL DATA ON THE DEVICE. Are you sure? [y/N] " answer2
case $answer2 in
[yY][eE][sS]|[yY])
true
;;
*)
cleanUp 3
;;
esac
;;
*)
cleanUp 3
;;
esac
# Remove partitions
printf 'Removing partitions from %s... ' "$usb_dev"
if sgdisk --zap-all "$usb_dev" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
fi
# Create GUID Partition Table
printf 'Creating GUID Partition Table on %s... ' "$usb_dev"
if sgdisk --mbrtogpt "$usb_dev" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Create BIOS boot partition (1M)
printf 'Creating BIOS boot partition on %s... ' "$usb_dev"
if sgdisk --new 1::+1M --typecode 1:ef02 \
--change-name 1:"BIOS boot partition" "$usb_dev" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
if [ "$eficonfig" -eq 1 ]; then
# Create EFI System partition (50M)
printf 'Creating EFI System partition on %s... ' "$usb_dev"
if sgdisk --new 2::+50M --typecode 2:ef00 --change-name 2:"EFI System" \
"$usb_dev" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
fi
# Create data partition
printf 'Creating data partition on %s... ' "$usb_dev"
case "$data_fmt" in
ext2|ext3|ext4)
type_code="8300"
part_name="Linux filesystem"
;;
msdos|fat|vfat|ntfs)
type_code="0700"
part_name="Microsoft basic data"
;;
*)
printf '%s: %s is an invalid filesystem type.\n' "$scriptname" "$data_fmt" >&2
showUsage
cleanUp 1
;;
esac
if sgdisk --new ${data_part}::: --typecode ${data_part}:"$type_code" \
--change-name ${data_part}:"$part_name" "$usb_dev" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Unmount device
umount --force ${usb_dev}* 2>/dev/null || true
# Create hybrid MBR
if [ "$hybrid" -eq 1 ]; then
if [ "$interactive" -eq 0 ]; then
printf 'Creating hybrid MBR on %s... ' "${usb_dev}"
if [ "$eficonfig" -eq 1 ]; then
if sgdisk --hybrid 1:2:3 "$usb_dev" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
else
if sgdisk --hybrid 1:2 "$usb_dev" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
fi
else
# Create hybrid MBR manually
# https://wiki.archlinux.org/index.php/Multiboot_USB_drive#Hybrid_UEFI_GPT_.2B_BIOS_GPT.2FMBR_boot
gdisk "$usb_dev"
fi
fi
# Set bootable flag for data partion
printf 'Setting bootable flag on %s... ' "${usb_dev}${data_part}"
if sgdisk --attributes ${data_part}:set:2 "$usb_dev" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Unmount device
umount --force ${usb_dev}* 2>/dev/null || true
# Format BIOS boot partition
printf 'Formatting BIOS boot partition on %s... ' "${usb_dev}1"
if dd if=/dev/zero of=${usb_dev}1 bs=1M count=1 >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
if [ "$eficonfig" -eq 1 ]; then
# Format EFI System partition
printf 'Formatting EFI System partition on %s... ' "${usb_dev}2"
if mkfs.vfat -v -F 32 "${usb_dev}2" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
fi
# Format data partition
printf 'Formatting data partition as %s on %s... ' \
"$data_fmt" "${usb_dev}${data_part}"
if [ "$data_fmt" = "ntfs" ]; then
# Use mkntfs quick format
mkfs_args="-t $data_fmt -f"
else
mkfs_args="-t $data_fmt"
fi
if mkfs $mkfs_args "${usb_dev}${data_part}" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Unmount device
umount --force ${usb_dev}* 2>/dev/null || true
if [ "$eficonfig" -eq 1 ]; then
# Mount EFI System partition
printf 'Mounting EFI System partition on %s... ' "$efi_mnt"
if mkdir -p "$efi_mnt" \
&& mount -v "${usb_dev}2" "$efi_mnt" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
fi
# Mount data partition
printf 'Mounting data partition on %s... ' "$data_mnt"
if mkdir -p "$data_mnt" \
&& mount -v "${usb_dev}${data_part}" "$data_mnt" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
if [ "$eficonfig" -eq 1 ]; then
# Install GRUB for EFI
printf 'Installing GRUB for EFI on %s... ' "$usb_dev"
if $grub_cmd --target=x86_64-efi --efi-directory=$efi_mnt \
--boot-directory=${data_mnt}boot --removable --recheck >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Unmount EFI System partition
printf 'Unmounting EFI System partition on %s... ' "$efi_mnt"
if umount -v $efi_mnt >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
fi
# Install GRUB for BIOS
printf 'Installing GRUB for BIOS on %s... ' "$usb_dev"
if $grub_cmd --force --target=i386-pc \
--boot-directory=${data_mnt}boot \
--recheck "$usb_dev" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Install fallback GRUB
printf 'Installing fallback GRUB on %s... ' "${usb_dev}${data_part}"
if $grub_cmd --force --target=i386-pc \
--boot-directory=${data_mnt}boot \
--recheck "${usb_dev}${data_part}" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
fi
# Create necessary directories
printf 'Creating directories on %s... ' "${data_mnt}boot"
if mkdir -p ${data_mnt}boot/bin ${data_mnt}boot/isos >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Detect GRUB directory name
if [ -d "${data_mnt}boot/grub" ]; then
grub_dir="${data_mnt}boot/grub/"
elif [ -d "${data_mnt}boot/grub2" ]; then
grub_dir="${data_mnt}boot/grub2/"
else
cleanUp 10
fi
# Copy files
printf 'Copying files to %s... ' "${data_mnt}boot"
if cp -rf ./grub.cfg ./grub.d ./multiboot.* "$grub_dir" >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Download memdisk
printf 'Downloading memdisk to %s... ' "${data_mnt}boot/grub"
if wget -qO - \
'https://www.kernel.org/pub/linux/utils/boot/syslinux/syslinux-6.03.tar.gz' \
| tar -xz -C "${data_mnt}boot/grub" --no-same-owner --strip-components 3 \
'syslinux-6.03/bios/memdisk/memdisk' 2>> "$log_file"; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Download Memtest86+
printf 'Downloading Memtest86+ to %s... ' "${data_mnt}boot/bin"
if wget -qO - 'http://www.memtest.org/download/5.01/memtest86+-5.01.bin.gz' \
| gunzip -c > "${data_mnt}boot/bin/memtest86+.bin" 2>> "$log_file"; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Unmount data partition
printf 'Unmounting data partition on %s... ' "$data_mnt"
if umount -v $data_mnt >> "$log_file" 2>&1; then
printf 'OK\n'
else
printf 'FAILED\n'
cleanUp 10
fi
# Clean up and exit
cleanUp