Code Monkey home page Code Monkey logo

chocolate_milk's Introduction

Summary

This is a bootloader and kernel written nearly entirely in Rust with no third party dependencies at all. Everything in this code base is all you need code wise.

Building

Requirements

To build this you need Rust, nasm, and lld-link (from LLVM's linker). This bootloader and kernel are built identically regardless of the build system. It should build just fine on Linux, Windows, OSX, BSD, whatever.

You can get nasm here or from apt install nasm

You can get LLVM binaries here or apt install lld

You can get Rust here. You must use nightly Rust!

This project requires that you have the i586-pc-windows-msvc and x86_64-pc-windows-msvc Rust targets installed.

rustup target add i586-pc-windows-msvc x86_64-pc-windows-msvc

Specifically nasm, lld-link, rustup, and cargo must be in your PATH. If one of these are not in your path, you may need to create a symlink to the specific version (eg: lld-link-10)

Building

To build this simply run cargo run this will create a folder called pxe that will contain the folder which needs to be exposed via a TFTP server. Optionally, the files could be copied from the pxe folder to your existing PXE deployment folder.

Usage

This bootloader and kernel require PXE booting. They do not support disks in any way, shape, or form. Everything is done over the network. To use this bootloader and kernel you need to set up a valid PXE boot environment. This is done with a DHCP server and a TFTP server.

The TFTP server must point to the directory containing chocolate_milk.boot and chocolate_milk.kern. And the DHCP server should be configured to point to using chocolate_milk.boot as the boot image. This is a BIOS specific bootloader and will not work with EFI/UEFI.

Design

Build System

We use a Rust-based build system found at src/main.rs. We built the build system in Rust such that we don't have to take on any other dependencies for the build process. This build system has some checks for installed programs which are required for building, builds and flattens the bootloader, and assembles the bootloader.

Bootloader

The bootloader is a simple i586 Rust program emit as a MSVC calling convention PE. This is flattened by our build system src/main.rs into an in-memory image of the loaded PE. This is then directly appended to the initial bootloader/src/stage0.asm entry stub. Once 32-bit mode has been entered and selectors have been set up, we branch directly into bootloader::entry()!

chocolate_milk's People

Contributors

gamozolabs avatar hippie0x90 avatar lqd avatar m1el avatar pacbypass 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

chocolate_milk's Issues

Kernel should not have an identity mapped address space

Currently we map in the first 4 GiB of physical memory, directly into the kernel's virtual address space at 0-4 GiB. This means that null page is mapped in, and other low addresses in general can be clobbered. This can lead to some unsound code.

mm::read_phys alignment bug

mm::read_phys uses read_volatile, read_volatile however requires the pointer to be aligned by the size of the pointer given when in debug mode.
This will break in situations like acpi discovery where table pointers are not necessarily 32 bit aligned in memory.

pub unsafe fn read_volatile<T>(src: *const T) -> T {
    if cfg!(debug_assertions) && !is_aligned_and_not_null(src) {
        // Not panicking to keep codegen impact smaller.
        abort();
    }
    // SAFETY: the caller must uphold the safety contract for `volatile_load`.
    unsafe { intrinsics::volatile_load(src) }
}
/// Checks whether `ptr` is properly aligned with respect to
/// `align_of::<T>()`.
pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
    !ptr.is_null() && ptr as usize % mem::align_of::<T>() == 0
}
active toolchain
----------------

nightly-x86_64-unknown-linux-gnu (default)
rustc 1.49.0-nightly (ffa2e7ae8 2020-10-24)

Chocolate milk fails to build when using LLVM v7

What happened:
I cloned the repository on commit 4e0c931, ran cargo run from the project root, which resulted in the following error:

lld-link.exe: error: could not open /filealign:0x1000: no such file or directory

Environment:

  • Windows 10 v1909
  • rustc 1.44.0-nightly
  • LLVM v7.0.0

Expected outcomes:

  • chocolate_milk notifying the user that lld-link is too old
  • removing requirement on /filealign command line flag
  • adding documentation about minimal supported lld-link version

I've checked LLVM versions 9 and 10, and chocolate milk successfully built binaries for the bootloader and the kernel.

Note: /filealign command line flag was added in llvm-svn: 361634, https://reviews.llvm.org/D62124

Duplicate memory affinity domain strict check

It's possible to have multiple memory affinities on the same domain. Relaxing this check causes the system to work just fine.

--- a/kernel/src/acpi.rs
+++ b/kernel/src/acpi.rs
@@ -454,8 +454,8 @@ unsafe fn parse_srat(ptr: PhysAddr) ->                // Log the affinity record
                if (flags & FLAGS_ENABLED) != 0 {
                    {+//+} assert!(memory_affinities.insert(domain, (base, [-size))-]
[-                            .is_none(),-]{+size)).is_none(),+} "Duplicate memory affinity domain");
                    {+memory_affinities.insert(domain, (base, size));+}
                }
            }```

Tested on PowerEdge T640 with Intel Xeon SIlver 4110

Incorrect rsdp checksum for ACPI 1.0

With QEMU 4.2 kernel panic because of wrong RSDP checksum.
In kernel/src/acpi.rs checksum calculation is not valid for ACPI 1.0.
QEMU seems to populate some 2.0 fields but marks the struct as rev 1.0 and calculate checksum accordingly.
Here is my RSDP table

{
  signature: [82, 83, 68, 32, 80, 84, 82, 32],
  checksum: 175,
  oem_id: [66, 79, 67, 72, 83, 32],
  revision: 0,
  rsdt_addr: 1073616209,
  length: 0,
  xsdt_addr: 0,
  extended_checksum: 95,
  reserved: [83, 77, 95]
}

Make page table mappings undo during failures

If we're mapping multiple pages and during the mapping we fail, we should undo the failed mappings.

We could alternatively do an initial pass which validates that no mapping can fail during the mapping process, but this can be difficult to rely on as the physical memory requirement would need to be computed assuming all tables and pages which need to be created.

cargo run fails with "Base address for bootloader did not match expected"

Hello,

I wanted to get the repo running but I encountered the error:

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/chocolate_milk`
warning: the feature `track_caller` has been stable since 1.46.0 and no longer requires an attribute to enable
 --> /home/lhebendanz/Projects/chocolate_milk/shared/lockcell/src/lib.rs:4:22
  |
4 | #![feature(const_fn, track_caller, llvm_asm)]
  |                      ^^^^^^^^^^^^
  |
  = note: `#[warn(stable_features)]` on by default

warning: 1 warning emitted

    Finished release [optimized + debuginfo] target(s) in 0.01s
Error: "Base address for bootloader did not match expected"

My active toolchain is:

nightly-x86_64-unknown-linux-gnu (default)
rustc 1.49.0-nightly (91a79fb29 2020-10-07)

Handle locks on fatal exceptions

If a fatal interrupt or exception occurs, we should have a mechanism to stop all other running processors, and then take full control of hardware such that we can handle printing to serial, if we happened to panic while the print lock was held.

Add DHCP timeouts

Currently DHCP blocks until a response. We should have timeouts and some retries

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.