buninu-linux 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +547 -190
- package/build-uki.sh +4 -2
- package/fetch-alpine.sh +78 -43
- package/index.js +4 -1
- package/initramfs/bin/ip +630 -0
- package/initramfs/bin/mount +401 -0
- package/initramfs/bin/poweroff +10 -0
- package/initramfs/bin/ps +256 -0
- package/initramfs/bin/reboot +10 -0
- package/initramfs/bin/tar +169 -0
- package/initramfs/bin/top +129 -0
- package/initramfs/bin/umount +71 -0
- package/initramfs/buninu/apps/bunmsh/CHANGELOG.md +36 -0
- package/initramfs/buninu/apps/bunmsh/README.md +7 -0
- package/initramfs/buninu/apps/bunmsh/package.json +1 -1
- package/initramfs/buninu/apps/bunmsh/src/fancy-ls.js +29 -14
- package/initramfs/buninu/apps/bunmsh/src/line-edit.js +43 -0
- package/initramfs/buninu/apps/bunmsh/src/main.js +15 -1
- package/initramfs/buninu/apps/bunmsh/src/mouse.js +29 -4
- package/initramfs/buninu/apps/bunmsh/src/shell.js +9 -1
- package/initramfs/buninu/apps/bunmsh/test/shell1.test.js +70 -0
- package/initramfs/buninu/apps/jsmdcui/CHANGELOG.md +10 -0
- package/initramfs/buninu/apps/jsmdcui/README.md +2 -0
- package/initramfs/buninu/apps/jsmdcui/package.json +1 -1
- package/initramfs/buninu/apps/jsmdcui/runtime/help/commands.md +4 -1
- package/initramfs/buninu/apps/jsmdcui/runtime/help/help.md +2 -0
- package/initramfs/buninu/apps/jsmdcui/src/index.js +40 -13
- package/initramfs/buninu/package.json +1 -1
- package/initramfs/init.js +164 -11
- package/initramfs/lib/dlopen.js +121 -0
- package/initramfs/lib/document.js +6 -0
- package/initramfs/lib/modprobe.js +235 -0
- package/initramfs/lib/power.js +35 -0
- package/initramfs/usr/share/doc/buninu-linux/ip.md +155 -0
- package/initramfs/usr/share/doc/buninu-linux/mount.md +155 -0
- package/initramfs/usr/share/doc/buninu-linux/poweroff.md +15 -0
- package/initramfs/usr/share/doc/buninu-linux/ps.md +94 -0
- package/initramfs/usr/share/doc/buninu-linux/reboot.md +15 -0
- package/initramfs/usr/share/doc/buninu-linux/tar.md +73 -0
- package/initramfs/usr/share/doc/buninu-linux/top.md +23 -0
- package/initramfs/usr/share/doc/buninu-linux/umount.md +48 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -22,84 +22,335 @@
|
|
|
22
22
|
+ **BUNinu Is Not Unix** 🐮
|
|
23
23
|
+ **幫你牛** 🐂 ・ **Bunに入魂** 🔥
|
|
24
24
|
- <img src="https://raw.githubusercontent.com/jjtseng93/buninu/main/icon.png" width="256">
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
- [Table of contents](#contents)
|
|
29
|
+
- .
|
|
25
30
|
- Still in the early stages
|
|
26
|
-
|
|
27
|
-
*
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
*
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
- [Video here](https://www.reddit.com/r/bun/comments/1wkpraj/buninu_linux_a_distro_with_bun_as_pid_1): Booted successfully on real x86-64 UEFI hardware with `--real`:
|
|
32
|
+
* Bun reaches its interactive REPL
|
|
33
|
+
* start() starts the Buninu userspace shell
|
|
34
|
+
* `cfg.disk` + shell `mount` mounts local disks
|
|
35
|
+
* `cfg.net` loads common wired NIC and Android USB-tethering drivers
|
|
36
|
+
* Android phone USB tethering over RNDIS has been tested successfully, allowing Buninu Linux to access the Internet through an Android phone
|
|
37
|
+
* IP addresses and routes are configured manually because the image does not yet include a DHCP client.
|
|
38
|
+
* The bundled `jmi` editor, jsmdcui editor/terminal multitasking, and local JavaScript execution also work.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
- The hello-world EFI application in [Section 1](#1-hello-world) is the starting point that the UKI replaces
|
|
34
43
|
- It still builds, and it is the quickest way to check whether the disk image and firmware path work at all.
|
|
35
44
|
|
|
36
45
|
## Quick start
|
|
37
46
|
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
* So both shells work on the same files
|
|
44
|
-
* (`~` differs between them, the full path does not)
|
|
47
|
+
- This guide builds a bootable `buninu-linux-<version>.img`
|
|
48
|
+
- The documented build environment is Debian 13 under Termux PRoot
|
|
49
|
+
- A regular Debian installation works as well.
|
|
50
|
+
- For a source checkout, clone into the Termux home so native Termux and PRoot
|
|
51
|
+
can share it; `~` differs between them, but the absolute path is the same.
|
|
45
52
|
|
|
46
53
|
### Steps
|
|
47
|
-
|
|
48
|
-
-
|
|
54
|
+
|
|
55
|
+
- Before anything, install Bun in Debian first:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
apt update
|
|
59
|
+
apt install curl unzip
|
|
60
|
+
curl -fsSL https://bun.sh/install | bash
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- Small tip: The below `apt install` command shows in the terminal when you run -b without the needed tools
|
|
64
|
+
|
|
65
|
+
#### Build directly with bun x
|
|
66
|
+
|
|
67
|
+
Install the build tools, enter a directory where
|
|
68
|
+
you want to keep the finished image, then run the published package:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
apt install binutils-mingw-w64-x86-64 cpio curl dosfstools fakeroot mtools parted unzip
|
|
72
|
+
|
|
73
|
+
mkdir -p /data/data/com.termux/files/home/buninu-build
|
|
74
|
+
cd /data/data/com.termux/files/home/buninu-build
|
|
75
|
+
|
|
76
|
+
$HOME/.bun/bin/bun x buninu-linux --version
|
|
77
|
+
|
|
78
|
+
$HOME/.bun/bin/bun x buninu-linux -fb --real --export
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`--export` copies the completed `vda.img` out of bunx's package directory and
|
|
82
|
+
into the directory where the command was invoked, as
|
|
83
|
+
`buninu-linux-<version>.img`. Use the exact exported filename printed by the
|
|
84
|
+
command when writing the USB drive.
|
|
85
|
+
|
|
86
|
+
#### Or build from a source checkout
|
|
87
|
+
|
|
88
|
+
In native Termux:
|
|
89
|
+
|
|
49
90
|
- git clone https://github.com/jjtseng93/buninu-linux.git ~/buninu-linux
|
|
50
91
|
|
|
51
|
-
|
|
92
|
+
In Debian 13 under PRoot:
|
|
93
|
+
|
|
52
94
|
- apt install binutils-mingw-w64-x86-64 cpio curl dosfstools fakeroot mtools parted unzip
|
|
53
95
|
- cd /data/data/com.termux/files/home/buninu-linux
|
|
54
|
-
- bun ./index.js -fb
|
|
55
|
-
*
|
|
96
|
+
- bun ./index.js -fb --real --export
|
|
97
|
+
* Fetches from Alpine/Bun
|
|
98
|
+
* Selects the physical-hardware modules
|
|
99
|
+
* Builds `vda.img`
|
|
100
|
+
* Exports it to `buninu-linux-<version>.img`
|
|
56
101
|
|
|
57
|
-
####
|
|
58
|
-
- cd ~/buninu-linux
|
|
59
|
-
- bun ./index.js -r
|
|
60
|
-
* boot it
|
|
102
|
+
#### Write the image to a USB drive
|
|
61
103
|
|
|
62
|
-
|
|
63
|
-
|
|
104
|
+
Write the complete exported image (or `vda.img` when not using `--export`), not
|
|
105
|
+
the FAT partition inside it, to a USB drive. The source filename below is an
|
|
106
|
+
example; replace it with the exact name printed by the build. The destination
|
|
107
|
+
is also only an example: identify the correct whole-disk device first, because
|
|
108
|
+
this overwrites it completely.
|
|
64
109
|
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
init.js: loading physical musl libc for FFI
|
|
69
|
-
init.js: mounted /proc, /sys, /dev, /tmp
|
|
70
|
-
network: lo 127.0.0.1/8
|
|
71
|
-
network: eth0 10.0.2.15/24 via 10.0.2.2
|
|
72
|
-
fetch example.com: HTTP 200, text/html
|
|
110
|
+
```sh
|
|
111
|
+
sudo dd if='buninu-linux-<version>.img' of=/dev/sdX bs=4M conv=fsync status=progress
|
|
112
|
+
```
|
|
73
113
|
|
|
114
|
+
#### Booting from the USB drive
|
|
115
|
+
|
|
116
|
+
Boot that drive as x86-64 UEFI media. The UKI is unsigned, so disable Secure
|
|
117
|
+
Boot unless you sign it yourself. A successful physical boot reaches the local
|
|
118
|
+
display and USB keyboard with a welcome ending like this:
|
|
119
|
+
|
|
120
|
+
```text
|
|
74
121
|
Welcome to Buninu Linux!
|
|
75
122
|
Bun 1.4.2 is now PID 1
|
|
76
|
-
|
|
77
123
|
Type start() to run buninu --local
|
|
124
|
+
Configuration getters: cfg.all, cfg.disk, cfg.net, cfg.power
|
|
125
|
+
|
|
78
126
|
bun-repl>
|
|
79
127
|
```
|
|
80
128
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
129
|
+
If this welcome is not visible, later kernel messages may simply have scrolled
|
|
130
|
+
over it on the same console. Press Enter at an empty REPL prompt; an empty or
|
|
131
|
+
whitespace-only line prints the welcome and current `cfg.*` getter list again.
|
|
132
|
+
|
|
133
|
+
Load only the subsystem needed, then enter the Buninu shell:
|
|
134
|
+
|
|
135
|
+
```js
|
|
136
|
+
cfg.net // wired NIC and Android USB-tethering drivers
|
|
137
|
+
cfg.disk // SATA/NVMe/USB storage drivers and detected block devices
|
|
138
|
+
cfg.power // battery, AC, button and thermal drivers
|
|
139
|
+
start()
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
There is no DHCP client yet; configure a detected wired interface with `ip` as
|
|
143
|
+
described under [Basic configuration](#basic-configuration). Run `poweroff` for a synced
|
|
144
|
+
shutdown. After editing the initramfs, `bun ./index.js -b --real --export` rebuilds the
|
|
145
|
+
image; `-h` lists all flags.
|
|
146
|
+
|
|
147
|
+
## Using Buninu Linux
|
|
148
|
+
|
|
149
|
+
### Basic configuration
|
|
150
|
+
|
|
151
|
+
Real hardware is the primary target. Boot the USB drive with Secure Boot
|
|
152
|
+
disabled unless you have signed the UKI yourself. The physical display and USB
|
|
153
|
+
keyboard provide the `bun-repl>` prompt.
|
|
154
|
+
|
|
155
|
+
Load only the hardware subsystem you need:
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
cfg.net
|
|
159
|
+
cfg.disk
|
|
160
|
+
cfg.power
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`cfg.net` loads the packaged wired-network and Android USB-tethering drivers and prints detected
|
|
164
|
+
interfaces and MAC addresses. There is no DHCP client yet, so configure the
|
|
165
|
+
interface manually after entering the Buninu shell with `start()`:
|
|
84
166
|
|
|
85
|
-
|
|
167
|
+
```sh
|
|
168
|
+
ip link set eth0 up
|
|
169
|
+
ip addr add 192.168.1.50/24 dev eth0
|
|
170
|
+
ip route add default via 192.168.1.1
|
|
171
|
+
```
|
|
86
172
|
|
|
87
|
-
|
|
88
|
-
|
|
173
|
+
The real image initializes `/etc/resolv.conf` with `1.1.1.1` and `8.8.8.8`;
|
|
174
|
+
replace them if your network requires different DNS servers. `cfg.disk` loads
|
|
175
|
+
common SATA/PATA/SCSI, NVMe/VMD and USB-storage drivers so detected disks and
|
|
176
|
+
partitions appear in `/dev`. To inspect a filesystem without mounting it:
|
|
89
177
|
|
|
90
178
|
```sh
|
|
91
|
-
|
|
179
|
+
mount -fv /dev/sda1 /mnt
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Run `poweroff` for a synced shutdown.
|
|
183
|
+
|
|
184
|
+
### Editor quick start
|
|
185
|
+
|
|
186
|
+
The bundled `jmi` terminal editor works without a network connection:
|
|
187
|
+
|
|
188
|
+
```sh
|
|
189
|
+
jmi hlw.js
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- The recommended `jmi` color theme is `cmc-tc`
|
|
193
|
+
- Set it by:
|
|
194
|
+
* Press `Ctrl-E`
|
|
195
|
+
* Type `theme ` (including the trailing space)
|
|
196
|
+
* Press `Tab`, select it with up/dn keys
|
|
197
|
+
* Press `Enter`.
|
|
198
|
+
|
|
199
|
+
- Enter and save(Ctrl-S) this content:
|
|
200
|
+
|
|
201
|
+
```js
|
|
202
|
+
console.log("Hello world from real hardware");
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
After leaving the editor with `Ctrl-Q`, run it locally:
|
|
206
|
+
|
|
207
|
+
```sh
|
|
208
|
+
bun hlw.js
|
|
92
209
|
```
|
|
93
210
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
211
|
+
If `Enter` is not recognized in a particular terminal, try `Ctrl-J` or
|
|
212
|
+
`Ctrl-M`.
|
|
213
|
+
|
|
214
|
+
### Panes, terminals, and tabs
|
|
215
|
+
|
|
216
|
+
`jmi` and jsmdcui can keep editors and terminal sessions open together. Press
|
|
217
|
+
`Ctrl-E`, type `term`, and press `Enter` to open the default Buninu shell in a
|
|
218
|
+
terminal pane. `term COMMAND` starts a specific command instead. Use `vsplit`,
|
|
219
|
+
`hsplit`, or `tab` from the same `Ctrl-E` command prompt to create another
|
|
220
|
+
editor pane or tab; each command optionally accepts a filename. From an editor
|
|
221
|
+
pane, `Ctrl-T` is the direct shortcut for a new empty tab.
|
|
222
|
+
|
|
223
|
+
#### Pane and tab controls
|
|
224
|
+
|
|
225
|
+
| Input | Result |
|
|
226
|
+
| --- | --- |
|
|
227
|
+
| Click a pane | Focus that editor or terminal pane. |
|
|
228
|
+
| `Ctrl-T` in an editor pane | Open a new empty tab. |
|
|
229
|
+
| `Ctrl-W` once | Move to the next pane in the current tab, from either an editor or terminal pane. |
|
|
230
|
+
| `Alt-T` | Move to the next tab. |
|
|
231
|
+
| **`Ctrl-W` twice quickly** | **Important escape hatch:** move to the next tab like `Alt-T`, or create an editor tab when needed. See the detailed explanation below. |
|
|
232
|
+
| `Esc` in a terminal pane | Close that terminal pane and return to its previous editor buffer |
|
|
233
|
+
| `Ctrl-Q` or `Alt-Q` in an editor pane | Close the current editor UI. |
|
|
234
|
+
|
|
235
|
+
**Why this escape hatch is important:** A terminal pane must forward almost every key combination unchanged to the
|
|
236
|
+
shell or application running inside it. `Ctrl-W` is therefore the one
|
|
237
|
+
multitasking escape key that jsmdcui intercepts: it lets you leave the active
|
|
238
|
+
terminal without terminating the work inside it. Press it once to move to the
|
|
239
|
+
next pane in the current tab. Press it twice quickly to move to the next tab.
|
|
240
|
+
|
|
241
|
+
The double press is especially important in an all-terminal workspace. When
|
|
242
|
+
the current tab is the rightmost tab and every existing tab contains only
|
|
243
|
+
terminal panes, it creates a new editor tab instead of wrapping back to the
|
|
244
|
+
first terminal tab. In every other case it performs the normal next-tab cycle.
|
|
245
|
+
Use `Esc` only when you actually want to close the current terminal pane.
|
|
246
|
+
|
|
247
|
+
### Using Bun Modern Shell
|
|
248
|
+
|
|
249
|
+
bunmsh is the dependency-free, mksh-inspired shell bundled with Buninu. Its
|
|
250
|
+
main features are:
|
|
251
|
+
|
|
252
|
+
- Lines beginning with `Bun.*` run as JavaScript; returned values are printed
|
|
253
|
+
and promises are awaited automatically. Use `Bun.e;` or `Bun.e,` for
|
|
254
|
+
arbitrary JavaScript.
|
|
255
|
+
- Lightweight cwd tabs keep several working directories ready. In bunmsh,
|
|
256
|
+
`Ctrl-T` creates or cycles right through tabs, while `Alt-T` cycles left.
|
|
257
|
+
* Also useful cmds: `tab n`, `tab c`(Alt-C)
|
|
258
|
+
- Shell variables and JavaScript share a live variable table by `$.`, and `Bun.sha`
|
|
259
|
+
can retain JavaScript values across commands and cwd tabs.
|
|
260
|
+
- Saved history, Bash/Fish history import, completions, and ghost suggestions
|
|
261
|
+
are available interactively.
|
|
262
|
+
- `serve [directory]` starts a browsable HTTP file server. Together with
|
|
263
|
+
Android USB tethering, it provides a simple way to transfer files between
|
|
264
|
+
Buninu Linux and the connected phone.
|
|
265
|
+
- Cross-platform builtins and PATH-fallback commands.
|
|
266
|
+
- `Ctrl-U` removes and saves the text before the cursor; press it again at the
|
|
267
|
+
beginning of the line to restore it. `Ctrl-K` independently toggles the text
|
|
268
|
+
after the cursor when at the end of the line.
|
|
269
|
+
- Unquoted pathname patterns use `Bun.Glob` and follow directory symbolic
|
|
270
|
+
links used as intermediate path components, as traditional shells do. This
|
|
271
|
+
matters for sysfs, where class entries are normally links. For example:
|
|
98
272
|
|
|
99
273
|
```sh
|
|
100
|
-
|
|
274
|
+
ls /sys/class/net/*/device
|
|
101
275
|
```
|
|
102
276
|
|
|
277
|
+
For a readable process overview, run:
|
|
278
|
+
|
|
279
|
+
```sh
|
|
280
|
+
pspac
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
`pspac` shows the real `PID COMMAND` process table and highlights each command
|
|
284
|
+
line as shell syntax with micro's Monokai colours. Leading directories are
|
|
285
|
+
dimmed so the program name stands out. Use `pspa` for the same table as plain
|
|
286
|
+
text.
|
|
287
|
+
|
|
288
|
+
See the [bunmsh repository](https://github.com/jjtseng93/bunmsh) for its full
|
|
289
|
+
syntax, interactive controls, builtins, and current compatibility details.
|
|
290
|
+
|
|
291
|
+
## Commands inside /bin
|
|
292
|
+
|
|
293
|
+
| command | does | manual |
|
|
294
|
+
| --- | --- | --- |
|
|
295
|
+
| `mount` | `mount(2)` with type detection, `-o` parsing, `LABEL=`/`UUID=`, bind/move/remount; loads required filesystem and disk modules | `mount --help` → `/usr/share/doc/buninu-linux/mount.md` |
|
|
296
|
+
| `umount` | `umount2(2)` with `-l`, `-f`, `-R` | `umount --help` |
|
|
297
|
+
| `ip` | iproute2 grammar over `SIOC*` ioctls and `/proc/net`: `link`, `addr`, `route`, `neigh` | `ip --help` |
|
|
298
|
+
| `ps` | composable process fields from `/proc`; also exports its snapshot and single-row formatter for other commands | `ps --help` |
|
|
299
|
+
| `top` | periodically refreshes the process snapshot and rows supplied by `ps` | `top --help` |
|
|
300
|
+
| `poweroff` | sync pending writes and power off through the Linux reboot system call | `poweroff --help` |
|
|
301
|
+
| `reboot` | sync pending writes and restart through the shared Linux reboot logic | `reboot --help` |
|
|
302
|
+
| `tar` | create, extract, or list tar archives with gzip and zstd compression through `Bun.Archive` | `tar --help` |
|
|
303
|
+
|
|
304
|
+
Besides `bun` (and `sh`/`node` pointing at it), `/bin` includes eight commands
|
|
305
|
+
implemented as Bun scripts.
|
|
306
|
+
|
|
307
|
+
The small `tar` follows the current `Bun.Archive` boundary: extraction
|
|
308
|
+
restores directories and symbolic links, while hard links are skipped by Bun
|
|
309
|
+
1.4.3. Creation stores regular files but not Unix metadata, links, or empty
|
|
310
|
+
directories, and listing reports regular files only. It supports gzip and
|
|
311
|
+
Bun's built-in zstd, not xz or bzip2.
|
|
312
|
+
|
|
313
|
+
`--help` renders each Markdown manual in the terminal. Common examples:
|
|
314
|
+
|
|
315
|
+
```sh
|
|
316
|
+
mount /dev/sda1 /mnt --mkdir
|
|
317
|
+
mount -fv /dev/sda1 /mnt
|
|
318
|
+
mount -t tmpfs -o size=64M tmpfs /tmp/x
|
|
319
|
+
mount -t ntfs3 -o force /dev/sda3 /mnt/windows
|
|
320
|
+
umount /mnt
|
|
321
|
+
umount -R /mnt
|
|
322
|
+
|
|
323
|
+
ip link set eth0 up
|
|
324
|
+
ip addr add 192.168.1.50/24 dev eth0
|
|
325
|
+
ip route add default via 192.168.1.1
|
|
326
|
+
|
|
327
|
+
ip -br addr && ip route
|
|
328
|
+
ip addr replace 192.168.1.50/24 dev eth0
|
|
329
|
+
ip route replace default via 192.168.1.1
|
|
330
|
+
|
|
331
|
+
ps -eo pid,args
|
|
332
|
+
ps -ef
|
|
333
|
+
ps aux
|
|
334
|
+
pspac
|
|
335
|
+
top
|
|
336
|
+
top -b -n 1
|
|
337
|
+
|
|
338
|
+
poweroff
|
|
339
|
+
reboot
|
|
340
|
+
|
|
341
|
+
tar cvf /tmp/buninu.tar README.md package.json
|
|
342
|
+
tar tvf /tmp/buninu.tar
|
|
343
|
+
mkdir -p /tmp/buninu-copy
|
|
344
|
+
tar xvf /tmp/buninu.tar -C /tmp/buninu-copy
|
|
345
|
+
|
|
346
|
+
# Add z to create a gzip-compressed archive
|
|
347
|
+
tar czvf /tmp/buninu.tar.gz README.md package.json
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
## Environment and dependencies
|
|
351
|
+
|
|
352
|
+
### Build environment
|
|
353
|
+
|
|
103
354
|
The baseline is the stock Debian 13 (trixie) OCI image, which is also what this
|
|
104
355
|
PRoot is; a dependency is anything that image does not already have.
|
|
105
356
|
`debian:13` and `debian:13-slim` carry the same 78 packages and identical
|
|
@@ -110,7 +361,16 @@ locales — so `debian:13-slim` is the better starting point at 105 MB against
|
|
|
110
361
|
The base image already provides `bash`, GNU `tar`, `gzip`, `sha256sum`,
|
|
111
362
|
`mknod`, `find`, `sort`, `mkdir`, `mktemp`, `cp`, `rm`, `chmod`, `truncate`,
|
|
112
363
|
`dd`, `printf`, `awk` and `dirname`, all used by these scripts as they are.
|
|
113
|
-
Everything else has to be added.
|
|
364
|
+
Everything else has to be added.
|
|
365
|
+
|
|
366
|
+
### Buninu Linux ([Section 2](#2-buninu-linux-bun-as-pid-1))
|
|
367
|
+
|
|
368
|
+
Buninu Linux needs no compiler: Bun is downloaded as a prebuilt binary and the
|
|
369
|
+
UKI is assembled with `objcopy`.
|
|
370
|
+
|
|
371
|
+
```sh
|
|
372
|
+
apt install binutils-mingw-w64-x86-64 cpio curl dosfstools fakeroot mtools parted unzip
|
|
373
|
+
```
|
|
114
374
|
|
|
115
375
|
* **`binutils-mingw-w64-x86-64`** — `x86_64-w64-mingw32-objcopy` appends the
|
|
116
376
|
`.osrel`, `.cmdline`, `.linux` and `.initrd` sections to the EFI stub, and
|
|
@@ -130,30 +390,35 @@ Everything else has to be added. For Section 2:
|
|
|
130
390
|
* **`parted`** — writes the protective MBR, the primary and backup GPT, and the
|
|
131
391
|
ESP partition entry with its type GUID.
|
|
132
392
|
* **`unzip`** — extracts the `bun` binary from the release zip.
|
|
393
|
+
* **`bun`** (or **`node`**) — runs `index.js` in the build environment.
|
|
394
|
+
+ Under bun, `--readme` renders the Markdown; under node it is printed as-is.
|
|
133
395
|
|
|
134
|
-
|
|
396
|
+
### Hello world ([Section 1](#1-hello-world))
|
|
397
|
+
|
|
398
|
+
The hello-world EFI application needs the C/PE toolchain plus the shared disk
|
|
399
|
+
image tools:
|
|
400
|
+
|
|
401
|
+
```sh
|
|
402
|
+
apt install clang lld dosfstools mtools parted
|
|
403
|
+
```
|
|
135
404
|
|
|
136
|
-
* **`
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
405
|
+
* **`clang`** — compiles `hello/hello.c` to a PE32+ object with
|
|
406
|
+
`--target=x86_64-pc-win32-coff`. It resolves to `clang-19` on trixie.
|
|
407
|
+
* **`lld`** — provides `lld-link`, which links `hello/hello.obj` into an EFI
|
|
408
|
+
application with `/subsystem:efi_application`. It resolves to `lld-19` on
|
|
409
|
+
trixie.
|
|
410
|
+
* **`dosfstools`**, **`mtools`** and **`parted`** — create the FAT ESP and wrap
|
|
411
|
+
it in the GPT `vda.img` through the shared `build-image.sh`.
|
|
142
412
|
|
|
143
|
-
|
|
413
|
+
### Retired native bootstrap
|
|
144
414
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
Resolves to `clang-19` on trixie.
|
|
149
|
-
* **`lld`** *(Section 1 only)* — `lld-link` links `hello/hello.obj` into an EFI
|
|
150
|
-
application (`/subsystem:efi_application`), and the same package backs
|
|
151
|
-
`clang -fuse-ld=lld` for the bootstrap. Resolves to `lld-19`.
|
|
415
|
+
The retired `test/build-init-bootstrap.sh` also needs `clang lld`. It compiles
|
|
416
|
+
the historical freestanding x86-64 `/init`; the current Buninu Linux path does
|
|
417
|
+
not use or compile it.
|
|
152
418
|
|
|
153
|
-
|
|
154
|
-
use.
|
|
419
|
+
## Implementation details
|
|
155
420
|
|
|
156
|
-
|
|
421
|
+
### 1. Hello world
|
|
157
422
|
|
|
158
423
|
- `hello/hello.c` is a freestanding PE32+ EFI application installed at the
|
|
159
424
|
removable media fallback path `EFI/BOOT/BOOTX64.EFI`.
|
|
@@ -162,67 +427,74 @@ use.
|
|
|
162
427
|
```sh
|
|
163
428
|
./hello/build-hello.sh # in PRoot
|
|
164
429
|
./build-image.sh # in PRoot
|
|
165
|
-
|
|
430
|
+
sudo dd if=vda.img of=/dev/sdX bs=4M conv=fsync status=progress
|
|
166
431
|
```
|
|
167
432
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
application waits after printing; press any key to return to the OVMF
|
|
172
|
-
interface, then Ctrl-C to stop QEMU.
|
|
433
|
+
After verifying `/dev/sdX` is the whole destination USB device, boot it on the
|
|
434
|
+
physical x86-64 UEFI machine. It writes `Hello world from x64 UEFI!` to the
|
|
435
|
+
firmware console and waits; press any key to return to the firmware interface.
|
|
173
436
|
|
|
174
|
-
`build-image.sh` is shared with Section 2 — see [Disk layout](#disk-layout).
|
|
437
|
+
`build-image.sh` is shared with [Section 2](#2-buninu-linux-bun-as-pid-1) — see [Disk layout](#disk-layout).
|
|
175
438
|
|
|
176
|
-
|
|
439
|
+
### 2. Buninu Linux – Bun as PID 1
|
|
177
440
|
|
|
178
441
|
An unsigned x64 Unified Kernel Image assembled from official Alpine packages,
|
|
179
442
|
with Bun as the init process, replaces the hello-world application:
|
|
180
443
|
|
|
181
444
|
```sh
|
|
182
|
-
|
|
183
|
-
bun ./index.js -
|
|
445
|
+
# physical-machine image, in PRoot Debian
|
|
446
|
+
bun ./index.js -fb --real --export
|
|
447
|
+
|
|
448
|
+
# bun x buninu-linux -fb --real --export
|
|
184
449
|
```
|
|
185
450
|
|
|
186
|
-
`index.js` is the single entry point (`npm run
|
|
187
|
-
|
|
188
|
-
|
|
451
|
+
`index.js` is the single entry point (`npm run fetch` and `npm run pack` call
|
|
452
|
+
it too). Its physical-image stages run as fetch → build:
|
|
453
|
+
|
|
454
|
+
#### Build flags
|
|
189
455
|
|
|
190
456
|
| flag | runs | use it when |
|
|
191
457
|
| --- | --- | --- |
|
|
192
458
|
| `-f`, `--fetch` | `fetch-alpine.sh`, `fetch-bun.sh` | first clone, or after bumping a pinned version |
|
|
193
459
|
| `-b`, `--build` | `build-uki.sh`, `build-image.sh` | after editing `initramfs/init.js` or the kernel command line |
|
|
194
|
-
|
|
460
|
+
|
|
461
|
+
`--export` is a post-build option: after `-b` finishes, it copies `vda.img` to
|
|
462
|
+
the directory where the command was invoked as
|
|
463
|
+
`buninu-linux-<version>.img`. It therefore requires `-b`/`--build` and is the
|
|
464
|
+
recommended way to retain an image produced through npx/bunx:
|
|
465
|
+
|
|
466
|
+
```sh
|
|
467
|
+
bun x buninu-linux -fb --real --export
|
|
468
|
+
```
|
|
195
469
|
|
|
196
470
|
`--linux-lts` selects Alpine's general-purpose LTS kernel. `--real` implies
|
|
197
471
|
`--linux-lts` and builds for physical hardware: it makes `tty0` the primary
|
|
198
|
-
console and includes
|
|
472
|
+
console and includes xHCI/USB HID, common wired NIC, Android USB-tethering,
|
|
473
|
+
storage and ACPI power modules needed by typical laptops and desktops.
|
|
199
474
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
what actually does the work and each still runs on its own.
|
|
475
|
+
For real hardware, `-fb --real` is the complete image pipeline and
|
|
476
|
+
`-b --real` is the edit-and-rebuild loop. Before starting, `index.js` checks
|
|
477
|
+
that every required tool is on `PATH` and lists what is missing instead of
|
|
478
|
+
failing halfway. The shell scripts do the actual work and each still runs on
|
|
479
|
+
its own.
|
|
206
480
|
|
|
207
481
|
```text
|
|
208
|
-
index.js entry point: -f / -b /
|
|
482
|
+
index.js entry point: -f / -b / --export / --linux-lts / --real
|
|
209
483
|
fetch-alpine.sh [fetch] kernel, EFI stub, musl, network/input modules
|
|
210
484
|
fetch-bun.sh [fetch] Bun, libstdc++, libgcc
|
|
211
485
|
build-uki.sh [build] UKI; calls scripts/pack-initramfs.sh
|
|
212
|
-
build-image.sh [build] GPT disk image; shared with
|
|
213
|
-
run-qemu.sh [run]
|
|
214
|
-
fetch-plus-build.sh shell-only -fb
|
|
486
|
+
build-image.sh [build] GPT disk image; shared with the hello-world EFI
|
|
215
487
|
scripts/fetch.sh hash-checked download helper, sourced by fetch-*.sh
|
|
216
488
|
scripts/pack-initramfs.sh cpio archive with the device nodes
|
|
217
|
-
hello/
|
|
489
|
+
hello/ hello-world EFI: hello.c and build-hello.sh
|
|
218
490
|
test/ the retired C bootstrap and its build script
|
|
219
491
|
initramfs/ init.js and the committed libraries; rest fetched
|
|
220
492
|
```
|
|
221
493
|
|
|
222
|
-
The
|
|
494
|
+
The `--real` inputs are Alpine v3.24 `linux-lts-6.18.52-r0`, musl `1.2.6-r2`,
|
|
223
495
|
`systemd-efistub-260.2-r0`, `libstdc++`/`libgcc` `15.2.0-r5`, and Bun 1.4.2
|
|
224
|
-
`linux-x64-musl-baseline
|
|
225
|
-
|
|
496
|
+
`linux-x64-musl-baseline`. There is no BusyBox and no userland beyond Bun
|
|
497
|
+
itself.
|
|
226
498
|
|
|
227
499
|
Every step is idempotent and `-f` re-downloads nothing: `scripts/fetch.sh`
|
|
228
500
|
treats each pinned SHA-256 as the cache key, so a file already in `downloads/`
|
|
@@ -231,14 +503,17 @@ tampered with is fetched again and has to pass the same hash before a script
|
|
|
231
503
|
extracts from it. Bumping a version changes both the file name and the hash, so
|
|
232
504
|
it always refetches.
|
|
233
505
|
|
|
234
|
-
|
|
506
|
+
#### Build pipeline
|
|
507
|
+
|
|
508
|
+
The primary `bun ./index.js -fb --real` pipeline runs the steps below in order;
|
|
509
|
+
each writes files the next one reads. When selected, `--export` runs afterward
|
|
510
|
+
and copies the final `vda.img` to the invocation directory.
|
|
235
511
|
|
|
236
|
-
|
|
237
|
-
runs the steps below in order. Each one writes files the next one reads.
|
|
512
|
+
##### Pipeline inputs and outputs
|
|
238
513
|
|
|
239
514
|
| script | reads | writes |
|
|
240
515
|
| --- | --- | --- |
|
|
241
|
-
| `fetch-alpine.sh` | Alpine CDN | `kernel/vmlinuz-
|
|
516
|
+
| `fetch-alpine.sh` | Alpine CDN | `kernel/vmlinuz-lts`, `kernel/linuxx64.efi.stub`, musl, and the selected network, storage, input, power and filesystem modules with trimmed module indexes |
|
|
242
517
|
| `fetch-bun.sh` | GitHub, Alpine CDN | `initramfs/bin/bun`, `initramfs/lib/{libc.musl-x86_64.so.1,libstdc++.so.6,libgcc_s.so.1}` |
|
|
243
518
|
| `scripts/pack-initramfs.sh` | `initramfs/` | `build/initramfs.cpio.gz` |
|
|
244
519
|
| `build-uki.sh` | that archive, kernel, stub | `build/cmdline`, `build/os-release`, `vda/EFI/BOOT/BOOTX64.EFI` |
|
|
@@ -251,30 +526,32 @@ The stages nest — the initramfs is baked into the UKI, and the UKI into the
|
|
|
251
526
|
disk image — so a one-line edit to `initramfs/init.js` still needs both of:
|
|
252
527
|
|
|
253
528
|
```sh
|
|
254
|
-
bun ./index.js -b
|
|
529
|
+
bun ./index.js -b --real
|
|
255
530
|
```
|
|
256
531
|
|
|
257
532
|
The kernel command line works the same way: `build-uki.sh` writes it to
|
|
258
533
|
`build/cmdline` and compiles it into the UKI. Nothing reads it from disk at
|
|
259
534
|
boot.
|
|
260
535
|
|
|
261
|
-
|
|
536
|
+
#### UKI layout
|
|
262
537
|
|
|
263
538
|
`build-uki.sh` appends sections to systemd's `linuxx64.efi.stub` with
|
|
264
539
|
`objcopy`, at hand-picked VMAs because `objcopy` will not lay them out for you:
|
|
265
540
|
|
|
541
|
+
##### UKI sections
|
|
542
|
+
|
|
266
543
|
| section | offset from image base | contents | size |
|
|
267
544
|
| --- | --- | --- | --- |
|
|
268
545
|
| `.text` | +0x0 | the stub itself | 66 KB |
|
|
269
546
|
| `.osrel` | +0x20000 | `build/os-release` | 78 B |
|
|
270
|
-
| `.cmdline` | +0x30000 | `build/cmdline` |
|
|
271
|
-
| `.linux` | +0x2000000 | `kernel/vmlinuz-
|
|
272
|
-
| `.initrd` | +0x3000000 | `build/initramfs.cpio.gz` |
|
|
547
|
+
| `.cmdline` | +0x30000 | `build/cmdline` | 136 B |
|
|
548
|
+
| `.linux` | +0x2000000 | `kernel/vmlinuz-lts` | 14.5 MB |
|
|
549
|
+
| `.initrd` | +0x3000000 | `build/initramfs.cpio.gz` | 44.6 MB |
|
|
273
550
|
|
|
274
|
-
The result is a single
|
|
551
|
+
The current `--real` result is a single 59.3 MB PE32+ file holding kernel, initramfs and command
|
|
275
552
|
line.
|
|
276
553
|
|
|
277
|
-
|
|
554
|
+
#### Disk layout
|
|
278
555
|
|
|
279
556
|
`build-image.sh` needs no mount, no loop device and no root privilege. It
|
|
280
557
|
formats a standalone FAT32 image, fills it with mtools, builds the GPT with
|
|
@@ -295,79 +572,83 @@ LBA 262111.. backup GPT
|
|
|
295
572
|
backup GPT. `EFI/BOOT/BOOTX64.EFI` is the removable-media fallback path, so the
|
|
296
573
|
firmware runs it without any NVRAM boot entry.
|
|
297
574
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
`bun ./index.js -r` runs `run-qemu.sh`, which boots `vda.img` on q35 under
|
|
301
|
-
TCG with 512 MiB, a virtio disk, virtio-net user networking, no display, and
|
|
302
|
-
COM1 on stdio; anything after `--` is appended to the QEMU command line. The
|
|
303
|
-
chain is OVMF → the stub's `.text` → the stub loading its own
|
|
304
|
-
`.linux`/`.initrd`/`.cmdline` → kernel → `rdinit=/bin/bun`.
|
|
305
|
-
|
|
306
|
-
Ctrl-C quits QEMU. Leaving the REPL does not end the session: `init.js`
|
|
307
|
-
restarts it, because a PID 1 that exits panics the kernel.
|
|
308
|
-
|
|
309
|
-
#### Real hardware
|
|
575
|
+
#### Real-hardware boot details
|
|
310
576
|
|
|
311
|
-
|
|
312
|
-
|
|
577
|
+
The physical boot chain is firmware → the UKI stub → its embedded
|
|
578
|
+
`.linux`/`.initrd`/`.cmdline` sections → kernel → `rdinit=/bin/bun`.
|
|
579
|
+
`--real` uses Alpine `linux-lts`, includes the xHCI and USB HID module chain,
|
|
580
|
+
and, with the currently pinned kernel, embeds this complete command line:
|
|
313
581
|
|
|
314
|
-
```
|
|
315
|
-
|
|
582
|
+
```text
|
|
583
|
+
console=ttyS0,115200 console=tty0 REAL_MACHINE=1 panic=0 PATH=/bin KERNEL_RELEASE=6.18.52-0-lts rdinit=/bin/bun -- -e import('/init.js')
|
|
316
584
|
```
|
|
317
585
|
|
|
318
|
-
|
|
319
|
-
|
|
586
|
+
Serial kernel logging is retained, while the final console makes
|
|
587
|
+
`/dev/console` and the Bun REPL use the physical display and keyboard. This
|
|
588
|
+
path has been tested successfully on real hardware.
|
|
320
589
|
|
|
321
|
-
|
|
322
|
-
console=ttyS0,115200 console=tty0
|
|
323
|
-
```
|
|
590
|
+
#### QEMU development
|
|
324
591
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
592
|
+
This optional path has been tested in native Android Termux and in an Ubuntu
|
|
593
|
+
24.04 cloud VM with QEMU 8.2.2, TCG and OVMF. In native Termux, install the
|
|
594
|
+
runner separately from the PRoot build dependencies:
|
|
328
595
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
expected to fail there; that failure is caught and does not prevent local use.
|
|
596
|
+
```sh
|
|
597
|
+
pkg install qemu-system-x86-64
|
|
598
|
+
```
|
|
333
599
|
|
|
334
|
-
|
|
600
|
+
That package supplies OVMF at `$PREFIX/share/qemu/edk2-x86_64-code.fd`. Build
|
|
601
|
+
without `--real`; this selects Alpine `linux-virt`, omits the physical-hardware
|
|
602
|
+
module set, and puts `ttyS0` last so serial stdio owns `/dev/console`:
|
|
335
603
|
|
|
336
604
|
```text
|
|
337
|
-
bun-
|
|
605
|
+
console=tty0 console=ttyS0,115200 panic=0 PATH=/bin KERNEL_RELEASE=6.18.52-0-virt rdinit=/bin/bun -- -e import('/init.js')
|
|
338
606
|
```
|
|
339
607
|
|
|
340
|
-
|
|
341
|
-
example, open a new `hlw.js` from the Buninu shell:
|
|
608
|
+
Build and boot it with:
|
|
342
609
|
|
|
343
610
|
```sh
|
|
344
|
-
|
|
611
|
+
bun ./index.js -fb
|
|
612
|
+
|
|
613
|
+
# When running inside PRoot with Termux's native qemu-system-x86_64,
|
|
614
|
+
# expose both the native executable and its OVMF path:
|
|
615
|
+
PREFIX=/data/data/com.termux/files/usr \
|
|
616
|
+
PATH="/data/data/com.termux/files/usr/bin:$PATH" \
|
|
617
|
+
bun ./index.js -r
|
|
345
618
|
```
|
|
346
619
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
use the `Up` and `Down` arrow keys to select `cmc-tc` and press `Enter`.
|
|
620
|
+
If QEMU is installed inside the current Debian environment instead, plain
|
|
621
|
+
`bun ./index.js -r` is sufficient; `run-qemu.sh` will use Debian's OVMF path.
|
|
350
622
|
|
|
351
|
-
|
|
623
|
+
`bun ./index.js -r` runs `run-qemu.sh`, which boots `vda.img` on q35 under TCG
|
|
624
|
+
with 512 MiB, a virtio disk, virtio-net user networking, no display, and COM1
|
|
625
|
+
on stdio. Anything after `--` is appended to the QEMU command line. Ctrl-C
|
|
626
|
+
quits QEMU. Leaving the REPL does not end the session: `init.js` restarts it,
|
|
627
|
+
because a PID 1 that exits panics the kernel.
|
|
352
628
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
629
|
+
The QEMU-only CLI stage is `-r`/`--run`; `-fbr` is the full virtual pipeline,
|
|
630
|
+
`-br` is its edit-and-boot loop, and arguments after `--` are passed through
|
|
631
|
+
verbatim, for example `-r -- -m 1G`. The corresponding repository entry is
|
|
632
|
+
`run-qemu.sh`. To smoke-test the [Section 1](#1-hello-world) EFI hello-world image instead, build
|
|
633
|
+
it and run the same `-r` stage; OVMF exposes its console over COM1.
|
|
634
|
+
The legacy `fetch-plus-build.sh` wrapper is equivalent to the virtual `-fb`
|
|
635
|
+
stages and does not select `--real`. `npm start` invokes the run stage.
|
|
356
636
|
|
|
357
|
-
|
|
637
|
+
For an even shorter initramfs loop, bypass the UKI and disk image:
|
|
358
638
|
|
|
359
639
|
```sh
|
|
360
|
-
|
|
640
|
+
qemu-system-x86_64 -machine q35,accel=tcg -cpu max -m 512M \
|
|
641
|
+
-kernel kernel/vmlinuz-virt -initrd build/initramfs.cpio.gz \
|
|
642
|
+
-append "console=ttyS0,115200 panic=0 PATH=/bin rdinit=/bin/bun -- -e console.log(1+1)" \
|
|
643
|
+
-nic user,model=virtio-net-pci -display none -serial stdio -no-reboot
|
|
361
644
|
```
|
|
362
645
|
|
|
363
|
-
|
|
364
|
-
|
|
646
|
+
Only `./scripts/pack-initramfs.sh` must be rerun between these tests. A panic
|
|
647
|
+
parks the guest because of `panic=0`, so press Ctrl-C. This shortcut does not
|
|
648
|
+
exercise the UKI stub, GPT, physical console or hardware drivers; validate the
|
|
649
|
+
result afterward with `bun ./index.js -b --real` on the real UEFI path.
|
|
365
650
|
|
|
366
|
-
|
|
367
|
-
bun ./index.js -fb --linux-lts
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
#### Networking
|
|
651
|
+
##### QEMU networking
|
|
371
652
|
|
|
372
653
|
The NIC is QEMU user-mode networking (SLIRP): the guest is `10.0.2.15/24`
|
|
373
654
|
behind a NAT with `10.0.2.2` as gateway and `10.0.2.3` as DNS, so it can reach
|
|
@@ -404,35 +685,45 @@ Two things to expect:
|
|
|
404
685
|
* **QEMU write-locks `vda.img`.** A second instance fails with `Failed to get
|
|
405
686
|
"write" lock`; copy the image first if you want two at once.
|
|
406
687
|
|
|
407
|
-
|
|
688
|
+
#### Command implementation
|
|
408
689
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
`./scripts/pack-initramfs.sh` has to be re-run between attempts.
|
|
690
|
+
The `/bin` commands described earlier are Bun scripts built on two shared
|
|
691
|
+
modules in `/lib`. `--help` uses `Bun.markdown.ansi` to render the Markdown
|
|
692
|
+
manual with hyperlinks. The shared pieces are:
|
|
413
693
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
694
|
+
* `/lib/dlopen.js` — one `bun:ffi` binding to `/lib/libc.musl-x86_64.so.1`
|
|
695
|
+
(`mount`, `umount2`, `ioctl`, `socket`, `sync`, `reboot`, `syscall`, …), `errno`/`strerror`,
|
|
696
|
+
a `SysError` class and the `showDocument()` helper behind every `--help`.
|
|
697
|
+
`init.js` keeps its own copy of the binding because it runs before `/proc`
|
|
698
|
+
exists and cannot import anything.
|
|
699
|
+
* `/lib/modprobe.js` — `modprobe(name)` resolves `modules.alias` and
|
|
700
|
+
`modules.dep` under `/lib/modules/<release>/` and calls `finit_module`
|
|
701
|
+
for each dependency in order. The kernel has no `/sbin/modprobe` to call
|
|
702
|
+
here, so `mount` preloads `ext4`+`jbd2`, `vfat`+NLS tables, `ntfs3`,
|
|
703
|
+
`sd_mod`, `nvme`, and so on itself.
|
|
420
704
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
705
|
+
Which modules the image carries is the list in `fetch-alpine.sh`; the
|
|
706
|
+
`select_module` helper there pulls in dependencies from Alpine's
|
|
707
|
+
`modules.dep`, and `--real` adds common storage paths (`sd_mod`, `ahci`,
|
|
708
|
+
`ata_generic`, `pata_acpi`, `nvme`, Intel `vmd`, `usb-storage` and `uas`),
|
|
709
|
+
the wired NICs, Android USB-tethering drivers and the ACPI power drivers. Alpine's
|
|
710
|
+
kernels build all of these as modules; a self-built kernel with them `=y`
|
|
711
|
+
works the same way, the loaders just find nothing to load.
|
|
424
712
|
|
|
425
|
-
|
|
713
|
+
#### Reaching JavaScript with nothing mounted
|
|
426
714
|
|
|
427
|
-
The default
|
|
715
|
+
The default `--real` image embeds this kernel command line (shown for the
|
|
716
|
+
currently pinned LTS release):
|
|
428
717
|
|
|
429
718
|
```text
|
|
430
|
-
console=
|
|
719
|
+
console=ttyS0,115200 console=tty0 REAL_MACHINE=1 panic=0 PATH=/bin KERNEL_RELEASE=6.18.52-0-lts rdinit=/bin/bun -- -e import('/init.js')
|
|
431
720
|
```
|
|
432
721
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
722
|
+
The physical display (`tty0`) is the final console and therefore owns PID 1's
|
|
723
|
+
standard streams; serial logging remains available on `ttyS0`. The kernel
|
|
724
|
+
execs `/bin/bun` itself, with nothing native in between, and `init.js` mounts
|
|
725
|
+
`/proc`, `/sys`, `/dev`, `/tmp` and `/dev/pts` through `bun:ffi` as its first
|
|
726
|
+
action. Everything before `--` needs an `=`, because the kernel appends
|
|
436
727
|
any bare word to the init argv instead of treating it as an environment
|
|
437
728
|
assignment; everything after `--` becomes `argv[1..]` verbatim, with `argv[0]`
|
|
438
729
|
set to the `rdinit=` path. Parameter order is otherwise free, so `rdinit=` is
|
|
@@ -463,8 +754,9 @@ Nothing has mounted devtmpfs at that point, so `scripts/pack-initramfs.sh`
|
|
|
463
754
|
records `urandom` — along with `console`, which the kernel opens as init's
|
|
464
755
|
fd 0/1/2 before the exec, and a few other harmless nodes — directly in the
|
|
465
756
|
cpio archive.
|
|
466
|
-
`
|
|
467
|
-
|
|
757
|
+
For `--real`, `tty0` is listed last among the `console=` arguments so the
|
|
758
|
+
physical display owns `/dev/console`; `ttyS0` remains available for serial
|
|
759
|
+
kernel logs.
|
|
468
760
|
|
|
469
761
|
The initramfs holds no `/init`; the kernel reaches Bun through `rdinit=` alone.
|
|
470
762
|
The retired native bootstrap is kept in `test/build-init-bootstrap.sh`, which
|
|
@@ -474,10 +766,14 @@ it, repack, and boot it with `rdinit=/init`. Varying which filesystems such a
|
|
|
474
766
|
bootstrap mounted before the exec is how the `/dev/urandom` requirement above
|
|
475
767
|
was found.
|
|
476
768
|
|
|
477
|
-
|
|
769
|
+
#### What init.js does
|
|
478
770
|
|
|
479
771
|
It installs signal handlers, loads a separate physical copy of musl through
|
|
480
|
-
`bun:ffi`,
|
|
772
|
+
`bun:ffi`, mounts `/proc`, `/sys`, `/dev`, `/tmp` and `/dev/pts` (without
|
|
773
|
+
the devpts mount every pty open fails with `ENODEV`, since `/dev/ptmx`
|
|
774
|
+
resolves through `/dev/pts/ptmx`), prints a greeting, and starts `node:repl`.
|
|
775
|
+
Submitting an empty or whitespace-only REPL line prints the welcome message
|
|
776
|
+
and the available `cfg` getters again. The loader and libc paths
|
|
481
777
|
contain identical bytes but are deliberately distinct inodes:
|
|
482
778
|
|
|
483
779
|
```text
|
|
@@ -490,16 +786,75 @@ deadlocks, while the independent physical libc works. It provides `mount`,
|
|
|
490
786
|
`waitpid`, networking calls, and the generic `syscall` entry point, so no
|
|
491
787
|
custom `libinit.so` is needed.
|
|
492
788
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
with
|
|
496
|
-
`
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
789
|
+
On a `--real` boot, init starts `/etc/resolv.conf` with `1.1.1.1` and
|
|
790
|
+
`8.8.8.8`; these are initial public resolvers until the user replaces them
|
|
791
|
+
with DNS appropriate for the local network. Hardware networking remains down
|
|
792
|
+
until `cfg.net` loads the packaged drivers and the user assigns an address and
|
|
793
|
+
route.
|
|
794
|
+
|
|
795
|
+
On a `--real` image the REPL also offers the getter-based `cfg` namespace:
|
|
796
|
+
`cfg.net`, `cfg.disk`, `cfg.power` and `cfg.all` run as soon as the property is read, without
|
|
797
|
+
parentheses. `cfg.net` loads every packaged network module (including PHY and bus support),
|
|
798
|
+
then reads the `modalias` of every PCI and USB network device, matches it
|
|
799
|
+
against the `pci:`/`usb:` lines
|
|
800
|
+
`fetch-alpine.sh` kept in `modules.alias` and lists the interfaces. `cfg.disk`
|
|
801
|
+
loads the packaged SATA/PATA/SCSI, NVMe/VMD and USB storage stacks so
|
|
802
|
+
their disks and partitions appear in `/dev`, then lists `/sys/class/block`. `cfg.all`
|
|
803
|
+
unconditionally attempts every packaged module and recursively loads its
|
|
804
|
+
declared dependencies. `--real` ships Intel `e1000`/`e1000e`/`igb`/`igc`,
|
|
805
|
+
Realtek `r8169`, Atheros `alx`, Broadcom `tg3`, common USB dongles, and
|
|
806
|
+
`rndis_host`/`cdc_ether`/`cdc_ncm`/`cdc_eem`/`cdc_subset`/`zaurus` for Android
|
|
807
|
+
USB tethering. `cfg.net` unconditionally attempts all of these packaged
|
|
808
|
+
network modules. `cfg.power` loads the ACPI
|
|
809
|
+
`battery`, `ac`, `button` and `thermal` modules through `/lib/modprobe.js`
|
|
810
|
+
and lists `/sys/class/power_supply` (a desktop without a battery simply
|
|
811
|
+
reports nothing registered). Nothing loads them at boot. PID 1 also installs
|
|
812
|
+
`uncaughtException`/`unhandledRejection` listeners: without them a stray
|
|
813
|
+
`Promise.reject()` at the prompt makes Bun exit, which is a kernel panic
|
|
814
|
+
(`Attempted to kill init!`).
|
|
815
|
+
|
|
816
|
+
`start()` launches the bundled Buninu userspace and its bunmsh (Bun Modern Shell) with
|
|
817
|
+
the current process environment preserved, while overriding `PATH` and `HOME`
|
|
818
|
+
for the userspace session.
|
|
819
|
+
|
|
820
|
+
## Contents
|
|
821
|
+
|
|
822
|
+
- [Quick start](#quick-start)
|
|
823
|
+
* [Steps](#steps)
|
|
824
|
+
+ [Build directly with bun x](#build-directly-with-bun-x)
|
|
825
|
+
+ [Or build from a source checkout](#or-build-from-a-source-checkout)
|
|
826
|
+
+ [Write the image to a USB drive](#write-the-image-to-a-usb-drive)
|
|
827
|
+
+ [Booting from the USB drive](#booting-from-the-usb-drive)
|
|
828
|
+
- [Using Buninu Linux](#using-buninu-linux)
|
|
829
|
+
* [Basic configuration](#basic-configuration)
|
|
830
|
+
* [Editor quick start](#editor-quick-start)
|
|
831
|
+
* [Panes, terminals, and tabs](#panes-terminals-and-tabs)
|
|
832
|
+
+ [Pane and tab controls](#pane-and-tab-controls)
|
|
833
|
+
* [Using Bun Modern Shell](#using-bun-modern-shell)
|
|
834
|
+
- [Commands inside /bin](#commands-inside-bin)
|
|
835
|
+
- [Environment and dependencies](#environment-and-dependencies)
|
|
836
|
+
* [Build environment](#build-environment)
|
|
837
|
+
* [Buninu Linux (Section 2)](#buninu-linux-section-2)
|
|
838
|
+
* [Hello world (Section 1)](#hello-world-section-1)
|
|
839
|
+
* [Retired native bootstrap](#retired-native-bootstrap)
|
|
840
|
+
- [Implementation details](#implementation-details)
|
|
841
|
+
* [1. Hello world](#1-hello-world)
|
|
842
|
+
* [2. Buninu Linux – Bun as PID 1](#2-buninu-linux-bun-as-pid-1)
|
|
843
|
+
+ [Build flags](#build-flags)
|
|
844
|
+
+ [Build pipeline](#build-pipeline)
|
|
845
|
+
- [Pipeline inputs and outputs](#pipeline-inputs-and-outputs)
|
|
846
|
+
+ [UKI layout](#uki-layout)
|
|
847
|
+
- [UKI sections](#uki-sections)
|
|
848
|
+
+ [Disk layout](#disk-layout)
|
|
849
|
+
+ [Real-hardware boot details](#real-hardware-boot-details)
|
|
850
|
+
+ [QEMU development](#qemu-development)
|
|
851
|
+
- [QEMU networking](#qemu-networking)
|
|
852
|
+
+ [Command implementation](#command-implementation)
|
|
853
|
+
+ [Reaching JavaScript with nothing mounted](#reaching-javascript-with-nothing-mounted)
|
|
854
|
+
+ [What init.js does](#what-initjs-does)
|
|
855
|
+
- [Authorship](#authorship)
|
|
856
|
+
- [License](#license)
|
|
857
|
+
* [Bundled component licenses](#bundled-component-licenses)
|
|
503
858
|
|
|
504
859
|
## Authorship
|
|
505
860
|
|
|
@@ -521,11 +876,13 @@ The repository also commits four third-party platform binaries under
|
|
|
521
876
|
`initramfs/lib/`, and the built image redistributes several more. Each stays
|
|
522
877
|
under its own terms, with the full texts in [`LICENSES/`](LICENSES/):
|
|
523
878
|
|
|
879
|
+
### Bundled component licenses
|
|
880
|
+
|
|
524
881
|
| Component | License | Where |
|
|
525
882
|
|---|---|---|
|
|
526
883
|
| musl (`ld-musl-x86_64.so.1`, `libc.musl-x86_64.so.1`) | MIT | committed |
|
|
527
884
|
| GCC runtime (`libgcc_s.so.1`, `libstdc++.so.6`) | GPL-3.0-or-later with the GCC Runtime Library Exception | committed |
|
|
528
|
-
| Linux
|
|
885
|
+
| Linux kernels and networking, storage, xHCI, USB and HID modules | GPL-2.0-only with the Linux syscall note | image only |
|
|
529
886
|
| systemd EFI stub | LGPL-2.1-or-later | image only |
|
|
530
887
|
| Bun | MIT, plus the licenses of what it statically links | image only |
|
|
531
888
|
|