Giter Site home page Giter Site logo

bootloader's Introduction

bootloader

Docs Build Status Join the chat at https://rust-osdev.zulipchat.com

An experimental x86_64 bootloader that works on both BIOS and UEFI systems. Written in Rust and some inline assembly, buildable on all platforms without additional build-time dependencies (just some rustup components).

Requirements

You need a nightly Rust compiler with the llvm-tools-preview component, which can be installed through rustup component add llvm-tools-preview.

Usage

To use this crate, you need to adjust your kernel to be bootable first. Then you can create a bootable disk image from your compiled kernel. These steps are explained in detail below.

If you're already using an older version of the bootloader crate, follow our migration guides.

Kernel

To make your kernel compatible with bootloader:

  • Add a dependency on the bootloader_api crate in your kernel's Cargo.toml.
  • Your kernel binary should be #![no_std] and #![no_main].
  • Define an entry point function with the signature fn kernel_main(boot_info: &'static mut bootloader_api::BootInfo) -> !. The function name can be arbitrary.
    • The boot_info argument provides information about available memory, the framebuffer, and more. See the API docs for bootloader_api crate for details.
  • Use the entry_point macro to register the entry point function: bootloader_api::entry_point!(kernel_main);
    • The macro checks the signature of your entry point function and generates a _start entry point symbol for it. (If you use a linker script, make sure that you don't change the entry point name to something else.)
    • To use non-standard configuration, you can pass a second argument of type &'static bootloader_api::BootloaderConfig to the entry_point macro. For example, you can require a specific stack size for your kernel:
      const CONFIG: bootloader_api::BootloaderConfig = {
          let mut config = bootloader_api::BootloaderConfig::new_default();
          config.kernel_stack_size = 100 * 1024; // 100 KiB
          config
      };
      bootloader_api::entry_point!(kernel_main, config = &CONFIG);
  • Compile your kernel to an ELF executable by running cargo build --target x86_64-unknown-none. You might need to run rustup target add x86_64-unknown-none before to download precompiled versions of the core and alloc crates.
  • Thanks to the entry_point macro, the compiled executable contains a special section with metadata and the serialized config, which will enable the bootloader crate to load it.

Booting

To combine your kernel with a bootloader and create a bootable disk image, follow these steps:

  • Move your full kernel code into a kernel subdirectory.
  • Create a new os crate at the top level that defines a workspace.
  • Add a build-dependencies on the bootloader crate.
  • Create a build.rs build script.
  • Set up an artifact dependency to add your kernel crate as a build-dependency:
    # in Cargo.toml
    [build-dependencies]
    kernel = { path = "kernel", artifact = "bin", target = "x86_64-unknown-none" }
    # .cargo/config.toml
    
    [unstable]
    # enable the unstable artifact-dependencies feature, see
    # https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dependencies
    bindeps = true
    Alternatively, you can use std::process::Command to invoke the build command of your kernel in the build.rs script.
  • Obtain the path to the kernel executable. When using an artifact dependency, you can retrieve this path using std::env::var_os("CARGO_BIN_FILE_MY_KERNEL_my-kernel")
  • Use bootloader::UefiBoot and/or bootloader::BiosBoot to create a bootable disk image with your kernel.
  • Do something with the bootable disk images in your main.rs function. For example, run them with QEMU.

See our disk image creation template for a more detailed example.

Architecture

This project is split into three separate entities:

  • A bootloader_api library with the entry point, configuration, and boot info definitions.
    • Kernels should include this library as a normal cargo dependency.
    • The provided entry_point macro will encode the configuration settings into a separate ELF section of the compiled kernel executable.
  • BIOS and UEFI binaries that contain the actual bootloader implementation.
    • The implementations share a higher-level common library.
    • Both implementations load the kernel at runtime from a FAT partition. This FAT partition is created
    • The configuration is read from a special section of the kernel's ELF file, which is created by the entry_point macro of the bootloader_api library.
  • A bootloader library to create bootable disk images that run a given kernel. This library is the top-level crate in this project.
    • The library builds the BIOS and UEFI implementations in the build.rs.
    • It provides functions to create FAT-formatted bootable disk images, based on the compiled BIOS and UEFI bootloaders.

License

Licensed under either of

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

bootloader's People

Contributors

64 avatar aaron1011 avatar abachmann avatar acheronfail avatar alexjmohr avatar andre-richter avatar asensio-project avatar bors[bot] avatar craftspider avatar darksecond avatar devsnek avatar freax13 avatar gitter-badger avatar hawkw avatar isaacwoods avatar jasoncouture avatar josephlr avatar kennystrawnmusic avatar lachlansneff avatar martica avatar mgr0dzicki avatar phil-opp avatar phip1611 avatar rkennedy9064 avatar rsribeiro avatar stary2001 avatar strake avatar toothbrush7777777 avatar tsatke avatar vinaychandra avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bootloader's Issues

How does one get the multiboot information address?

From your first volume, you would do something like

start:
    mov %esp, stack_top
    mov %edi, %ebx

and then add multiboot_information_address: usize to the "kmain" (or in the case of volume 2, _start).

However, when I add

global_asm!(r#"
start:
    mov %esp, stack_top
    mov %edi, %ebx
"#);

to the top of my main.rs, and do

pub extern "C" fn _start(multiboot_information_address: usize) -> ! {
    let boot_info = unsafe{ multiboot2::load(multiboot_information_address)};
    let memory_map_tag = boot_info.memory_map_tag()
        .expect("Memory map tag required");

    println!("memory areas:");
    for area in memory_map_tag.memory_areas() {
        println!("    start: 0x{:x}, length: 0x{:x}",
            area.base_addr, area.length);
    }
    ...

The kernel panics with
screenshot from 2018-05-06 12-40-27
(I added a function to handle panics)

Thank you in advance

Decrease Kernel Stack Size

The bootloader currently sets up huge stack for the kernel by default (512 pages = 2MB). Now that the stack size is configurable, we should probably reduce the default.

cc @64

PhysFrames mapped multiple times?

Yeah, stuff gets mapped multiple times. Here is my log output [from an isa-debugcon]:

; STUFF HERE
MAP @ PhysFrame[4KiB](0x5f8000) to Page[4KiB](0xf001f7000)
Now mapping Seg
MAP @ PhysFrame[4KiB](0x5f8000) to Page[4KiB](0xf001f7000)
panicked at 'kernel mapping failed: Mapping(PageAlreadyMapped(PhysFrame[4KiB](0x5f8000)))', src/main.rs:268:6

And it just hangs. So... It seems that sections do NOT have to be 4k-aligned in ELFs. The culprit in my case was .got. Forcing it to stay aligned fixed my problem. But, this should just work and not require custom linker scripts.

Can't build the code

Building the bootloader fails during the linking stage. It appears some funcs are not implemented in rlibc.

error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/home/cylon2p0/.xargo/HOST/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.114xigf1yyw2gcw0.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.16u6js6g0l3k1ic6.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.170lmw1sqqfe80qo.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.1dk5kk1ooqmqppyo.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.1dqvxks6k2bzkxe.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.1dtnwzxvq606tnr.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.1gwav539dtqo5mpz.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.1jlhl2cwhfjqk73.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.1rumt9cqnarag56v.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.1y0f1d2ywo4h8fck.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.1y16o1qfye96o7m0.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.236iz806sghm3wx.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.27e9glo77wiztta4.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.2jqywn86b2gsqohu.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.2lyh15q6cjwzy18c.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.2qnu5lz8itx5t8lt.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.2uoyeb1ud6wb16nh.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.340hcms0rqmw1pjh.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.39fsqmmlmfbk11x5.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.3ab2w6r2t45b4bca.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.3ik0x0hz6l66cx38.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.3ldk0i2zxftngav8.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.3mf543h185mr1r9y.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.436dotimmrgzkwfa.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.43v6g0y2xsxoggnt.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.45pc7c65foh9i35f.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.48721dc4k5qxei0u.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.49a7n47po4ttqjl7.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.4h0kvux6xasoqj9f.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.4hqczukarqnsxim3.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.4re5h8xun1god8vx.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.4svjkysiwylw53vz.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.4tz198z0woys4rj8.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.4xq48u46a1pwiqn7.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.4yh8x2b62dcih00t.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.4ypvbwho0bu5tnww.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.51s1w397y42gpez1.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.56dhlykxk36fnj7k.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.57k06xfugllsc526.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.594xacf7fal17zd5.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.5csepo1d58sdgir4.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.7p53qlves2rwxx0.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.8xzrsc1ux72v29j.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.98g0d9x8aw3akpe.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.9elsx31vb4it187.rcgu.o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.ehly403ieh2api9.rcgu.o" "-o" "/home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "-L" "/home/cylon2p0/bootloader/target/debug/deps" "-L" "/home/cylon2p0/.xargo/HOST/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "/home/cylon2p0/bootloader/target/debug/deps/libspin-c51b2e86c2de1538.rlib" "/home/cylon2p0/bootloader/target/debug/deps/libos_bootinfo-dba7815e5fe96d50.rlib" "/home/cylon2p0/bootloader/target/debug/deps/libarrayvec-53c961d979185dfa.rlib" "/home/cylon2p0/bootloader/target/debug/deps/libnodrop-5ac98ef241ef76ef.rlib" "/home/cylon2p0/bootloader/target/debug/deps/libx86_64-8aa0ca550f385699.rlib" "/home/cylon2p0/bootloader/target/debug/deps/libux-1c933097b4b69b23.rlib" "/home/cylon2p0/bootloader/target/debug/deps/libusize_conversions-5b96477c65312c01.rlib" "/home/cylon2p0/bootloader/target/debug/deps/libbit_field-f6dd7c703522e559.rlib" "/home/cylon2p0/bootloader/target/debug/deps/libbitflags-a50202da937bfed0.rlib" "/home/cylon2p0/bootloader/target/debug/deps/libxmas_elf-28f6da88f7f9c0cf.rlib" "/home/cylon2p0/bootloader/target/debug/deps/libzero-359b6889bcf3f9b5.rlib" "/home/cylon2p0/bootloader/target/debug/deps/librlibc-a70e38fe72970e76.rlib" "/home/cylon2p0/.xargo/HOST/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-6b8006ed673e894b.rlib" "-Tlinker.ld" "-Wl,-Bdynamic"
  = note: /home/cylon2p0/bootloader/target/debug/deps/bootloader-135935f7d9f3d13c.170lmw1sqqfe80qo.rcgu.o: In function `_start':
          170lmw1sqqfe80qo-d74921964f837aa8fb1308e78eea466c.rs:(.boot+0x0): multiple definition of `_start'
          /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/../../../../lib/Scrt1.o:(.text+0x0): first defined here
          /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/../../../../lib/Scrt1.o: In function `_start':
          (.text+0x12): undefined reference to `__libc_csu_fini'
          (.text+0x19): undefined reference to `__libc_csu_init'
          (.text+0x20): undefined reference to `main'
          (.text+0x26): undefined reference to `__libc_start_main'
          collect2: error: ld returned 1 exit status

Deprecation: `asm!` > `llvm_asm!`

Should be a pretty simple problem to fix, but as of 24 April 2020, use of the asm! macro is triggering multiple deprecation warnings:

warning: use of deprecated item 'asm': the syntax of asm! will change soon, use llvm_asm! to avoid breakage
  --> src/main.rs:46:5
   |
46 |     asm!("call $1; ${:private}.spin.${:uid}: jmp ${:private}.spin.${:uid}" ::
   |     ^^^ help: replace the use of the deprecated item: `llvm_asm`
   |
   = note: `#[warn(deprecated)]` on by default

warning: use of deprecated item 'asm': the syntax of asm! will change soon, use llvm_asm! to avoid breakage
  --> src/main.rs:92:5
   |
92 |     asm!("mov bx, 0x0
   |     ^^^ help: replace the use of the deprecated item: `llvm_asm`

Should be an easy fix if you ask me โ€• since there's probably a lot more instances than those two, is this being worked on already?

Map critical memory regions before loading kernel if detected

I'm wondering if its possible to explicitly map memory regions in the bootloader? For example, could we detect to see if the APIC is available, then map its entire memory region into the page table before loading the kernel, and then let the kernel configure the IDT? We can even pass the address of the APIC region (its default is FE0000, if I'm not mistaken, but this can change) in the boot information structure. Is this feasible, and if so how would it be accomplished?

Enable tls sections

tdata and tbss section stores thread local storage for the system. In kernel, we will need to initialize this section per-cpu or per-thread depending on usages. Rust provides a #[thread_local] attribute which puts the data in the above sections.

Please enable that section in bootloader and pass its location to the kernel so that it can map the TLS data as needed.

Allow specifying address of boot_info structure.

When making a higher half kernel it would be useful to move the boot_info into the higher half. It would also have to remap all the child structures, like memory_map

I imagine it would go into the [package.metadata.bootloader] like physical-memory-offset and kernel-stack-address.

Improve Build System and Documentation

Things we have to do in order to improve this crate:

  • Use cargo-xbuild instead of xargo (since the latter is no longer maintained)
  • Run travis CI build on Linux, Windows, and macOS (only the cargo build step for now, not the objcopy step)
  • Create a build sub-crate that builds the bootloader and links it with a kernel to create a bootable disk image. The tool needs to do the following:
    • Run cargo xbuild --target x86_64-bootloader.json --release
    • Convert the resulting ELF file to a binary file. Either in Rust code (like bootimage does) or through the bundled llvm-objcopy and cargo-binutils
    • Append a "kernel info block" to the binary file: A 512 byte structure which contains the total size of the kernel (this is used by the bootloader to figure out how many bytes it needs to load into memory)
    • Append an ELF kernel right behind the kernel info block. The build tool could e.g. take the path to the ELF file as an argument.
  • Update the Readme

Handle bss sections

At the moment, the bootloader only handles normal loadable ELF sections. It should also zero .bss and similar sections.

Booting from USB gets stuck with "Booting (first stage)..."

image

i get stuck with this screen on Oracle Virtual box, and 2 hardware devices, if i use a USB stick with the image.
it works fine if i use qemu-system-x86_64 to load the binary.
it works fine if i use qemu-system-x86_64 to boot from a USB stick with the image.

i am using this source code to build the binary (pinned to the commit i was using) https://github.com/CaptainOachkatzl/RustOS/tree/de6aaee00cc11f8274ca9b003730c7a10dd11210

in the zip are the binary and the virtualbox USB drive image i was using
bootloader_stuck.zip


this was the information part. i also want to say what you are doing is amazing and it helped me out a lot so thank you for that!

Incorrect stack alignment

The boot loader provides the kernel with a miss aligned stack.

This cause issues when SSE is enabled, as some of those instructions expect 16-aligned stacks and the alignment is off by eight.

Reproduction steps:

Take blog-os post-03, enable SSE in the boot loader and target, call panic! in main, if running under bochs you will get a fault.
(QEMU appears to ignore the issue)

The fault occurs on movaps instruction form xmm0 to the (mis-aligned stack).

The stack alignment is mess-ed up because when the _start function is called the compiler assumes a return address has been pushed on the stack, making it 16x +8 aligned, while it is apparently 16 aligned when called by the bootloader.

From reading OS dev wiki, the kernel entry point should be reached using a call instruction so that it matches the compiler assumptions, (Even in C) whereas the boot loader appears to use a jmp.

Compiling with "binary" feature with example kernel fails

When building the bootloader as a dependency (i.e. to enjoy the extra features) the build fails:

thread 'main' panicked at 'The bootloader must be compiled for the `x86_64-bootloader.json` target.', C:\Users\ethin\.cargo\registry\src\github.com-1ecc6299db9ec823\bootloader-0.8.0\build.rs:108:9

I am attempting to take advantage of the dynamic stack selection, dynamic kernel placement, etc., that I would not otherwise enjoy had I not specified the "binary" feature. Is this doable?

Mutable BootInfo

Hey there! I have a question and, maybe, a suggestion: should bootinfo be passed as a mutable static reference? Or maybe there is no need at all for it to be a static reference? Maybe the struct itself should just contain the address (which can be easily copied) and all the other copies of bootinfo can operate on it during the function calls?

Right now, there seems to be a slight problem / inconvenience, where you cannot allocate any physical frames, because you have a static immutable reference to the bootinfo struct, which contains the required structs / functions.

Cheers, Alex!

Failed to load second stage of bootloader

The booloader fails to load the second stage when run in qemu. In func load_second_stage_from_disk in file boot.s the code jumps to label second_stage_load_failed as the carry flag has been set.

Rewrite

Bootloader Rewrite

This is the tracking issue for the bootloader rewrite. We're tracking our progress under the "Rewrite" milsestone. Our progress is as follows

  • Successfully execute Rust in real mode
  • Enter protected mode
  • Use virtual 8086 mode to read the kernel in chunks, copying to protected mode
  • Set up paging
  • Enter long mode
  • Jump to the kernel

Our eventual roadmap is to include UEFI support (@phil-opp is working on that) and multiboot client support, so we can load our kernel from GRUB (and other complaint loaders)

Make the kernel stack movable

Right now the kernel stack is always fixed in memory. If I want to make my kernel higher-half the kernel will need to move. This can be done by providing a custom linker script to the kernel target. This works fine. The stack that is setup by the bootloader however is always fixed in memory and will not move with the kernel.

I suggest making the stack location configurable like the physical memory offset already is. A more elegant solution would be to switch to an offset and automatically calculate the stack location.

Documentation on initial state

Is there any documentation about the state of the system when _start function is invoked by the bootloader? For example, what features are enabled, what is the layout of memory, what state are the processors in?

VGA video modes

I've finally had some spare time to start working on my OS again and was hoping I might have a chance to give back after all the great work you've done so far. I know there's currently an open issue for VESA video modes #37, but I didn't want to hijack that thread.

Since you have plans for VESA video modes in the future, would you also be interested in adding support for VGA modes? I've just finished a minimal example that has support for switching to 80x25 text mode from the kernel using VGA registers. The current code can be found here https://gist.github.com/RKennedy9064/374ed861f743079e43b1c5da87af63f8.

I was able to successfully boot my OS using the vga_320x200 mode from bootloader, then switch to 80x25 text mode and use the println! macro to display messages again.

I'm not sure if this is on the road map, or even something you're interested in, but if you are I'd love to possible collaborate to include something like this. My plan is to clean up the existing code, add more comments and tests and then try to add more support for additional modes. I figured it would be nice to have the ability to switch video modes from the kernel at run time.

Let me know what you think when you have the time and thanks for all the great work so far on the tutorials!

PXE support (with iPXE)

Would it be possible to have support to boot using PXE or iPXE (with iPXE downloading the bootimage.bin using TFTP for instance).

This would require changing the logic to load the files in memory (which iPXE probably takes care of).

This could be poretty helpful for development on real hardware, as it wuld allow to network boot instead of going through the write to USB manipulations.

Hangs before kernel entry

It seems to be a regression between 0.2.0 and 0.2.1: 0.2.0 works fine but 0.2.1 and 0.3.0 both hang.

Tested on qemu-3.0.0 on linux 4.14.18 x86_64, built with rustc 1.30.0-nightly (4141a4079 2018-09-25)

Explanation / Tutorial

I love the idea of a pure Rust bootloader, but I'd love to know how it works, and perhaps write my own. Are there some good resources for this? I'd love to see a Phil-Opp tutorial about writing your own bootloader...

Hangs before second stage on a real machine, works fine in QEMU

Im following the OS dev tutorial series and decided to try to run the kernel on a real machine, but it hangs indefinitely before the second stage of the bootloader.

It prints Booting... (first stage) and then hangs. No other output unfortunately.

I've tried building it in release mode (as suggested in a similar issue) but it doesn't make a difference. Everything works fine when I run it in QEMU, release or debug.

Any ideas? Would be cool to see it running on real hardware :)

Edit: I'm on macOS, booting from a USB stick. Writing the image with dd if=target/x86_64-blog_os/release/bootimage-blog_os.bin of=/dev/disk3 && sync

Cargo warning about `publish-lockfile` feature when compiling

Hello! When I test an handwritten OS following the toturial Writing an OS in Rust, the test is successful, but there is a warning on configuration when building the bootloader. Here's my console output:

PS D:\RustProjects\spicy_os> cargo xtest
   Compiling spicy_os v0.1.0 (D:\RustProjects\spicy_os)
    Finished dev [unoptimized + debuginfo] target(s) in 0.38s
     Running target\x86_64-spicy_os\debug\deps\spicy_os-990499773c553c1e
Building bootloader
warning: The `publish-lockfile` feature is deprecated and currently has no effect. It may be removed in a future version.
   Compiling bootloader v0.6.0 (C:\Users\luojia65\.cargo\registry\src\mirrors.ustc.edu.cn-61ef6e0cd06fb9b8\bootloader-0.6.0)
    Finished release [optimized + debuginfo] target(s) in 1.88s
Running: `qemu-system-x86_64 -drive format=raw,file=D:\RustProjects\spicy_os\target\x86_64-spicy_os\debug\deps\bootimage-spicy_os-990499773c553c1e.bin -device isa-debug-exit,iobase=0xf4,iosize=0x04 -serial stdio -display none

According to this warning, cargo feature publish-lockfile has currently no effect. It looks like this is related to the piece of code here. Would it be possible to remove this cargo feature configuration, or do another way to fix this warning?

Here's my Rustup and Rustc version:

C:\Users\luojia65>rustup -V
rustup 1.18.3 (435397f48 2019-05-22)

C:\Users\luojia65>rustc -V
rustc 1.35.0 (3c235d560 2019-05-20)

Windows/macOS Support

Will bootloader support windows/macOS ? I went to x86_64-bootlader.json, but there's only "x86_64-unknown-none-gnu" target for llvm

Configuration does not work

I am slightly new to rust. Apologize for any mistakes.
I am trying to add [package.metadata.bootloader] but it does not take effect.

Steps for repro:

  1. Checkout post-10 from blog_os
  2. Add println!("{:X}", boot_info.physical_memory_offset); to kernel_main
  3. Add the following snippet to cargo.toml at the end
[package.metadata.bootloader]
kernel-stack-address = "0xFFFFFF8000000000"
kernel-stack-size = 128
physical-memory-offset = "0xFFFF800000000000"

Expected output: 0xFFFF800000000000
Current output: not 0xFFFF800000000000

Am I missing something? Should I have to build bootloader myself to use the configuration?

`error: This crate currently does not support 32-bit protected mode` when compiling kernel with x86_64-unknown-none target

After updating bootloader to 0.8.3 I started getting error: This crate currently does not support 32-bit protected mode error but I am pretty sure that I cross-compile x86_64 arch binary.
This issue is not reproducible with bootloader version 0.7.1 or lower. Here is the content of my target x86_64-unknown-none.json:
{
"llvm-target": "x86_64-unknown-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"arch": "x86_64",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"executables": true,
"linker-flavor": "ld.lld",
"linker": "rust-lld",
"panic-strategy": "abort",
"disable-redzone": true,
"features": "-mmx,-sse,+soft-float"
}

I am compiling with this command:
cargo bootimage --target x86_64-unknown-none.json

Best regards!

Building error when kernel filename containing special characters

Hi all,

A building error occurs when renaming the kernel binary and building

cp example-kernel/target/x86_64-example-kernel/debug/example-kernel example-kernel/target/x86_64-example-kernel/debug/example-kernel.elf

KERNEL=example-kernel/target/x86_64-example-kernel/debug/example-kernel.elf KERNEL_MANIFEST=example-kernel/Cargo.toml cargo xbuild --release --features binary

Error: rust-lld: error: undefined symbol: _kernel_start_addr.

It seems that build.rs does not redefine the symbols correctly, i.e., _binary_objfile_* set by objcopy, when objfile name contains the special character ..

Running under HAXM?

I want to run my kernel under HAXM but whenever I do that Qemu immediately gives me two VCPU shutdown requests (that's using -accel hax). Is there a way we can add HAXM support or is this a bug in Qemu itself?

Basic instructions for FileSystem

The current bootloader generates a ".bin" file at the end which is a hard disk image. Is it possible to provide some instructions to generate a simple FAT disk with that bin file of ELF file?

Because the bootloader is completely customized, i am struggling to understand how to put the bin file or some part of the kernel in an actual file system.
For example, using GRUB one can follow these to generate disks

Or alternatively, can we make GRUB boot this bootloader (not chainloading because it works on different disks)

Enable support for SMP Trampoline

The current entry point is hardcoded to _start (or the entry_point! macro). This provides a single entry point to the code.

When bootstrapping SMP, the new processor starts up at a given physical address in the IPI (Inter-Processor Interrupt) in 16 bit mode. This requires us to start at 16 bit code and enable 64 bit mode again. Please provide a way to define multiple "entry points" which defaults to the current _start but can also be used to bootstrap SMP.

`extern` fn uses type `core::panic::PanicInfo`, which is not FFI-safe

https://github.com/rust-osdev/bootloader/blob/master/src/main.rs#L368

does the panic handler really need to be extern "C"?

it causes a warning due to PanicInfo not being ffi-safe:

   Compiling bootloader v0.8.2 (/Users/user/.cargo/registry/src/github.com-1ecc6299db9ec823/bootloader-0.8.2)
warning: `extern` fn uses type `core::panic::PanicInfo`, which is not FFI-safe
   --> src/main.rs:368:31
    |
368 | pub extern "C" fn panic(info: &PanicInfo) -> ! {
    |                               ^^^^^^^^^^ not FFI-safe
    |
    = note: `#[warn(improper_ctypes)]` on by default
    = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
    = note: this struct has unspecified layout

    Finished release [optimized + debuginfo] target(s) in 3.16s

Don't construct invalid references when building BootInfo

The references are currently only valid in the kernel address space, and not in the current bootloader address space. We could fix this by either:

  • Map the kernel to the same address space as the bootloader.
  • Use a BootInfo address from the identity mapped area.

ld.bfd not found

I try to build the code in MacOS 10.13.3 by using

$ RUST_TARGET_PATH=$(pwd) xargo build --target x86_64-bootloader --release

However, I got the error below:

wx20180401-201247 2x

Rewrite build system?

Currently the build process is a bit strange:

  • First, we build the kernel
  • Then we convert the ELF file to a binary
  • Then we append a 512 byte sized structure that contains the kernel length
  • Finally we append the kernel

We could change it in the following way:

  • We could create a build script that reads an BOOTLOADER_KERNEL_PATH environment variable, converts it to a binary blob and then back to an object file (e.g. cargo objcopy -- -I binary -O elf64-x86-64 target/x86_64-blog_os/debug/blog_os blog_os_bin.o --binary-architecture=i386:x86-64)
  • Rename the default .data section to .kernel
  • The build script then passes the object file to the linker
  • This means that we can directly access the kernel blob in the linker script and directly access start/end/size of the kernel

The new build process would be:

  • Build the kernel
  • Build the bootloader (with an environment variable set to the kernel path)
  • Convert the bootloader ELF file to a binary

The big disadvantage of this is that we need to rebuild the bootloader for each kernel change, so maybe it is better to keep the current build system.

Build successfully with benign errors in WSL

When I build the bootloader under WSL (Windows subsystem Linux), it finishes while reporting errors:

Compiling bootloader v0.8.0 (/mnt/d/devs/Rust/bootloader)
error: failed to remove /mnt/d/devs/Rust/bootloader/target/x86_64-bootloader/release/deps/bootloader-589b595378e59014.bootloader.3pdwijpa-cgu.0.rcgu.o: Input/output error (os error 5)

error: failed to remove /mnt/d/devs/Rust/bootloader/target/x86_64-bootloader/release/deps/bootloader-589b595378e59014.bootloader.3pdwijpa-cgu.1.rcgu.o: Input/output error (os error 5)

error: failed to remove /mnt/d/devs/Rust/bootloader/target/x86_64-bootloader/release/deps/bootloader-589b595378e59014.bootloader.3pdwijpa-cgu.12.rcgu.o: Input/output error (os error 5)

error: aborting due to 3 previous errors

Finished release [optimized + debuginfo] target(s) in 3.83s

  1. It does not report the errors if I enter the build command again.
  2. The mentioned files can be removed manually since they have all the r/w file permissions set.
  3. The same errors reported when building blog_os as well, and does not block anything. I.e., blog_os can run/test in WSL as expected. The same situation happens since post-02.

Failed to load rest of bootloader

I'm getting the following error when I try to build and run this bootloader:

image

FWIW this happens both on linux (ubuntu 18.10) as well as on macOS (10.14).

Any pointers you can give me for debugging this?

Make builder executable available as binary?

Would you consider adding the builder executable to a [[bin]] section of the cargo manifest a good idea? That should simplify things for people who don't want to clone the repo and manually cd into the builder directory to make use of it.

If so, I'm happy to whip up the short PR

VESA video modes

Hello there! I need to start by saying that this project is awesome and I strongly believe it will spark the creation of some very creative pieces of software!

Nevertheless, I think it would have being awesome to add support for choosing one of the available VESA modes. Right now, you have to do it in real-time mode, while bootloader switches the processor to go to 64-bits and therefore, if you need to work with it, then you need to somehow go back to 16-bits in the kernel (or 32-bits with emulation?) and do the setup. Making bootloader do it might be the best idea (as well as give it an option to automatically choose the highest option).

As far as I understand, it can be quite a challenge, considering you have to fit it into 16-bit processor mode memory (512 first bytes?), but as far as I know, it is rather doable.

I think that this implementation from Redox OS can serve as a good example.

Cheers, Alex!

Advanced Documentation

Currently we only provide some minimal build instructions in the Readme. We should also document advanced patterns such as:

  • Creating a higher half kernel
  • Chainloading with GRUB (see #49) Completed in #66

I think the best approach for now is to just create a doc folder with markdown files in it and link it from the Readme.

Don't mask IRQs

Currently the bootloader masks all hardware interrupts:

disable_irqs:
mov al, 0xFF # Out 0xFF to 0xA1 and 0x21 to disable all IRQs.
out 0xA1, al
out 0x21, al

They shouldn't be masked when control is passed to the kernel.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.