First pass at getting Acadia running under bochs.
- Create a bochs build script. - Properly configure COM1
This commit is contained in:
parent
93d1299bd9
commit
5a20c23569
|
@ -0,0 +1,12 @@
|
||||||
|
megs: 1024
|
||||||
|
ata0-master: type=disk, path=builddbg/disk.img, mode=flat, cylinders=512, heads=16, spt=50
|
||||||
|
display_library: sdl2, options="gui_debug"
|
||||||
|
boot: disk
|
||||||
|
com1: enabled=1, mode=file, dev=serial.out, baud=9600, parity=none, bits=8, stopbits=1
|
||||||
|
cpu: model=corei7_sandy_bridge_2600k
|
||||||
|
pci: enabled=1, chipset=i440bx
|
||||||
|
log: bochs.log
|
||||||
|
# TODO: Make this portable, by building bochs locally.
|
||||||
|
romimage: file=/home/drew/opt/bochs/share/bochs/BIOS-bochs-latest
|
||||||
|
vgaromimage: file=/home/drew/opt/bochs/share/bochs/VGABIOS-lgpl-latest.bin
|
||||||
|
vga: extension=vbe
|
|
@ -4,6 +4,9 @@ __pycache__/
|
||||||
.ccls-cache/
|
.ccls-cache/
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
|
||||||
|
bochs.log
|
||||||
|
serial.out
|
||||||
|
|
||||||
sysroot/bin
|
sysroot/bin
|
||||||
sysroot/usr
|
sysroot/usr
|
||||||
sysroot/.crates.toml
|
sysroot/.crates.toml
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
BUILD_DIR="${DIR}/../builddbg"
|
||||||
|
|
||||||
|
bash ${DIR}/build.sh
|
||||||
|
sudo sh ${DIR}/build_image.sh ${BUILD_DIR}/disk.img
|
||||||
|
|
||||||
|
BOCHS_ARGS=
|
||||||
|
if [[ $1 == "debug" ]]; then
|
||||||
|
BOCHS_ARGS+="--dbg"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# TODO Make this portable, build bochs as a part of toolchain?
|
||||||
|
~/opt/bochs/bin/bochs
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
echo $DIR
|
||||||
|
|
||||||
|
BUILD_DIR="${DIR}/../builddbg"
|
||||||
|
|
||||||
|
pushd $BUILD_DIR
|
||||||
|
ninja
|
||||||
|
ninja install
|
||||||
|
|
||||||
|
CARGO_USR_ROOT="${DIR}/../sysroot/usr/"
|
||||||
|
CARGO_SYS_ROOT="${DIR}/../sysroot/"
|
||||||
|
|
||||||
|
# Need to pushd so rustup gets the toolchain from rust/rust_toolchain.toml
|
||||||
|
pushd "${DIR}/../rust"
|
||||||
|
|
||||||
|
for BIN in ${DIR}/../rust/usr/*/; do
|
||||||
|
cargo install --force --path "${BIN}" --root $CARGO_USR_ROOT
|
||||||
|
done
|
||||||
|
|
||||||
|
for BIN in ${DIR}/../rust/sys/*/; do
|
||||||
|
cargo install --all-features --force --path "${BIN}" --root $CARGO_SYS_ROOT
|
||||||
|
done
|
||||||
|
popd
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
#!/us
|
#! /bin/bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||||
|
REPO_ROOT="$SCRIPT_DIR/.."
|
||||||
|
BUILD_DIR="$REPO_ROOT/builddbg"
|
||||||
|
|
||||||
if [[ $# -ne 1 ]]; then
|
if [[ $# -ne 1 ]]; then
|
||||||
echo "Must specify disk image name."
|
echo "Must specify disk image name."
|
||||||
fi
|
fi
|
||||||
|
@ -15,11 +19,14 @@ if [ -z "$dev" ]; then
|
||||||
fi
|
fi
|
||||||
echo "Loopback device: ${dev}"
|
echo "Loopback device: ${dev}"
|
||||||
|
|
||||||
|
EFI_DIR="$BUILD_DIR/efi"
|
||||||
|
SYSROOT="$BUILD_DIR/sysroot"
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
umount efi
|
umount $EFI_DIR
|
||||||
rm -rf efi
|
rm -rf $EFI_DIR
|
||||||
umount sysroot
|
umount $SYSROOT
|
||||||
rm -rf sysroot
|
rm -rf $SYSROOT
|
||||||
losetup -d $dev
|
losetup -d $dev
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
@ -30,22 +37,23 @@ mke2fs "${dev}p2"
|
||||||
|
|
||||||
limine bios-install "${dev}"
|
limine bios-install "${dev}"
|
||||||
|
|
||||||
mkdir -p efi/
|
|
||||||
mount "${dev}p1" efi/
|
|
||||||
|
|
||||||
mkdir -p efi/EFI/BOOT
|
mkdir -p $EFI_DIR
|
||||||
cp /usr/share/limine/BOOTX64.EFI efi/EFI/BOOT
|
mount "${dev}p1" $EFI_DIR
|
||||||
cp /usr/share/limine/limine-bios.sys efi/
|
|
||||||
cp ../zion/boot/limine.conf efi/
|
|
||||||
cp zion/zion efi/
|
|
||||||
mkdir -p efi/sys
|
|
||||||
cp ../sysroot/bin/yellowstone efi/sys/yellowstone
|
|
||||||
cp ../sysroot/bin/denali efi/sys/denali
|
|
||||||
cp ../sysroot/bin/victoriafalls efi/sys/victoriafalls
|
|
||||||
|
|
||||||
mkdir -p sysroot
|
mkdir -p $EFI_DIR/EFI/BOOT
|
||||||
mount "${dev}p2" sysroot/
|
cp /usr/share/limine/BOOTX64.EFI $EFI_DIR/EFI/BOOT
|
||||||
rsync -a ../sysroot .
|
cp /usr/share/limine/limine-bios.sys $EFI_DIR
|
||||||
ls sysroot/
|
cp $REPO_ROOT/zion/boot/limine.conf $EFI_DIR/
|
||||||
|
cp $BUILD_DIR/zion/zion $EFI_DIR/
|
||||||
|
mkdir -p $EFI_DIR/sys
|
||||||
|
cp $REPO_ROOT/sysroot/bin/yellowstone $EFI_DIR/sys/yellowstone
|
||||||
|
cp $REPO_ROOT/sysroot/bin/denali $EFI_DIR/sys/denali
|
||||||
|
cp $REPO_ROOT/sysroot/bin/victoriafalls $EFI_DIR/sys/victoriafalls
|
||||||
|
|
||||||
|
mkdir -p $SYSROOT
|
||||||
|
mount "${dev}p2" $SYSROOT
|
||||||
|
rsync -a "$REPO_ROOT/sysroot" $BUILD_DIR
|
||||||
|
ls $SYSROOT
|
||||||
|
|
||||||
chown drew:drew $1
|
chown drew:drew $1
|
||||||
|
|
|
@ -8,26 +8,9 @@ echo $DIR
|
||||||
|
|
||||||
BUILD_DIR="${DIR}/../builddbg"
|
BUILD_DIR="${DIR}/../builddbg"
|
||||||
|
|
||||||
pushd $BUILD_DIR
|
|
||||||
ninja
|
|
||||||
ninja install
|
|
||||||
|
|
||||||
CARGO_USR_ROOT="${DIR}/../sysroot/usr/"
|
bash ${DIR}/build.sh
|
||||||
CARGO_SYS_ROOT="${DIR}/../sysroot/"
|
sudo sh ${DIR}/build_image.sh ${BUILD_DIR}/disk.img
|
||||||
|
|
||||||
# Need to pushd so rustup gets the toolchain from rust/rust_toolchain.toml
|
|
||||||
pushd "${DIR}/../rust"
|
|
||||||
|
|
||||||
for BIN in ${DIR}/../rust/usr/*/; do
|
|
||||||
cargo install --force --path "${BIN}" --root $CARGO_USR_ROOT
|
|
||||||
done
|
|
||||||
|
|
||||||
for BIN in ${DIR}/../rust/sys/*/; do
|
|
||||||
cargo install --all-features --force --path "${BIN}" --root $CARGO_SYS_ROOT
|
|
||||||
done
|
|
||||||
popd
|
|
||||||
|
|
||||||
sudo sh ${DIR}/build_image.sh disk.img
|
|
||||||
|
|
||||||
QEMU_ARGS=
|
QEMU_ARGS=
|
||||||
if [[ $1 == "debug" ]]; then
|
if [[ $1 == "debug" ]]; then
|
||||||
|
@ -35,7 +18,7 @@ if [[ $1 == "debug" ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Use machine q35 to access PCI devices.
|
# Use machine q35 to access PCI devices.
|
||||||
qemu-system-x86_64 -machine q35 -d guest_errors -m 1G -serial stdio -hda disk.img ${QEMU_ARGS} -device nec-usb-xhci,id=xhci -device usb-kbd,bus=xhci.0
|
qemu-system-x86_64 -machine q35 -d guest_errors -m 1G -serial stdio -hda ${BUILD_DIR}/disk.img ${QEMU_ARGS} -device nec-usb-xhci,id=xhci -device usb-kbd,bus=xhci.0
|
||||||
popd
|
popd
|
||||||
|
|
||||||
# Extra options to add to this script in the future.
|
# Extra options to add to this script in the future.
|
||||||
|
|
|
@ -39,3 +39,52 @@ void dbgln(const glcr::StringView& str) {
|
||||||
dbg(str);
|
dbg(str);
|
||||||
dbg("\n");
|
dbg("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Helper function to write a byte to a specified COM1 register offset
|
||||||
|
void write_serial_port(uint16_t offset, uint8_t value) {
|
||||||
|
outb(COM1 + offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to read a byte from a specified COM1 register offset
|
||||||
|
uint8_t read_serial_port(uint16_t offset) { return inb(COM1 + offset); }
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace serial {
|
||||||
|
|
||||||
|
// Function to initialize the serial port with a given baud rate
|
||||||
|
void initialize(uint32_t baud_rate) {
|
||||||
|
// Disable interrupts
|
||||||
|
write_serial_port(1, 0x00);
|
||||||
|
|
||||||
|
// Enable DLAB (Divisor Latch Access Bit) in Line Control Register (LCR)
|
||||||
|
write_serial_port(3, read_serial_port(3) | 0x80);
|
||||||
|
|
||||||
|
// Calculate the divisor
|
||||||
|
// Baud rate = 115200 / divisor (approximately)
|
||||||
|
uint16_t divisor = 115200 / baud_rate;
|
||||||
|
|
||||||
|
// Set the low byte of the divisor
|
||||||
|
write_serial_port(0, divisor & 0xFF);
|
||||||
|
|
||||||
|
// Set the high byte of the divisor
|
||||||
|
write_serial_port(1, (divisor >> 8) & 0xFF);
|
||||||
|
|
||||||
|
// Clear DLAB and set data bits, stop bits, and parity
|
||||||
|
// 8 data bits, 1 stop bit, no parity
|
||||||
|
write_serial_port(3, 0x03); // 00000011b
|
||||||
|
|
||||||
|
// Enable FIFO, clear buffers, set trigger level (e.g., 1 byte)
|
||||||
|
write_serial_port(2, 0xC7); // 11000111b
|
||||||
|
|
||||||
|
// Enable IRQs (optional, for interrupt-driven communication)
|
||||||
|
// write_serial_port(1, 0x01);
|
||||||
|
|
||||||
|
// Set Modem Control Register (MCR)
|
||||||
|
// Enable RTS, DTR, OUT1, OUT2, loopback off, IRQs enabled
|
||||||
|
write_serial_port(4, 0x0B); // 00001011b
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace serial
|
||||||
|
|
|
@ -37,3 +37,9 @@ void panic(const char* str, Args&&... args) {
|
||||||
#define UNREACHABLE \
|
#define UNREACHABLE \
|
||||||
panic("Unreachable {}, {}", glcr::StringView(__FILE__), __LINE__); \
|
panic("Unreachable {}, {}", glcr::StringView(__FILE__), __LINE__); \
|
||||||
__builtin_unreachable();
|
__builtin_unreachable();
|
||||||
|
|
||||||
|
namespace serial {
|
||||||
|
|
||||||
|
void initialize(uint32_t baud_rate);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "syscall/syscall.h"
|
#include "syscall/syscall.h"
|
||||||
|
|
||||||
extern "C" void zion() {
|
extern "C" void zion() {
|
||||||
|
serial::initialize(9600);
|
||||||
dbgln("[boot] Init GDT & IDT.");
|
dbgln("[boot] Init GDT & IDT.");
|
||||||
InitGdt();
|
InitGdt();
|
||||||
InitIdt();
|
InitIdt();
|
||||||
|
|
Loading…
Reference in New Issue