Skip to content

Commit

Permalink
Graphicalize Boot2Snow and add interrupts.rs
Browse files Browse the repository at this point in the history
We replaced Allocator with Boot2Snow.
Added Interrupts support to the kernel basically.
  • Loading branch information
ANEP-ET committed Jun 10, 2018
1 parent 8486d35 commit e2c2ad0
Show file tree
Hide file tree
Showing 48 changed files with 781 additions and 165 deletions.
Empty file modified .gitignore
100755 → 100644
Empty file.
Empty file modified .vscode/settings.json
100755 → 100644
Empty file.
Empty file modified .vscode/tasks.json
100755 → 100644
Empty file.
Empty file modified LICENSE
100755 → 100644
Empty file.
Empty file modified Makefile
100755 → 100644
Empty file.
32 changes: 29 additions & 3 deletions README.md
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ Technology is free, SnowFlakeOS
### Boot2Snow (x86_64, UEFI)
- [x] Add uefi_alloc support
- [x] Load kernel from disk
- [ ] Basical UI
- [ ] Enable boot timeout
- [x] Basical UI
- [x] Enable boot timeout
### SnowKernel
- [x] Kernel heap
- [ ] IDT
- [x] IDT
- [ ] Better GUI library support
- [ ] Add modular support
- [ ] Multitasking support
Expand All @@ -38,6 +38,32 @@ Requirements to build
- Rust (https://www.rust-lang.org)

### Windows
#### Windows 10 or later
Starting with Windows 10, you can use Ubuntu Bash. You can run it by typing C:\Windows\System32\bash.exe. For more information, please visit https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/

You need to install Rust, qemu, mtools on Ubuntu Bash. You can install Rust using the following command.
```
$ curl https://sh.rustup.rs -sSf | sh
$ sudo apt install qemu
$ sudo apt install mtools
```
This script will download and install the rustup-init executable for your current platform.

After the installation is complete, you should clone the SnowFlake repository.
```
$ git clone https://github.com/SnowFlake/SnowFlake.git
```
To build SnowFlake as an x86_64 target, x86_64-elf cross-compilation is required. If you do not have the x86_64-elf compiler, and your system is x86_64, you can use the 'x86_64-linux_env.sh' script. And you should add rustup component.
```
$ cd SnowFlake
$ sh x86_64-linux_env.sh
$ cd kernel
$ rustup component add rust-src
$ cd ./../
$ make run
```

#### Windows 8.1 or lower
Will be added later

### Mac
Expand Down
6 changes: 3 additions & 3 deletions boot2snow/Cargo.toml
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ git = "https://github.com/rust-lang-nursery/compiler-builtins"
features = ["mem"]

[dependencies]
uefi = {git = "https://github.com/SnowFlakeOS/uefi", rev = "ad7346f"}
uefi_alloc = {git = "https://github.com/SnowFlakeOS/uefi_alloc", rev = "9e75de6"}
uefi = {git = "https://github.com/SnowFlakeOS/uefi"}
rlibc = "1.0"
utf16_literal = "0.1.0"
bitflags = "1"
x86_64 = "0.1.2"
slab_allocator = { git = "https://github.com/redox-os/slab_allocator.git", rev = "0a53a0b" }
orbclient = { git = "https://github.com/redox-os/orbclient.git", branch = "no_std" }

[lib]
name = "Boot2Snow"
Expand Down
Empty file modified boot2snow/Xargo.toml
100755 → 100644
Empty file.
143 changes: 97 additions & 46 deletions boot2snow/src/boot2snow.rs
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -7,62 +7,93 @@

//! Some code was borrowed from [Tifflin Bootloader](https://github.com/thepowersgang/rust_os)
use core::{mem, slice, ptr};

use color::*;
use {EntryPoint, elf, kernel_proto};

use conf::Configuration;

use uefi::CStr16;
use core::{mem, slice};
use uefi::status::*;
use uefi::boot_services::protocols;
use uefi::boot_services::{BootServices,
AllocateType,
use uefi::boot_services::{AllocateType,
MemoryDescriptor,
MemoryType};
use uefi::boot_services::protocols::PixelFormat;
use orbclient::{Color as InnerColor, Renderer};

use {EntryPoint, elf, kernel_proto};
use color::*;
use conf::load_conf;
use memory_map::{MM_BASE, memory_map};
use paging::paging;
use string::wstr;
use fs::{find, load};
use io::wait_timeout;
use image;
use image::Image;
use display::{Display, Output};

static mut KERNEL_BASE: usize = 0;
static mut KERNEL_SIZE: usize = 0;
static STACK_BASE: usize = 0xFFFFFF0000080000;
static mut KERNEL_ENTRY: usize = 0;
static STACK_BASE: usize = 0x80000;
static STACK_SIZE: usize = 0x1F000;

use {PATH_CONFIG,
PATH_FALLBACK_KERNEL};
use {get_conout,
get_boot_services,
use {get_boot_services,
get_image_handle,
get_runtime_services,
get_graphics_output};
get_runtime_services};

pub extern fn init() -> Result<(), ()> {
let boot_services = get_boot_services();
let image_handle = get_image_handle();
let runtime_services = get_runtime_services();
let gop = get_graphics_output();

{
// Obtain the "LoadedImage" representing the bootloader, from which we get the boot volume
let image_proto: &protocols::LoadedImage = boot_services.handle_protocol(&image_handle).expect("image_handle - LoadedImage");

if image_proto.file_path.type_code() != (4,4) {
panic!("Loader wans't loaded from a filesystem - type_code = {:?}", image_proto.file_path.type_code());
}
let (mut display, vid_addr) = {
let output = Output::one().unwrap();

let mut mode: u32 = 0;

for i in 0..output.0.mode.max_mode {
let info = output.0.query_mode(i).unwrap();

let system_volume_fs: &protocols::SimpleFileSystem = boot_services.handle_protocol(&image_proto.device_handle).expect("image_proto - FileProtocol");
// - Get the root of this volume and load the bootloader configuration file from it
let system_volume_root = system_volume_fs.open_volume().expect("system_volume_fs - File");
let config = match Configuration::from_file(boot_services, &system_volume_root, PATH_CONFIG.into()) {
Ok(c) => c,
Err(e) => panic!("Failed to load config file: {:?}", e),
if info.pixel_format != PixelFormat::RGBX
&& info.pixel_format != PixelFormat::BGRX { continue; }
if info.horizontal_resolution > 1920 && info.vertical_resolution > 1080 { continue; }
if info.horizontal_resolution == 1920 && info.vertical_resolution == 1080 { mode = i; break; }
mode = i;
};

let _ = output.0.set_mode(mode);
let vid_addr = output.0.mode.frame_buffer_base;

(Display::new(output), vid_addr)
};

let conf = load_conf();

let mut splash = Image::new(0, 0);
{
if let Ok(data) = load("\\boot2snow\\only_logo.bmp") {
if let Ok(image) = image::bmp::parse(&data) {
splash = image;
}
}
}

{
let bg = InnerColor::rgb(0x00, 0x00, 0x00);

display.set(bg);

{
let x = (display.width() as i32 - splash.width() as i32) / 2;
let y = ((display.height() as i32 - splash.height() as i32) / 2) as i32 - 32;
splash.draw(&mut display, x, y);
}

display.sync();
}

status_msg(&mut display, splash.height(), concat!("Boot2Snow ", env!("CARGO_PKG_VERSION")));
wait_timeout(conf.boot_timeout);

// - Load the kernel.
let entrypoint = load_kernel_file(&system_volume_root, &config.kernel).expect("Unable to load kernel");
let sections = load_kernel_sections(&system_volume_root, &config.kernel).expect("Unable to load sections");
let entrypoint = load_kernel_file(&conf.kernel).expect("Unable to load kernel");
let sections = load_kernel_sections(&conf.kernel).expect("Unable to load sections");

// Save memory map
let (map_size, map_key, ent_size, ent_ver, map) = unsafe { memory_map() };
Expand All @@ -78,9 +109,9 @@ pub extern fn init() -> Result<(), ()> {
}

let video_info = kernel_proto::VideoInfo {
physbaseptr: gop.mode.frame_buffer_base as *mut Color,
xresolution: unsafe { (*gop.mode.info).horizontal_resolution },
yresolution: unsafe { (*gop.mode.info).vertical_resolution }
physbaseptr: vid_addr as *mut Color,
xresolution: display.width(),
yresolution: display.height()
};

let boot_info = kernel_proto::Info {
Expand Down Expand Up @@ -111,9 +142,29 @@ pub extern fn init() -> Result<(), ()> {
Ok(())
}

fn load_kernel_sections(sys_vol: &protocols::File, filename: &CStr16) -> Result<elf::PhEntIter<'static>, Status> {
let mut kernel_file = match sys_vol.open_read(filename) {
Ok(k) => k,
fn status_msg(display: &mut Display, splash_height: u32, msg: &str) {
let prompt = msg.clone();
let mut x = (display.width() as i32 - prompt.len() as i32 * 8) / 2;
let y = ((display.height() as i32 - splash_height as i32) / 2) as i32 + 256;

let rect_x = 0;
let rect_y = (y - 16);
let rect_width = display.width();
let rect_height = (y + 16) as u32;

display.rect(rect_x, rect_y, rect_width, rect_height, InnerColor::rgb(0x00, 0x00, 0x00));

for c in prompt.chars() {
display.char(x, y, c, InnerColor::rgb(0xff, 0xff, 0xff));
x += 8;
}

display.sync();
}

fn load_kernel_sections(filename: &str) -> Result<elf::PhEntIter<'static>, Status> {
let mut kernel_file = match find(filename) {
Ok(k) => { k.1 },
Err(e) => panic!("Failed to open kernel '{}' - {:?}", filename, e),
};

Expand All @@ -133,11 +184,11 @@ fn load_kernel_sections(sys_vol: &protocols::File, filename: &CStr16) -> Result<
Ok(elf::PhEntIter(slice))
}

fn load_kernel_file(sys_vol: &protocols::File, filename: &CStr16) -> Result<EntryPoint, Status> {
fn load_kernel_file(filename: &str) -> Result<EntryPoint, Status> {
let boot_services = get_boot_services();

let mut kernel_file = match sys_vol.open_read(filename) {
Ok(k) => k,
let mut kernel_file = match find(filename) {
Ok(k) => { k.1 },
Err(e) => panic!("Failed to open kernel '{}' - {:?}", filename, e),
};

Expand All @@ -152,7 +203,7 @@ fn load_kernel_file(sys_vol: &protocols::File, filename: &CStr16) -> Result<Entr
elf_hdr.check_header();
for i in 0 .. elf_hdr.e_phnum {
let mut ent = elf::PhEnt::default();
kernel_file.set_position(elf_hdr.e_phoff + (i as usize * mem::size_of::<elf::PhEnt>()) as u64).expect("PhEnt seek");
kernel_file.set_position(elf_hdr.e_phoff + (i as usize * mem::size_of::<elf::PhEnt>()) as u64);
// SAFE: Converts to POD for read
kernel_file.read( unsafe { slice::from_raw_parts_mut( &mut ent as *mut _ as *mut u8, mem::size_of::<elf::PhEnt>() ) } ).expect("PhEnt read");

Expand All @@ -178,8 +229,8 @@ fn load_kernel_file(sys_vol: &protocols::File, filename: &CStr16) -> Result<Entr

// SAFE: This memory has just been allocated by the above
let data_slice = unsafe { slice::from_raw_parts_mut(addr as usize as *mut u8, ent.p_memsz as usize) };
kernel_file.set_position(ent.p_offset as u64).expect("seek segment");
kernel_file.read( &mut data_slice[.. ent.p_filesz as usize] ).expect("read segment");
kernel_file.set_position(ent.p_offset as u64);
kernel_file.read( &mut data_slice[.. ent.p_filesz as usize] );
for b in &mut data_slice[ent.p_filesz as usize .. ent.p_memsz as usize] {
*b = 0;
}
Expand Down
70 changes: 37 additions & 33 deletions boot2snow/src/conf.rs
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
//! Some code was borrowed from [Tifflin Bootloader](https://github.com/thepowersgang/rust_os)
// =======================================================================
// Copyleft SnowFlakeOS Team 2018-∞.
// Distributed under the terms of the 3-Clause BSD License.
// (See accompanying file LICENSE or copy at
// https://opensource.org/licenses/BSD-3-Clause)
// =======================================================================

use uefi::boot_services::protocols;
use uefi::boot_services::BootServices;
use uefi::{CStr16,
Status};
use uefi::status::NOT_FOUND;
use string::utf8_to_string;
use fs::load;
use core::mem;
use alloc::vec::Vec;
use alloc::string::{ToString, String};

use PATH_FALLBACK_KERNEL;

pub struct Configuration<'bs>
{
pub kernel: ::uefi::borrow::Cow<'bs, 'static, CStr16>,
//commandline: ::uefi::borrow::Cow<'bs, 'static, str>,
pub struct Conf {
pub kernel: String,
pub kernel_option: String,
pub boot_timeout: u64
}

impl<'bs> Configuration<'bs>
{
pub fn from_file(_bs: &'bs BootServices, sys_vol: &protocols::File, filename: &CStr16) -> Result<Configuration<'bs>, Status> {
match sys_vol.open_read(filename) {
Ok(_cfg_file) => {
//panic!("TODO: Read config file (allocating strings with `bs`)");
Ok(Configuration {
kernel: ::uefi::CStr16::from_slice(PATH_FALLBACK_KERNEL).into(),
//commandline: "".into(),
})
},
Err(NOT_FOUND) => {
Ok(Configuration {
kernel: ::uefi::CStr16::from_slice(PATH_FALLBACK_KERNEL).into(),
//commandline: "".into(),
})
},
Err(e) => Err(e),
}
}
}
pub fn load_conf() -> Conf {
let mut conf: Conf = unsafe { mem::zeroed() };

if let Ok(file) = load("\\boot2snow\\boot2snow.conf") {
let line: Vec<String> = utf8_to_string(file).replace(" ", "").split("\n")
.map(|s: &str| s.to_string())
.collect();

for data in &line {
let s = data.split("=").nth(0).unwrap().to_string();
if s == "kernel" {
conf.kernel = data.split("=").nth(1).unwrap().to_string();
} else if s == "kernel_option" {
conf.kernel_option = data.split("=").nth(1).unwrap().to_string();
} else if s == "boot_timeout" {
conf.boot_timeout = data.split("=").nth(1).unwrap().to_string().parse::<u64>().unwrap();
}
}
}

conf
}
Loading

0 comments on commit e2c2ad0

Please sign in to comment.