aboutsummaryrefslogtreecommitdiffstats
path: root/web/demo/fetch-vendor
blob: 576cbced17e5cb93b86d6393dd402845937f603e (plain) (blame)
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
#!/bin/sh
# Fetch the third-party pieces of the web demo into vendor/.
#
# None of this is committed. The emulator is MIT and could be, but the kernel
# and the busybox userland are GPL binaries, and a repository that ships those
# owes their source -- so we point at the upstream tarball instead and let it
# stay Bellard's to distribute. Everything is pinned by sha256, tarball and
# extracted member both: a mirror that quietly changes underneath us should
# fail the build rather than boot something else in the visitor's browser.
set -eu

here=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
vendor="$here/vendor"
cache="$vendor/.cache"
mkdir -p "$cache"

JSLINUX_URL=https://bellard.org/tinyemu/jslinux-2019-12-21.tar.gz
JSLINUX_SHA=c57e46f8eab6656cd9ce5c7e2825230177919b147c8c2befd1f327bbdf254088
JSLINUX_DIR=jslinux-2019-12-21

# The guest userland: Alpine's riscv64 minirootfs. A musl busybox userland with
# apk, vi, less and top in it, which is a machine worth being dropped into --
# and, unlike a rootfs lifted out of the jslinux tarball, one whose provenance
# and licence we can point at.
ALPINE_VER=3.22.5
ALPINE_URL=https://dl-cdn.alpinelinux.org/alpine/v3.22/releases/riscv64/alpine-minirootfs-$ALPINE_VER-riscv64.tar.gz
ALPINE_SHA=24cd94b1be923179737cd50cb357aa7e72ed086ac08c2360f7e866ae2eb0cba5

# Only for the licence text: the jslinux tarball ships none, and we redistribute
# Bellard's MIT-licensed emulator in build/site.
TINYEMU_URL=https://bellard.org/tinyemu/tinyemu-2019-12-21.tar.gz
TINYEMU_SHA=be8351f2121819b3172fcedce5cb1826fa12c87da1b7ed98f269d3e802a05555
TINYEMU_DIR=tinyemu-2019-12-21

XTERM_VER=5.5.0
XTERM_JS_URL=https://unpkg.com/@xterm/xterm@$XTERM_VER/lib/xterm.js
XTERM_JS_SHA=1f991ac3b4b283ebf96e60ae23a00a52765dd3a2e46fa6fdda9f1aab032f7495
XTERM_CSS_URL=https://unpkg.com/@xterm/xterm@$XTERM_VER/css/xterm.css
XTERM_CSS_SHA=ba8e6985669488981ccf40c0cefe3aba80722cb6c92de7ad628b0bd717faf2b6

sha() { sha256sum "$1" | cut -d' ' -f1; }

# Re-downloading a 4 MB tarball on every make is rude to bellard.org; the cache
# is checked by hash, so a truncated download is refetched and a good one is not.
fetch() { # url sha dest
	if [ -f "$3" ] && [ "$(sha "$3")" = "$2" ]; then
		printf '  have  %s\n' "$(basename "$3")"
		return 0
	fi
	printf '  get   %s\n' "$(basename "$3")"
	curl -fsSL --retry 3 -o "$3.part" "$1"
	got=$(sha "$3.part")
	if [ "$got" != "$2" ]; then
		rm -f "$3.part"
		printf 'sha256 mismatch for %s\n  expected %s\n  got      %s\n' "$1" "$2" "$got" >&2
		exit 1
	fi
	mv "$3.part" "$3"
}

# member sha dest: extract one file from a tarball and check it on its own, so a
# right tarball unpacked wrong is still an error.
take() { # tarball member sha dest
	tar -xzf "$1" -O "$2" >"$4.part"
	got=$(sha "$4.part")
	if [ "$got" != "$3" ]; then
		rm -f "$4.part"
		printf 'sha256 mismatch for %s\n  expected %s\n  got      %s\n' "$2" "$3" "$got" >&2
		exit 1
	fi
	mv "$4.part" "$4"
	printf '  ok    %s\n' "$(basename "$4")"
}

fetch "$JSLINUX_URL" "$JSLINUX_SHA" "$cache/jslinux.tar.gz"
fetch "$TINYEMU_URL" "$TINYEMU_SHA" "$cache/tinyemu.tar.gz"

# Deliberately NOT taken from the tarball: riscvemu64-wasm.{js,wasm}. Bellard's
# prebuilt blob does not match his source release -- it stops issuing block
# fetches at 16 MiB into the disk, which his 4 MiB demo images never noticed
# and our 32 MiB one hit as a hang or a segfault in the guest. The emulator we
# ship is built from this same tarball's source by emulator/build-emulator and
# committed in emulator/dist/.

# bbl is the BIOS, and the kernel is Bellard's 4.15 riscv64 build. We keep his
# kernel deliberately: it is what these emulator binaries were tested against,
# and building our own means building a riscv toolchain to get one feature
# (CONFIG_BLK_DEV_INITRD) that a virtio root device does not need.
take "$cache/jslinux.tar.gz" "$JSLINUX_DIR/bbl64.bin" \
	293610cea7af6c75e4a8337e16c0d62834becbf31ffd9cca35e0c211602349db \
	"$vendor/bbl64.bin"
take "$cache/jslinux.tar.gz" "$JSLINUX_DIR/kernel-riscv64.bin" \
	65ca70a6560a730396ab61488d1cf46089b32da5af7e535e03c180cd5bcc8e75 \
	"$vendor/kernel-riscv64.bin"

# The guest userland. build-rootfs unpacks this into a staging tree, lays the
# overlay and slosh on top, and makes an image out of the result -- the
# tarball itself is never modified. Bellard's own root-riscv64.bin is the
# obvious alternative and is deliberately not used: it is a 2017 glibc busybox
# image with 1.4 MiB free, no package manager, and /sbin/init as a shell script
# that loops a bare shell.
fetch "$ALPINE_URL" "$ALPINE_SHA" "$vendor/alpine-minirootfs-riscv64.tar.gz"

# Guest packages beyond the minirootfs, as pinned .apk files. The machine has
# no network, so anything it is to have must be baked into the image;
# build-rootfs unpacks these into the staging tree (and prunes them -- vim
# alone unpacks to 26 MiB of which the syntax machinery is under half).
# An .apk is tar.gz segments, so nothing here needs apk-tools.
APK_BASE=https://dl-cdn.alpinelinux.org/alpine/v3.22/main/riscv64
mkdir -p "$vendor/apks"
fetch "$APK_BASE/vim-9.1.1566-r0.apk" \
	a6c60d2343b3432c7b1cf0953132e67b83e666da969a05196a23fb6a41f6dbfa \
	"$vendor/apks/vim.apk"
fetch "$APK_BASE/vim-common-9.1.1566-r0.apk" \
	cd0b9d6990cb1d89c9559c8683b071689eef79b6b78c10e7906551ef8d429937 \
	"$vendor/apks/vim-common.apk"
fetch "$APK_BASE/xxd-9.1.1566-r0.apk" \
	9e8e77c39c286d5f515bd377be0c2c55e706d9821910ecaa51e4880b0c0706b1 \
	"$vendor/apks/xxd.apk"
fetch "$APK_BASE/libncursesw-6.5_p20250503-r0.apk" \
	7d88384bd34c276bafcaae52289e62b895bc5265f74369dc0ad523ef204d9607 \
	"$vendor/apks/libncursesw.apk"
fetch "$APK_BASE/ncurses-terminfo-base-6.5_p20250503-r0.apk" \
	8e523158d782d13d311fffde76d891812be9e4e0d5b4e30dd14ad1c21848243a \
	"$vendor/apks/ncurses-terminfo-base.apk"

take "$cache/tinyemu.tar.gz" "$TINYEMU_DIR/MIT-LICENSE.txt" \
	a75690160a50d8085bcd25acf34faa5b1c484e15ffd0bd662e5f4d7a289da080 \
	"$vendor/TINYEMU-MIT-LICENSE.txt"

# xterm.js rather than the term.js in the jslinux tarball: that one has no
# truecolor and no wide characters, and a demo of a multiplexer that renders
# 24-bit shaders and CJK would be lying about both. UMD bundle, so a plain
# <script> puts Terminal on the global object -- no npm, no bundler.
fetch "$XTERM_JS_URL" "$XTERM_JS_SHA" "$vendor/xterm.js"
fetch "$XTERM_CSS_URL" "$XTERM_CSS_SHA" "$vendor/xterm.css"

printf 'vendor/ ready (%s)\n' "$vendor"