|
| 1 | +#![no_std] |
| 2 | +#![no_main] |
| 3 | +#![feature(asm)] |
| 4 | + |
| 5 | +use core::convert::TryInto; |
| 6 | +use core::fmt; |
| 7 | +use core::panic::PanicInfo; |
| 8 | + |
| 9 | +#[panic_handler] |
| 10 | +fn panic(_info: &PanicInfo) -> ! { |
| 11 | + loop {} |
| 12 | +} |
| 13 | + |
| 14 | +// https://doc.rust-lang.org/beta/unstable-book/library-features/asm.html |
| 15 | + |
| 16 | +fn write_io_port(port: u16, data: u8) { |
| 17 | + unsafe { |
| 18 | + asm!("out dx, al", |
| 19 | + in("al") data, |
| 20 | + in("dx") port) |
| 21 | + } |
| 22 | +} |
| 23 | +fn read_io_port(port: u16) -> u8 { |
| 24 | + let mut data: u8; |
| 25 | + unsafe { |
| 26 | + asm!("in al, dx", |
| 27 | + out("al") data, |
| 28 | + in("dx") port) |
| 29 | + } |
| 30 | + data |
| 31 | +} |
| 32 | + |
| 33 | +// const IO_ADDR_COM1: u16 = 0x3f8; |
| 34 | +const IO_ADDR_COM2: u16 = 0x2f8; |
| 35 | +fn com_initialize(base_io_addr: u16) { |
| 36 | + write_io_port(base_io_addr + 1, 0x00); // Disable all interrupts |
| 37 | + write_io_port(base_io_addr + 3, 0x80); // Enable DLAB (set baud rate divisor) |
| 38 | + const BAUD_DIVISOR: u16 = 0x0001; // baud rate = (115200 / BAUD_DIVISOR) |
| 39 | + write_io_port(base_io_addr, (BAUD_DIVISOR & 0xff).try_into().unwrap()); |
| 40 | + write_io_port(base_io_addr + 1, (BAUD_DIVISOR >> 8).try_into().unwrap()); |
| 41 | + write_io_port(base_io_addr + 3, 0x03); // 8 bits, no parity, one stop bit |
| 42 | + write_io_port(base_io_addr + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold |
| 43 | + write_io_port(base_io_addr + 4, 0x0B); // IRQs enabled, RTS/DSR set |
| 44 | +} |
| 45 | + |
| 46 | +fn com_send_char(base_io_addr: u16, c: char) { |
| 47 | + while (read_io_port(base_io_addr + 5) & 0x20) == 0 { |
| 48 | + unsafe { asm!("pause") } |
| 49 | + } |
| 50 | + write_io_port(base_io_addr, c as u8) |
| 51 | +} |
| 52 | + |
| 53 | +fn com_send_str(base_io_addr: u16, s: &str) { |
| 54 | + let mut sc = s.chars(); |
| 55 | + let slen = s.chars().count(); |
| 56 | + for _ in 0..slen { |
| 57 | + com_send_char(base_io_addr, sc.next().unwrap()); |
| 58 | + } |
| 59 | +} |
| 60 | + |
| 61 | +pub struct Writer {} |
| 62 | + |
| 63 | +impl Writer { |
| 64 | + pub fn write_str(&mut self, s: &str) { |
| 65 | + com_send_str(IO_ADDR_COM2, s); |
| 66 | + } |
| 67 | +} |
| 68 | + |
| 69 | +impl fmt::Write for Writer { |
| 70 | + fn write_str(&mut self, s: &str) -> fmt::Result { |
| 71 | + com_send_str(IO_ADDR_COM2, s); |
| 72 | + Ok(()) |
| 73 | + } |
| 74 | +} |
| 75 | + |
| 76 | +#[no_mangle] |
| 77 | +pub extern "C" fn efi_entry() -> ! { |
| 78 | + use core::fmt::Write; |
| 79 | + com_initialize(IO_ADDR_COM2); |
| 80 | + let mut writer = Writer {}; |
| 81 | + let mut n = 0; |
| 82 | + loop { |
| 83 | + write!(writer, "liumOS loader! n = {}\n\r", n).unwrap(); |
| 84 | + n += 1; |
| 85 | + } |
| 86 | +} |
0 commit comments