merge
This commit is contained in:
@@ -10,7 +10,7 @@ git clone https://git.zxq5.dev/OsDev/FoundryOS.git
|
|||||||
* latest rust nightly release
|
* latest rust nightly release
|
||||||
* all necessary rust components installed
|
* all necessary rust components installed
|
||||||
* xorriso: creates ISO images to be booted from.
|
* xorriso: creates ISO images to be booted from.
|
||||||
* (Optional / Recommended) Qemu: to run the kernel. (this may be packaged as qemu-desktop)
|
* (Optional / Recommended) qemu: to run the kernel. (this may be packaged as qemu-desktop)
|
||||||
* (Optional) GDB: for debugging the kernel.
|
* (Optional) GDB: for debugging the kernel.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@@ -20,12 +20,29 @@ rustup component add rust-src
|
|||||||
rustup component add llvm-tools-preview
|
rustup component add llvm-tools-preview
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building & Running in Qemu:
|
## Building & Running in qemu
|
||||||
```sh
|
```sh
|
||||||
cargo run
|
cargo run
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running in GDB:
|
## Running in GDB
|
||||||
```sh
|
```sh
|
||||||
USE_GDB=1 cargo run
|
USE_GDB=1 cargo run
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Build errors
|
||||||
|
|
||||||
|
If you see a qemu error like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
qemu-system-x86_64: -drive if=pflash,format=raw,readonly=on,file=<...>/OVMF_CODE.fd: Could not open '<...>/OVMF_CODE.fd': No such file or directory
|
||||||
|
```
|
||||||
|
|
||||||
|
Simply delete the ./build directory and try to rebuild the program. Using the runner script or `cargo run` will download the required files for you, this is because the script only checks for the presence of one file and not the VARS file.
|
||||||
|
|
||||||
|
Alternatively, you may disable using a UEFI firmware with qemu like so:
|
||||||
|
```sh
|
||||||
|
USE_LEGACY_BIOS=1 cargo run
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have any other issues, feel free to create an issue or a PR.
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
# Timeout in seconds that Limine will use before automatically booting.
|
# Timeout in seconds that Limine will use before automatically booting.
|
||||||
timeout: 1
|
timeout: 0
|
||||||
|
|
||||||
# The entry name that will be displayed in the boot menu.
|
# The entry name that will be displayed in the boot menu.
|
||||||
/foundry-os
|
/foundry-os
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use libk::drivers::apic::enable_apic;
|
use libk::drivers::apic::enable_apic;
|
||||||
use libk::drivers::pic::ChainedPics;
|
|
||||||
use libk::prelude::*;
|
use libk::prelude::*;
|
||||||
|
use pic8259::ChainedPics;
|
||||||
use x86_64::registers::control::Cr2;
|
use x86_64::registers::control::Cr2;
|
||||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
|
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
|
||||||
|
|
||||||
@@ -22,8 +22,8 @@ static IDT: Lazy<InterruptDescriptorTable> = Lazy::new(|| {
|
|||||||
.set_handler_fn(general_protection_fault_handler);
|
.set_handler_fn(general_protection_fault_handler);
|
||||||
idt.page_fault.set_handler_fn(page_fault_handler);
|
idt.page_fault.set_handler_fn(page_fault_handler);
|
||||||
|
|
||||||
// idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler);
|
idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler);
|
||||||
// idt[InterruptIndex::Keyboard.as_u8()].set_handler_fn(keyboard_interrupt_handler);
|
idt[InterruptIndex::Keyboard.as_u8()].set_handler_fn(keyboard_interrupt_handler);
|
||||||
idt
|
idt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -5,8 +5,8 @@ extern crate alloc;
|
|||||||
|
|
||||||
use libk::{
|
use libk::{
|
||||||
drivers::{
|
drivers::{
|
||||||
|
async_io::task::{Executor, Task},
|
||||||
io,
|
io,
|
||||||
scheduling::task::{Executor, Task},
|
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
util::shell::shell,
|
util::shell::shell,
|
||||||
|
|||||||
@@ -43,3 +43,7 @@ pub fn enable_apic() {
|
|||||||
|
|
||||||
write_apic_register(0xF0, read_apic_register(0xF0) | 0x100);
|
write_apic_register(0xF0, read_apic_register(0xF0) | 0x100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Apic {}
|
||||||
|
|
||||||
|
pub enum ApicVector {}
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
//! Allows creation of asynchronous IO bound tasks.
|
||||||
|
//!
|
||||||
|
//! Written by @zxq5 for the most part with code from
|
||||||
|
//! [here](https://github.com/phil-opp/blog_os/).
|
||||||
|
//!
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use alloc::collections::BTreeMap;
|
use alloc::collections::BTreeMap;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
pub mod io;
|
pub mod io;
|
||||||
pub mod kalloc;
|
pub mod kalloc;
|
||||||
pub mod scheduling;
|
|
||||||
|
|
||||||
pub mod apic;
|
pub mod apic;
|
||||||
|
pub mod async_io;
|
||||||
pub mod cpu;
|
pub mod cpu;
|
||||||
pub mod pic;
|
pub mod pic;
|
||||||
|
|||||||
+3
-8
@@ -1,6 +1,4 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![allow(async_fn_in_trait)]
|
|
||||||
#![warn(tail_expr_drop_order)]
|
|
||||||
#![warn(
|
#![warn(
|
||||||
clippy::correctness,
|
clippy::correctness,
|
||||||
clippy::nursery,
|
clippy::nursery,
|
||||||
@@ -9,18 +7,15 @@
|
|||||||
clippy::suspicious,
|
clippy::suspicious,
|
||||||
clippy::perf,
|
clippy::perf,
|
||||||
rustdoc::missing_errors_doc,
|
rustdoc::missing_errors_doc,
|
||||||
rustdoc::missing_panics_doc
|
rustdoc::missing_panics_doc,
|
||||||
|
tail_expr_drop_order
|
||||||
)]
|
)]
|
||||||
|
|
||||||
// alloc
|
|
||||||
// io : serial, framebuffer, ascii(?), keyboard
|
|
||||||
// ?????
|
|
||||||
// scheduling / tasks : async
|
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
pub mod drivers;
|
pub mod drivers;
|
||||||
pub mod resources;
|
pub mod resources;
|
||||||
|
pub mod threads;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
#[allow(unused)] // We aren't using much of this right now.
|
#[allow(unused)] // We aren't using much of this right now.
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ mod window;
|
|||||||
pub trait Application {
|
pub trait Application {
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
async fn run(&mut self, args: Vec<String>) -> Result<Self::Output, Error>;
|
fn run(
|
||||||
|
&mut self,
|
||||||
|
args: Vec<String>,
|
||||||
|
) -> impl core::future::Future<Output = Result<Self::Output, Error>> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
mod io;
|
|
||||||
pub use io::*;
|
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct Thread {
|
||||||
|
id: usize,
|
||||||
|
/// This shall be default before the program is interrupted, otherwise it will store
|
||||||
|
/// CPU registers etc to be restored on context switch.
|
||||||
|
ctx: ThreadContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CPU state to be saved on context switches.
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ThreadContext {
|
||||||
|
/// Accumulator register.
|
||||||
|
rax: u64,
|
||||||
|
/// Base register.
|
||||||
|
rbx: u64,
|
||||||
|
/// Counter register.
|
||||||
|
rcx: u64,
|
||||||
|
/// Data register.
|
||||||
|
rdx: u64,
|
||||||
|
/// Source index register.
|
||||||
|
rsi: u64,
|
||||||
|
/// Destination index register.
|
||||||
|
rdi: u64,
|
||||||
|
/// Base pointer register.
|
||||||
|
rbp: u64,
|
||||||
|
/// Stack pointer register.
|
||||||
|
rsp: u64,
|
||||||
|
/// An extended register.
|
||||||
|
r8: u64,
|
||||||
|
/// An extended register.
|
||||||
|
r9: u64,
|
||||||
|
/// An extended register.
|
||||||
|
r10: u64,
|
||||||
|
/// An extended register.
|
||||||
|
r11: u64,
|
||||||
|
/// An extended register.
|
||||||
|
r12: u64,
|
||||||
|
/// An extended register.
|
||||||
|
r13: u64,
|
||||||
|
/// An extended register.
|
||||||
|
r14: u64,
|
||||||
|
/// An extended register.
|
||||||
|
r15: u64,
|
||||||
|
/// The instruction pointer.
|
||||||
|
rip: u64,
|
||||||
|
/// RFLAGS register.
|
||||||
|
rflags: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ThreadContext {
|
||||||
|
/// Saves the current registers of the CPU before a context switch
|
||||||
|
/// to be restored later.
|
||||||
|
///
|
||||||
|
/// # Notes
|
||||||
|
///
|
||||||
|
/// This function should ONLY be called in interrupt handlers such
|
||||||
|
/// as that of the timer. This will then save registers as required
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// This function is unsafe because of the usage of inline ASM.
|
||||||
|
#[inline(always)]
|
||||||
|
pub unsafe fn save_registers() -> Self {
|
||||||
|
let mut context = Self::default();
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"mov {0}, rax",
|
||||||
|
"mov {1}, rbx",
|
||||||
|
"mov {2}, rcx",
|
||||||
|
"mov {3}, rdx",
|
||||||
|
"mov {4}, rsi",
|
||||||
|
"mov {5}, rdi",
|
||||||
|
"mov {6}, rbp",
|
||||||
|
"mov {7}, rsp",
|
||||||
|
"mov {8}, r8",
|
||||||
|
"mov {9}, r9",
|
||||||
|
"mov {10}, r10",
|
||||||
|
"mov {11}, r11",
|
||||||
|
"mov {12}, r12",
|
||||||
|
"mov {13}, r13",
|
||||||
|
"mov {14}, r14",
|
||||||
|
"mov {15}, r15",
|
||||||
|
"lea {16}, [rip]",
|
||||||
|
"pushf",
|
||||||
|
"pop {17}",
|
||||||
|
out(reg) context.rax,
|
||||||
|
out(reg) context.rbx,
|
||||||
|
out(reg) context.rcx,
|
||||||
|
out(reg) context.rdx,
|
||||||
|
out(reg) context.rsi,
|
||||||
|
out(reg) context.rdi,
|
||||||
|
out(reg) context.rbp,
|
||||||
|
out(reg) context.rsp,
|
||||||
|
out(reg) context.r8,
|
||||||
|
out(reg) context.r9,
|
||||||
|
out(reg) context.r10,
|
||||||
|
out(reg) context.r11,
|
||||||
|
out(reg) context.r12,
|
||||||
|
out(reg) context.r13,
|
||||||
|
out(reg) context.r14,
|
||||||
|
out(reg) context.r15,
|
||||||
|
out(reg) context.rip,
|
||||||
|
out(reg) context.rflags,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
context
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use x86_64::registers::rflags::read;
|
// use x86_64::registers::rflags::read;
|
||||||
|
|
||||||
use crate::{drivers::io::ascii::clear_screen, prelude::stdin::read_line, print, println};
|
use crate::{drivers::io::ascii::clear_screen, prelude::stdin::read_line, print, println};
|
||||||
|
|
||||||
|
|||||||
+23
-1
@@ -1,2 +1,24 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
sudo dd if=./build/image.iso of="$1"
|
|
||||||
|
# Colors
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
BOLD='\033[1m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
info() {
|
||||||
|
echo -e "${BLUE}${BOLD}info${NC}: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
warning() {
|
||||||
|
echo -e "${YELLOW}${BOLD}warning${NC}: $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
warning "This script will OVERWRITE whatever media you throw at it\nwith the built ISO."
|
||||||
|
info "sudo ./hardware.sh /dev/yourdisk"
|
||||||
|
|
||||||
|
if echo "$1" | grep -q "/dev"; then
|
||||||
|
dd if=./build/image.iso of="$1"
|
||||||
|
fi
|
||||||
|
|||||||
@@ -135,6 +135,23 @@ else
|
|||||||
debug_flags=""
|
debug_flags=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ $USE_LEGACY_BIOS ]; then
|
||||||
|
boot_flags=""
|
||||||
|
else
|
||||||
|
# Check for the presence of the OVMF firmware.
|
||||||
|
if [ ! -f $build_dir/RELEASEX64_OVMF_CODE.fd ]; then
|
||||||
|
info "Downloading OVMF UEFI firmware for QEMU"
|
||||||
|
info "To disable this, set USE_LEGACY_BIOS=1."
|
||||||
|
pushd $build_dir
|
||||||
|
curl https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF_CODE.fd -LO || error "failed to download OVMF firmware for UEFI"
|
||||||
|
curl https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF_VARS.fd -LO || error "failed to download OVMF firmware for UEFI"
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
boot_flags="-drive if=pflash,format=raw,readonly=on,file=$build_dir/RELEASEX64_OVMF_CODE.fd \
|
||||||
|
-drive if=pflash,format=raw,file=$build_dir/RELEASEX64_OVMF_VARS.fd"
|
||||||
|
fi
|
||||||
|
|
||||||
# Set up test-specific flags
|
# Set up test-specific flags
|
||||||
if [ $is_test -eq 1 ]; then
|
if [ $is_test -eq 1 ]; then
|
||||||
test_flags="-device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none"
|
test_flags="-device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none"
|
||||||
@@ -189,5 +206,6 @@ qemu-system-x86_64 -M q35 \
|
|||||||
-no-reboot \
|
-no-reboot \
|
||||||
${test_flags} \
|
${test_flags} \
|
||||||
${debug_flags} \
|
${debug_flags} \
|
||||||
|
${boot_flags} \
|
||||||
${QEMU_FLAGS:-}
|
${QEMU_FLAGS:-}
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,23 @@ fi
|
|||||||
# I'm lazy but I just remove GDB flags when running this script.
|
# I'm lazy but I just remove GDB flags when running this script.
|
||||||
debug_flags=""
|
debug_flags=""
|
||||||
|
|
||||||
|
if [ $USE_LEGACY_BIOS ]; then
|
||||||
|
boot_flags=""
|
||||||
|
else
|
||||||
|
# Check for the presence of the OVMF firmware.
|
||||||
|
if [ ! -f $build_dir/RELEASEX64_OVMF_CODE.fd ]; then
|
||||||
|
info "Downloading OVMF UEFI firmware for QEMU"
|
||||||
|
info "To disable this, set USE_LEGACY_BIOS=1."
|
||||||
|
pushd $build_dir
|
||||||
|
curl https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF_CODE.fd -LO || error "failed to download OVMF firmware for UEFI"
|
||||||
|
curl https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF_VARS.fd -LO || error "failed to download OVMF firmware for UEFI"
|
||||||
|
popd
|
||||||
|
fi
|
||||||
|
|
||||||
|
boot_flags="-drive if=pflash,format=raw,readonly=on,file=$build_dir/RELEASEX64_OVMF_CODE.fd \
|
||||||
|
-drive if=pflash,format=raw,file=$build_dir/RELEASEX64_OVMF_VARS.fd"
|
||||||
|
fi
|
||||||
|
|
||||||
# Set up test-specific flags
|
# Set up test-specific flags
|
||||||
if [ $is_test -eq 1 ]; then
|
if [ $is_test -eq 1 ]; then
|
||||||
test_flags="-device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none"
|
test_flags="-device isa-debug-exit,iobase=0xf4,iosize=0x04 -display none"
|
||||||
|
|||||||
Reference in New Issue
Block a user