-
Notifications
You must be signed in to change notification settings - Fork 192
/
mknet.sh
executable file
·274 lines (240 loc) · 11.9 KB
/
mknet.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
#!/bin/sh
#
#-
# Copyright (c) 2009-2015 Juan Romero Pardines.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#-
readonly PROGNAME=$(basename "$0")
readonly REQTOOLS="xbps-install tar"
# This script needs to jump around, so we'll remember where we started
# so that we can get back here
readonly CURDIR="$(pwd)"
# This source pulls in all the functions from lib.sh. This set of
# functions makes it much easier to work with chroots and abstracts
# away all the problems with running binaries with QEMU.
# shellcheck source=./lib.sh
. ./lib.sh
# Die is a function provided in lib.sh which handles the cleanup of
# the mounts and removal of temporary directories if the running
# program exists unexpectedly.
trap 'bailout' INT TERM
bailout() {
[ -d "$BOOT_DIR" ] && rm -rf "$BOOT_DIR"
die "An unchecked exception has occured!"
}
usage() {
cat <<-EOH
Usage: $PROGNAME [options] <rootfs-tarball>
Generates a network-bootable tarball from a Void Linux ROOTFS generated by mkrootfs.
OPTIONS
-r <repo> Use this XBPS repository. May be specified multiple times
-c <cachedir> Use this XBPS cache directory (default: )
-i <lz4|gzip|bzip2|xz>
Compression type for the initramfs image (default: xz)
-o <file> Output file name for the netboot tarball (default: automatic)
-K linux<version> Install a custom Linux version on ISO image (default: linux metapackage)
-k <keymap> Default keymap to use (default: us)
-l <locale> Default locale to use (default: en_US.UTF-8)
-C "<arg> ..." Add additional kernel command line arguments
-T <title> Modify the bootloader title (default: Void Linux)
-S <image> Set a custom splash image for the bootloader (default: data/splash.png)
-h Show this help and exit
-V Show version and exit
EOH
}
# ########################################
# SCRIPT EXECUTION STARTS HERE
# ########################################
while getopts "r:c:C:T:K:i:o:k:l:S:Vh" opt; do
case $opt in
r) XBPS_REPOSITORY="--repository=$OPTARG $XBPS_REPOSITORY";;
c) XBPS_CACHEDIR="--cachedir=$OPTARG";;
i) INITRAMFS_COMPRESSION="$OPTARG";;
K) KERNELPKG="$OPTARG";;
o) OUTPUT_FILE="$OPTARG";;
k) KEYMAP="$OPTARG";;
l) LOCALE="$OPTARG";;
C) BOOT_CMDLINE="$OPTARG";;
T) BOOT_TITLE="$OPTARG";;
S) SPLASH_IMAGE="$OPTARG";;
V) version; exit 0;;
h) usage; exit 0;;
*) usage >&2; exit 1;;
esac
done
shift $((OPTIND - 1))
BASE_TARBALL="$1"
# We need to infer the target architecture from the filename. All
# other scripts are able to get this from the platforms map because a
# platform is manually specified. Since the netboot tarballs target
# only architectures, its necessary to pull this information from the
# filename.
XBPS_TARGET_ARCH=${BASE_TARBALL%%-ROOTFS*}
XBPS_TARGET_ARCH=${XBPS_TARGET_ARCH##void-}
# Knowing the target arch, we can set the cache up if it hasn't
# already been set
set_cachedir
# This is an aweful hack since the script isn't using privesc
# mechanisms selectively. This is a TODO item.
if [ "$(id -u)" -ne 0 ]; then
die "need root perms to continue, exiting."
fi
# Before going any further, check that the tools that are needed are
# present. If we delayed this we could check for the QEMU binary, but
# its a reasonable tradeoff to just bail out now.
check_tools
# We need to operate on a tempdir, if this fails to create, it is
# absolutely crucial to bail out so that we don't hose the system that
# is running the script.
ROOTFS=$(mktemp -d) || die "failed to create ROOTFS tempdir, exiting..."
BOOT_DIR=$(mktemp -d) || die "failed to create BOOT_DIR tempdir, exiting..."
PXELINUX_DIR="$BOOT_DIR/pxelinux.cfg"
# Now that we have a directory for the ROOTFS, we can expand the
# existing base filesystem into the directory
info_msg "Expanding base tarball $BASE_TARBALL into $ROOTFS for $PLATFORM build."
tar xf "$BASE_TARBALL" -C "$ROOTFS"
info_msg "Install additional dracut modules"
# This section sets up the dracut modules that need to be present on
# the ROOTFS to build the PXE tarball. This includes the netmenu
# module and the autoinstaller
mkdir -p "$ROOTFS/usr/lib/dracut/modules.d/05netmenu"
cp dracut/netmenu/* "$ROOTFS/usr/lib/dracut/modules.d/05netmenu/"
# The netmenu can directly launch the manual installer from the
# initrd. This is the same installer that's on the live media with
# all its quirks, oddities, and wierdness. It's included here for
# places where you might have a lab network and need to run manual
# installs from the network.
cp installer.sh "$ROOTFS/usr/lib/dracut/modules.d/05netmenu/"
# Of course with a PXE environment unattended installs are the norm.
# The autoinstaller is loaded as a very high priority dracut module
# and will fail the build if it can't be installed.
mkdir -p "$ROOTFS/usr/lib/dracut/modules.d/01autoinstaller"
cp dracut/autoinstaller/* "$ROOTFS/usr/lib/dracut/modules.d/01autoinstaller/"
info_msg "Install kernel and additional required netboot packages"
# The rootfs has no kernel in it, so it needs to have at the very
# least dracut, syslinux, and linux installed. binutils provides
# /usr/bin/strip which lets us shrink down the size of the initrd
# dracut-network provides the in-initrd network stack dialog is needed
# by the install environment. ${INITRAMFS_COMPRESSION} is the name of
# the compressor we want to use (lz4 by default).
if [ -z "${XBPS_TARGET_ARCH##*86*}" ] ; then
# This platform is x86 or compatible, we should use
# syslinux/pxelinux to boot the system.
info_msg "Selecting syslinux bootloader"
bootloader_pkg=syslinux
else
# This is likely an arm platform of some kind. In general these
# either have u-boot or a u-boot compatible loader, so we'll use
# that to produce a uImage and a uInitrd
info_msg "Selecting u-boot bootloader"
bootloader_pkg=uboot-mkimage
fi
run_cmd_target "xbps-install $XBPS_CONFFILE $XBPS_CACHEDIR $XBPS_REPOSITORY -r $ROOTFS -Sy ${KERNELPKG-linux} dracut binutils dracut-network dialog ${INITRAMFS_COMPRESSION-xz} ${bootloader_pkg}"
run_cmd_chroot "$ROOTFS" "xbps-reconfigure -a"
# Dracut needs to know the kernel version that will be using this
# initrd so that it can install the kernel drivers in it. Normally
# this check is quite complex, but since this is a clean rootfs and we
# just installed exactly one kernel, this check can get by with a
# really naive command to figure out the kernel version
KERNELVERSION=$(ls "$ROOTFS/usr/lib/modules/")
# Now that things are setup, we can call dracut and build the initrd.
# This will pretty much step through the normal process to build
# initrd with the exception that the autoinstaller and netmenu are
# force added since no module depends on them.
info_msg "Building initrd for kernel version $KERNELVERSION"
run_cmd_chroot "$ROOTFS" "env -i /usr/bin/dracut \
-N \
--${INITRAMFS_COMPRESSION-xz} \
--add-drivers ahci \
--force-add 'autoinstaller netmenu' \
--omit systemd \
/boot/initrd \
$KERNELVERSION"
[ $? -ne 0 ] && die "Failed to generate the initramfs"
info_msg "Collect netboot components"
if [ ${bootloader_pkg} = "syslinux" ] ; then
# The whole point of this endeavor is to get the files needed for PXE.
# Now that they have been generated, we copy them out of the doomed
# ROOTFS and into the $BOOT_DIR where we're staging the rest of the
# tarball
mv -v "$ROOTFS/boot/initrd" "$BOOT_DIR"
cp -v "$ROOTFS/boot/vmlinuz-$KERNELVERSION" "$BOOT_DIR/vmlinuz"
# The initrd has *very* restrictive permissions by default. To
# prevent some SysAdmin down the road having a very frustrating time
# debugging this, we just fix this here and now.
chmod 0644 "$BOOT_DIR/initrd"
# Now we need to grab the rest of the files that go in the tarball.
# Some of these are always required, some of these are canonical, and
# some of this list is from trial and error. Either way, this is the
# minimum needed to get Void up and booting on metal from the network.
for prog in pxelinux.0 ldlinux.c32 libcom32.c32 vesamenu.c32 libutil.c32 chain.c32 ; do
cp -v "$ROOTFS/usr/lib/syslinux/$prog" "$BOOT_DIR"
done
# Lastly we need the default pxelinux config and the splash image.
# This is user configurable, but if that isn't set then we'll use the
# one from data/splash.png instead
mkdir -p "$PXELINUX_DIR"
cp -f pxelinux.cfg/pxelinux.cfg.in "$PXELINUX_DIR/default"
cp -f "${SPLASH_IMAGE-data/splash.png}" "$BOOT_DIR"
# This sets all the variables in the default config file
info_msg "Configuring pxelinux.0 default boot menu"
sed -i -e "s|@@SPLASHIMAGE@@|$(basename "${SPLASH_IMAGE-splash.png}")|" \
-e "s|@@KERNVER@@|${KERNELVERSION}|" \
-e "s|@@KEYMAP@@|${KEYMAP-us}|" \
-e "s|@@ARCH@@|$XBPS_TARGET_ARCH|" \
-e "s|@@LOCALE@@|${LOCALE-en_US.UTF-8}|" \
-e "s|@@BOOT_TITLE@@|${BOOT_TITLE-Void Linux}|" \
-e "s|@@BOOT_CMDLINE@@|${BOOT_CMDLINE}|" \
"$PXELINUX_DIR/default"
else
# u-boot has far far fewer components, but u-boot artifacts do
# require some pre-processing
if [ ! -f "$ROOTFS/boot/uImage" ] ; then
# Build the uImage, this is really just the kernel with a wrapper
# to make u-boot happy. It also sets the load and entry
# addresses, though in general these are overriden by the u-boot
# configuration.
run_cmd_chroot "$ROOTFS" "env -i /usr/bin/mkimage -A arm -O linux -T kernel -C none -a 0x00000000 -e 0x00000000 -n 'Void Kernel' -d /boot/zImage /boot/uImage"
# Build the uInitrd which is similarly just a copy of the real
# initrd in a format that u-boot is willing to ingest.
run_cmd_chroot "$ROOTFS" "env -i /usr/bin/mkimage -A arm -O linux -T ramdisk -C none -a 0 -e 0 -n 'Void Installer Initrd' -d /boot/initrd /boot/uInitrd"
# Copy out the artifacts that are worth keeping
cp "$ROOTFS/boot/uImage" "$BOOT_DIR"
cp "$ROOTFS/boot/uInitrd" "$BOOT_DIR"
cp -r "$ROOTFS/boot/dtbs" "$BOOT_DIR"
else
# Copy the existing uImage out
cp "$ROOTFS/boot/uImage" "$BOOT_DIR"
fi
fi
# Compress the artifacts for distribution
OUTPUT_FILE="void-${XBPS_TARGET_ARCH}-NETBOOT-$(date -u +%Y%m%d).tar.gz"
info_msg "Compressing results to $OUTPUT_FILE"
cd "$BOOT_DIR" || die "Could not enter image dir"
tar -zcvf "$CURDIR/$OUTPUT_FILE" .
cd "$CURDIR" || die "Could not return to working directory"
# As a final cleanup step, remove the ROOTFS and the expanded BOOT_DIR
info_msg "Cleaning up and removing build directories"
cleanup_chroot
[ -d "$ROOTFS" ] && rm -rf "$ROOTFS"
[ -d "$BOOT_DIR" ] && rm -rf "$BOOT_DIR"