1// SPDX-License-Identifier: MIT
2
3package vm
4
5import (
6 "fmt"
7 "net/netip"
8 "strconv"
9 "strings"
10
11 "bnema.dev/ermite-runner/internal/sandbox"
12)
13
14// bootArgs builds the guest kernel command line.
15//
16// - console=ttyS0 reboot=k panic=1: serial console; a reboot (what init does
17// at the end) or a panic ends the VMM instead of hanging;
18// - ipv6.disable=1: the guest has no IPv6 (the host policy drops it too);
19// - root=/dev/vda ro: the exec disk; init=/ermite-runner -- init: the runner
20// executable is PID 1 and runs its init subcommand;
21// - ip=…: static address, gateway and DNS from the kernel, no DHCP client;
22// - ermite.*: read by init from /proc/cmdline (connect target, gateway, time).
23func bootArgs(guest, gateway netip.Addr, unixSeconds int64) string {
24 args := []string{
25 "console=ttyS0", "reboot=k", "panic=1", "pci=off", "acpi=off", "8250.nr_uarts=1",
26 "ipv6.disable=1", "random.trust_cpu=on", "i8042.noaux", "i8042.nomux", "i8042.nopnp", "i8042.dumbkbd",
27 "root=/dev/vda", "ro", "rootfstype=ext4",
28 "init=/" + sandbox.GuestExecName,
29 fmt.Sprintf("ip=%s::%s:255.255.255.252:ermite-job:eth0:off:%s", guest, gateway, gateway),
30 sandbox.CmdlineSandbox + "=" + string(sandbox.VM),
31 sandbox.CmdlineConnect + "=vsock:" + strconv.Itoa(sandbox.VsockPort),
32 sandbox.CmdlineGateway + "=" + gateway.String(),
33 "ermite.time=" + strconv.FormatInt(unixSeconds, 10),
34 "--", "init",
35 }
36 return strings.Join(args, " ")
37}
38
39// macFor derives a locally administered MAC from the slot.
40func macFor(slot int) string {
41 return fmt.Sprintf("06:00:ac:10:%02x:%02x", (slot>>8)&0xff, slot&0xff)
42}