From 3f79814e056501007d379188c1acc0d10f183bd9 Mon Sep 17 00:00:00 2001 From: Fabian Date: Mon, 8 Oct 2018 16:19:50 -0300 Subject: [PATCH] Detect initrd/bzimage in 9p filesystem and load before boot --- lib/filesystem.js | 28 +++++++++++ src/browser/main.js | 9 ++-- src/browser/starter.js | 111 ++++++++++++++++++++++++++++++++--------- 3 files changed, 119 insertions(+), 29 deletions(-) diff --git a/lib/filesystem.js b/lib/filesystem.js index 604f452e..e339587a 100644 --- a/lib/filesystem.js +++ b/lib/filesystem.js @@ -1931,3 +1931,31 @@ FS.prototype.Lock = function(id, request, flags) return P9_LOCK_SUCCESS; }; + +FS.prototype.read_dir = function(path) +{ + const p = this.SearchPath(path); + + if(p.id === -1) + { + return Promise.resolve(null); + } + + const dir = this.GetInode(p.id); + + return Array.from(dir.direntries.keys()).filter(path => path !== "." && path !== ".."); +}; + +FS.prototype.read_file = function(file) +{ + const p = this.SearchPath(file); + + if(p.id === -1) + { + return undefined; + } + + const inode = this.GetInode(p.id); + + return this.Read(p.id, 0, inode.size); +}; diff --git a/src/browser/main.js b/src/browser/main.js index 7662142c..01a9134c 100644 --- a/src/browser/main.js +++ b/src/browser/main.js @@ -289,12 +289,7 @@ id: "debian-boot", name: "Debian", memory_size: 512 * 1024 * 1024, - bzimage: { - "url": "images/debian-9p-rootfs/vmlinuz", - }, - initrd: { - "url": "images/debian-9p-rootfs/initrd.img", - }, + bzimage_initrd_from_filesystem: true, cmdline: "rw init=/bin/systemd root=host9p console=ttyS0 spectre_v2=off pti=off", vga_memory_size: 8 * 1024 * 1024, filesystem: { @@ -562,6 +557,7 @@ settings.bzimage = infos.bzimage; settings.initrd = infos.initrd; settings.cmdline = infos.cmdline; + settings.bzimage_initrd_from_filesystem = infos.bzimage_initrd_from_filesystem; settings.memory_size = infos.memory_size; settings.vga_memory_size = infos.vga_memory_size; @@ -787,6 +783,7 @@ "bzimage": settings.bzimage, "initrd": settings.initrd, "cmdline": settings.cmdline, + "bzimage_initrd_from_filesystem": settings.bzimage_initrd_from_filesystem, "initial_state": settings.initial_state, "filesystem": settings.filesystem || {}, diff --git a/src/browser/starter.js b/src/browser/starter.js index 6771a67e..77150b52 100644 --- a/src/browser/starter.js +++ b/src/browser/starter.js @@ -27,6 +27,12 @@ * - `hda Object` (No hard drive) - First hard disk, see below. * - `fda Object` (No floppy disk) - First floppy disk, see below. * - `cdrom Object` (No CD) - See below. + * + * - `bzimage Object` - A Linux kernel image to boot (only bzimage format), see below. + * - `initrd Object` - A Linux ramdisk image, see below. + * - `bzimage_initrd_from_filesystem boolean` - Automatically fetch bzimage and + * initrd from the specified `filesystem`. + * * - `initial_state Object` (Normal boot) - An initial state to load, see * [`restore_state`](#restore_statearraybuffer-state) and below. * @@ -542,38 +548,97 @@ V86Starter.prototype.continue_init = function(emulator, options) // settings.memory_size = 0; //} - this.bus.send("cpu-init", settings); - - setTimeout(function() + if(settings.fs9p && settings.fs9p_json) { - if(settings.fs9p && settings.fs9p_json) + settings.fs9p.OnJSONLoaded(settings.fs9p_json); + + if(options["bzimage_initrd_from_filesystem"]) { - settings.fs9p.OnJSONLoaded(settings.fs9p_json); + const { bzimage, initrd } = this.get_bzimage_initrd_from_filesystem(settings.fs9p); + + dbg_log("Found bzimage: " + bzimage + " and initrd: " + initrd); + + Promise.all([ + settings.fs9p.read_file(initrd), + settings.fs9p.read_file(bzimage), + ]).then(([initrd, bzimage]) => { + put_on_settings.call(this, "initrd", new SyncBuffer(initrd.buffer)); + put_on_settings.call(this, "bzimage", new SyncBuffer(bzimage.buffer)); + finish.call(this); + }); + } + else + { + finish.call(this); + } + } + else + { + console.assert( + !options["bzimage_initrd_from_filesystem"], + "bzimage_initrd_from_filesystem: Requires a filesystem"); + finish.call(this); + } + + function finish() + { + this.bus.send("cpu-init", settings); + + if(settings.initial_state) + { + emulator.restore_state(settings.initial_state); + + // The GC can't free settings, since it is referenced from + // several closures. This isn't needed anymore, so we delete it + // here + settings.initial_state = undefined; } - setTimeout(function() + if(options["autostart"]) { - if(settings.initial_state) - { - emulator.restore_state(settings.initial_state); + this.bus.send("cpu-run"); + } - // The GC can't free settings, since it is referenced from - // several closures. This isn't needed anymore, so we delete it - // here - settings.initial_state = undefined; - } - - if(options["autostart"]) - { - this.bus.send("cpu-run"); - } - - this.emulator_bus.send("emulator-loaded"); - }.bind(this), 0); - }.bind(this), 0); + this.emulator_bus.send("emulator-loaded"); + } } }; +V86Starter.prototype.get_bzimage_initrd_from_filesystem = function(filesystem) +{ + const root = (filesystem.read_dir("/") || []).map(x => "/" + x); + const boot = (filesystem.read_dir("/boot/") || []).map(x => "/boot/" + x); + + let initrd; + let bzimage; + + for(let f of [].concat(root, boot)) + { + const old = /old/.test(f) || /fallback/.test(f); + const is_bzimage = /vmlinuz/.test(f); + const is_initrd = /initrd/.test(f) || /initramfs/.test(f); + + if(is_bzimage && (!bzimage || !old)) + { + bzimage = f; + } + + if(is_initrd && (!initrd || !old)) + { + initrd = f; + } + } + + if(!initrd || !bzimage) + { + console.log("Failed to find bzimage or initrd in filesystem. Files:"); + console.log(root.join(" ")); + console.log(boot.join(" ")); + } + + return { initrd, bzimage }; +}; + /** * Start emulation. Do nothing if emulator is running already. Can be * asynchronous.