forked from raspberrypi/pi-gen-micro
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.sh
executable file
·413 lines (348 loc) · 12.4 KB
/
build.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
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
#!/usr/bin/env bash
# Set up some parameters for building!
KERNEL_VERSION_STR="6.6.31+rpt-rpi-v8"
KERNEL_BIT_SIZE=64
OUT_IMAGE_NAME="boot.img"
# Overwrite the defaults with that from the build.parameters file
source config
CONFIGURATION_FOLDER="${CONFIGURATION_ROOT}"$1
export OUT_DIR=$PWD/out_image
source "${CONFIGURATION_FOLDER}"/build.parameters
source "${CONFIGURATION_FOLDER}"/components.parameters
echo "${CONFIGURATION_FOLDER}"
echo "${TARGET_DEVICE}"
rm -rf build
rm -f initramfs
rm -rf "${OUT_DIR}"
mkdir "${OUT_DIR}"
mkdir -p build/usr/bin
mkdir -p build/usr/lib
cd build || exit
ln -s usr/bin bin
ln -s usr/lib lib
cd ..
export ROOTFS_DIR=$PWD/build
export DPKG_ROOT=$ROOTFS_DIR
export TOP="${PWD}"
# Relies on GNU sed extension (/dev/stdin file for 'r' command)
sed '/^#/d;s/^/ "--/;s/$/";/' cfg/dpkg_extra_args | \
sed "
s%PWD%${PWD}%
s%REALROOTREL%$(realpath -s --relative-to="$PWD" /)/%
/DPKG_EXTRA_ARGS/{r /dev/stdin
d}" cfg/apt.cfg > apt.cfg
export APT_CONFIG=$PWD/apt.cfg
DPKG_EXTRA_ARGS="$(sed '/^#/d;s/^/--/' "${CONFIGURATION_FOLDER}"/dpkg_extra_args | xargs)"
apt_download() {
apt-get install --download-only "$@"
}
# Can't use install until it's possible to chroot
apt_install() {
apt-get install "$@" --no-install-recommends
}
get_package_path() {
# Not fully URL-encoded (no spec found)
PKG_VERSION=$(apt-cache policy "$1" | grep -oP 'Candidate: \K.*' | sed 's/:/%3a/')
find apt/cache/archives/ -name "${1}_${PKG_VERSION}*"
}
dpkg_unpack() {
apt_download "$1"
set -o noglob
# shellcheck disable=SC2086
dpkg ${DPKG_EXTRA_ARGS} --no-triggers --unpack "$(get_package_path $1)"
set +o noglob
}
dpkg_install() {
apt_download "$1"
set -o noglob
# shellcheck disable=SC2086
dpkg ${DPKG_EXTRA_ARGS} --install "$(get_package_path $1)"
set +o noglob
}
apt-get update
mkdir -p build/var/lib/dpkg
touch build/var/lib/dpkg/lock-frontend
# Download, patch, install libc6-udeb
apt_download libc6-udeb
PACKAGE_PATH="$(get_package_path libc6-udeb)"
EXTRACT_DIR="$(mktemp --directory --tmpdir deb-extract.XXX)"
dpkg-deb --raw-extract "${PACKAGE_PATH}" "${EXTRACT_DIR}"
rm "${PACKAGE_PATH}"
LIBC_VERSION="$(grep -oP '^Version:\s*\K.*' "${EXTRACT_DIR}"/DEBIAN/control)"
sed --in-place "/^Provides:/s/libc6,/libc6 (= ${LIBC_VERSION}),/" "${EXTRACT_DIR}/DEBIAN/control"
echo "Replaces: libc6 (= ${LIBC_VERSION})
Conflicts: libc6 (= ${LIBC_VERSION})" >> "${EXTRACT_DIR}/DEBIAN/control"
dpkg-deb --build "${EXTRACT_DIR}" "${PACKAGE_PATH}"
rm -rf "${EXTRACT_DIR}"
set -o noglob
# shellcheck disable=SC2086
dpkg ${DPKG_EXTRA_ARGS} --install "${PACKAGE_PATH}"
set +o noglob
dpkg_install busybox
cd build/bin || exit
ln -s busybox sh
ln -s mawk awk
echo '#!/bin/sh' > update-alternatives
echo 'return 0' >> update-alternatives
chmod +x update-alternatives
cp update-alternatives dpkg-trigger
cd - || exit
# awk is Pre-Depends of base-files (unfortunately)
dpkg_install mawk
# Just unpack base-files for now (can't postinst without base-passwd)
dpkg_unpack base-files
chroot build /bin/busybox --install -s
# Need to properly install base-passwd before base-files can be completed
apt_download libpcre2-8-0 libselinux1 libdebconfclient0 base-passwd
dpkg_install libpcre2-8-0
dpkg_install libselinux1
dpkg_install libdebconfclient0
dpkg_install base-passwd
# Allow root login without password (and use busybox shell)
sed --in-place '/^root/ {s/\*//; s/bash/sh/}' build/etc/passwd
dpkg_install base-files
# Manually move the dpkg excludes file into the rootfs
cp cfg/dpkg.cfg.d/excludes /etc/dpkg/dpkg.cfg.d/excludes
# Manually move the dpkg excludes file into the rootfs
cp cfg/dpkg.cfg.d/excludes /etc/dpkg/dpkg.cfg.d/excludes
# 'mount' will be installed by systemd below, ensure util-linux dep can be met
dpkg_unpack util-linux-extra
rm -rf build/etc/init.d
apt-get --fix-broken install
# We *should* now have a working system for apt.
# Try to install cryptsetup-bin (+deps) (libgcc-s1 required for pthread_exit)
apt_install cryptsetup-bin libgcc-s1
apt_install android-libsparse
apt_install android-libbase
apt_install android-liblog
apt_install zlib1g
apt_install android-libcutils
apt_install libfdisk1
apt_install liburing2
apt_install openssl
# Tiny debconf for libpam0g (systemd dep)
apt_install cdebconf-udeb cdebconf-text-udeb
sed --in-place 's/newt/text/g' build/etc/cdebconf.conf
if [ "${SSH}" = 1 ]
then
echo "Installing SSH!"
apt_install dropbear-bin
apt_install ./packages/dropbear-ssh-service_1.0.0_arm64.deb
fi
# TODO: postinst failure, fstrim settings using deb-systemd-helper
apt_install util-linux
# Install systemd and symlinks
cp build/bin/update-alternatives build/bin/dpkg-maintscript-helper
cp build/bin/update-alternatives build/bin/dpkg
apt_install systemd-sysv
rm build/bin/dpkg-maintscript-helper
rm build/bin/dpkg
IFS=', ' read -r -a array <<< "$(< "${CONFIGURATION_FOLDER}"/packages.list tr '\n' ', ')"
for package in "${array[@]}"
do
echo "Installing ${package}"
apt_install "${package}"
done
cd "${CONFIGURATION_FOLDER}" || exit
./installer_scripts.list
cd "${TOP}" || exit
apt_install kmod
if [ "${UDEV}" = 1 ]
then
echo "Installing UDEV!"
# libc-bin required for passwd postinst
apt_install libc-bin
# Setup passwd (udev dep)
cp build/bin/update-alternatives build/bin/dpkg-maintscript-helper
apt_install passwd
rm build/bin/dpkg-maintscript-helper
# Install perl-base, addgroup dep (used by udev postinst)
apt_install perl-base
# Setup udev
dpkg_unpack udev
rm -rf build/etc/init.d
apt-get --fix-broken install
fi
if [ "${NETWORK}" = 1 ]
then
if [ "${UDEV}" = 1 ]
then
echo "Installing & Enabling networking"
cp prebuilts/20-wired.network build/etc/systemd/network/20-wired.network
ln -s /lib/systemd/system/systemd-networkd.service build/etc/systemd/system/dbus-org.freedesktop.network1.service
ln -s /lib/systemd/system/systemd-networkd.service build/etc/systemd/system/multi-user.target.wants/systemd-networkd.service
ln -s /lib/systemd/system/systemd-networkd.socket build/systemd/system/sockets.target.wants/systemd-networkd.socket
ln -s /lib/systemd/system/systemd-network-generator.service build/etc/systemd/system/sysinit.target.wants/systemd-network-generator.service
ln -s /lib/systemd/system/systemd-networkd-wait-online.service build/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service
else
echo "--------------- ERROR - Network cannot be installed without UDEV Support. This component will not work! --------------------"
fi
fi
# Symlink to regular /sbin/init
# ln -s /sbin/init build/init
if [ "${AUTOLOGIN}" = 1 ]
then
# Ensure getty on tty1 is autologin
mkdir -p build/etc/systemd/system/getty@tty1.service.d
# shellcheck disable=SC2028
echo "[Service]
ExecStart=
ExecStart=-/sbin/agetty -o '-p -f -- \\\\u' --noclear --autologin root %I \$TERM
TTYVTDisallocate=no
" > build/etc/systemd/system/getty@tty1.service.d/autologin.conf
# getty-static.service starts tty2-tty6 if dbus / logind are not available
# Override this behaviour
mkdir -p build/etc/systemd/system/getty-static.service.d
echo "[Service]
ExecStart=
ExecStart=/bin/true
" > build/etc/systemd/system/getty-static.service.d/override.conf
# serial-getty shouldn't wait for device unit (no udev) and should autologin as
# root
sed '
/^BindsTo/d
/^After=/s/dev-%i\.device\s*//
s/\(--keep-baud\)/--noclear --autologin root \1/' \
build/usr/lib/systemd/system/serial-getty@.service \
> build/etc/systemd/system/serial-getty@.service
fi
# Ensure compressed modules can be loaded (busybox implementation of modprobe
# is insufficient)
dpkg_unpack kmod
rm -rf build/etc/init.d
apt-get --fix-broken install
### CUSTOM CHANGES ARE MADE HERE
#
### CUSTOM CHANGES ARE MADE HERE
# Boot firmare
apt_download raspi-firmware
RASPI_FIRMWARE_TMPDIR=$(mktemp -d)
cd "${RASPI_FIRMWARE_TMPDIR}" || exit
ar -x "$(find "${TOP}"/apt/cache/archives/ -name 'raspi-firmware*' | sort | tail -1)"
tar xvf data.tar.xz ./
mv ./usr/lib/raspi-firmware/* "${DPKG_ROOT}"/boot/
cd - || exit
rm -rf "${RASPI_FIRMWARE_TMPDIR}"
# Find kernel
KERNEL_META=linux-image-rpi-v8
apt_download "${KERNEL}"
KERNEL_PACKAGE=$(apt-cache depends $KERNEL_META | grep -oP 'Depends: \K.*')
KERNEL_VERSION_STR=${KERNEL_PACKAGE#linux-image-}
KPKG_EXTRACT="$(mktemp --directory --tmpdir kernel_package.XXX)"
dpkg-deb --raw-extract "$(get_package_path "${KERNEL_PACKAGE}")" "${KPKG_EXTRACT}"
# Copy requested kernel modules (+deps) into image and generate module dependencies
depmod --basedir "${KPKG_EXTRACT}" "${KERNEL_VERSION_STR}"
cd "${KPKG_EXTRACT}" >/dev/null || exit
module_paths=()
get_deps() {
local module_name=$1
# shellcheck disable=SC2046
readarray -t file_deps <<<$(modinfo --basedir . -k "${KERNEL_VERSION_STR}" "${module_name}" | grep -oP '^(?:filename|depends):\s+\K.*')
module_paths+=("${file_deps[0]}")
if [ ${#file_deps[@]} -eq "2" ]
then
# shellcheck disable=SC2086
readarray -t -d , deps <<<${file_deps[1]}
for dep in "${deps[@]}"
do
# shellcheck disable=SC2086
get_deps $dep
done
fi
}
for dep in $(sed '/^#/d' "${CONFIGURATION_FOLDER}"/kernel_modules.list | xargs)
do
# shellcheck disable=SC2086
get_deps $dep
done
cd - || exit
printf "
${KPKG_EXTRACT}/./lib/modules/${KERNEL_VERSION_STR}/modules.order
${KPKG_EXTRACT}/./lib/modules/${KERNEL_VERSION_STR}/modules.builtin
${KPKG_EXTRACT}/./lib/modules/${KERNEL_VERSION_STR}/modules.builtin.modinfo
%s
" "${module_paths[@]}" | sort | uniq | \
rsync \
--perms \
--times \
--group \
--owner \
--acls \
--xattrs \
--files-from=- \
/ \
"${ROOTFS_DIR}/"
depmod --basedir "${ROOTFS_DIR}" "${KERNEL_VERSION_STR}"
# Manually form-up the kernel and bootfs
mkdir -p "${OUT_DIR}"/overlays
# mv ${DPKG_ROOT}/boot/vmlinuz-${KERNEL_VERSION_STR} ${OUT_DIR}/zImage
mv "${DPKG_ROOT}"/usr/lib/linux-image-"${KERNEL_VERSION_STR}"/broadcom/*.dtb "${OUT_DIR}"/
mv "${DPKG_ROOT}"/usr/lib/linux-image-"${KERNEL_VERSION_STR}"/overlays/*.dtb* "${OUT_DIR}"/overlays/
mv "${DPKG_ROOT}"/usr/lib/linux-image-"${KERNEL_VERSION_STR}"/overlays/README "${OUT_DIR}"/overlays/
mv "${DPKG_ROOT}"/boot/* "${OUT_DIR}"/
mkdir build/data/
cp prebuilts/config.txt "${OUT_DIR}"/config.txt
cp prebuilts/cmdline.txt "${OUT_DIR}"/cmdline.txt
# apt_install debconf
dpkg_unpack linux-image-"${KERNEL_VERSION_STR}"
# # Manually form-up the kernel and bootfs
# mkdir -p ${OUT_DIR}/overlays
mv "${DPKG_ROOT}"/boot/vmlinuz-"${KERNEL_VERSION_STR}" "${OUT_DIR}"/kernel8.img
# mv ${DPKG_ROOT}/usr/lib/linux-image-${KERNEL_VERSION_STR}/broadcom/*.dtb ${OUT_DIR}/
# mv ${DPKG_ROOT}/usr/lib/linux-image-${KERNEL_VERSION_STR}/overlays/*.dtb* ${OUT_DIR}/overlays/
# mv ${DPKG_ROOT}/usr/lib/linux-image-${KERNEL_VERSION_STR}/overlays/README ${OUT_DIR}/overlays/
# mv ${DPKG_ROOT}/boot/* ${OUT_DIR}/
# # Install Systemd by building into build folder
# /mnt/install_systemd.sh
#cd components
#./install_package.sh https://github.com/systemd/systemd.git
#cd ..
cp -r packages/built/* build/
cp -r packages/built/lib/* build/usr/lib/
cp -r packages/built/bin/* build/usr/bin/
# Copy init
cp prebuilts/init build/init
# ln build/usr/sbin /sbin
cd build/sbin || exit
rm init
ln -s /usr/lib/systemd/systemd init
cd ..
ln -s /bin/udevadm /lib/systemd/systemd-udevd
cd ..
mkdir build/data/
cp prebuilts/config.txt "${OUT_DIR}"/config.txt
cp prebuilts/cmdline.txt "${OUT_DIR}"/cmdline.txt
cp prebuilts/cryptkey-fetch build/bin/
cp prebuilts/vcmailbox build/bin/
cp prebuilts/vcgencmd build/bin/
mkdir build/usr/local/bin
cp prebuilts/rpi-otp-private-key build/usr/local/bin
## Fix up systemd-modules-load
cp prebuilts/load_modules.sh build/usr/local/bin/load_modules
cp prebuilts/systemd-modules-load.service build/etc/systemd/system/systemd-modules-load.service
if [ "${SSH}" = 1 ]
then
echo "Installing SSH!"
mkdir -p build/root/.ssh
cat prebuilts/authorized_keys > build/root/.ssh/authorized_keys
chmod 0600 build/root/.ssh/authorized_keys
mkdir build/dev/pts
fi
cat prebuilts/authorized_keys > build/root/.ssh/authorized_keys
chmod 0600 build/root/.ssh/authorized_keys
mkdir build/dev/pts
sed --in-place 's/bash/sh/g' build/etc/passwd
echo "systemd-journal:x:104:
systemd-network:x:105:
systemd-resolve:x:106:
systemd-timesync:x:107:
kvm:*:1023" >> build/etc/group
# Package initramfs
cd build || exit
find . -print0 | cpio --null -ov --format=newc > ../initramfs.cpio 2>/dev/null
cd ..
zstd --no-progress --rm -15 initramfs.cpio -o "${OUT_DIR}"/rootfs.cpio.zst
echo "Making boot img"
echo "Out directory = ${OUT_DIR}"
mkdir -p "${OUT_DIR}"
make-boot-image -d "${OUT_DIR}"/ -o "${OUT_IMAGE_NAME}" -a "${KERNEL_BIT_SIZE}"