Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix the issue#1 #2

Merged
merged 1 commit into from
Jan 23, 2021
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
3 changes: 3 additions & 0 deletions .cargo/config → .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[unstable]
build-std = ["core", "compiler_builtins", "alloc"]

[build]
target = "i586-rust_dos.json"
rustflags = ["-C", "link-arg=-Tlink.x"]
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ edition = "2018"
opt-level = "z"

[dependencies]
rlibc = "1.0.0"
32 changes: 18 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,41 @@ 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
```

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:
Expand All @@ -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)
2 changes: 1 addition & 1 deletion i586-rust_dos.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@
"vendor": "unknown",
"panic-strategy": "abort",
"disable-redzone": true
}
}
3 changes: 2 additions & 1 deletion link.x
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ SECTIONS {
.data : { *(.data) } > dos
.bss : { *(.bss) } > dos
.stack : { *(.stack) } > dos
}
/DISCARD/ : { *(.eh_frame*) }
}
9 changes: 3 additions & 6 deletions src/dos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
}
}
8 changes: 2 additions & 6 deletions src/dos/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
24 changes: 5 additions & 19 deletions src/dos/io.rs
Original file line number Diff line number Diff line change
@@ -1,41 +1,27 @@
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
}

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);
}
}
}
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ fn main() {
println!("Hello, World!");
// println!("Hit any Key, please.");
// dpkey::keymap();
}
}