mirror of
https://github.com/copy/v86.git
synced 2026-10-12 02:12:23 +00:00
add debian xfce setup example
This commit is contained in:
@@ -65,6 +65,7 @@ list of emulated hardware:
|
||||
[Dial-up modem networking](docs/modem.md) —
|
||||
[Alpine Linux guest setup](tools/docker/alpine/) —
|
||||
[Arch Linux guest setup](docs/archlinux.md) —
|
||||
[Debian with xfce guest setup](tools/docker/debian/) —
|
||||
[MS-DOS/FreeDOS guest setup](docs/dos.md) —
|
||||
[Windows 3.1x guest setup](docs/windows-31x.md) —
|
||||
[Windows 9x guest setup](docs/windows-9x.md) —
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ export default [
|
||||
"no-extra-semi": "error",
|
||||
"no-tabs": "error",
|
||||
"id-match": ["error",
|
||||
"^([a-z][a-z0-9_]*|[A-Z][a-zA-Z0-9_]*|_|\\$|__dirname|__filename|spawnSync|execFile|createServer|workerData|parentPort|isMainThread|fileURLToPath|registerProcessor|sampleRate)$",
|
||||
"^([a-z][a-z0-9_]*|[A-Z][a-zA-Z0-9_]*|_|\\$|__dirname|__filename|spawnSync|execFile|execFileSync|createServer|workerData|parentPort|isMainThread|fileURLToPath|registerProcessor|sampleRate)$",
|
||||
{ "onlyDeclarations": true, "properties": false }],
|
||||
"quotes": ["error", "double", { "avoidEscape": true, "allowTemplateLiterals": true }],
|
||||
"keyword-spacing": ["error", { "overrides": {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>debian example</title>
|
||||
<script src="../build/libv86.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="screen_container" tabindex="0" style="outline: none;">
|
||||
<div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
|
||||
<canvas style="display: none"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
window.onload = function () {
|
||||
const screen = document.getElementById("screen_container");
|
||||
screen.addEventListener("mousedown", function() {
|
||||
screen.focus();
|
||||
});
|
||||
|
||||
const emulator = new V86({
|
||||
wasm_path: "../build/v86.wasm",
|
||||
memory_size: 1636 * 1024 * 1024,
|
||||
vga_memory_size: 8 * 1024 * 1024,
|
||||
screen_container: screen,
|
||||
initial_state: { url: "../images/debian-state-base.bin.zst" },
|
||||
filesystem: { baseurl: "../images/debian-9p-rootfs-flat/" },
|
||||
network_relay_url: "wss://relay.widgetry.org/",
|
||||
autostart: true,
|
||||
});
|
||||
|
||||
const canvas = document.querySelector("canvas");
|
||||
canvas.addEventListener("click", function() {
|
||||
canvas.requestPointerLock();
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,48 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>debian example</title>
|
||||
<script src="../build/libv86.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="screen_container" tabindex="0" style="outline: none;">
|
||||
<div style="white-space: pre; font: 14px monospace; line-height: 14px"></div>
|
||||
<canvas style="display: none"></canvas>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
window.onload = function () {
|
||||
const screen = document.getElementById("screen_container");
|
||||
screen.addEventListener("mousedown", function() {
|
||||
screen.focus();
|
||||
});
|
||||
|
||||
const emulator = new V86({
|
||||
wasm_path: "../build/v86.wasm",
|
||||
memory_size: 1636 * 1024 * 1024,
|
||||
vga_memory_size: 8 * 1024 * 1024,
|
||||
screen_container: screen,
|
||||
initial_state: { url: "../images/debian-state-base.bin.zst" },
|
||||
hda: {
|
||||
url: "../images/debian-chunks/chunk.zst",
|
||||
async: true,
|
||||
use_parts: true,
|
||||
fixed_chunk_size: 128 * 1024,
|
||||
size: 5 * 1024 * 1024 * 1024,
|
||||
},
|
||||
network_relay_url: "wss://relay.widgetry.org/",
|
||||
autostart: true,
|
||||
});
|
||||
|
||||
const canvas = document.querySelector("canvas");
|
||||
canvas.addEventListener("click", function() {
|
||||
canvas.requestPointerLock();
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,109 @@
|
||||
FROM i386/debian:bookworm-slim
|
||||
|
||||
WORKDIR /root/build
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Base Setup
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
linux-image-686 \
|
||||
systemd-sysv \
|
||||
locales \
|
||||
libterm-readline-perl-perl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen && \
|
||||
locale-gen && \
|
||||
echo 'LANG="en_US.UTF-8"' > /etc/default/locale && \
|
||||
chsh -s /bin/bash root
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
xserver-xorg-core xserver-xorg-video-fbdev xinit \
|
||||
xfce4 xfce4-terminal \
|
||||
xserver-xorg-input-mouse xserver-xorg-input-kbd xserver-xorg-input-evdev \
|
||||
libxext6 libxrender1 libxtst6 libxi6 libx11-xcb1 libxrender-dev \
|
||||
libfontconfig1 fonts-dejavu-core adwaita-icon-theme fonts-wqy-microhei fonts-symbola \
|
||||
wget tar unzip ca-certificates xterm \
|
||||
xdg-utils shared-mime-info dbus-x11 desktop-base \
|
||||
thunar-archive-plugin xfce4-taskmanager ristretto \
|
||||
gvfs fonts-liberation xfce4-notifyd gvfs-backends \
|
||||
isc-dhcp-client iproute2 iputils-ping sudo \
|
||||
cmake git tmux mc htop vim nano p7zip-full geany mousepad atril engrampa curl build-essential \
|
||||
firefox-esr libreoffice thunar pavucontrol xfce4-screenshooter thunderbird gimp \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Configure Root and Standard User ('username')
|
||||
RUN passwd -d root && \
|
||||
sed -i 's/nullok_secure/nullok/' /etc/pam.d/common-auth && \
|
||||
useradd -m -s /bin/bash username && \
|
||||
passwd -d username && \
|
||||
usermod -aG sudo,video,tty,input,dialout username && \
|
||||
echo "username ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||
|
||||
# Configure Serial Console Auto-login
|
||||
RUN mkdir -p /etc/systemd/system/[email protected] /etc/systemd/system/[email protected] && \
|
||||
printf '%s\n' \
|
||||
'[Service]' \
|
||||
'TTYVTDisallocate=no' \
|
||||
> /etc/systemd/system/[email protected]/getty-noclear.conf && \
|
||||
printf '%s\n' \
|
||||
'[Service]' \
|
||||
'ExecStart=' \
|
||||
'ExecStart=-/sbin/agetty --autologin username --noissue --noclear %I 38400 $TERM' \
|
||||
> /etc/systemd/system/[email protected]/getty-override.conf && \
|
||||
printf '%s\n' \
|
||||
'[Service]' \
|
||||
'ExecStart=' \
|
||||
'ExecStart=-/sbin/agetty --autologin username --noissue --noclear -s %I 115200,38400,9600 vt102' \
|
||||
> /etc/systemd/system/[email protected]/getty-autologin-serial.conf
|
||||
|
||||
# Disable Unnecessary Services
|
||||
RUN systemctl disable systemd-timesyncd.service && \
|
||||
systemctl disable apt-daily.timer && \
|
||||
systemctl disable apt-daily-upgrade.timer
|
||||
|
||||
# 9p Filesystem Boot Configuration
|
||||
# the boot script switches on the kernel command line: root=host9p mounts the
|
||||
# 9p filesystem, anything else falls back to the standard disk boot
|
||||
RUN printf '%s\n' 9p 9pnet 9pnet_virtio virtio virtio_ring virtio_pci | tee -a /etc/initramfs-tools/modules
|
||||
|
||||
RUN printf '%s\n' \
|
||||
'#!/bin/sh' \
|
||||
'case $1 in prereqs) exit 0;; esac' \
|
||||
'. /scripts/functions' \
|
||||
'if [ "${ROOT}" = "host9p" ]; then' \
|
||||
' mkdir -p ${rootmnt}' \
|
||||
' mount -n -t 9p -o trans=virtio,version=9p2000.L,cache=loose,rw host9p ${rootmnt}' \
|
||||
'else' \
|
||||
' . /scripts/local' \
|
||||
'fi' \
|
||||
> /etc/initramfs-tools/scripts/boot-9p && \
|
||||
chmod +x /etc/initramfs-tools/scripts/boot-9p
|
||||
|
||||
RUN echo 'BOOT=boot-9p' | tee -a /etc/initramfs-tools/initramfs.conf
|
||||
RUN update-initramfs -u
|
||||
|
||||
# Configure X11, Networking, and Auto-start for 'username'
|
||||
RUN echo '(sleep 5 && sudo bash -c "printf \"\\n\\nGUI_READY\\n\" > /dev/ttyS0") & \n\
|
||||
exec startxfce4' > /home/username/.xinitrc
|
||||
|
||||
RUN { \
|
||||
echo 'if [ -z "$DISPLAY" ]; then'; \
|
||||
echo ' sudo bash -c "echo 127.0.0.1 localhost > /etc/hosts"'; \
|
||||
echo ' sudo bash -c "echo localhost > /etc/hostname"'; \
|
||||
echo ' sudo hostname localhost'; \
|
||||
echo ' startx -- -ac'; \
|
||||
echo 'fi'; \
|
||||
} >> /home/username/.bashrc
|
||||
|
||||
RUN chown username:username /home/username/.xinitrc /home/username/.bashrc
|
||||
|
||||
# Force Xorg to use the FBDEV driver
|
||||
RUN mkdir -p /etc/X11/xorg.conf.d && \
|
||||
echo 'Section "Device"\n\
|
||||
Identifier "Card0"\n\
|
||||
Driver "fbdev"\n\
|
||||
EndSection' > /etc/X11/xorg.conf.d/10-fbdev.conf
|
||||
|
||||
WORKDIR /home/username
|
||||
@@ -0,0 +1,31 @@
|
||||
Debian-xfce docker example:
|
||||
|
||||
For using split raw disk:
|
||||
1. run `bash build-raw-disk.sh` to build images
|
||||
2. run `./build-state-raw-disk.js` to build the state
|
||||
3. An example frontend is `examples/debian-raw-disk.html`
|
||||
|
||||
For using 9p filesystem:
|
||||
|
||||
1. run `bash build-9p.sh` to build images
|
||||
2. run `./build-state-9p.js` to build the state
|
||||
3. An example frontend is `examples/debian-9p.html`
|
||||
|
||||
For setting up website:
|
||||
|
||||
1. Either build v86 or downloading the release and place `v86.wasm` and `libv86.js` in `build` directory
|
||||
2. Launch a server at the root of this repository, e.g. `python3 -m http.server 8000`
|
||||
3. Open `http://localhost:8000/examples/debian-raw-disk.html` (raw disk) or `http://localhost:8000/examples/debian-9p.html` (9p filesystem)
|
||||
|
||||
Network:
|
||||
|
||||
Enable network by typing the following command in the xfce terminal:
|
||||
|
||||
```
|
||||
sudo dhclient enp0s5
|
||||
```
|
||||
|
||||
Credit:
|
||||
|
||||
v86 debian config from sandbox-bio: https://github.com/sandbox-bio/v86/tree/master/tools/docker/debian
|
||||
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
set -veuo pipefail
|
||||
|
||||
# Use 'dirname' so this script works from any folder
|
||||
DIR="$(dirname "$0")"
|
||||
IMAGES="$DIR"/../../../images
|
||||
OUT_ROOTFS_TAR="$IMAGES"/debian-9p-rootfs.tar
|
||||
OUT_ROOTFS_FLAT="$IMAGES"/debian-9p-rootfs-flat
|
||||
OUT_FSJSON="$IMAGES"/debian-base-fs.json
|
||||
CONTAINER_NAME=debian-xfce-build
|
||||
IMAGE_NAME=local/debian-xfce-v86
|
||||
|
||||
mkdir -p "$IMAGES"
|
||||
|
||||
echo "Building Docker image..."
|
||||
docker build "$DIR" --platform linux/386 --rm --tag "$IMAGE_NAME"
|
||||
|
||||
echo "Exporting filesystem..."
|
||||
docker rm "$CONTAINER_NAME" || true
|
||||
docker create --platform linux/386 --name "$CONTAINER_NAME" "$IMAGE_NAME"
|
||||
|
||||
docker export "$CONTAINER_NAME" > "$OUT_ROOTFS_TAR"
|
||||
|
||||
echo "Converting to JSON..."
|
||||
"$DIR"/../../../tools/fs2json.py --zstd --out "$OUT_FSJSON" "$OUT_ROOTFS_TAR"
|
||||
|
||||
echo "Creating flat filesystem..."
|
||||
# Clear old files to save space
|
||||
rm -rf "$OUT_ROOTFS_FLAT"
|
||||
mkdir -p "$OUT_ROOTFS_FLAT"
|
||||
"$DIR"/../../../tools/copy-to-sha256.py --zstd "$OUT_ROOTFS_TAR" "$OUT_ROOTFS_FLAT"
|
||||
|
||||
echo "Done. Artifacts created at $IMAGES"
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
set -veuo pipefail
|
||||
|
||||
# Use 'dirname' so this script works from any folder
|
||||
DIR="$(dirname "$0")"
|
||||
IMAGES="$DIR"/../../../images
|
||||
OUT_ROOTFS_TAR="$IMAGES"/debian-rootfs.tar
|
||||
OUT_IMG="$IMAGES"/debian.img
|
||||
OUT_CHUNKS="$IMAGES"/debian-chunks
|
||||
MNT="$DIR"/mnt
|
||||
CONTAINER_NAME=debian-xfce-build
|
||||
IMAGE_NAME=local/debian-xfce-v86
|
||||
|
||||
mkdir -p "$IMAGES"
|
||||
|
||||
echo "Building Docker image..."
|
||||
docker build "$DIR" --platform linux/386 --rm --tag "$IMAGE_NAME"
|
||||
|
||||
echo "Exporting filesystem..."
|
||||
docker rm "$CONTAINER_NAME" || true
|
||||
docker create --platform linux/386 --name "$CONTAINER_NAME" "$IMAGE_NAME"
|
||||
docker export "$CONTAINER_NAME" > "$OUT_ROOTFS_TAR"
|
||||
|
||||
echo "Creating ext4 disk image..."
|
||||
truncate -s 5G "$OUT_IMG"
|
||||
mkfs.ext4 -F "$OUT_IMG"
|
||||
|
||||
echo "Mounting and transferring files..."
|
||||
mkdir -p "$MNT"
|
||||
sudo mount "$OUT_IMG" "$MNT"
|
||||
trap 'sudo umount "$MNT"' EXIT
|
||||
sudo tar -xf "$OUT_ROOTFS_TAR" -C "$MNT"
|
||||
|
||||
echo "Extracting kernel and initrd for v86 boot..."
|
||||
cp "$MNT"/boot/vmlinuz-* "$IMAGES"/debian-bzImage
|
||||
cp "$MNT"/boot/initrd.img-* "$IMAGES"/debian-initrd
|
||||
|
||||
sudo umount "$MNT"
|
||||
trap - EXIT
|
||||
rmdir "$MNT"
|
||||
|
||||
echo "Splitting image into 128KB chunks..."
|
||||
rm -rf "$OUT_CHUNKS"
|
||||
mkdir -p "$OUT_CHUNKS"
|
||||
python3 "$DIR"/../../split-image.py --zstd 128k "$OUT_IMG" "$OUT_CHUNKS/chunk-%d-%d"
|
||||
|
||||
echo "Done. Artifacts created at $IMAGES"
|
||||
echo "Chunks are ready in $OUT_CHUNKS"
|
||||
Executable
+115
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
import url from "node:url";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { V86 } from "../../../build/libv86.mjs";
|
||||
|
||||
// TODO:
|
||||
// - Timeout
|
||||
|
||||
console.log("Don't forget to run `make all` before running this script");
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
||||
|
||||
const V86_ROOT = path.join(__dirname, "../../..");
|
||||
var OUTPUT_FILE = path.join(V86_ROOT, "images/debian-state-base.bin");
|
||||
|
||||
process.stdin.setRawMode(true);
|
||||
process.stdin.resume();
|
||||
process.stdin.setEncoding("utf8");
|
||||
process.stdin.on("data", handle_key);
|
||||
|
||||
var emulator = new V86({
|
||||
wasm_path: path.join(V86_ROOT, "build/v86.wasm"),
|
||||
bios: { url: path.join(V86_ROOT, "/bios/seabios.bin") },
|
||||
vga_bios: { url: path.join(V86_ROOT, "/bios/vgabios.bin") },
|
||||
autostart: true,
|
||||
memory_size: 1636 * 1024 * 1024,
|
||||
vga_memory_size: 8 * 1024 * 1024,
|
||||
network_relay_url: "<UNUSED>",
|
||||
bzimage_initrd_from_filesystem: true,
|
||||
// enable communication b/w JavaScript and v86 on serial port 1 (input) and 2 (output)
|
||||
uart1: true,
|
||||
uart2: true,
|
||||
// Remove unneeded security features since running in a sandbox (spectre_v2=off, pti=off).
|
||||
// Make state file half the size by setting "init_on_free=on", i.e. Linux overwrites freed memory with zeroes.
|
||||
// Set "rootflags=trans=virtio,cache=none --> doesn't help with FS cache"
|
||||
cmdline: "rw init=/bin/systemd root=host9p console=ttyS0 spectre_v2=off pti=off init_on_free=on",
|
||||
filesystem: {
|
||||
basefs: {
|
||||
url: path.join(V86_ROOT, "/images/debian-base-fs.json"),
|
||||
},
|
||||
baseurl: path.join(V86_ROOT, "/images/debian-9p-rootfs-flat/"),
|
||||
},
|
||||
screen_dummy: true,
|
||||
});
|
||||
|
||||
console.log("Now booting, please stand by ...");
|
||||
|
||||
var boot_start = Date.now();
|
||||
var serial_text = "";
|
||||
let booted = false;
|
||||
let saving = false;
|
||||
|
||||
emulator.add_listener("serial0-output-byte", function(byte)
|
||||
{
|
||||
var c = String.fromCharCode(byte);
|
||||
process.stdout.write(c);
|
||||
|
||||
serial_text += c;
|
||||
|
||||
if(!booted && serial_text.includes("GUI_READY"))
|
||||
{
|
||||
console.error("\nBooted in %d", (Date.now() - boot_start) / 1000);
|
||||
booted = true;
|
||||
|
||||
// Sync and drop caches: Makes it safer to change the filesystem as fewer files are rendered
|
||||
// Disable kernel logging with dmesg (drop_caches outputs things to ttyS0 even if run it on another port)
|
||||
emulator.serial0_send("sudo dmesg -n 1; sync; echo 3 | sudo tee /proc/sys/vm/drop_caches\n");
|
||||
|
||||
}
|
||||
|
||||
if(booted && !saving && serial_text.includes("GUI_READY"))
|
||||
{
|
||||
saving = true;
|
||||
console.error("\n\n'GUI_READY' signal received!");
|
||||
console.error("Waiting 240 seconds for GUI to fully render before saving state...");
|
||||
|
||||
// Delay the state save by 240 seconds
|
||||
setTimeout(function() {
|
||||
console.error("\nTime is up! Saving state now...");
|
||||
emulator.save_state().then(function(s)
|
||||
{
|
||||
fs.writeFile(OUTPUT_FILE, new Uint8Array(s), function(e)
|
||||
{
|
||||
if(e) throw e;
|
||||
console.error("Saved as " + OUTPUT_FILE);
|
||||
console.error("Compressing to " + OUTPUT_FILE + ".zst");
|
||||
execFileSync("zstd", ["-19", "-f", OUTPUT_FILE, "-o", OUTPUT_FILE + ".zst"], { stdio: "inherit" });
|
||||
stop();
|
||||
});
|
||||
});
|
||||
}, 240000);
|
||||
}
|
||||
});
|
||||
|
||||
function handle_key(c)
|
||||
{
|
||||
if(c === "\u0003")
|
||||
{
|
||||
// ctrl c
|
||||
stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
emulator.serial0_send(c);
|
||||
}
|
||||
}
|
||||
|
||||
function stop()
|
||||
{
|
||||
emulator.stop();
|
||||
process.stdin.pause();
|
||||
}
|
||||
Executable
+115
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
import url from "node:url";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { V86 } from "../../../build/libv86.mjs";
|
||||
|
||||
// TODO:
|
||||
// - Timeout
|
||||
|
||||
console.log("Don't forget to run `make all` before running this script");
|
||||
|
||||
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
||||
|
||||
const V86_ROOT = path.join(__dirname, "../../..");
|
||||
var OUTPUT_FILE = path.join(V86_ROOT, "images/debian-state-base.bin");
|
||||
|
||||
process.stdin.setRawMode(true);
|
||||
process.stdin.resume();
|
||||
process.stdin.setEncoding("utf8");
|
||||
process.stdin.on("data", handle_key);
|
||||
|
||||
var emulator = new V86({
|
||||
wasm_path: path.join(V86_ROOT, "build/v86.wasm"),
|
||||
bios: { url: path.join(V86_ROOT, "/bios/seabios.bin") },
|
||||
vga_bios: { url: path.join(V86_ROOT, "/bios/vgabios.bin") },
|
||||
autostart: true,
|
||||
memory_size: 1636 * 1024 * 1024,
|
||||
vga_memory_size: 8 * 1024 * 1024,
|
||||
network_relay_url: "<UNUSED>",
|
||||
bzimage: { url: path.join(V86_ROOT, "images/debian-bzImage") },
|
||||
initrd: { url: path.join(V86_ROOT, "images/debian-initrd") },
|
||||
hda: {
|
||||
url: path.join(V86_ROOT, "images/debian.img"),
|
||||
async: true,
|
||||
size: 5 * 1024 * 1024 * 1024,
|
||||
},
|
||||
// enable communication b/w JavaScript and v86 on serial port 1 (input) and 2 (output)
|
||||
uart1: true,
|
||||
uart2: true,
|
||||
// Remove unneeded security features since running in a sandbox (spectre_v2=off, pti=off).
|
||||
// Make state file half the size by setting "init_on_free=on", i.e. Linux overwrites freed memory with zeroes.
|
||||
// Set "rootflags=trans=virtio,cache=none --> doesn't help with FS cache"
|
||||
cmdline: "rw init=/bin/systemd root=/dev/sda console=ttyS0 spectre_v2=off pti=off init_on_free=on",
|
||||
screen_dummy: true,
|
||||
});
|
||||
|
||||
console.log("Now booting, please stand by ...");
|
||||
|
||||
var boot_start = Date.now();
|
||||
var serial_text = "";
|
||||
let booted = false;
|
||||
let saving = false;
|
||||
|
||||
emulator.add_listener("serial0-output-byte", function(byte)
|
||||
{
|
||||
var c = String.fromCharCode(byte);
|
||||
process.stdout.write(c);
|
||||
|
||||
serial_text += c;
|
||||
|
||||
if(!booted && serial_text.includes("GUI_READY"))
|
||||
{
|
||||
console.error("\nBooted in %d", (Date.now() - boot_start) / 1000);
|
||||
booted = true;
|
||||
|
||||
// Sync and drop caches: Makes it safer to change the filesystem as fewer files are rendered
|
||||
// Disable kernel logging with dmesg (drop_caches outputs things to ttyS0 even if run it on another port)
|
||||
emulator.serial0_send("sudo dmesg -n 1; sync; echo 3 | sudo tee /proc/sys/vm/drop_caches\n");
|
||||
|
||||
}
|
||||
|
||||
if(booted && !saving && serial_text.includes("GUI_READY"))
|
||||
{
|
||||
saving = true;
|
||||
console.error("\n\n'GUI_READY' signal received!");
|
||||
console.error("Waiting 240 seconds for GUI to fully render before saving state...");
|
||||
|
||||
// Delay the state save by 240 seconds
|
||||
setTimeout(function() {
|
||||
console.error("\nTime is up! Saving state now...");
|
||||
emulator.save_state().then(function(s)
|
||||
{
|
||||
fs.writeFile(OUTPUT_FILE, new Uint8Array(s), function(e)
|
||||
{
|
||||
if(e) throw e;
|
||||
console.error("Saved as " + OUTPUT_FILE);
|
||||
console.error("Compressing to " + OUTPUT_FILE + ".zst");
|
||||
execFileSync("zstd", ["-19", "-f", OUTPUT_FILE, "-o", OUTPUT_FILE + ".zst"], { stdio: "inherit" });
|
||||
stop();
|
||||
});
|
||||
});
|
||||
}, 240000);
|
||||
}
|
||||
});
|
||||
|
||||
function handle_key(c)
|
||||
{
|
||||
if(c === "\u0003")
|
||||
{
|
||||
// ctrl c
|
||||
stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
emulator.serial0_send(c);
|
||||
}
|
||||
}
|
||||
|
||||
function stop()
|
||||
{
|
||||
emulator.stop();
|
||||
process.stdin.pause();
|
||||
}
|
||||
Reference in New Issue
Block a user