Skip to content

Instantly share code, notes, and snippets.

@tux7k
Created March 30, 2024 04:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tux7k/9077e422e80c38dd84509eb05e041e84 to your computer and use it in GitHub Desktop.
Save tux7k/9077e422e80c38dd84509eb05e041e84 to your computer and use it in GitHub Desktop.
Code for my multiboot attempt
/*
* Rust BareBones OS
* - By John Hodge (Mutabah/thePowersGang)
*
* main.rs
* - Top-level file for kernel
*
* This code has been put into the public domain, there are no restrictions on
* its use, and the author takes no liability.
*/
#![feature(panic_info_message)] //< Panic handling
#![no_std] //< Kernels can't use std
#![crate_name="kernel"]
/// Macros, need to be loaded before everything else due to how rust parses
#[macro_use]
mod macros;
// Achitecture-specific modules
#[cfg(target_arch="x86_64")] #[path="arch/amd64/mod.rs"]
pub mod arch;
#[cfg(target_arch="x86")] #[path="arch/x86/mod.rs"]
pub mod arch;
/// Exception handling (panic)
pub mod unwind;
pub mod utils;
pub use utils::*;
/// Logging code
mod logging;
use core::arch::asm;
// import multiboot2 package infos
// using the pkg bc im too stupid to know haow to make a multiboot header parsing :(
// Kernel entrypoint (called by arch/<foo>/start.S)
#[no_mangle]
pub fn kmain(mb_addr: usize)
{
log!("Wintergreen");
arch::idt::idt_init();
log!("IDT [OK]");
// unsafe { core::ptr::write_volatile(0xdeadbeef as *mut u32, 0x1); }
/*
for (tag = (struct multiboot_tag *) (addr + 8); // sets the initial tag equal to 0x9500 + 8
// casted as a structure of MultibootTag
tag->type != MULTIBOOT_TAG_TYPE_END; // if the tag type is not equal to the ending tag type
// of 0, keep going
tag = (struct multiboot_tag *) ((multiboot_uint8_t *) tag
+ ((tag->size + 7) & ~7))) // each time set the tag equal to
// the tag size +7 & ~7
{
*/
// log!("{:#?}", mb_addr);
unsafe {
let mut p;
let mut mbS = {
p = core::ptr::NonNull::new((
//0xFFFFFFFF80009500
mb_addr // 0x9500
+ 8
+ 0xFFFFFFFF80000000
) as *mut MultibootTag).unwrap();
p.as_mut()
};
log!("{:#?}", mbS);
//while mbS.typ != MULTIBOOT_TAG_TYPE_END {
// mbS = ((mbS as *const usize) + ((mbS.size + 7) & !7) as *const u32);
// }
}
loop {}
}
const MULTIBOOT_TAG_TYPE_FRAMEBUFFER: u32 = 8;
const MULTIBOOT_TAG_TYPE_END: u32 = 0;
#[repr(C)]
#[derive(Debug)]
struct MultibootTag {
typ: u32,
size: u32
}
/*
* Rust BareBones OS
* - By John Hodge (Mutabah/thePowersGang)
*
* arcm/amd64/start.S
* - AMD64 Entrypoint
*
* == LICENCE ==
* This code has been put into the public domain, there are no restrictions on
* its use, and the author takes no liability.
*/
/* The kernel is linked to run at -2GB. This allows efficient addressing */
KERNEL_BASE = 0xFFFFFFFF80000000
/* === Multiboot Header === */
MULTIBOOT_PAGE_ALIGN = (1<<0)
MULTIBOOT_MEMORY_INFO = (1<<1)
MULTIBOOT_REQVIDMODE = (1<<2)
MULTIBOOT_HEADER_MAGIC = 0x1BADB002
MULTIBOOT_HEADER_FLAGS = (MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO | MULTIBOOT_REQVIDMODE)
MULTIBOOT_CHECKSUM = -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
.section .multiboot, "a"
.globl mboot
mboot:
.long MULTIBOOT_HEADER_MAGIC
.long MULTIBOOT_HEADER_FLAGS
.long MULTIBOOT_CHECKSUM
.long mboot
/* a.out kludge (not used, the kernel is elf) */
.long 0, 0, 0, 0 /* load_addr, load_end_addr, bss_end_addr, entry_addr */
/* Video mode */
.long 0 /* Mode type (0: LFB) */
.long 0 /* Width (no preference) */
.long 0 /* Height (no preference) */
.long 32 /* Depth (32-bit preferred) */
#define DEBUG(c) mov $0x3f8, %dx ; mov $c, %al ; outb %al, %dx
/* === Code === */
.section .inittext, "ax"
.globl start
.code32
start:
/* The kernel starts in protected mode (32-bit mode, we want to switch to long mode) */
/* 1. Save multiboot state */
mov %eax, mboot_sig - KERNEL_BASE
mov %ebx, mboot_ptr - KERNEL_BASE
/* 2. Ensure that the CPU support long mode */
mov $0x80000000, %eax
cpuid
/* - Check if CPUID supports the field we want to query */
cmp $0x80000001, %eax
jbe not64bitCapable
/* - Test the IA-32e bit */
mov $0x80000001, %eax
cpuid
test $0x20000000, %edx /* bit 29 = */
jz not64bitCapable
/* 3. Set up state for long mode */
/* Enable:
PGE (Page Global Enable)
+ PAE (Physical Address Extension)
+ PSE (Page Size Extensions)
*/
mov %cr4, %eax
or $(0x80|0x20|0x10), %eax
mov %eax, %cr4
/* Load PDP4 */
mov $(init_pml4 - KERNEL_BASE), %eax
mov %eax, %cr3
/* Enable IA-32e mode (Also enables SYSCALL and NX) */
mov $0xC0000080, %ecx
rdmsr
or $(1 << 11)|(1 << 8)|(1 << 0), %eax /* NXE, LME, SCE */
wrmsr
/* Enable paging and enter long mode */
mov %cr0, %eax
or $0x80010000, %eax /* PG & WP */
mov %eax, %cr0
lgdt GDTPtr_low - KERNEL_BASE
ljmp $0x08, $start64
not64bitCapable:
/* If the CPU isn't 64-bit capable, print a message to serial/b8000 then busy wait */
mov $0x3f8, %dx
mov $'N', %al ; outb %al, %dx
movw $0x100|'N', 0xb8000
mov $'o', %al ; outb %al, %dx
movw $0x100|'o', 0xb8002
mov $'t', %al ; outb %al, %dx
movw $0x100|'t', 0xb8004
mov $'6', %al ; outb %al, %dx
movw $0x100|'6', 0xb8006
mov $'4', %al ; outb %al, %dx
movw $0x100|'4', 0xb8008
not64bitCapable.loop:
hlt
jmp not64bitCapable.loop
.code64
.globl start64
start64:
/* Running in 64-bit mode, jump to high memory */
lgdt GDTPtr
mov $start64_high, %rax
jmp *%rax
.section .text
.extern kmain
.globl start64_high
start64_high:
/* and clear low-memory mapping */
mov $0, %rax
mov %rax, init_pml4 - KERNEL_BASE + 0
/* Set up segment registers */
mov $0x10, %ax
mov %ax, %ss
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
/* Set up stack pointer */
mov $init_stack, %rsp
/* call the rust code & pass magic multiboot number to the function */
mov mboot_ptr - KERNEL_BASE, %edi
/*push %eax*/
/* push %rax */
call kmain
/* and if that returns (it shouldn't) loop forever */
start64.loop:
hlt
jmp start64.loop
/*
RDI = Destination
RSI = Value
RDX = Count
*/
.section .text.memset
.globl memset
memset:
mov %rsi, %rax
mov %rdx, %rcx
rep stosb
ret
/*
RDI = Destination
RSI = Source
RDX = Count
*/
.section .text.memcpy
.globl memcpy
memcpy:
mov %rdx, %rcx
rep movsb
ret
/* === Page-aligned data === */
.section .padata
/* Initial paging structures, four levels */
/* The +3 for sub-pages indicates "present (1) + writable (2)" */
init_pml4:
.quad low_pdpt - KERNEL_BASE + 3 /* low map for startup, will be cleared before rust code runs */
.rept 512 - 3
.quad 0
.endr
.quad 0 /* If you so wish, this is a good place for the "Fractal" mapping */
.quad init_pdpt - KERNEL_BASE + 3 /* Final mapping */
low_pdpt:
.quad init_pd - KERNEL_BASE + 3 /* early init identity map */
.rept 512 - 1
.quad 0
.endr
init_pdpt: /* covers the top 512GB, 1GB each entry */
.rept 512 - 2
.quad 0
.endr
.quad init_pd - KERNEL_BASE + 3 /* at -2GB, identity map the kernel image */
.quad 0
init_pd:
/* 0x80 = Page size extension */
.quad 0x000000 + 0x80 + 3 /* Map 2MB, enough for a 1MB kernel */
.quad 0x200000 + 0x80 + 3 /* - give it another 2MB, just in case */
.rept 512 - 2
.quad 0
.endr
init_stack_base:
.rept 0x1000 * 2
.byte 0
.endr
init_stack:
/* === General Data === */
.section .data
.globl mboot_sig
.globl mboot_ptr
mboot_sig: .long 0
mboot_ptr: .long 0
/* Global Descriptor Table */
GDTPtr_low:
.word GDTEnd - GDT - 1
.long GDT - KERNEL_BASE
GDTPtr:
.word GDTEnd - GDT - 1
.quad GDT
.globl GDT
GDT:
.long 0, 0
.long 0x00000000, 0x00209A00 /* 0x08: 64-bit Code */
.long 0x00000000, 0x00009200 /* 0x10: 64-bit Data */
.long 0x00000000, 0x0040FA00 /* 0x18: 32-bit User Code */
.long 0x00000000, 0x0040F200 /* 0x20: User Data */
.long 0x00000000, 0x0020FA00 /* 0x28: 64-bit User Code */
.long 0x00000000, 0x0000F200 /* 0x30: User Data (64 version) */
GDTEnd:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment