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,
23// and whether the externals disk is attached as the fourth drive).
24func bootArgs(guest, gateway netip.Addr, unixSeconds int64, externals bool) string {
25 args := []string{
26 "console=ttyS0", "reboot=k", "panic=1", "pci=off", "acpi=off", "8250.nr_uarts=1",
27 "ipv6.disable=1", "random.trust_cpu=on", "i8042.noaux", "i8042.nomux", "i8042.nopnp", "i8042.dumbkbd",
28 "root=/dev/vda", "ro", "rootfstype=ext4",
29 "init=/" + sandbox.GuestExecName,
30 fmt.Sprintf("ip=%s::%s:255.255.255.252:ermite-job:eth0:off:%s", guest, gateway, gateway),
31 sandbox.CmdlineSandbox + "=" + string(sandbox.VM),
32 sandbox.CmdlineConnect + "=vsock:" + strconv.Itoa(sandbox.VsockPort),
33 sandbox.CmdlineGateway + "=" + gateway.String(),
34 "ermite.time=" + strconv.FormatInt(unixSeconds, 10),
35 }
36 if externals {
37 args = append(args, sandbox.CmdlineExternals+"=1")
38 }
39 args = append(args, "--", "init")
40 return strings.Join(args, " ")
41}
42
43// macFor derives a locally administered MAC from the slot.
44func macFor(slot int) string {
45 return fmt.Sprintf("06:00:ac:10:%02x:%02x", (slot>>8)&0xff, slot&0xff)
46}