Skip to content

Another attempt at a kernel to learn low level x86_64

Notifications You must be signed in to change notification settings

quackitsquinn/novos

Repository files navigation

novos: A little kernel written in rust. (so I can learn osdev)

Running the kernel

To run the kernel, you need to have the following dependencies installed:

  • qemu
  • xorriso
  • rustc and cargo
    • You need to have the x86_64-unknown-none target installed, and nightly rust.
      rustup override set nightly
      rustup target add x86_64-unknown-none
      # This isn't strictly necessary, but it's a good idea to update installed toolchains
      rustup update

Then, you can run the kernel with the following command from the root of the repository:

cargo run

This will build the kernel, generate an image, and run it in QEMU.

Project structure

The project is split into several crates:

  • kbuild: A library for building the kernel. Used in build.rs and the test runner.
  • kernel: The main kernel crate.
  • kproc: Various procedural macros used in the kernel. Currently only contains the test macro.
  • kerial: A qemu serial driver for the kernel. Used for debugging.

Some other folders that appear in the root of the repository:

  • boot_cfg: Configuration files for limine.
  • boot_images: ISO images generated by the build process.
  • output: Files generated by kserial commands.
  • tools: Various python scripts used for debugging. Both scripts are currently old and unused.

Debugging the kernel

All debugging is done through environment variables. The following environment variables are supported:

Runtime options

  • DEBUG: If set, QEMU will wait for a debugger to attach on port 1234.
  • QEMU_FLAGS: Additional flags to pass to QEMU.
  • VERBOSE: Shows QEMU's invocation command.
  • NO_DISPLAY: Disables the graphical display in QEMU.
  • KERNEL_MEM: Sets the amount of memory to allocate for the kernel in QEMU.
  • ISO: Override the iso file to boot from.
  • NO_EXIT: Prevents QEMU from exiting after the kernel exits.
  • REBUILD: Forces a rebuild of the test binary. This will have no effect on the kernel itself, as the kernel is not build at runtime.

Build-time options

  • ALLOC_DEBUG: If set, will print out information about memory allocations and deallocations.
  • REINSTALL_LIMINE: If set, limine will be re-downloaded from it's git repository and reinstalled.
  • ARTIFACT_DIR: The directory to store build artifacts in.
    • TODO: Rename this to BUILD_DIR or something.
  • LIMINE_CONFIG: The path to the limine configuration file.
  • ISO_NAME: The name of the ISO file to generate.
  • ISO_ROOT: The directory to store ISO files in.

Alright, you hit the point where you don't have to read the rest of this README. Have fun tinkering with the kernel!

How I have developed this project

I have written this kernel in a kinda circular way. I have a general idea of what I want to implement, but I don't know how to implement it. So, I do the following:

  1. Do a whole heck of a lot of research about the feature I want to implement.
  2. Write some kinda poorly written code that does the thing I want to do.
  3. Work on other parts of the kernel for a while.
  4. Come back to the code with more knowledge and rewrite it.

I did this heavily for the memory management system, and am currently doing it for context switching and scheduling.

History

This project originally started as snakian. I was just trying to make a snake operating system, much inspired by jdh's Tetris OS Video. If you look at snakian, I want to warn you that the code is.. not the best.

I quickly in that project realized I wanted to do more than just a snake game (that I never even implemented anyways), so that project shifted to more of a general kernel. By that point though, I had made a lot of mistakes in the codebase, so I decided to start over. That's when I started this project.

This project does a lot differently than snakian. Snakian was almost a word-for-word following of Philipp Oppermann's blog. With nova though, I was confident enough to start off with something quite different. I used limine instead of bootloader, and implemented stuff a lot more abstractly.

Personal note

This is the longest I have ever worked on a single project (15 months... holy cow), so I am really proud of this project. Yes, all this knowledge is incredibly niche, but I have learned a lot about the inner workings of computers and operating systems.

Also, Honestly, It's really cool to have gotten to this point when I remember at the start seeing so many resources saying to not even attempt it if you don't have 10 years of experience or like a bachelor's degree in computer science. I am a senior in high school with no formal education in computer science, and I have gotten to this point. I am really proud of myself for that.

If your reading this, and you are thinking about starting a project this massive and research-heavy, I say do it.

It wouldn't hurt to try, and you'd at least learn a lot.

Amazing resources

  • Philipp Oppermann's Blog
  • OSDev Wiki
    • Heavy on this. So much good information.
  • Redox Kernel
    • The whole redox project is helpful, but I have found the kernel to be the most helpful.
  • EuraliOS
    • Small kernel written in rust. Helped me with context switching. (Mainly the assembly stub)

About

Another attempt at a kernel to learn low level x86_64

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published