Skip to content

Commit dedaae3

Browse files
committed
WIP: Reduced userland full launch
1 parent 63b2450 commit dedaae3

File tree

2 files changed

+269
-0
lines changed

2 files changed

+269
-0
lines changed

.github/workflows/qemu.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# SPDX-FileCopyrightText: 2023 fosslinux <[email protected]>
2+
#
3+
# SPDX-License-Identifier: GPL-3.0-or-later
4+
5+
name: Run under QEMU
6+
7+
on:
8+
workflow_dispatch:
9+
pull_request:
10+
push:
11+
branches:
12+
- master
13+
14+
jobs:
15+
build:
16+
name: Run under bubblewrap
17+
runs-on: ubuntu-22.04
18+
steps:
19+
- name: Install qemu
20+
run: sudo apt-get install qemu-system-x86
21+
- name: enable kvm
22+
run: |
23+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
24+
sudo udevadm control --reload-rules
25+
sudo udevadm trigger --name-match=kvm
26+
- name: Checkout repo
27+
uses: actions/checkout@v4
28+
with:
29+
submodules: recursive
30+
# There is a strange bug(?) in nongnu, when you clone a git repository
31+
# against a commit != HEAD with depth=1, it errors out.
32+
fetch-depth: 0
33+
- name: Query cache for sources
34+
id: cache
35+
uses: actions/cache/restore@v4
36+
with:
37+
path: |
38+
mirror
39+
mirror-state
40+
key: cache-${{ hashFiles('steps/*/sources') }}
41+
restore-keys: |
42+
cache-
43+
- name: Get sources
44+
if: steps.cache.outputs.cache-hit != 'true'
45+
run: mkdir -p mirror mirror-state && ./mirror.sh mirror mirror-state
46+
- name: Cache sources
47+
if: steps.cache.outputs.cache-hit != 'true'
48+
uses: actions/cache/save@v4
49+
with:
50+
path: |
51+
mirror
52+
mirror-state
53+
key: cache-${{ hashFiles('steps/*/sources') }}
54+
- name: Run bootstrap
55+
run: bash qemu.sh

qemu.sh

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
#!/usr/bin/env sh
2+
3+
# SPDX-FileCopyrightText: 2025 Alexandre Gomes Gaigalas <[email protected]>
4+
#
5+
# SPDX-License-Identifier: GPL-3.0-or-later
6+
7+
set -euf
8+
9+
# Runtime dependencies
10+
SH="${SH:-$(command -v sh)}"
11+
12+
# Userland dependencies
13+
CAT="${CAT:-$(command -v cat)}"
14+
DD="${DD:-$(command -v dd)}"
15+
FIND="${FIND:-$(command -v find)}"
16+
MKDIR="${MKDIR:-$(command -v mkdir)}"
17+
WC="${WC:-$(command -v wc)}"
18+
19+
# Emulation dependencies
20+
QEMU="${QEMU:-$(command -v qemu-system-i386)}"
21+
MKFIFO="${MKFIFO:-$(command -v mkfifo)}"
22+
NC="${NC:-$(command -v nc)}"
23+
24+
# Don't look PATH anymore
25+
PATH=
26+
27+
# Remember home folder
28+
SH_FILE="$PWD/$0"
29+
LB_ROOT="${SH_FILE%\/*}"
30+
31+
# Reads from a pipe from `find` and writes a builder-hex0 compatible src,
32+
# optionally adding a $1 prefix to the destination filename
33+
to_builder_hex0_src () {
34+
local prefix="${1:-}"
35+
local fs_entry=
36+
local wc_out=
37+
38+
while read -r fs_entry; do
39+
case $fs_entry in
40+
*'/.git'*) continue;; # Ignore lengthy .git filetrees
41+
esac
42+
43+
if [ -d "$fs_entry" ]; then
44+
printf %s\\n "src 0 ${fs_entry#\.}"
45+
else
46+
wc_out="$($WC -c "$fs_entry")"
47+
printf %s\\n "src ${wc_out%% *} ${prefix}${fs_entry#\.}"
48+
$CAT "$fs_entry"
49+
fi
50+
51+
done
52+
}
53+
54+
# Walk the manifest looking for sources and does $1 on them
55+
walk_manifest_distfiles () {
56+
local action=$1
57+
local manifest_entry=
58+
local entry=
59+
local file=
60+
local walked=":"
61+
62+
while read -r manifest_entry || [ -n "$manifest_entry" ]; do
63+
case $manifest_entry in
64+
'improve: get_network'*)
65+
break
66+
;;
67+
'build:'*)
68+
entry="${manifest_entry#'build: '}"
69+
entry="${entry%% *}"
70+
[ -e "./steps/${entry}/sources" ] || continue
71+
while read -r line; do
72+
file="${line##* }"
73+
if [ ! -e "./mirror/$file" ]; then
74+
file="${line##*\/}"
75+
file="${file%% *}"
76+
fi
77+
case $walked in *":$file:"*) continue;;esac
78+
walked="$walked$file:"
79+
$action "./distfiles/$file"
80+
done < "./steps/${entry}/sources"
81+
;;
82+
esac
83+
done < "./steps/manifest"
84+
}
85+
86+
cd "$LB_ROOT"
87+
88+
$MKDIR "$LB_ROOT/target"
89+
$MKDIR "$LB_ROOT/target/steps"
90+
91+
$CAT <<@ > "$LB_ROOT/steps/bootstrap.cfg"
92+
ARCH=x86
93+
ARCH_DIR=x86
94+
FORCE_TIMESTAMPS=False
95+
CHROOT=False
96+
UPDATE_CHECKSUMS=False
97+
JOBS=6
98+
SWAP_SIZE=0
99+
FINAL_JOBS=6
100+
INTERNAL_CI=False
101+
INTERACTIVE=False
102+
BARE_METAL=False
103+
QEMU=True
104+
DISK=sda
105+
KERNEL_BOOTSTRAP=True
106+
BUILD_KERNELS=True
107+
CONFIGURATOR=False
108+
MIRRORS="http://10.0.2.2:42645"
109+
MIRRORS_LEN=1
110+
@
111+
112+
# Creates ./target/init.builder-hex0-src
113+
{
114+
printf %s\\n "Copying stage0-posix..." 1>&2
115+
cd "$LB_ROOT/seed/stage0-posix";
116+
$FIND ./ | to_builder_hex0_src
117+
118+
printf %s\\n "Copying seed folder..." 1>&2
119+
cd "$LB_ROOT/seed";
120+
$FIND ./ -maxdepth 1 | to_builder_hex0_src
121+
122+
# Write steps
123+
printf %s\\n "Copying steps..." 1>&2
124+
cd "$LB_ROOT"
125+
printf %s\\n "src 0 /steps"
126+
$FIND ./steps | to_builder_hex0_src
127+
128+
# Write distfiles as /external/distfiles
129+
cd "$LB_ROOT";
130+
printf %s\\n "src 0 /external"
131+
printf %s\\n "src 0 /external/distfiles"
132+
printf %s\\n "Copying distfiles..." 1>&2
133+
walk_manifest_distfiles echo | to_builder_hex0_src "/external"
134+
135+
# Initialization sequence
136+
printf %s\\n "src 0 /dev"
137+
printf %s\\n "src 0 /bootstrap-seeds"
138+
printf %s\\n "src 0 /bootstrap-seeds/POSIX"
139+
printf %s\\n "src 0 /bootstrap-seeds/POSIX/x86"
140+
printf %s\\n "hex0 /x86/hex0_x86.hex0 /bootstrap-seeds/POSIX/x86/hex0-seed"
141+
printf %s\\n "hex0 /x86/kaem-minimal.hex0 /bootstrap-seeds/POSIX/x86/kaem-optional-seed"
142+
printf %s\\n "hex0 /x86/kaem-minimal.hex0 /init"
143+
printf %s\\n "/bootstrap-seeds/POSIX/x86/kaem-optional-seed /kaem.x86"
144+
} >> ./target/init.builder-hex0-src
145+
146+
# Creates the builder_hex0 image
147+
printf %s\\n "Creating image (this might take a while)..." 1>&2
148+
$DD if=/dev/zero of="target/init.img" bs=512 count=33554432
149+
$DD if=seed/stage0-posix/bootstrap-seeds/NATIVE/x86/builder-hex0-x86-stage1.img of="target/init.img" conv=notrunc
150+
$DD if="builder-hex0/builder-hex0-x86-stage2.hex0" of="target/init.img" seek=1 bs=512 conv=notrunc
151+
152+
STAGE2_LEN="$($WC -c builder-hex0/builder-hex0-x86-stage2.hex0)"
153+
STAGE2_LEN="${STAGE2_LEN% *}"
154+
if [ $((STAGE2_LEN % 512)) = 0 ]; then
155+
STAGE2_SECTORS=$((STAGE2_LEN / 512))
156+
else
157+
STAGE2_SECTORS=$((STAGE2_LEN / 512 + 1))
158+
fi
159+
SRC_LBA_SECTOR=$((STAGE2_SECTORS + 1))
160+
161+
# Appends the generated source to the image
162+
printf %s\\n "Adding sources to image..." 1>&2
163+
$DD if="target/init.builder-hex0-src" of="target/init.img" seek=$SRC_LBA_SECTOR bs=512 conv=notrunc
164+
165+
# Starts a simple HTTP file server for ./distfiles in the background
166+
{
167+
$MKFIFO $LB_ROOT/target/httpmirror.fifo
168+
while true; do
169+
$NC -l 127.0.0.1 42645 < $LB_ROOT/target/httpmirror.fifo | {
170+
ret="$(printf \\r)"
171+
while read -r line; do
172+
case $line in
173+
'GET /'*)
174+
distfile="${line#* \/}"
175+
distfile="${distfile% *}"
176+
;;
177+
"$ret")
178+
break
179+
;;
180+
*)
181+
continue
182+
;;
183+
esac
184+
done
185+
if ! [ -f "$LB_ROOT/mirror/$distfile" ]; then
186+
echo "HTTP/1.1 404 Not Found"
187+
echo "Content-Length: 0"
188+
echo "Connection: close"
189+
printf \\r\\n\\r\\n
190+
else
191+
echo "HTTP/1.1 200 OK"
192+
echo "Content-Length: $($WC -c "$LB_ROOT/mirror/$distfile")"
193+
echo "Connection: close"
194+
printf \\r\\n\\r\\n
195+
$CAT "$LB_ROOT/mirror/$distfile"
196+
fi
197+
} > $LB_ROOT/target/httpmirror.fifo
198+
done
199+
} &
200+
HTTPMIRROR_PID=$!
201+
202+
# Launch image
203+
$QEMU \
204+
--enable-kvm \
205+
-m 4G \
206+
-smp 6 \
207+
-nographic \
208+
-no-reboot \
209+
-nic user,ipv6=off,model=e1000 \
210+
-drive file="target/init.img",format=raw \
211+
-machine kernel-irqchip=split || :
212+
213+
kill -9 $HTTPMIRROR_PID
214+

0 commit comments

Comments
 (0)