-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrefind-installer.sh
308 lines (265 loc) · 9.05 KB
/
refind-installer.sh
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
#!/bin/sh
[ "$BASH" ] && \
export PS4=' +\t $BASH_SOURCE:$LINENO: ${FUNCNAME[0]:+${FUNCNAME[0]}():}'
######## CUSTOM SETTINGS #############
# modules to preload for the standalone grub
grub_modules=""
# name of configfile for grub to expect in mbusb.d/$distro
# .ref is automatically added to avoid self-sourcing via *.cfg
grub_standalone_config="refind-helper.cfg"
# set the directory containing the iso's relative to the root of the USB device
# eg. /isos for /mnt/stick/isos/some.iso
# the default is multibootusb's setting /boot/isos
iso_dir="/boot/isos"
# change the location of the configfiles from multibootusb,
# relative to the root of the drive
# most of the time you can leave this unchanged
# Note, that this is relative to the /boot dir in the root of the device
mbusbd="/grub/mbusb.d"
### DON'T CHANGE STUFF BELOW THIS POINT ###
# Exit on errors and unbound variables
set -o nounset
set -o errexit
# Make sure only root can run this script
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run as root" 1>&2
echo "Trying with sudo now"
exec sudo -k -- /bin/sh "$0" "$@" || cleanUp 2
fi
# Show usage
usage() {
cat <<-EOF
Usage: refind-multiboot-installer.sh [OPTIONS] [TARGET_DISK] eg. refind-multiboot-installer.sh /dev/sda1
Install refind to a target drive and add a standalone efi bootloader for each iso file contained in the iso directory.
device Device to install on
-h, --help Display this message
-s, --subdirectory <NAME> Specify a data subdirectory (e.g. "boot" or "")
-m, --mbusbdevice Specify a device, in case mbusb.d does not reside on ESP
Further options have to be edited in the CUSTOM section of this file.
Note, that this script needs to be run as root.
EOF
}
# check for arguments
parseArgs() {
[ $# -eq 0 ] && usage && exit 0
scriptname=$(basename "$0")
data_subdir="/boot"
esp_part="/dev/null"
mbusb_part="/dev/null"
use_extra_partition=false
while [ "${#}" -gt 0 ]; do
case "${1}" in
# Show help
-h|--help)
showUsage
exit 0
;;
-m|--mbusbdevice)
# if esp differs from data partition, use this
mbusb_part="${2}"
export use_extra_partitio=true
shift
shift
;;
-s|--subdirectory)
data_subdir="${2}"
shift
shift
;;
/dev/*)
if [ -b "${1}" ]; then
esp_part="${1}"
else
printf '%s: %s is not a valid device.\n' "${scriptname}" "${1}" >&2
cleanUp 1
fi
shift
;;
*)
printf '%s: %s is not a valid argument.\n' "${scriptname}" "${1}" >&2
cleanUp 1
;;
esac
done
if [ "${mbusb_part}" = "/dev/null" ] ;then
mbusb_part="${esp_part}"
use_extra_partition=false
fi
}
# Confirm the device
confirmDevice() {
printf 'Are you sure you want to use %s? [y/N] ' "${esp_part}"
read -r answer1
case "${answer1}" in
[yY][eE][sS]|[yY])
echo "Alright..."
;;
*)
cleanUp 3
;;
esac
}
checkIfMounted() {
mount="$(lsblk -r -no MOUNTPOINT "${1}")"
name="${2}"
is_mounted=false
is_mounted_by_script=false
[ -z "${mount}" ] || is_mounted=true
}
mountDevice() {
name="${2}"
device="${1}"
mount="/tmp/""${name}"
mkdir "${mount}"
mount "${device}" "${mount}" && is_mounted=true
is_mounted_by_script=true
}
checkRefindInstalled() {
# check if refind.conf is there, so we may skip reinstalling
if [ -f "${esp_mount}/efi/boot/refind.conf" ]; then
echo "Refind is already installed. Skipping install."
refind_installed=true
else
refind_installed=false
fi
}
# Make an EFI file to load with rEFInd
makeEFIfile() {
# needed for external grub.cfg to work
grub_modules="${grub_modules} ""part_gpt part_msdos regexp all_video"
# create embedded grub.cfg
echo "configfile \${cmdpath}/${grub_standalone_config}" > /tmp/grub.cfg
[ -d "${script_path}/refind" ] || mkdir "${script_path}/refind"
grub-mkstandalone \
-O x86_64-efi\
-o "${script_path}/refind/iso.efi" \
--modules="${grub_modules}" \
--locales="en@quot" \
--compress="xz" \
"boot/grub/grub.cfg=/tmp/grub.cfg"
rm /tmp/grub.cfg
# ^ embed /tmp/grub.cfg into memdisk as (memdisk)/boot/grub/grub.cfg
}
# create an additional configfile, so rEFInd finds our new bootloaders
createRefindIsoConf() {
configstring=""
refind_path="${esp_mount}/efi/boot"
# Populate a list of entries to be looked at by rEFInd
for confd in "${mbusbd}"/*.d; do
relative_path="$(realpath --relative-to "${esp_mount}" "${confd}")"
configstring="${configstring},""${relative_path}"
done
# write our file
cat <<-EOT > "${refind_path}""/refind-iso.conf"
### This file will be overwritten by refind-multiboot-installer.sh
### If you want to add to this list, do so in refind.conf
# Set our custom folders to be looked at by rEFInd
# The comma after the colon is intended and circumvents a bug in rEFInd, where the first entry of a list is ignored.
also_scan_dirs +${mbusb_uuid}:${configstring}
EOT
# Make rEFInd source our file
# Add line to config, if it isn't there yet
line="include refind-iso.conf"
if ! grep -qF "${line}" "${refind_path}""/refind.conf" ;then
echo -e "### source the config file for booting ISO files\n""${line}" >> "${refind_path}""/refind.conf"
fi
}
copyFiles() {
echo -e "\nCopying files to target"
for isofile in "${mbusb_mount}${iso_dir}"/*; do
# parse name of distro
filename="$(basename "${isofile}")"
distro="$(awk -v file="${filename}" 'BEGIN{FS="-"; $0=file; print tolower($1)}')"
## check for existing config folders
if [ -d "${mbusbd}/${distro}.d" ]; then
echo "Creating config for \"""${distro}""\""
createConfig "${mbusbd}/${distro}.d/${grub_standalone_config}"
cp -f "${script_path}""/refind/iso.efi" "${mbusbd}""/""${distro}"".d/""${distro}"".efi"
## add icons to be copied, if refind offers no auto-detection
# ^ todo
else
echo "no matching folder found: " "${distro}" " -> " "${distro}.d"
fi
done
}
# Create the file that loads another grub.cfg to display menuentries
createConfig() {
tee <<EOT > "${1}"
## GRUB CFG file for ISO boot helper
seach --no-floppy --set=root --fs-uuid ${mbusb_uuid}
set isopath=$iso_dir
imgdevpath=\$root
export isopath imgdevpath
for configfile in \$cmdpath/*.cfg; do
source \$configfile
done
EOT
}
cleanUp() {
for part in esp mbusb; do
look_at_bool="${part}""_is_mounted_by_script"
look_at_path="${part}""_mount"
if [ "${look_at_bool}" = true ]; then
# unmount
umount -f "${look_at_path}" 2>/dev/null || true
# remove dirs
[ -d "${look_at_path}" ] && rmdir "${look_at_path}"
fi
done
if [ "${refind_installed}" ] && [ -d /tmp/refind_install ]; then
# unmount
umount -f /tmp/refind_install
# remove dir
rmdir /tmp/refind_install
fi
# exit
exit "${1-0}"
}
###########################################################
#### Main ####
###########################################################
# Trap kill signals (SIGHUP, SIGINT, SIGTERM) to do some cleanup and exit
trap "cleanUp" 1 2 15
grub_standalone_config="${grub_standalone_config}"".ref"
script_path="$(dirname "$(realpath "${0}")")"
refind_installed=false
# Get UUID of partition, where mbusb.d resides
# Parse the arguments given
parseArgs "${@}"
confirmDevice
# Mount the device and get mountpoint, set config directory
#is_mounted="$("basename ${partition}")""_is_mounted"
checkIfMounted "${esp_part}" "esp"
if [ "${is_mounted}" ] ; then
esp_mount="${mount}"
else
mountDevice "${esp_part}" "esp"
esp_mount="/tmp/esp"
export esp_mounted_by_script="${is_mounted_by_script}"
fi
if [ ${use_extra_partition} ] ; then
checkIfMounted "${mbusb_part}" "mbusb"
if [ "${is_mounted}" ] ; then
mbusb_mount="${mount}"
else
mountDevice "${mbusb_part}" "mbusb"
mbusb_mount="/tmp/mbusb"
export mbusb_mounted_by_script="${is_mounted_by_script}"
fi
fi
#[ "${mbusb_part_is_mounted}" = true ] || mount-device "${mbusb_part}" "mbusb"
mbusbd="${mbusb_mount}${data_subdir}${mbusbd}"
mbusb_uuid="$(lsblk -r -no UUID "${mbusb_part}")"
# If rEFInd is not installed, do it
checkRefindInstalled
[ "$refind_installed" = true ] || refind-install --usedefault "${esp_part}"
# Add config file to rEFInd
createRefindIsoConf
# Build the EFI file once
[ -e "${script_path}"/refind/iso.efi ] || makeEFIfile "${script_path}"/refind/iso.efi
# Copy EFI file and config to target
copyFiles
# Clean up and exit
cleanUp
echo "All done."
# vim: set tabstop=2: set shiftwith=2: