-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBuild.sh
More file actions
executable file
·551 lines (493 loc) · 18.9 KB
/
Copy pathBuild.sh
File metadata and controls
executable file
·551 lines (493 loc) · 18.9 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
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
#!/bin/bash
## Build.sh 17.0.4 for netbootcd-neo - BIOS + UEFI support (x86_64)
## Copyright (C) 2022 Isaac Schemm <isaacschemm@gmail.com>
## Edited by Jonathan A. Wingo <spcwingo1@gmail.com> to support
## only x86_64 in either BIOS or UEFI mode.
##
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## as published by the Free Software Foundation; either version 2
## of the License, or (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
##
## The full text of the GNU GPL, versions 2 or 3, can be found at
## <http://www.gnu.org/copyleft/gpl.html> or on the CD itself.
set -e
PATH=$PATH:/sbin
WORK=$(pwd)/work
DONE=$(pwd)/done
NBINIT=${WORK}/nbinit
KEXEC_BUILD=
cleanup() {
rm -rf "${WORK:-}" squashfs-root opt
rm -rf "${KEXEC_BUILD:-}"
rm -f "vmlinuz64-${COREVER}" "corepure64-${COREVER}.gz" \
"kexec-tools-${KEXEC_VER}.tar.xz"
for _pkg in ${CACHED_TCZ_PKGS:-}; do
rm -f "${_pkg}-x86_64.tcz"
done
for _pkg in ${WIFI_PKGS_ALL:-}; do
rm -f "${_pkg}-x86_64.tcz"
done
}
trap cleanup EXIT
NBCDVER=17.0.4
COREVER=17.0
KEXEC_VER=2.0.32
TCX64="http://distro.ibiblio.org/tinycorelinux/${COREVER%.*}.x/x86_64"
BASE_TCZ_PKGS="dialog ncursesw openssl 7zip zstd libzstd xz liblzma liblz4 firmware-lan firmware-rtl_nic firmware-cavium_nic"
CACHED_TCZ_PKGS="$BASE_TCZ_PKGS firmware-broadcom_bnx2 firmware-broadcom_bnx2x"
# --- Locate GRUB EFI modules directory ---
GRUB_MODULES_DIR=""
for dir in /usr/lib/grub/x86_64-efi \
/usr/lib/grub2/x86_64-efi \
/boot/grub2/x86_64-efi \
/usr/share/grub2/x86_64-efi; do
if [ -d "$dir" ] && [ -f "$dir/linux.mod" ]; then
GRUB_MODULES_DIR="$dir"
break
fi
done
if [ -z "$GRUB_MODULES_DIR" ]; then
echo "ERROR: GRUB EFI modules not found."
echo "Install with: sudo apt install grub-efi-amd64-bin"
exit 1
fi
# --- Download TinyCore x86_64 kernel and rootfs ---
# We use TinyCore x86_64 (not i386) because the i386 kexec binary hardcodes
# bzImage_support_efi_boot=0, making UEFI kexec handoff impossible. The
# x86_64 kexec binary sets it to 1 and properly fills boot_params.efi_info.
if [ ! -f "vmlinuz64-${COREVER}" ]; then
wget "$TCX64/release/distribution_files/vmlinuz64" \
-O "vmlinuz64-${COREVER}"
fi
if [ ! -f "corepure64-${COREVER}.gz" ]; then
wget "$TCX64/release/distribution_files/corepure64.gz" \
-O "corepure64-${COREVER}.gz"
fi
# x86_64 TCZ packages (downloaded once, cached locally)
for pkg in $CACHED_TCZ_PKGS; do
if [ ! -f "${pkg}-x86_64.tcz" ]; then
wget "$TCX64/tcz/${pkg}.tcz" -O "${pkg}-x86_64.tcz"
fi
done
# Detect the kernel version shipped in corepure64 so we can request the
# matching wireless kernel module package (wireless-<kver>.tcz).
# TinyCore ships zero wireless drivers in corepure64 itself; they live in a
# separate version-stamped package that installs into /usr/local/lib/modules/.
KVER=$(gzip -cd "corepure64-${COREVER}.gz" | cpio -t 2>/dev/null \
| grep '^lib/modules/[^/]*$' | head -1 | sed 's|lib/modules/||')
if [ -z "$KVER" ]; then
echo "ERROR: Could not detect kernel version from corepure64-${COREVER}.gz"
exit 1
fi
echo "Detected kernel version: $KVER"
WIFI_PKGS="wifi wpa_supplicant-dbus iw wireless-${KVER} wireless-regdb wireless_tools \
firmware-atheros \
firmware-broadcom_bcm43xx firmware-broadcom_bnx2 firmware-broadcom_bnx2x \
firmware-cavium_nic \
firmware-ipw2100 firmware-ipw2200 firmware-iwimax \
firmware-iwl8000 firmware-iwl9000 firmware-iwlax20x firmware-iwlwifi \
firmware-lan firmware-marvel firmware-mediatek firmware-mellanox \
firmware-myri10ge firmware-netronome firmware-netxen \
firmware-openfwwf firmware-qca firmware-qed \
firmware-ralinkwifi firmware-rtl_nic firmware-rtlwifi \
firmware-ti-connectivity firmware-tigon \
firmware-vxge firmware-wlan firmware-zd1211"
# Download a TCZ package plus all of its transitive dependencies by reading
# the .tcz.dep file that TinyCore publishes alongside each package.
# Discovered names accumulate in WIFI_PKGS_ALL for extraction and cleanup.
fetch_tcz() {
local pkg="$1"
if [ -z "$pkg" ]; then return 0; fi
case " ${WIFI_PKGS_ALL} " in *" ${pkg} "*) return 0 ;; esac
WIFI_PKGS_ALL="${WIFI_PKGS_ALL} ${pkg}"
if [ ! -f "${pkg}-x86_64.tcz" ]; then
if ! wget -T 15 "$TCX64/tcz/${pkg}.tcz" -O "${pkg}-x86_64.tcz"; then
rm -f "${pkg}-x86_64.tcz"
echo "WARNING: Could not download ${pkg}.tcz — skipping"
return 0
fi
fi
local depfile
depfile=$(mktemp)
wget -q -T 15 "$TCX64/tcz/${pkg}.tcz.dep" -O "$depfile" 2>/dev/null || true
if [ -s "$depfile" ]; then
while read -r dep; do
dep="${dep%.tcz}"
dep="${dep//KERNEL/$KVER}" # TinyCore uses KERNEL as a placeholder
if [ -n "$dep" ]; then
fetch_tcz "$dep"
fi
done < "$depfile"
fi
rm -f "$depfile"
return 0
}
WIFI_PKGS_ALL=""
echo "Resolving WiFi package dependencies..."
for pkg in $WIFI_PKGS; do
fetch_tcz "$pkg"
done
echo "WiFi packages to install: ${WIFI_PKGS_ALL}"
# kexec-tools source (for 64-bit static build)
if [ ! -f "kexec-tools-${KEXEC_VER}.tar.xz" ]; then
wget "https://mirrors.edge.kernel.org/pub/linux/utils/kernel/kexec/kexec-tools-${KEXEC_VER}.tar.xz"
fi
# --- Dependency checks ---
NO=0
for i in nbscript.sh tc-config.diff; do
if [ ! -e "$i" ]; then
echo "Couldn't find $i!"
NO=1
fi
done
for i in mkfs.vfat unsquashfs grub-mkstandalone mcopy \
xorriso gcc make; do
if ! command -v "$i" >/dev/null 2>&1; then
echo "Please install $i!"
NO=1
fi
done
if [ "$NO" = 1 ]; then exit 1; fi
if [ "$(whoami)" != "root" ]; then
echo "Please run as root or through fakeroot:"
echo " sudo ./Build.sh"
echo " fakeroot ./Build.sh"
exit 1
fi
# --- Clean slate ---
rm -rf "${WORK}" "${DONE}"
mkdir -p "${WORK}" "${DONE}" "${NBINIT}"
FDIR=$(pwd)
# --- Copy x86_64 kernel ---
cp "vmlinuz64-${COREVER}" "${DONE}/vmlinuz"
chmod +w "${DONE}/vmlinuz"
# --- Build nbinit4.gz from TinyCore x86_64 rootfs ---
if [ -d "${NBINIT}" ]; then rm -rf "${NBINIT}"; fi
mkdir "${NBINIT}"
cd "${NBINIT}"
echo "Extracting corepure64..."
gzip -cd "${FDIR}/corepure64-${COREVER}.gz" | cpio -id
mkdir -p "${NBINIT}/usr/bin"
cd -
cat > "${NBINIT}/usr/bin/netboot" << "EOF"
#!/bin/sh
if [ "$(whoami)" != "root" ]; then
exec sudo "$0" "$@"
fi
if [ ! -f /tmp/internet-is-up ]; then
NETBOOT_WAIT_SECONDS=10
echo "Waiting briefly for internet connection (up to ${NETBOOT_WAIT_SECONDS}s)"
printf '%s' "Testing example.com"
NETBOOT_WAIT_START=$(date +%s)
while :; do
if wget --no-check-certificate --tries=1 -T 1 --spider \
http://www.example.com >/dev/null 2>&1; then
echo > /tmp/internet-is-up
echo
echo "Internet connection detected."
break
fi
NETBOOT_WAIT_NOW=$(date +%s)
if [ $(( NETBOOT_WAIT_NOW - NETBOOT_WAIT_START )) -ge "$NETBOOT_WAIT_SECONDS" ]; then
echo
if command -v wpa_supplicant >/dev/null 2>&1; then
echo "No internet connection detected."
echo "Use the 'wifi' option in the menu to connect to a wireless network."
else
echo "Proceeding without an internet connection."
fi
break
fi
sleep 1
printf '.'
done
fi
if [ -x /tmp/nbscript.sh ]; then
/tmp/nbscript.sh
else
/usr/bin/nbscript.sh
fi
echo "Type \"netboot\" to return to the menu."
EOF
chmod +x "${NBINIT}/usr/bin/netboot"
# Patch tc-config (disable swap in NetbootCD-Neo)
cd "${NBINIT}/etc/init.d"
patch -p0 < "${FDIR}/tc-config.diff" || {
echo "ERROR: tc-config.diff did not apply cleanly."
echo "The swap-disable patch may need updating for TinyCore x86_64."
exit 1
}
cd -
# Expose the live shell on serial as well as the VGA console.
# BIOS still uses tty1, while UEFI gains a readable ttyS0 login.
INITTAB="${NBINIT}/etc/inittab"
if ! grep -q '^ttyS0::respawn:/sbin/getty -nl /sbin/autologin 115200 ttyS0$' "$INITTAB"; then
awk '
{ print }
$0 == "tty1::respawn:/sbin/getty -nl /sbin/autologin 38400 tty1" {
print "ttyS0::respawn:/sbin/getty -nl /sbin/autologin 115200 ttyS0"
}
' "$INITTAB" > "${INITTAB}.new" && mv "${INITTAB}.new" "$INITTAB"
fi
# Per-controlling-tty one-shot autologin.
# The stock /sbin/autologin guards autologin with a single shared flag
# (/var/log/autologin). With getty respawning /sbin/autologin on both tty1
# (VGA) and ttyS0 (serial), whichever fires first consumes that flag and the
# loser falls through to a plain "box login:" prompt -- so the serial console
# could steal the VGA console's autologin and drop the user at a password
# prompt instead of the NetbootCD menu. Key the one-shot per tty so tty1 and
# ttyS0 each autologin exactly once, independently.
cat > "${NBINIT}/sbin/autologin" << "EOF"
#!/bin/busybox ash
_tty=$(tty 2>/dev/null)
_tty=${_tty#/dev/}
[ -n "$_tty" ] || _tty=tty1
_flag="/var/log/autologin.$_tty"
if [ -f "$_flag" ]; then
exec /sbin/getty 38400 "$_tty"
else
touch "$_flag"
exec login -f root
fi
EOF
chmod 755 "${NBINIT}/sbin/autologin"
cp -v nbscript.sh "${NBINIT}/usr/bin"
# x86_64 TCZ packages
if [ -e squashfs-root ]; then rm -rf squashfs-root; fi
for pkg in $BASE_TCZ_PKGS; do
unsquashfs "${pkg}-x86_64.tcz"
cp -a squashfs-root/* "${NBINIT}"
rm -r squashfs-root
done
# --- Build 64-bit static kexec-tools ---
# A 64-bit kexec binary is required for UEFI kexec handoff:
# the i386 bzImage loader sets bzImage_support_efi_boot=0 unconditionally,
# so it never fills boot_params.efi_info. The x86_64 loader sets it to 1.
KEXEC_BUILD=$(mktemp -d /tmp/netbootcd-kexec-build.XXXXXX)
rm -rf "${KEXEC_BUILD}"
mkdir -p "${KEXEC_BUILD}"
tar -C "${KEXEC_BUILD}" --strip-components=1 -xf "kexec-tools-${KEXEC_VER}.tar.xz"
(
cd "${KEXEC_BUILD}"
LDFLAGS='-static' ./configure --sbindir=/sbin --with-lzma --with-zlib
make -j"$(nproc)"
)
KEXEC_BIN="${KEXEC_BUILD}/build/sbin/kexec"
if ! "${KEXEC_BIN}" --help 2>&1 | grep -q -- '-s'; then
echo "ERROR: kexec built without kexec_file_load (-s) support."
echo "Check that linux/kexec.h is present on the build host."
exit 1
fi
install -D -m 0755 "${KEXEC_BIN}" "${NBINIT}/sbin/kexec"
strip "${NBINIT}/sbin/kexec"
echo "Installed kexec-tools ${KEXEC_VER} (64-bit static, -s supported)"
rm -rf "${KEXEC_BUILD}"
echo "if ! command -v startx >/dev/null 2>&1; then netboot; else sleep 5; echo '** Type netboot to start **'; fi" \
>> "${NBINIT}/etc/skel/.profile"
cd "${NBINIT}"
find . | cpio -o -H 'newc' | gzip -c > "${DONE}/nbinit4.gz"
cd -
echo "Made initrd: $(wc -c < "${DONE}/nbinit4.gz") bytes"
# --- Prepare ISO tree ---
rm -rf "${WORK}/iso"
mkdir -p "${WORK}/iso/boot/isolinux"
# Get isolinux from system package (architecture-independent BIOS bootloader)
ISOLINUX_BIN=""
for f in /usr/lib/ISOLINUX/isolinux.bin \
/usr/share/syslinux/isolinux.bin \
/usr/lib/syslinux/modules/bios/isolinux.bin; do
[ -f "$f" ] && { ISOLINUX_BIN="$f"; break; }
done
if [ -z "$ISOLINUX_BIN" ]; then
echo "ERROR: isolinux.bin not found. Install: sudo apt install isolinux"
exit 1
fi
cp "$ISOLINUX_BIN" "${WORK}/iso/boot/isolinux/"
SYSLINUX_BIOS_DIR=""
for d in /usr/lib/syslinux/modules/bios \
/usr/share/syslinux \
/usr/lib/ISOLINUX; do
[ -f "$d/menu.c32" ] && { SYSLINUX_BIOS_DIR="$d"; break; }
done
if [ -z "$SYSLINUX_BIOS_DIR" ]; then
echo "ERROR: syslinux modules not found. Install: sudo apt install syslinux-common"
exit 1
fi
# Syslinux 5+ requires ldlinux.c32, libcom32.c32, and libutil.c32 alongside
# menu.c32; copy whichever ones exist (older versions don't have them).
for mod in menu.c32 ldlinux.c32 libcom32.c32 libutil.c32; do
[ -f "$SYSLINUX_BIOS_DIR/$mod" ] && \
cp "$SYSLINUX_BIOS_DIR/$mod" "${WORK}/iso/boot/isolinux/"
done
cp "${DONE}/vmlinuz" "${DONE}/nbinit4.gz" "${WORK}/iso/boot/"
# Fetch netboot.xyz binaries. netboot.xyz.lkrn is loaded by isolinux in
# BIOS mode; netboot.xyz.efi is chainloaded by GRUB in UEFI mode. Both
# drop into the live iPXE menu fetched from boot.netboot.xyz at runtime.
echo "Downloading netboot.xyz binaries..."
wget -q --show-progress https://boot.netboot.xyz/ipxe/netboot.xyz.lkrn \
-O "${WORK}/iso/boot/netboot.xyz.lkrn"
# Use the -snp build for UEFI: it prefers the firmware's Simple Network
# Protocol (avoiding the "iPXE initialising devices..." hang seen with
# the full-driver netboot.xyz.efi) but retains fallback driver code, so
# its PE/COFF layout is compatible with GRUB's chainloader. The smaller
# -snponly build trips GRUB chainloader.c with "unknown error".
wget -q --show-progress https://boot.netboot.xyz/ipxe/netboot.xyz-snp.efi \
-O "${WORK}/iso/boot/netboot.xyz.efi"
# BIOS boot menu
cat > "${WORK}/iso/boot/isolinux/isolinux.cfg" << EOF
DEFAULT menu.c32
PROMPT 0
TIMEOUT 100
ONTIMEOUT nbcd
LABEL hd
MENU LABEL Boot from hard disk
localboot 0x80
LABEL nbcd
menu label Start ^NetbootCD-Neo $NBCDVER
menu default
kernel /boot/vmlinuz
initrd /boot/nbinit4.gz
append quiet
LABEL netbootxyz
menu label Boot ^netboot.xyz
kernel /boot/netboot.xyz.lkrn
EOF
# --- Build UEFI EFI boot image ---
echo "Building self-contained UEFI binary with grub-mkstandalone..."
mkdir -p "${WORK}/efifiles/EFI/BOOT"
cat > "${WORK}/grub-full.cfg" << EOF
set default=0
set timeout=5
insmod all_video
insmod gfxterm
insmod font
search --no-floppy --file --set=root /boot/vmlinuz
menuentry "Start NetbootCD-Neo $NBCDVER" {
linux /boot/vmlinuz quiet console=ttyS0,115200 console=tty0
initrd /boot/nbinit4.gz
}
menuentry "Boot netboot.xyz" {
chainloader /boot/netboot.xyz.efi
}
menuentry "Boot from hard disk" {
exit
}
EOF
grub-mkstandalone \
-O x86_64-efi \
-d "$GRUB_MODULES_DIR" \
--modules="iso9660 linux search search_fs_file normal configfile \
fat part_gpt part_msdos all_video gfxterm font \
boot echo halt reboot ls cat chain" \
--locales="" \
--themes="" \
-o "${WORK}/efifiles/EFI/BOOT/BOOTx64.EFI" \
"boot/grub/grub.cfg=${WORK}/grub-full.cfg"
# Size the FAT image from the actual EFI binary with headroom
EFI_SIZE=$(du -m "${WORK}/efifiles/EFI/BOOT/BOOTx64.EFI" | cut -f1)
IMG_SIZE=$(( EFI_SIZE + 8 ))
[ "$IMG_SIZE" -lt 16 ] && IMG_SIZE=16
dd if=/dev/zero of="${WORK}/efiboot.img" bs=1M count="${IMG_SIZE}"
mkfs.vfat -F 16 "${WORK}/efiboot.img"
mcopy -i "${WORK}/efiboot.img" -s "${WORK}/efifiles/EFI" ::/EFI
cp "${WORK}/efiboot.img" "${WORK}/iso/efiboot.img"
# Also copy the EFI tree into the ISO filesystem so that Windows-based USB
# preparation tools (which copy the filesystem rather than writing a raw image)
# end up with a UEFI-bootable stick.
cp -r "${WORK}/efifiles/EFI" "${WORK}/iso/"
# --- Build hybrid ISO (BIOS El Torito + UEFI El Torito) ---
# xorriso marks the alt-boot entry as EFI automatically and writes a proper
# GPT EFI System Partition entry; genisoimage/mkisofs do not set platform
# ID 0xEF, so UEFI firmware skips those entries.
xorriso -as mkisofs \
-r -J -l \
-b boot/isolinux/isolinux.bin \
-c boot/isolinux/boot.cat \
-no-emul-boot -boot-load-size 4 -boot-info-table \
-eltorito-alt-boot \
-e efiboot.img \
-no-emul-boot \
-isohybrid-gpt-basdat \
-o "${DONE}/NetbootCD-Neo-$NBCDVER.iso" \
"${WORK}/iso"
# --- Build wireless initrd ---
echo "Building wireless initrd..."
cp -a "${NBINIT}" "${WORK}/nbinit-wifi"
# lib/firmware in corepure64 is a symlink: lib/firmware -> ../usr/local/lib/firmware
# That target directory does not exist in the base image, so the symlink is
# dangling. Create the target so the symlink resolves; firmware TCZ packages
# install to usr/local/lib/firmware/ and will then be reachable at lib/firmware/
# where the kernel firmware loader expects them.
mkdir -p "${WORK}/nbinit-wifi/usr/local/lib/firmware"
if [ -e squashfs-root ]; then rm -rf squashfs-root; fi
for pkg in $WIFI_PKGS_ALL; do
if [ -s "${pkg}-x86_64.tcz" ]; then
unsquashfs "${pkg}-x86_64.tcz"
tar -C squashfs-root -c . | tar -C "${WORK}/nbinit-wifi" -x
rm -rf squashfs-root
fi
done
# --- Fix wireless module visibility and regulatory database ---
# wireless-regdb installs regulatory.db to /usr/local/share/wireless-regdb/files/
# but cfg80211 loads it via the kernel firmware API, which searches /lib/firmware/.
REGDB="${WORK}/nbinit-wifi/usr/local/share/wireless-regdb/files/regulatory.db"
[ -f "$REGDB" ] && cp "$REGDB" "${WORK}/nbinit-wifi/lib/firmware/regulatory.db"
# Build-time depmod cannot follow kernel.tclocal because that symlink has an
# absolute target (/usr/local/lib/modules/…) that doesn't exist on the build
# host. Instead we run depmod -a inside bootsync.sh, which executes
# synchronously during the TinyCore boot, where the symlink resolves correctly
# to the wireless TCZ content at /usr/local/lib/modules/.
#
# After depmod rebuilds modules.alias we replay hardware events with
# "udevadm trigger" so udev's MODALIAS rule (modprobe -bv $MODALIAS) picks up
# the newly indexed drivers, then "udevadm settle" blocks until every queued
# event — including driver loads — has finished. All interfaces are therefore
# present before the user reaches the netboot menu.
cat > "${WORK}/nbinit-wifi/opt/bootsync.sh" << 'BOOTSYNC'
#!/bin/sh
/usr/bin/sethostname box
depmod -a 2>/dev/null || true
# TCZ packages install libraries to /usr/local/lib which ldconfig doesn't
# search by default. Register it so every TCZ binary can find its libs.
mkdir -p /etc/ld.so.conf.d
echo '/usr/local/lib' > /etc/ld.so.conf.d/usrlocal.conf
ldconfig 2>/dev/null || true
udevadm trigger --action=add 2>/dev/null
udevadm settle --timeout=15 2>/dev/null || true
/opt/bootlocal.sh &
BOOTSYNC
chmod +x "${WORK}/nbinit-wifi/opt/bootsync.sh"
cd "${WORK}/nbinit-wifi"
find . | cpio -o -H 'newc' | gzip -c > "${DONE}/nbinit4-wifi.gz"
cd -
echo "Made wireless initrd: $(wc -c < "${DONE}/nbinit4-wifi.gz") bytes"
# Swap initrd in the ISO tree and rebuild for the wireless variant.
# The EFI binary is reused as-is since grub.cfg references /boot/nbinit4.gz
# by the same path in both ISOs.
cp "${DONE}/nbinit4-wifi.gz" "${WORK}/iso/boot/nbinit4.gz"
xorriso -as mkisofs \
-r -J -l \
-b boot/isolinux/isolinux.bin \
-c boot/isolinux/boot.cat \
-no-emul-boot -boot-load-size 4 -boot-info-table \
-eltorito-alt-boot \
-e efiboot.img \
-no-emul-boot \
-isohybrid-gpt-basdat \
-o "${DONE}/NetbootCD-Neo-$NBCDVER-wifi.iso" \
"${WORK}/iso"
chown -R 1000:1000 "${DONE}"
echo ""
echo "Build complete!"
echo " Base ISO: ${DONE}/NetbootCD-Neo-$NBCDVER.iso"
echo " Wifi-enabled ISO: ${DONE}/NetbootCD-Neo-$NBCDVER-wifi.iso"