diff --git a/.cargo/config b/.cargo/config.toml similarity index 55% rename from .cargo/config rename to .cargo/config.toml index b8e4014..f7cf539 100644 --- a/.cargo/config +++ b/.cargo/config.toml @@ -1,3 +1,6 @@ +[unstable] +build-std = ["core", "compiler_builtins", "alloc"] + [build] target = "i586-rust_dos.json" rustflags = ["-C", "link-arg=-Tlink.x"] \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index d4f95c8..da37c76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,4 @@ edition = "2018" opt-level = "z" [dependencies] +rlibc = "1.0.0" diff --git a/README.md b/README.md index 69b5099..3e436f1 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,9 @@ It is possible to create a DOS executable or 1st stage bootloader with Rust. This is a quick demo of creating COM executable for DOS. ## Building -You need a nightly Rust compiler and binutils. First you need to install the [cargo-xbuild](https://github.com/rust-osdev/cargo-xbuild) and [cargo-binutils](https://github.com/rust-embedded/cargo-binutils): +You need a binutils and llvm-tools-preview. ```shell -cargo install cargo-xbuild cargo install cargo-binutils rustup component add llvm-tools-preview ``` @@ -15,26 +14,31 @@ rustup component add llvm-tools-preview Then you can build the project by running: ```shell -cargo xbuild --release +cargo build --release ``` To create a COM executable for DOS, run: ```shell -cargo objcopy -- -I elf32-i386 -O binary --binary-architecture=i386:x86 \ - target/i586-rust_dos/release/rust_dos target/i586-rust_dos/release/rust_dos.com +cargo objcopy --release -O binary --binary-architecture=i386:x86 rust_dos.com ``` ## Running -You can copy `rust_dos.com` to your DOS image. +You can copy `rust_dos.com` to your DOS image. -examples on macOS: +examples on Linux ```shell -$ hdiutil attach path/to/freedos.img -/dev/disk2 FDisk_partition_scheme -/dev/disk2s1 DOS_FAT_16 /Volumes/FREEDOS2016 -$ cp target/i586-rust_dos/release/rust_dos.com /Volumes/FREEDOS2016/ +$ sudo partx -av freedos.img +partition: none, disk: freedos.img, lower: 0, upper: 0 +Trying to use '/dev/loop1' for the loop device +/dev/loop1: partition table type 'dos' detected +range recount: max partno=1, lower=0, upper=0 +/dev/loop1: partition #1 added +$ sudo mount /dev/loop1p1 /mnt +$ sudo cp rust_dos.com /mnt/ +$ sudo umount /mnt +$ sudo partx -dv /dev/loop1 ``` Then, you can test it using QEMU: @@ -43,13 +47,13 @@ Then, you can test it using QEMU: qemu-system-i386 freedos.img -boot c ``` -You can use the `println!` macro. +You can use the `println!` macro. Below is an example of HelloWorld: -![sample](https://github.com/ellbrid/rust_dos/blob/images/rust_dos_hello.png) +![sample](https://github.com/o8vm/rust_dos/blob/images/rust_dos_hello.png) ### Others dpkey module steals key input processing from DOS and converts scan code to ascii code. about scan code: see [PS/2 Keyboard - OSDev Wiki](https://wiki.osdev.org/PS/2_Keyboard). -![sample2](https://github.com/ellbrid/rust_dos/blob/images/dpkey.gif) +![sample2](https://github.com/o8vm/rust_dos/blob/images/dpkey.gif) diff --git a/i586-rust_dos.json b/i586-rust_dos.json index 0b37e35..f391cd1 100644 --- a/i586-rust_dos.json +++ b/i586-rust_dos.json @@ -22,4 +22,4 @@ "vendor": "unknown", "panic-strategy": "abort", "disable-redzone": true -} \ No newline at end of file +} diff --git a/link.x b/link.x index 847de1e..155b791 100644 --- a/link.x +++ b/link.x @@ -10,4 +10,5 @@ SECTIONS { .data : { *(.data) } > dos .bss : { *(.bss) } > dos .stack : { *(.stack) } > dos -} \ No newline at end of file + /DISCARD/ : { *(.eh_frame*) } +} diff --git a/src/dos.rs b/src/dos.rs index 51f304b..41e8fee 100644 --- a/src/dos.rs +++ b/src/dos.rs @@ -6,11 +6,8 @@ pub mod kbc; pub fn exit(rt: u8) -> ! { unsafe { - asm!("mov $$0x4C, %ah - int $$0x21" - : - : "{al}"(rt) - : "eax"); + asm!("mov ah, 0x4C", + "int 0x21", in("al") rt); } loop {} -} \ No newline at end of file +} diff --git a/src/dos/console.rs b/src/dos/console.rs index b681db4..4125721 100644 --- a/src/dos/console.rs +++ b/src/dos/console.rs @@ -36,10 +36,6 @@ impl Write for DosWriter { fn printc(ch: u8) { unsafe { - asm!("mov $$0x2, %ah - int $$0x21" - : - : "{dl}"(ch) - : "eax", "edx"); + asm!("int 0x21", in("ah") 0x02_u8, in("dl") ch) } -} \ No newline at end of file +} diff --git a/src/dos/io.rs b/src/dos/io.rs index 9450bee..c27bc51 100644 --- a/src/dos/io.rs +++ b/src/dos/io.rs @@ -1,11 +1,7 @@ pub fn inb(port: usize) -> u8 { let mut ret: u8; unsafe { - asm!("xorl %eax, %eax - inb %dx, %al" - : "={al}"(ret) - : "{dx}"(port) - ); + asm!("in al, dx", out("al") ret, in("dx") port); } ret } @@ -13,29 +9,19 @@ pub fn inb(port: usize) -> u8 { pub fn inw(port: usize) -> u16 { let mut ret: u16; unsafe { - asm!("xorl %eax, %eax - inw %dx, %ax" - : "={ax}"(ret) - : "{dx}"(port) - ); + asm!("in ax, dx", out("ax") ret, in("dx") port) } ret } pub fn outb(data: u8, port: usize) { unsafe { - asm!("outb %al, %dx" - : - : "{al}"(data), "{dx}"(port) - ); + asm!("out dx, al", in("dx") port, in("al") data); } } pub fn outw(data: u16, port: usize) { unsafe { - asm!("outw %ax, %dx" - : - : "{ax}"(data), "{dx}"(port) - ); + asm!("out dx, ax", in("dx") port, in("ax") data); } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index b80a364..900c225 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,4 +9,4 @@ fn main() { println!("Hello, World!"); // println!("Hit any Key, please."); // dpkey::keymap(); -} \ No newline at end of file +}