forked from DGNum/liminix
bootable aarch64 liminux with qemu
I may have broken the run-liminix-vm command a bit for MIPS due to necessary changes in how we pass the command line. If CI isn't green for this commit and youre trying the worked examples, I suggest reverting to the commit before this one.
This commit is contained in:
parent
9f87fd8625
commit
be22fbbb0a
5 changed files with 131 additions and 12 deletions
69
devices/qemu-aarch64/default.nix
Normal file
69
devices/qemu-aarch64/default.nix
Normal file
|
@ -0,0 +1,69 @@
|
|||
# This "device" generates images that can be used with the QEMU
|
||||
# emulator. The default output is a directory containing separate
|
||||
# kernel ("Image" format) and root filesystem (squashfs or jffs2)
|
||||
# images
|
||||
{
|
||||
system = {
|
||||
crossSystem = {
|
||||
config = "aarch64-unknown-linux-musl";
|
||||
};
|
||||
};
|
||||
|
||||
module = {pkgs, config, ... }: {
|
||||
imports = [ ../../modules/arch/aarch64.nix ];
|
||||
kernel = {
|
||||
src = pkgs.pkgsBuildBuild.fetchurl {
|
||||
name = "linux.tar.gz";
|
||||
url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.71.tar.gz";
|
||||
hash = "sha256-yhO2cXIeIgUxkSZf/4aAsF11uxyh+UUZu6D1h92vCD8=";
|
||||
};
|
||||
config = {
|
||||
VIRTUALIZATION = "y";
|
||||
PCI_HOST_GENERIC="y";
|
||||
|
||||
MTD = "y";
|
||||
MTD_BLOCK2MTD = "y";
|
||||
MTD_BLKDEVS = "y";
|
||||
MTD_BLOCK = "y";
|
||||
|
||||
VIRTIO_MENU = "y";
|
||||
PCI = "y";
|
||||
VIRTIO_PCI = "y";
|
||||
BLOCK = "y";
|
||||
VIRTIO_BLK = "y";
|
||||
NETDEVICES = "y";
|
||||
VIRTIO_NET = "y";
|
||||
|
||||
SERIAL_EARLYCON_ARM_SEMIHOST = "y"; # earlycon=smh
|
||||
SERIAL_AMBA_PL011 = "y";
|
||||
SERIAL_AMBA_PL011_CONSOLE = "y";
|
||||
};
|
||||
};
|
||||
hardware =
|
||||
let
|
||||
mac80211 = pkgs.mac80211.override {
|
||||
drivers = ["mac80211_hwsim"];
|
||||
klibBuild = config.system.outputs.kernel.modulesupport;
|
||||
};
|
||||
in {
|
||||
defaultOutput = "vmroot";
|
||||
loadAddress = "0x0";
|
||||
entryPoint = "0x0";
|
||||
rootDevice = "/dev/mtdblock0";
|
||||
|
||||
flash.eraseBlockSize = "65536"; # c.f. pkgs/mips-vm/mips-vm.sh
|
||||
networkInterfaces =
|
||||
let inherit (config.system.service.network) link;
|
||||
in {
|
||||
wan = link.build { ifname = "eth0"; };
|
||||
lan = link.build { ifname = "eth1"; };
|
||||
|
||||
wlan_24 = link.build {
|
||||
ifname = "wlan0";
|
||||
dependencies = [ mac80211 ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
|
@ -49,6 +49,7 @@
|
|||
};
|
||||
in {
|
||||
defaultOutput = "vmroot";
|
||||
rootDevice = "/dev/mtdblock0";
|
||||
flash.eraseBlockSize = "65536"; # c.f. pkgs/run-liminix-vm/run-liminix-vm.sh
|
||||
networkInterfaces =
|
||||
let inherit (config.system.service.network) link;
|
||||
|
|
16
modules/arch/aarch64.nix
Normal file
16
modules/arch/aarch64.nix
Normal file
|
@ -0,0 +1,16 @@
|
|||
{ lib, pkgs, config, ...}:
|
||||
{
|
||||
config = {
|
||||
kernel.config = {
|
||||
CPU_LITTLE_ENDIAN= "y";
|
||||
CPU_BIG_ENDIAN= "n";
|
||||
# CMDLINE_FROM_BOOTLOADER availability is conditional
|
||||
# on CMDLINE being set to something non-empty
|
||||
CMDLINE="\"console=ttyAMA0\"";
|
||||
CMDLINE_FROM_BOOTLOADER = "y";
|
||||
};
|
||||
boot.commandLine = [
|
||||
"console=ttyAMA0,38400"
|
||||
];
|
||||
};
|
||||
}
|
|
@ -7,6 +7,12 @@
|
|||
let
|
||||
inherit (lib) mkOption types concatStringsSep;
|
||||
inherit (pkgs) liminix callPackage writeText;
|
||||
arch = let s = pkgs.stdenv; in
|
||||
if s.isAarch64
|
||||
then "aarch64"
|
||||
else if s.isMips
|
||||
then "mips"
|
||||
else throw "can't determine arch";
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
|
@ -76,14 +82,27 @@ in
|
|||
inherit dtb;
|
||||
};
|
||||
# could use trivial-builders.linkFarmFromDrvs here?
|
||||
vmroot = pkgs.runCommand "qemu" {} ''
|
||||
mkdir $out
|
||||
cd $out
|
||||
ln -s ${config.system.outputs.rootfs} rootfs
|
||||
ln -s ${kernel} vmlinux
|
||||
ln -s ${manifest} manifest
|
||||
ln -s ${kernel.headers} build
|
||||
'';
|
||||
vmroot =
|
||||
let
|
||||
cmdline = builtins.toJSON (concatStringsSep " " config.boot.commandLine);
|
||||
makeBootableImage = pkgs.runCommandCC "objcopy" {}
|
||||
(if pkgs.stdenv.isAarch64
|
||||
then "${pkgs.stdenv.cc.targetPrefix}objcopy -O binary -S ${kernel} $out"
|
||||
else "cp ${kernel} $out");
|
||||
in pkgs.runCommandCC "vmroot" {} ''
|
||||
mkdir $out
|
||||
cd $out
|
||||
ln -s ${config.system.outputs.rootfs} rootfs
|
||||
ln -s ${kernel} vmlinux
|
||||
ln -s ${manifest} manifest
|
||||
ln -s ${kernel.headers} build
|
||||
echo ${cmdline} > commandline
|
||||
cat > run.sh << EOF
|
||||
#!${pkgs.runtimeShell}
|
||||
CMDLINE=${cmdline} run-liminix-vm --arch ${arch} ${makeBootableImage} ${config.system.outputs.rootfs}
|
||||
EOF
|
||||
chmod +x run.sh
|
||||
'';
|
||||
|
||||
manifest = writeText "manifest.json" (builtins.toJSON config.filesystem.contents);
|
||||
};
|
||||
|
|
|
@ -12,6 +12,12 @@ usage(){
|
|||
exit 1
|
||||
}
|
||||
|
||||
arch="mips"
|
||||
if test "$1" = "--arch" ; then
|
||||
arch=$2
|
||||
shift;shift
|
||||
fi
|
||||
|
||||
if test "$1" = "--background" ; then
|
||||
statedir=$2
|
||||
if test -z "$statedir" || ! test -d $statedir ; then
|
||||
|
@ -39,13 +45,21 @@ if test -n "$3"; then
|
|||
initramfs="-initrd $3"
|
||||
fi
|
||||
|
||||
case "$arch" in
|
||||
mips)
|
||||
QEMU="qemu-system-mips -M malta"
|
||||
;;
|
||||
aarch64)
|
||||
QEMU="qemu-system-aarch64 -M virt -semihosting -cpu cortex-a72"
|
||||
;;
|
||||
esac
|
||||
|
||||
INIT=${INIT-/bin/init}
|
||||
echo $QEMU_OPTIONS
|
||||
qemu-system-mips \
|
||||
-M malta -m 256 \
|
||||
set -x
|
||||
$QEMU \
|
||||
-m 256 \
|
||||
-echr 16 \
|
||||
-append "liminix default console=ttyS0,38400n8 panic=10 oops=panic init=$INIT loglevel=8 root=/dev/mtdblock0 block2mtd.block2mtd=/dev/vda,65536" \
|
||||
-append "$CMDLINE liminix root=/dev/mtdblock0 block2mtd.block2mtd=/dev/vda,65536" \
|
||||
-drive file=$rootfs,format=raw,readonly=off,if=virtio,index=0 \
|
||||
${initramfs} \
|
||||
-netdev socket,id=access,mcast=230.0.0.1:1234,localaddr=127.0.0.1 \
|
||||
|
|
Loading…
Reference in a new issue