summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Kobert <dennis@kobert.dev>2019-11-04 03:25:16 +0100
committerDennis Kobert <dennis@kobert.dev>2019-11-04 03:25:16 +0100
commit403c53fd6c7059c159db1604eb178251239fc4bf (patch)
tree99cbba45f546ea23ad8b66274fd9a122ba9f3a8c
parentb47731c6fd99d80b1023d906dd4b3bb377e49438 (diff)
Implement serial connection and basic testing
-rw-r--r--kernel/.cargo/config4
-rw-r--r--kernel/Cargo.toml2
-rwxr-xr-xkernel/run39
-rw-r--r--kernel/src/io/mod.rs2
-rw-r--r--kernel/src/io/qemu.rs15
-rw-r--r--kernel/src/io/serial.rs53
-rw-r--r--kernel/src/io/vga_text.rs1
-rw-r--r--kernel/src/lib.rs16
8 files changed, 97 insertions, 35 deletions
diff --git a/kernel/.cargo/config b/kernel/.cargo/config
index a0b86ef..b74f97c 100644
--- a/kernel/.cargo/config
+++ b/kernel/.cargo/config
@@ -1,2 +1,6 @@
[build]
target = "x86_64-uff.json"
+rustflags = ["-Clink-arg=-r","-Clink-dead-code"]
+
+[target.'cfg(target_os = "none")']
+runner = "./run test -test"
diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml
index e14865e..660cb80 100644
--- a/kernel/Cargo.toml
+++ b/kernel/Cargo.toml
@@ -13,6 +13,8 @@ sysroot_path = "target/sysroot"
[dependencies]
x86_64 = "0.7.5"
+uart_16550 = "0.2.1"
+spin = "0.5"
[dependencies.compiler_builtins]
version = "0.1.19"
diff --git a/kernel/run b/kernel/run
index d8aa011..c18450b 100755
--- a/kernel/run
+++ b/kernel/run
@@ -16,6 +16,7 @@ function define_vars() {
target_name="$target-$name"
target_path="target/"
rust_target_path="$target_path/$target_name/$build_mode/"
+ kernel_libary="$rust_target_path/libkernel.a"
iso_path="$target_path/iso/"
obj_path="$iso_path/obj/"
src_path="src/"
@@ -42,11 +43,12 @@ print_help() {
}
get_rust_bin() {
- if $test_mode; then
- echo "$rust_target_path/$(ls -t1 $rust_target_path | grep -P '^kernel-[a-fA-F0-9]+$' | head -n1)"
- else
- echo "$rust_target_path/libkernel.a"
- fi
+ #if $test_mode; then
+ # echo "$rust_target_path/$(ls -t1 $rust_target_path | grep -P '^kernel-[a-fA-F0-9]+$' | head -n1)"
+ #else
+ # echo "$rust_target_path/libkernel.a"
+ #fi
+ echo "$kernel_libary"
}
prepare_iso() {
@@ -64,16 +66,20 @@ prepare_iso() {
build_iso() {
ld -n -o "$iso_path/isofiles/boot/kernel.bin" -gc-sections -T "$link_script" "$obj_path"/*.o "$(get_rust_bin)"
- grub-mkrescue -d /usr/lib/grub/i386-pc -o "$iso_path/$name.iso" "$iso_path/isofiles"
+ grub-mkrescue -d /usr/lib/grub/i386-pc -o "$iso_path/$name.iso" "$iso_path/isofiles" &> /dev/null
+ echo "$kernel_libary"
}
build() {
if test ! -d "$iso_path/isofiles"; then
prepare_iso
fi
- if $test_mode; then
- RUSTFLAGS="-Clink-arg=-r -Clink-dead-code" cargo xtest --no-run
- else
+ #if $test_mode; then
+ # RUSTFLAGS="-Clink-arg=-r -Clink-dead-code" cargo xtest --no-run
+ #else
+ # cargo xbuild
+ #fi
+ if ! $test_mode; then
cargo xbuild
fi
build_iso
@@ -82,7 +88,18 @@ build() {
run() {
case "$target" in
"x86_64")
- qemu-system-x86_64 -cdrom "$iso_path/$name.iso";;
+ qemu="qemu-system-x86_64 -cdrom $iso_path/$name.iso"
+ if $test_mode; then
+ qemu="$qemu -device isa-debug-exit,iobase=0xf4,iosize=0x04 -serial stdio -display none"
+ fi
+ $qemu
+ case "$?" in
+ 33) exit 0;;
+ 35) exit 1;;
+ *)
+ echo "qemu exited unexpectedly $?";
+ exit 1;;
+ esac;;
*)
echo "error: no laucher defined for target '$target'";;
esac
@@ -98,6 +115,8 @@ for arg in "$@"; do
target="$(echo $arg | sed "s/^-target=//")"; define_vars;;
-test)
test_mode=true; define_vars;;
+ /*kernel-*)
+ kernel_libary=$arg;;
"run") action=run;;
"build") action=build;;
"test") action=test;;
diff --git a/kernel/src/io/mod.rs b/kernel/src/io/mod.rs
index 8a0652e..9ac924a 100644
--- a/kernel/src/io/mod.rs
+++ b/kernel/src/io/mod.rs
@@ -1,3 +1,3 @@
+pub mod qemu;
pub mod serial;
pub mod vga_text;
-
diff --git a/kernel/src/io/qemu.rs b/kernel/src/io/qemu.rs
new file mode 100644
index 0000000..8b01885
--- /dev/null
+++ b/kernel/src/io/qemu.rs
@@ -0,0 +1,15 @@
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(u32)]
+pub enum QemuExitCode {
+ Success = 0x10, // The actual exit code is (value << 1) | 1.
+ Failed = 0x11,
+}
+
+pub fn exit_qemu(exit_code: QemuExitCode) {
+ use x86_64::instructions::port::Port;
+
+ unsafe {
+ let mut port = Port::new(0xf4);
+ port.write(exit_code as u32);
+ }
+}
diff --git a/kernel/src/io/serial.rs b/kernel/src/io/serial.rs
index e1d4660..2a3bae8 100644
--- a/kernel/src/io/serial.rs
+++ b/kernel/src/io/serial.rs
@@ -1,25 +1,42 @@
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-#[repr(u32)]
-pub enum QemuExitCode {
- Success = 0x10, // The actual exit code is (value << 1) | 1.
- Failed = 0x11,
+use spin::Mutex;
+use uart_16550::SerialPort;
+
+/*lazy_static! {
+ pub static ref SERIAL1: Mutex<SerialPort> = {
+ let mut serial_port = unsafe { SerialPort::new(0x3F8) };
+ serial_port.init();
+ Mutex::new(serial_port)
+ };
+}*/
+const SERIAL_IO_PORT: u16 = 0x3F8;
+
+static CONNECTION: Mutex<Serial> = Mutex::new(Serial {
+ initialized: false,
+ port: unsafe { SerialPort::new(SERIAL_IO_PORT) },
+});
+
+struct Serial {
+ pub initialized: bool,
+ pub port: SerialPort,
}
-pub fn exit_qemu(exit_code: QemuExitCode) {
- use x86_64::instructions::port::Port;
+pub struct SerialStream {}
- unsafe {
- let mut port = Port::new(0xf4);
- port.write(exit_code as u32);
+impl SerialStream {
+ pub fn new() -> Self {
+ SerialStream {}
}
}
-fn trivial_assertion() {
- use crate::io::vga_text::OStream;
- let mut stdout = OStream::new();
- stdout.clear();
-
- stdout.print(b"trivial assertion... ");
- assert_eq!(0, 1);
- stdout.print(b"[ok]");
+impl core::fmt::Write for SerialStream {
+ fn write_str(&mut self, s: &str) -> core::fmt::Result {
+ let mut guard = CONNECTION.lock();
+ if !guard.initialized {
+ unsafe {
+ guard.port.init();
+ }
+ guard.initialized = true;
+ }
+ guard.port.write_str(s)
+ }
}
diff --git a/kernel/src/io/vga_text.rs b/kernel/src/io/vga_text.rs
index 34f13a8..fddb3e1 100644
--- a/kernel/src/io/vga_text.rs
+++ b/kernel/src/io/vga_text.rs
@@ -1,3 +1,4 @@
+#[allow(dead_code)]
#[repr(u8)]
pub enum Color {
Black = 0,
diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs
index 74daa8a..8d967ad 100644
--- a/kernel/src/lib.rs
+++ b/kernel/src/lib.rs
@@ -10,8 +10,8 @@ extern crate compiler_builtins;
mod io;
use core::fmt::Write;
-use io::vga_text;
use io::vga_text::OStream;
+use io::{qemu, serial, vga_text};
#[cfg(test)]
pub fn test_runner(tests: &[&dyn Fn(&mut OStream)]) {
@@ -26,6 +26,8 @@ pub fn test_runner(tests: &[&dyn Fn(&mut OStream)]) {
#[test_case]
fn test01(stdout: &mut OStream) {
write!(stdout, "running test01 . . . OK");
+ write!(serial::SerialStream::new(), "running test01 . . . OK\n");
+ assert_eq!(0, 1);
}
#[no_mangle]
@@ -33,16 +35,14 @@ pub extern "C" fn _start() -> ! {
if cfg!(test) {
#[cfg(test)]
test_main();
- loop {}
+ qemu::exit_qemu(qemu::QemuExitCode::Success);
}
- let mut stdout = vga_text::OStream::new();
+ let mut stdout = OStream::new();
stdout.clear();
write!(&mut stdout, "hello world!");
- // panic!("i has panicing");
-
core::iter::successors(Some(0), |n| Some(n + 1))
.for_each(|n| write!(&mut stdout, "hello world {}!", n).unwrap());
@@ -52,7 +52,7 @@ pub extern "C" fn _start() -> ! {
#[panic_handler]
#[no_mangle]
pub extern "C" fn panic_handler(_info: &core::panic::PanicInfo) -> ! {
- let mut stderr = vga_text::OStream::new();
+ let mut stderr = OStream::new();
stderr.set_state(vga_text::CharState::from_colors(
vga_text::Color::LightRed,
vga_text::Color::Red,
@@ -75,5 +75,9 @@ pub extern "C" fn panic_handler(_info: &core::panic::PanicInfo) -> ! {
vga_text::Color::Red,
));
stderr.print_centered(text.as_bytes());
+ if cfg!(test) {
+ write!(serial::SerialStream::new(), "Testing failed\n");
+ qemu::exit_qemu(qemu::QemuExitCode::Failed);
+ }
loop {}
}