Skip to content

Commit

Permalink
Merge #53
Browse files Browse the repository at this point in the history
53: Updates for new build system r=phil-opp a=phil-opp

Update the documentation for the new build system and add an `example-kernel` that provides an easy way to try the `bootloader`.

Builds upon #51.

Co-authored-by: Philipp Oppermann <dev@phil-opp.com>
  • Loading branch information
bors[bot] and phil-opp committed Apr 1, 2019
2 parents e1c6330 + 44b436d commit ab071c6
Show file tree
Hide file tree
Showing 12 changed files with 201 additions and 26 deletions.
6 changes: 6 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## Breaking

- Change the build system: Use a build script that expects a `KERNEL` environment variable instead of using a separate `builder` executable as before. See [#51](https://github.com/rust-osdev/bootloader/pull/51) and [#53](https://github.com/rust-osdev/bootloader/pull/53) for more information.
- This makes the bootloader incompatible with versions `0.6.*` and earlier of the `bootimage` tool.
- The bootloader also requires the `llvm-tools-preview` rustup component now.

# 0.4.0

## Breaking
Expand Down
56 changes: 46 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,50 @@ Written for the [second edition](https://github.com/phil-opp/blog_os/issues/360)

TODO

## Build and Run
You need a nightly [Rust](https://www.rust-lang.org) compiler and [cargo xbuild](https://github.com/rust-osdev/cargo-xbuild).
## Requirements

Then you can run the `builder` executable with your kernel as argument:
You need a nightly [Rust](https://www.rust-lang.org) compiler and [cargo xbuild](https://github.com/rust-osdev/cargo-xbuild). You also need the `llvm-tools-preview` component, which can be installed through `rustup component add llvm-tools-preview`.

## Build

The simplest way to use the bootloader is in combination with the [bootimage](https://github.com/rust-osdev/bootimage) tool. With the tool installed, you can add a normal cargo dependency on the `bootloader` crate to your kernel and then run `bootimage build` to create a bootable disk image. You can also execute `bootimage run` to run your kernel in [QEMU](https://www.qemu.org/) (needs to be installed).

To compile the bootloader manually, you need to invoke `cargo xbuild` with a `KERNEL` environment variable that points to your kernel executable (in the ELF format):

```
cd builder
cargo run -- --kernel path/to/your/kernel/elf/file
KERNEL=/path/to/your/kernel/target/debug/your_kernel cargo xbuild
```

This will output a file named `bootimage.bin` in the `../target/x86_64-bootloader/release` folder.
As an example, you can build the bootloader with example kernel from the `example-kernel` directory with the following commands:

You can run this file using [QEMU](https://www.qemu.org/):
```
cd example-kernel
cargo xbuild
cd ..
KERNEL=example-kernel/target/x86_64-example-kernel/debug/example-kernel cargo xbuild --release
```

This results in a bootloader executable at `target/x86_64-bootloader.json/release/bootloader`. This executable is still an ELF file, which can't be run directly.

## Run

To run the compiled bootloader executable, you need to convert it to a binary file. You can use the `llvm-objcopy` tools that ships with the `llvm-tools-preview` rustup component. The easiest way to use this tool is using [`cargo-binutils`](https://github.com/rust-embedded/cargo-binutils), which can be installed through `cargo install cargo-binutils`. Then you can perform the conversion with the following command:

```
qemu-system-x86_64 -drive format=raw,file=target/x86_64-bootloader/release/bootimage.bin
cargo objcopy -- -I elf64-x86-64 -O binary --binary-architecture=i386:x86-64 \
target/x86_64-bootloader/release/bootloader target/x86_64-bootloader/release/bootloader.bin
```

Or burn it to an USB drive:
You can run the `bootloader.bin` file using [QEMU](https://www.qemu.org/):

```
dd if=target/x86_64-blog_os/debug/bootimage-blog_os.bin of=/dev/sdX && sync
qemu-system-x86_64 -drive format=raw,file=target/x86_64-bootloader/release/bootloader.bin
```

Or burn it to an USB drive to boot it on real hardware:

```
dd if=target/x86_64-bootloader/release/bootloader.bin of=/dev/sdX && sync
```

Where sdX is the device name of your USB stick. **Be careful** to choose the correct device name, because everything on that device is overwritten.
Expand All @@ -40,3 +62,17 @@ Where sdX is the device name of your USB stick. **Be careful** to choose the cor
The bootloader crate can be configured through some cargo features:

- `vga_320x200`: This feature switches the VGA hardware to mode 0x13, a graphics mode with resolution 320x200 and 256 colors per pixel. The framebuffer is linear and lives at address `0xa0000`.
- `recursive_page_table`: Maps the level 4 page table recursively and adds the [`recursive_page_table_address`](https://docs.rs/bootloader/0.4.0/bootloader/bootinfo/struct.BootInfo.html#structfield.recursive_page_table_addr) field to the passed `BootInfo`.
- `map_physical_memory`: Maps the complete physical memory in the virtual address space and passes a [`physical_memory_offset`](https://docs.rs/bootloader/0.4.0/bootloader/bootinfo/struct.BootInfo.html#structfield.physical_memory_offset) field in the `BootInfo`.

## License

Licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)

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.
11 changes: 7 additions & 4 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,13 @@ steps:
failOnStderr: true
displayName: 'Install QEMU (Windows)'

- script: cargo xbuild --target x86_64-example-kernel.json
workingDirectory: example-kernel
displayName: 'Build Example Kernel'
- script: cargo xbuild
workingDirectory: test-kernel
displayName: 'Build Test Kernel'

- script: cargo xbuild --release
displayName: 'Build Bootloader'
env: { KERNEL: "example-kernel/target/x86_64-example-kernel/debug/example-kernel" }
env: { KERNEL: "test-kernel/target/x86_64-test-kernel/debug/test-kernel" }

- script: cargo objcopy -- -I elf64-x86-64 -O binary --binary-architecture=i386:x86-64 target/x86_64-bootloader/release/bootloader target/x86_64-bootloader/release/bootloader.bin
displayName: 'Convert Bootloader ELF to Binary'
Expand All @@ -106,3 +106,6 @@ steps:
if [ $? -eq 123 ]; then (exit 0); else (exit 1); fi
displayName: 'Test Bootloader'

- script: cargo xbuild
workingDirectory: example-kernel
displayName: 'Build Example Kernel'
2 changes: 2 additions & 0 deletions example-kernel/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target = "x86_64-example-kernel.json"
27 changes: 15 additions & 12 deletions example-kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,29 @@

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
static HELLO: &[u8] = b"Hello World!";

#[no_mangle] // don't mangle the name of this function
pub extern "C" fn _start() -> ! {
// this function is the entry point, since the linker looks for a function
// named `_start` by default

// exit QEMU (see https://os.phil-opp.com/integration-tests/#shutting-down-qemu)
unsafe { exit_qemu(); }
let vga_buffer = 0xb8000 as *mut u8;

// print `HELLO` to the screen (see
// https://os.phil-opp.com/minimal-rust-kernel/#printing-to-screen)
for (i, &byte) in HELLO.iter().enumerate() {
unsafe {
*vga_buffer.offset(i as isize * 2) = byte;
*vga_buffer.offset(i as isize * 2 + 1) = 0xb;
}
}

loop {}
}

pub unsafe fn exit_qemu() {
use x86_64::instructions::port::Port;

let mut port = Port::<u32>::new(0xf4);
port.write(61); // exit code is (61 << 1) | 1 = 123
/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
1 change: 1 addition & 0 deletions rust-toolchain
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nightly
2 changes: 2 additions & 0 deletions test-kernel/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[build]
target = "x86_64-test-kernel.json"
2 changes: 2 additions & 0 deletions test-kernel/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target/
**/*.rs.bk
69 changes: 69 additions & 0 deletions test-kernel/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions test-kernel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "test-kernel"
version = "0.1.0"
authors = ["Philipp Oppermann <dev@phil-opp.com>"]
edition = "2018"

[dependencies]
x86_64 = "0.3.4"
28 changes: 28 additions & 0 deletions test-kernel/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#![no_std] // don't link the Rust standard library
#![no_main] // disable all Rust-level entry points

use core::panic::PanicInfo;

/// This function is called on panic.
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}

#[no_mangle] // don't mangle the name of this function
pub extern "C" fn _start() -> ! {
// this function is the entry point, since the linker looks for a function
// named `_start` by default

// exit QEMU (see https://os.phil-opp.com/integration-tests/#shutting-down-qemu)
unsafe { exit_qemu(); }

loop {}
}

pub unsafe fn exit_qemu() {
use x86_64::instructions::port::Port;

let mut port = Port::<u32>::new(0xf4);
port.write(61); // exit code is (61 << 1) | 1 = 123
}
15 changes: 15 additions & 0 deletions test-kernel/x86_64-test-kernel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"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"
}

0 comments on commit ab071c6

Please sign in to comment.