diff --git a/.travis.yml b/.travis.yml index a786fdb6..b8c8837a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,16 +25,3 @@ notifications: script: - RUST_TARGET_PATH=`pwd` xargo build --target x86_64-bootloader --release - objcopy -O binary -S target/x86_64-bootloader/release/bootloader bootimage.bin - -deploy: - provider: script - skip_cleanup: true - on: - repo: rust-osdev/bootloader - tags: true - script: - - | - if [[ "$TRAVIS_TAG" == v* ]]; then - echo "Deploy for $TRAVIS_TAG" - echo "UNIMPLEMENTED!" - fi diff --git a/Cargo.lock b/Cargo.lock index 1a285586..686779dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,12 +5,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bootloader" -version = "0.2.0-alpha-004" +version = "0.2.0" dependencies = [ "fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "os_bootinfo 0.2.1", @@ -32,7 +32,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -43,24 +43,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "getopts" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "libc" -version = "0.2.40" +version = "0.2.42" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "os_bootinfo" version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pulldown-cmark" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -69,16 +73,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "remove_dir_all" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -96,9 +100,14 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "usize_conversions" version = "0.2.0" @@ -106,12 +115,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ux" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -131,12 +140,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "x86_64" version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "os_bootinfo 0.2.1", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ux 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ux 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -154,21 +164,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" -"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" "checksum fixedvec 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c6c16d316ccdac21a4dd648e314e76facbbaf316e83ca137d0857a9c07419d0" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" -"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" +"checksum getopts 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0a7292d30132fb5424b354f5dc02512a86e4c516fe544bb7a25e7f266951b797" +"checksum libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b685088df2b950fccadf07a7187c8ef846a959c142338a48f9dc0b94517eb5f1" +"checksum os_bootinfo 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "66481dbeb5e773e7bd85b63cd6042c30786f834338288c5ec4f3742673db360a" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" -"checksum remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum skeptic 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "061203a849117b0f7090baf8157aa91dac30545208fbb85166ac58b4ca33d89c" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum usize_conversions 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f70329e2cbe45d6c97a5112daad40c34cd9a4e18edb5a2a18fefeb584d8d25e5" -"checksum ux 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8762764bede2cc5fa0fe3bd279e243258531bb51cff1f1ff9a3cb3d3a1ed5235" -"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" +"checksum ux 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53d8df5dd8d07fedccd202de1887d94481fadaea3db70479f459e8163a1fab41" +"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum x86_64 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f14cca51c44bb0f4b5d8048789c46ae2df9bf04cc30dae5242584fa16802ef83" "checksum xmas-elf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22678df5df766e8d1e5d609da69f0c3132d794edf6ab5e75e7abcd2270d4cf58" "checksum zero 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5f1bc8a6b2005884962297587045002d8cfb8dcec9db332f4ca216ddc5de82c5" diff --git a/Cargo.toml b/Cargo.toml index 9a657520..e7238a46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,16 @@ +cargo-features = ["publish-lockfile"] + [package] name = "bootloader" -version = "0.2.0-alpha-004" +version = "0.2.0" authors = ["Philipp Oppermann "] license = "MIT/Apache-2.0" description = "An experimental pure-Rust x86 bootloader." +publish-lockfile = true [dependencies] xmas-elf = "0.6.2" -# x86_64 = "0.2.0-alpha" -x86_64 = { git = "https://github.com/nebulet/x86_64" } +x86_64 = "0.2.7" usize_conversions = "0.2.0" # os_bootinfo = "0.2.0" os_bootinfo = { git = "https://github.com/nebulet/os_bootinfo" } diff --git a/src/boot.s b/src/boot.s index 0e32dacd..b9f00782 100644 --- a/src/boot.s +++ b/src/boot.s @@ -12,7 +12,8 @@ _start: mov fs, ax mov gs, ax - # TODO explain + # clear the direction flag (e.g. go forward in memory when using + # instructions like lodsb) cld @@ -29,6 +30,7 @@ enable_a20: out 0x92, al enter_protected_mode: + # clear interrupts cli push ds push es @@ -118,6 +120,9 @@ println: print: cld print_loop: + # note: if direction flag is set (via std) + # this will DECREMENT the ptr, effectively + # reading/printing in reverse. lodsb al, BYTE PTR [esi] test al, al jz print_done diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..360fb649 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,27 @@ +#![no_std] + +extern crate os_bootinfo; + +pub mod bootinfo { + pub use os_bootinfo::*; +} + +/// Defines the entry point function. +/// +/// The function must have the signature `fn(&'static BootInfo) -> !`. +/// +/// This macro just creates a function named `_start`, which the linker will use as the entry +/// point. The advantage of using this macro instead of providing an own `_start` function is +/// that the macro ensures that the function and argument types are correct. +#[macro_export] +macro_rules! entry_point { + ($path:path) => { + #[export_name = "_start"] + pub extern "C" fn __impl_start(boot_info: &'static $crate::bootinfo::BootInfo) -> ! { + // validate the signature of the program entry point + let f: fn(&'static $crate::bootinfo::BootInfo) -> ! = $path; + + f(boot_info) + } + }; +} diff --git a/src/main.rs b/src/main.rs index 91b7b8b2..03b97282 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,10 @@ #![feature(lang_items)] #![feature(global_asm)] -#![feature(iterator_step_by)] #![feature(try_from)] #![feature(step_trait)] #![feature(asm)] #![feature(nll)] -#![feature(pointer_methods)] #![feature(const_fn)] -#![feature(nll)] #![feature(panic_implementation)] #![no_std] #![no_main] @@ -174,9 +171,7 @@ pub extern "C" fn load_elf( let kernel_end_page: Page = Page::containing_address(kernel_start.virt() + kernel_size - 1u64); for page in Page::range_inclusive(kernel_start_page, kernel_end_page) { - rec_page_table - .unmap(page) - .expect("dealloc error").1.flush(); + rec_page_table.unmap(page).expect("dealloc error").1.flush(); } // Map kernel segments. @@ -252,9 +247,7 @@ fn enable_write_protect_bit() { #[no_mangle] pub extern "C" fn panic(info: &PanicInfo) -> ! { use core::fmt::Write; - - let _ = write!(printer::Printer, "{}", info); - + write!(printer::Printer, "{}", info).unwrap(); loop {} } diff --git a/src/page_table.rs b/src/page_table.rs index 3072e937..4b787818 100644 --- a/src/page_table.rs +++ b/src/page_table.rs @@ -1,7 +1,7 @@ use fixedvec::FixedVec; use frame_allocator::FrameAllocator; use os_bootinfo::MemoryRegionType; -use x86_64::structures::paging::{MapToError, RecursivePageTable, UnmapError}; +use x86_64::structures::paging::{self, MapToError, RecursivePageTable, UnmapError}; use x86_64::structures::paging::{Mapper, MapperFlush, Page, PageSize, PageTableFlags, PhysFrame, Size4KiB}; use x86_64::{align_up, PhysAddr, VirtAddr}; use xmas_elf::program::{self, ProgramHeader64}; @@ -158,5 +158,13 @@ where S: PageSize, RecursivePageTable<'a>: Mapper, { - page_table.map_to(page, phys_frame, flags, frame_allocator) + struct PageTableAllocator<'a, 'b: 'a>(&'a mut FrameAllocator<'b>); + + impl<'a, 'b> paging::FrameAllocator for PageTableAllocator<'a, 'b> { + fn alloc(&mut self) -> Option> { + self.0.allocate_frame(MemoryRegionType::PageTable) + } + } + + page_table.map_to(page, phys_frame, flags, &mut PageTableAllocator(frame_allocator)) } diff --git a/src/second_stage.s b/src/second_stage.s index 5b2b1b41..b44e794e 100644 --- a/src/second_stage.s +++ b/src/second_stage.s @@ -10,6 +10,18 @@ second_stage: lea si, second_stage_start_str call println +set_target_operating_mode: + # Some BIOSs assume the processor will only operate in Legacy Mode. We change the Target + # Operating Mode to "Long Mode Target Only", so the firmware expects each CPU to enter Long Mode + # once and then stay in it. This allows the firmware to enable mode-specifc optimizations. + # We save the flags, because CF is set if the callback is not supported (in which case, this is + # a NOP) + pushf + mov ax, 0xec00 + mov bl, 0x2 + int 0x15 + popf + load_kernel_from_disk: # start of memory buffer lea eax, _kernel_buffer @@ -50,7 +62,11 @@ load_next_kernel_block_from_disk: push ecx push esi mov ecx, 512 / 4 + # move with zero extension + # because we are moving a word ptr + # to esi, a 32-bit register. movzx esi, word ptr [dap_buffer_addr] + # move from esi to edi ecx times. rep movsd [edi], [esi] pop esi pop ecx @@ -71,13 +87,7 @@ check_cpu: call check_cpuid call check_long_mode -disable_irqs: - mov al, 0xFF # Out 0xFF to 0xA1 and 0x21 to disable all IRQs. - out 0xA1, al - out 0x21, al - - nop - nop + cli # disable interrupts lidt zero_idt # Load a zero length IDT so that any NMI causes a triple fault. @@ -250,7 +260,7 @@ gdt_64_pointer: long_mode: # call load_elf with kernel start address, size, and memory map as arguments - movabs rdi, 0x400000 + movabs rdi, 0x400000 # move absolute 64-bit to register mov rsi, _kib_kernel_size lea rdx, _memory_map movzx rcx, word ptr mmap_ent