Git Product home page Git Product logo

simple-kernel's Introduction

Simple Kernel Development Framework

A minimal, cross-platform development environment for building bare-metal x86-64 programs, kernels, and/or full operating systems on UEFI 2.x systems. It is primarily designed to make programs for use with https://github.com/KNNSpeed/Simple-UEFI-Bootloader.

Version 0.z (not considered "release-ready" until 1.0)

The included build system compiles operating system kernels or bare metal programs as native executables for the builder's platform (Windows, Mac, or Linux), which can then be loaded by the bootloader. A kernel framework, containing a software renderer, flexible text output, multi-GPU graphical support, and a whole host of low-level system control functions, is also included, and many of the provided support functions feature full AVX optimization for x86-64.

See Simple_Kernel/inc/Kernel64.h, Simple_Kernel/inc/ISR.h, and Simple_Kernel/startup/avxmem.h for complete function listings. Detailed descriptions are provided for each function in the functions' corresponding .c files (or .S file in the case of ISRs).

See "Issues" for my to-do list before hitting "official release-ready" version 1.0, and see the "Releases" tab of this project for executable demos. See the "Building an OS Kernel/Bare-Metal x86-64 Application" and "How to Build from Source" sections below for details on how to use this project.

Apologies to AMD Ryzen users: I can't test Ryzen-optimized binaries very thoroughly as I don't have any Ryzen machines. The build scripts are provided with the caveat that they ought to produce optimized binaries (I don't see why they wouldn't).

Features

This project is designed to inherit all of the features provided by https://github.com/KNNSpeed/Simple-UEFI-Bootloader, in addition to providing the following:

  • Tons of low-level support functionality in C, like text printing and scrolling, screen drawing, and system register control and diagnostic functions
  • AVX support (1)
  • Full access to UEFI 2.x runtime services and other parameters passed by the bootloader, including 1+ linear frame buffer(s) for display output
  • Unrestricted access to available hardware (2)
  • Minimal development environment tuned for Windows, Mac, and Linux included in repository (can be used with the same Backend folder as the bootloader, barring differences in compiler version requirements)

(1) A CPU with AVX is required to use most of the above functionality, see "Target System Requirements" below to see where to check if you have it. Most post-2011 systems do.
(2) You will need to write your own interfaces (essentially drivers or kernel extensions, depending on the term you're most familiar with) for access to more advanced hardware. I don't yet have drivers for things like PCI-Express, and things like on-board audio differ wildly between systems. Remember: this is not an operating system, this is meant to help make them and other kinds of bare-metal/operating system-less programs.

Target System Requirements

These are the nearly same as the bootloader's requirements. If your target system can run the bootloader and you have a CPU with AVX, you're all set.

  • x86-64 architecture with AVX (most Intel ix-2xxx or newer or AMD Ryzen or newer CPUs have it, see the Wikipedia page on AVX)
  • Secure Boot must be disabled
  • More than 4GB RAM (though it seems to work OK with less, e.g. Hyper-V with only 1GB)
  • A graphics card (Intel, AMD, NVidia, etc.) with UEFI GOP support
  • A keyboard

The earliest GPUs with UEFI GOP support were released around the Radeon HD 7xxx series (~2011). Anything that age or newer should have UEFI GOP support, though older models, like early 7970s, required owners to contact GPU vendors to get UEFI-compatible firmware. On Windows, you can check if your graphics card(s) have UEFI GOP support by downloading TechPowerUp's GPU-Z utility and seeing whether or not the UEFI checkbox is checked. If it is, you're all set!

NOTE: You need to check each graphics card if there is a mix, as you will only be able to use the ones with UEFI GOP support. Per the system requirements above, you need at least one compliant device.

License and Crediting

Please see the LICENSE file for information on all licenses covering code created for and used in this project.

TL;DR:

If you don't give credit to this project, per the license you aren't allowed to do anything with any of its source code that isn't already covered by an existing license (in other words, my license covers most of the code I wrote). That's pretty much it, and why it's "almost" PD, or "PD with Credit" if I have to give it a nickname, as there's no restriction on what it gets used for as long as the license is satisfied. If you have any issues, feature requests, etc. please post in "Issues" so it can be attended to/fixed.

Note that each of these files already has appropriate crediting at the top, so you could just leave what's already there to satisfy the terms. You really should see the license file for complete information, though (it's short!!).

Building an OS Kernel/Bare-Metal x86-64 Application

The below "How to Build from Source" section contains complete compilation instructions for each platform, and then all you need to do is put your code in "src" and "inc" in place of mine (leave the "startup" folder as-is). Once compiled, your program can be run in the same way as described in the "Releases" section of https://github.com/KNNSpeed/Simple-UEFI-Bootloader using a UEFI-supporting VM like Hyper-V or on actual hardware.

Important Points to Consider:

The entry point function (i.e. the "main" function) of your program should look like this, otherwise the kernel will fail to run:

__attribute__((naked)) void kernel_main(LOADER_PARAMS * LP) // Loader Parameters  
{  

}

The LOADER_PARAMS data type is defined as the following structure:

typedef struct {
  UINT16                  Bootloader_MajorVersion;        // The major version of the bootloader
  UINT16                  Bootloader_MinorVersion;        // The minor version of the bootloader

  UINT32                  Memory_Map_Descriptor_Version;  // The memory descriptor version
  UINTN                   Memory_Map_Descriptor_Size;     // The size of an individual memory descriptor
  EFI_MEMORY_DESCRIPTOR  *Memory_Map;                     // The system memory map as an array of EFI_MEMORY_DESCRIPTOR structs
  UINTN                   Memory_Map_Size;                // The total size of the system memory map

  EFI_PHYSICAL_ADDRESS    Kernel_BaseAddress;             // The base memory address of the loaded kernel file
  UINTN                   Kernel_Pages;                   // The number of pages (1 page == 4096 bytes) allocated for the kernel file

  CHAR16                 *ESP_Root_Device_Path;           // A UTF-16 string containing the drive root of the EFI System Partition as converted from UEFI device path format
  UINT64                  ESP_Root_Size;                  // The size (in bytes) of the above ESP root string
  CHAR16                 *Kernel_Path;                    // A UTF-16 string containing the kernel's file path relative to the EFI System Partition root (it's the first line of Kernel64.txt)
  UINT64                  Kernel_Path_Size;               // The size (in bytes) of the above kernel file path
  CHAR16                 *Kernel_Options;                 // A UTF-16 string containing various load options (it's the second line of Kernel64.txt)
  UINT64                  Kernel_Options_Size;            // The size (in bytes) of the above load options string

  EFI_RUNTIME_SERVICES   *RTServices;                     // UEFI Runtime Services
  GPU_CONFIG             *GPU_Configs;                    // Information about available graphics output devices; see below GPU_CONFIG struct for details
  EFI_FILE_INFO          *FileMeta;                       // Kernel file metadata
  void                   *RSDP;                           // A pointer to the RSDP ACPI table
} LOADER_PARAMS;

Of those pointers, the only data type not defined by UEFI spec is GPU_CONFIG, which looks like this:

typedef struct {
  EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE  *GPUArray;             // This array contains the EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE structures for each available framebuffer
  UINT64                              NumberOfFrameBuffers; // The number of pointers in the array (== the number of available framebuffers)
} GPU_CONFIG;

You will find some relevant structures defined in "Kernel64.h" of the sample kernel, with the rest defined in the "EfiBind.h" and "EfiTypes.h" files in the "startup" directory.

You will also need to #include the "Efi" files from "startup" in your code: refer to the "Kernel64.h" file in the "inc" directory for an example. You may find it easiest to just #include "Kernel64.h" in your code after removing any unnecessary function prototypes from the file, as it already has all the requisite inclusions and EFI structures for LOADER_PARAMS defined within it.

How to Build from Source

Windows: Requires MinGW-w64 based on GCC 8.1.0 or later
Mac: Requires Mac OS Sierra or later with the latest XCode Command Line Tools for the OS
Linux: Requires GCC 8.0.0 or later and Binutils 2.29.1 or later

I cannot make any guarantees whatsoever for earlier versions, especially with the number of compilation and linking flags used.

Windows:

  1. Download and extract or clone this repository into a dedicated folder, preferably somewhere easy like C:\BareMetalx64

  2. Download MinGW-w64 "x86_64-posix-seh" from https://sourceforge.net/projects/mingw-w64/ (click "Files" and scroll down - pay attention to the version numbers!).

  3. Extract the archive into the "Backend" folder.

  4. Open Windows PowerShell or the Command Prompt in the "Simple-Kernel" folder and type ".\Compile.bat"

    That's it! It should compile and a binary called "Kernel64.exe" will be output into the "Backend" folder.

Mac:

  1. Download and extract or clone this repository into a dedicated folder, preferably somewhere easy like ~/BareMetalx64

  2. Open Terminal in the "Simple-Kernel" folder and run "./Compile-Mac.sh"

    That's it! It should compile and a binary called "Kernel64.mach64" will be output into the "Backend" folder.

Linux:

  1. Download and extract or clone this repository into a dedicated folder, preferably somewhere easy like ~/BareMetalx64

  2. If, in the terminal, "gcc --version" reports GCC 8.0.0 or later and "ld --version" reports 2.29.1 or later, do steps 2a, 2b, and 2c. Otherwise go to step 3.

    2a. Type "which gcc" in the terminal, and make a note of what it says (something like /usr/bin/gcc or /usr/local/bin/gcc)

    2b. Open Compile.sh in an editor of your choice (nano, gedit, vim, etc.) and set the GCC_FOLDER_NAME variable at the top to be the part before "bin" (e.g. /usr or /usr/local, without the last slash). Do the same thing for BINUTILS_FOLDER_NAME, except use the output of "which ld" to get the directory path preceding "bin" instead.

    2c. Now set the terminal to the Simple-Kernel folder and run "./Compile.sh", which should work and output Kernel64.elf in the Backend folder. That's it!

  3. Looks like we need to build GCC & Binutils. Navigate to the "Backend" folder in terminal and do "git clone git://gcc.gnu.org/git/gcc.git" there. This will download a copy of GCC 8.0.0, which is necessary for "static-pie" support (when combined with Binutils 2.29.1 or later, it allows statically-linked, position-independent executables to be created; earlier versions do not). If that git link ever changes, you'll need to find wherever the official GCC git repository ran off to.

  4. Once GCC has been cloned, in the cloned folder do "contrib/download_prerequisites" and then "./configure -v --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --prefix=$PWD/../gcc-8 --enable-checking=release --enable-languages=c --disable-multilib"

    NOTE: If you want, you can enable other languages like c++, fortran, objective-c (objc), go, etc. with enable-languages. You can also change the name of the folder it will built into by changing --prefix=[desired folder]. The above command line will configure GCC to be made in a folder called gcc-8 inside the "Backend" folder. Be aware that --prefix requires an absolute path.

  5. After configuration completes, do "make -j [twice the number of cores of your CPU]" and go eat lunch. Unfortunately, sometimes building the latest GCC produces build-time errors; I ran into an "aclocal-1.15" issue when building via Linux on Windows (fixed by installing the latest version of Ubuntu on Windows and using the latest autoconf).

  6. Now just do "make install" and GCC will be put into the gcc-8 folder from step 4.

  7. Next, grab binutils 2.29.1 or later from https://ftp.gnu.org/gnu/binutils/ and extract the archive to Backend.

  8. In the extracted Binutils folder, do "mkdir build" and "cd build" before configuring with "../configure --prefix=$PWD/../binutils-binaries --enable-gold --enable-ld=default --enable-plugins --enable-shared --disable-werror"

    NOTE: The "prefix" flag means the same thing as GCC's.

  9. Once configuration is finished, do "make -j [twice the number of CPU cores]" and go have dinner.

  10. Once make is done making, do "make -k check" and do a crossword or something. There should be a very small number of errors, if any.

  11. Finally, do "make install" to install the package into binutils-binaries. Congratulations, you've just built some of the biggest Linux sources ever!

  12. Open Compile.sh in an editor of your choice (nano, gedit, vim, etc.) and set the GCC_FOLDER_NAME variable at the top (e.g. gcc-8 without any slashes). Do the same thing for the BINUTILS_FOLDER_NAME, except use the binutils-binaries folder.

  13. At long last, you should be able to run "./Compile.sh" from within the "Simple-Kernel" folder.

    That's it! It should compile and a binary called "Kernel64.elf" will be output into the "Backend" folder.

    For more information about building GCC and Binutils, see these: http://www.linuxfromscratch.org/blfs/view/cvs/general/gcc.html & http://www.linuxfromscratch.org/lfs/view/development/chapter06/binutils.html

Change Log

V0.z (2/20/2019) - Major update: AVX is now required, separated code out of code files, added a TON of low-level system control functions (port I/O, control register manipulation, HWP support for systems supporting it, cpu feature checks), added CPU frequency measurement (average since boot and for specific user-defined code segments), updated text printing to include wraparound, smooth scrolling, and quick-scrolling, and prettied up code styling. Also, spun-off a new project from this one: https://github.com/KNNSpeed/AVX-Memmove

V0.y (2/1/2019) - Major code cleanup, added printf() and a whole host of text-displaying functions, resolved issues #5 and #6. No new binaries will be made for this version.

V0.x (2/2/2018) - Initial upload of environment and compilable sample. Not yet given a version number.

Acknowledgements

simple-kernel's People

Stargazers

 avatar

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.