Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,29 +31,29 @@ distclean:

test: disk
echo 'running $< in qemu'
./run.sh '$<' | tee serial.log
grep -xF 'Found GPT disk: 01234567-ABCD-0123-ABCD-0123456789AB' < serial.log > /dev/null
grep -xF 'Found ESP partition: AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE' < serial.log > /dev/null
grep -xF 'Using ESP partiton @00000800' < serial.log > /dev/null
./run_vm.sh -n '$<' | tee serial.log
grep -F 'Found GPT disk: 01234567-ABCD-0123-ABCD-0123456789AB' < serial.log > /dev/null
grep -F 'Found ESP partition: AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE' < serial.log > /dev/null
grep -F 'Using ESP partiton @00000800' < serial.log > /dev/null
grep -F 'hello from the initrd' < serial.log > /dev/null

uki_test: uki.efi uki_disk
echo 'running $< as EFI binary'
./run_efi.sh '$<' | tee serial.log
./run_vm.sh -n --efi --kernel '$<' | tee serial.log
grep -F 'hello from the initrd' < serial.log > /dev/null
echo 'running $< as kernel bzImage'
./run_kernel.sh '$<' | tee serial.log
./run_vm.sh -n --kernel '$<' | tee serial.log
grep -F 'hello from the initrd' < serial.log > /dev/null
echo 'running $(word 2,$^) in qemu'
./run.sh '$(word 2,$^)' | tee serial.log
grep -xF 'Found GPT disk: 01234567-ABCD-0123-ABCD-0123456789AB' < serial.log > /dev/null
grep -xF 'Found ESP partition: AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE' < serial.log > /dev/null
grep -xF 'Using ESP partiton @00000800' < serial.log > /dev/null
./run_vm.sh -n '$(word 2,$^)' | tee serial.log
grep -F 'Found GPT disk: 01234567-ABCD-0123-ABCD-0123456789AB' < serial.log > /dev/null
grep -F 'Found ESP partition: AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE' < serial.log > /dev/null
grep -F 'Using ESP partiton @00000800' < serial.log > /dev/null
grep -F 'hello from the initrd' < serial.log > /dev/null

kexec_test: kexec.cpio
kexec_test: kernel kexec.cpio
echo 'running $< as initrd in qemu'
./run_init.sh kernel '$<' rdinit=/mini_kexec | tee serial.log
./run_vm.sh -n --kernel '$<' --initrd '$(word 2,$^)' --append rdinit=/mini_kexec | tee serial.log
grep -F 'kexec_core: Starting new kernel' < serial.log > /dev/null
grep -F 'hello from the initrd' < serial.log > /dev/null

Expand Down
11 changes: 8 additions & 3 deletions make_demo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@ mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t tmpfs -o mode=0755 none /run
mount -t tmpfs none /tmp
mount -t vfat /dev/sda1 /efi
mount -t vfat -o ro /dev/sda1 /efi

ln -s /proc/self/fd /dev/fd
ln -s /proc/self/fd/0 /dev/stdin
ln -s /proc/self/fd/1 /dev/stdout
ln -s /proc/self/fd/2 /dev/stderr

echo 4 > /proc/sys/kernel/printk

sh
exec setsid -c /bin/sh -i
EOF

cat > "$tmpdir/rootfs/etc/passwd" << EOF
Expand Down Expand Up @@ -82,7 +87,7 @@ mcopy -i "$disk@@2048s" - ::/loader/entries/example-00.conf << EOF
title Demo
version 0.1
linux /kernel
options root=/dev/sda2 ro
options loglevel=6 root=/dev/sda2 ro
EOF

mdir -i "$disk@@2048s" -/ ::
11 changes: 8 additions & 3 deletions make_demo_uki.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ mount -t sysfs sysfs /sys
mount -t devtmpfs devtmpfs /dev
mount -t tmpfs -o mode=0755 none /run
mount -t tmpfs none /tmp
mount -t vfat /dev/sda1 /efi
mount -t vfat -o ro /dev/sda1 /efi

ln -s /proc/self/fd /dev/fd
ln -s /proc/self/fd/0 /dev/stdin
ln -s /proc/self/fd/1 /dev/stdout
ln -s /proc/self/fd/2 /dev/stderr

echo 4 > /proc/sys/kernel/printk

sh
exec setsid -c /bin/sh -i
EOF

cat > "$tmpdir/rootfs/etc/passwd" << EOF
Expand All @@ -51,7 +56,7 @@ chmod a+x "$tmpdir/rootfs/sbin/init"

(cd "$tmpdir/rootfs" && find . | cpio -o -H newc) > "$tmpdir/rootfs.cpio"

ukify build --stub /usr/lib/systemd/boot/efi/linuxx64.efi.stub --linux "$kernel" --initrd "$tmpdir/rootfs.cpio" --cmdline "rdinit=/sbin/init" --os-release $'PRETTY_NAME=Demo\nVERSION=0.1\n' -o "$tmpdir/uki_base.efi"
ukify build --stub /usr/lib/systemd/boot/efi/linuxx64.efi.stub --linux "$kernel" --initrd "$tmpdir/rootfs.cpio" --cmdline "loglevel=6 rdinit=/sbin/init" --os-release $'PRETTY_NAME=Demo\nVERSION=0.1\n' -o "$tmpdir/uki_base.efi"
./pe_inject.py "$tmpdir/uki_base.efi" "$kernel_stub" "$pe_loader" "$tmpdir/uki.efi"

truncate -s 0 "$disk"
Expand Down
6 changes: 0 additions & 6 deletions run.sh

This file was deleted.

7 changes: 0 additions & 7 deletions run_demo_efi.sh

This file was deleted.

6 changes: 0 additions & 6 deletions run_demo_legacy.sh

This file was deleted.

6 changes: 0 additions & 6 deletions run_efi.sh

This file was deleted.

6 changes: 0 additions & 6 deletions run_init.sh

This file was deleted.

6 changes: 0 additions & 6 deletions run_kernel.sh

This file was deleted.

35 changes: 35 additions & 0 deletions run_vm.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bash

set -euo pipefail

machine="pc"
serial="mon:stdio"
qemu_opts=()

while [[ $# -gt 0 ]]; do
case "$1" in
--efi)
machine="q35"; qemu_opts+=(-drive if=pflash,unit=0,file=/usr/share/OVMF/OVMF_CODE_4M.fd,readonly=on); shift;;
--legacy)
machine="pc"; shift;;
-n|--no-monitor)
serial="stdio"; shift;;
--kernel)
qemu_opts+=(-kernel "$2"); shift 2;;
--initrd)
qemu_opts+=(-initrd "$2"); shift 2;;
--append)
qemu_opts+=(-append "$2"); shift 2;;
*)
break;;
esac
done

for disk in "$@"; do
qemu_opts+=(-drive "file=$disk,format=raw")
done

exec ./term_emu.py qemu-system-x86_64 \
-machine "$machine" -cpu qemu64 -accel tcg -m 1024 \
-nodefaults -no-reboot -nographic -serial "$serial" \
"${qemu_opts[@]}"
102 changes: 102 additions & 0 deletions term_emu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env python3

import errno
import os
import pty
import selectors
import sys
import termios
import tty

class EscSeqFilter:
def __init__(self):
self.state = "TXT"

def feed(self, data):
out = bytearray()
for ch in data:
if self.state == "TXT":
if ch == 0x1B:
self.state = "ESC"
elif 0x20 <= ch <= 0x7F or ch == 0x0A or ch == 0x0D or ch == 0x08:
out.append(ch)
elif self.state == "ESC":
if ch == ord("["):
self.state = "CSI"
elif ch == ord("]"):
self.state = "OSC"
elif ch == ord("P"):
self.state = "DCS"
else:
self.state = "TXT"
elif self.state == "CSI":
if 0x40 <= ch <= 0x7E:
self.state = "TXT"
elif self.state == "OSC":
if ch == 0x07:
self.state = "TXT"
elif ch == 0x1B:
self.state = "OSC_ESC"
elif self.state == "OSC_ESC":
if ch == ord("\\"):
self.state = "TXT"
else:
self.state = "OSC"
elif self.state == "DCS":
if ch == 0x1B:
self.state = "DCS_ESC"
elif self.state == "DCS_ESC":
if ch == ord("\\"):
self.state = "TXT"
else:
self.state = "DCS"
return bytes(out)

stdin_fd = sys.stdin.fileno()
stdout_fd = sys.stdout.fileno()

try:
old_tios = termios.tcgetattr(stdin_fd)
tty.setraw(stdin_fd)
except Exception:
pass

pid, master_fd = pty.fork()
if pid == 0:
os.execvp(sys.argv[1], sys.argv[1:])
os._exit(127)

sel = selectors.DefaultSelector()
try:
sel.register(stdin_fd, selectors.EVENT_READ)
except Exception:
pass
sel.register(master_fd, selectors.EVENT_READ)

esc_filter = EscSeqFilter()

try:
while True:
for key, _ in sel.select():
if key.fd == stdin_fd:
data = os.read(stdin_fd, 65536)
if not data:
os.close(master_fd); raise SystemExit
os.write(master_fd, data)
else:
try:
data = os.read(master_fd, 65536)
except OSError as e:
if e.errno == errno.EIO:
os.waitpid(pid, 0); raise SystemExit
else:
raise
if not data:
os.waitpid(pid, 0); raise SystemExit
data = esc_filter.feed(data)
os.write(stdout_fd, data)
finally:
try:
termios.tcsetattr(stdin_fd, termios.TCSADRAIN, old_tios)
except Exception:
pass