initial commit

This commit is contained in:
Zoe
2023-06-25 17:09:32 -05:00
commit 3e19945c40
14 changed files with 422 additions and 0 deletions

5
.cargo/config Normal file
View File

@@ -0,0 +1,5 @@
[build]
target = "x86_64-unknown-none"
[unstable]
build-std = ["core", "compiler_builtins"]

7
Cargo.lock generated Normal file
View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "operating-system"
version = "0.1.0"

10
Cargo.toml Normal file
View File

@@ -0,0 +1,10 @@
[package]
name = "operating-system"
version = "0.1.0"
edition = "2021"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

26
Makefile Normal file
View File

@@ -0,0 +1,26 @@
.PHONY: all clean
all: cargo-build compile-bootloader copy-bootloader objcopy-elf-file build-os-image
build-os-image:
dd if=target/x86_64-unknown-none/release/bootloader.bin conv=notrunc of=os-image bs=512
dd if=target/x86_64-unknown-none/release/operating-system.bin conv=notrunc of=os-image bs=512 seek=1
compile-bootloader:
nasm -f bin bootloader/bootloader.asm -o bootloader/bootloader.bin
objcopy-elf-file:
objcopy -O binary target/x86_64-unknown-none/release/operating-system.elf target/x86_64-unknown-none/release/operating-system.bin
copy-bootloader:
cp bootloader/bootloader.bin target/x86_64-unknown-none/release/bootloader.bin
cargo-build:
cargo rustc --release --target x86_64-unknown-none.json
run: all
qemu-system-x86_64 -drive format=raw,file=os-image -serial mon:stdio -s
clean:
cargo clean
rm -f os-image bootloader/bootloader.bin

89
bootloader/bootloader.asm Normal file
View File

@@ -0,0 +1,89 @@
[BITS 16]
[org 0x7c00]
mov [BOOT_DEVICE], dl
; setup stack
mov bp, 0x9000
mov sp, bp
; Set video mode (640 x 480 @ 16 colors)
mov ah, 0x00
mov al, 0x12
int 0x10
call load_kernel
call switch_to_32bit
load_kernel:
mov bx, 0x1000 ; Destination address
mov dh, 2 ; Sector number
mov dl, [BOOT_DEVICE] ; Drive Number
mov al, dh
mov ch, 0x00 ; Cylinder number
mov cl, 0x02 ; Start from sector 2, sector 1 is our bootloader
mov ah, 0x02 ; Set read mode
mov dh, 0x00
int 0x13
ret
gdtp:
dw gdt_end - gdt_start - 1
dw gdt_start
gdt_start:
dq 0x0
gdt_code_segment:
dw 0xFFFF ; Limit (16-bit) (set to 0xFFFF for maximum)
dw 0x0 ; Base (16-bit)
db 0x0 ; Base (8-bit)
db 10011010b ; Access flags
db 11001111b ; Granularity flags (set to 0xCF for 4 KB granularity)
db 0x0 ; Segment bits
gdt_data_segment:
dw 0xFFFF ; Limit (16-bit) (set to 0xFFFF for maximum)
dw 0x0 ; Base (16-bit)
db 0x0 ; Base (8-bit)
db 10010010b ; Access flags
db 11001111b ; Granularity flags (set to 0xCF for 4 KB granularity)
db 0x0 ; Segment bits
gdt_end:
GDT_CODE_SEG_ADDR equ gdt_code_segment - gdt_start
GDT_DATA_SEG_ADDR equ gdt_data_segment - gdt_start
switch_to_32bit:
; Disable interrupts and setup gdt
cli
lgdt [gdtp]
; Set PE (Protection Enable) bit in CR0
mov eax, cr0
or eax, 0x01
mov cr0, eax
jmp GDT_CODE_SEG_ADDR:init_32bit
[BITS 32]
init_32bit:
mov ax, GDT_DATA_SEG_ADDR
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov ebp, 0x90000
mov esp, ebp
call init_kernel
init_kernel:
call 0x1000
jmp $
BOOT_DEVICE db 0x00
times 510 - ($ - $$) db 0 ; make sure file is 510 bytes in size
dw 0xAA55 ; write boot signature

BIN
bootloader/bootloader.bin Normal file

Binary file not shown.

28
linker.ld Normal file
View File

@@ -0,0 +1,28 @@
/* We want the symbol _start to be our entry point */
ENTRY(_start)
SECTIONS
{
. = 0xFFFFF;
.text : {
*(.text)
}
/* Read-only data. */
.rodata : {
*(.rodata)
}
/* Read-write data (initialized) */
.data : {
*(.data)
}
/* Read-write data (uninitialized) and stack */
.bss : {
*(COMMON)
*(.bss)
}
}

2
src/drivers/mod.rs Normal file
View File

@@ -0,0 +1,2 @@
pub mod serial;
pub mod vga;

33
src/drivers/serial.rs Normal file
View File

@@ -0,0 +1,33 @@
use crate::libs::io::{inb, outb};
pub static PORT: u16 = 0x3f8;
pub fn init_serial() -> u8 {
outb(PORT + 1, 0x00);
outb(PORT + 3, 0x80);
outb(PORT + 0, 0x03);
outb(PORT + 1, 0x00);
outb(PORT + 3, 0x03);
outb(PORT + 2, 0xC7);
outb(PORT + 4, 0x0B);
outb(PORT + 4, 0x1E);
outb(PORT + 0, 0xAE);
// Check if serial is faulty
if inb(PORT + 0) != 0xAE {
return 1;
}
// Set serial in normal operation mode
outb(PORT + 4, 0x0F);
return 0;
}
fn is_transmit_empty() -> bool {
return (inb(PORT + 5) & 0x20) != 0x20;
}
pub fn write_serial(a: u8) {
while is_transmit_empty() {}
outb(PORT, a);
}

137
src/drivers/vga.rs Normal file
View File

@@ -0,0 +1,137 @@
use crate::libs::io::{inb, outb};
static VGA_AC_INDEX: u16 = 0x3C0;
static VGA_AC_WRITE: u16 = 0x3C0;
static VGA_AC_READ: u16 = 0x3C1;
static VGA_MISC_WRITE: u16 = 0x3C2;
static VGA_SEQ_INDEX: u16 = 0x3C4;
static VGA_SEQ_DATA: u16 = 0x3C5;
static VGA_DAC_READ_INDEX: u16 = 0x3C7;
static VGA_DAC_WRITE_INDEX: u16 = 0x3C8;
static VGA_DAC_DATA: u16 = 0x3C9;
static VGA_MISC_READ: u16 = 0x3CC;
static VGA_GC_INDEX: u16 = 0x3CE;
static VGA_GC_DATA: u16 = 0x3CF;
/* COLOR emulation MONO emulation */
static VGA_CRTC_INDEX: u16 = 0x3D4; /* 0x3B4 */
static VGA_CRTC_DATA: u16 = 0x3D5; /* 0x3B5 */
static VGA_INSTAT_READ: u16 = 0x3DA;
static VGA_NUM_SEQ_REGS: u16 = 5;
static VGA_NUM_CRTC_REGS: u16 = 25;
static VGA_NUM_GC_REGS: u16 = 9;
static VGA_NUM_AC_REGS: u16 = 21;
static VGA_NUM_REGS: u16 = 1 + VGA_NUM_SEQ_REGS + VGA_NUM_CRTC_REGS + VGA_NUM_GC_REGS + VGA_NUM_AC_REGS;
const VGA_BUFFER: *mut u8 = 0xA0000 as *mut u8;
pub fn init_vga() {
// Set the registers for mode 12h
let mut registers_720x480x16 = [
/* MISC */
0xE7,
/* SEQ */
0x03, 0x01, 0x08, 0x00, 0x06,
/* CRTC */
0x6B, 0x59, 0x5A, 0x82, 0x60, 0x8D, 0x0B, 0x3E,
0x00, 0x40, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
0xEA, 0x0C, 0xDF, 0x2D, 0x08, 0xE8, 0x05, 0xE3,
0xFF,
/* GC */
0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F,
0xFF,
/* AC */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x01, 0x00, 0x0F, 0x00, 0x00,
];
write_regs(&mut registers_720x480x16);
for x in 0..2 {
put_pixel(x, 0, 9);
}
}
fn put_pixel(mut pos_x: usize, pos_y: usize, vga_color: u8) {
unsafe {
let width_in_bytes = 720 / 8;
let offset = width_in_bytes * pos_y + pos_x / 8;
pos_x = (pos_x & 7) * 1;
let mask: u8 = 0x80 >> pos_x;
let mut pmask: u8 = 1;
for plane in 0..4 {
set_plane(plane);
if pmask & vga_color != 0 {
*VGA_BUFFER.offset(offset as isize) = *VGA_BUFFER.offset(offset as isize) | mask;
} else {
*VGA_BUFFER.offset(offset as isize) = *VGA_BUFFER.offset(offset as isize) & !mask;
}
pmask <<= 1;
}
}
}
fn set_plane(plane: u8) {
let plane = plane & 3;
let pmask = 1 << plane;
/* set read plane */
outb(VGA_GC_INDEX, 4);
outb(VGA_GC_DATA, plane);
/* set write plane */
outb(VGA_SEQ_INDEX, 2);
outb(VGA_SEQ_DATA, pmask);
}
fn write_regs(mut regs: &mut [u8]) {
/* write MISCELLANEOUS reg */
outb(VGA_MISC_WRITE, regs[0]);
regs = &mut regs[1..];
/* write SEQUENCER regs */
for i in 0..VGA_NUM_SEQ_REGS {
outb(VGA_SEQ_INDEX, i as u8);
outb(VGA_SEQ_DATA, regs[0]);
regs = &mut regs[1..];
}
/* unlock CRTC registers */
outb(VGA_CRTC_INDEX, 0x03);
outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) | 0x80);
outb(VGA_CRTC_INDEX, 0x11);
outb(VGA_CRTC_DATA, inb(VGA_CRTC_DATA) & !0x80);
/* make sure they remain unlocked */
regs[0x03] |= 0x80;
regs[0x11] &= !0x80;
/* write CRTC regs */
for i in 0..VGA_NUM_CRTC_REGS {
outb(VGA_CRTC_INDEX, i as u8);
outb(VGA_CRTC_DATA, regs[0]);
regs = &mut regs[1..];
}
/* write GRAPHICS CONTROLLER regs */
for i in 0..VGA_NUM_GC_REGS {
outb(VGA_GC_INDEX, i as u8);
outb(VGA_GC_DATA, regs[0]);
regs = &mut regs[1..];
}
/* write ATTRIBUTE CONTROLLER regs */
for i in 0..VGA_NUM_AC_REGS {
// inb(VGA_INSTAT_READ);
outb(VGA_AC_INDEX, i as u8);
outb(VGA_AC_WRITE, regs[0]);
regs = &mut regs[1..];
}
/* lock 16-color palette and unblank display */
inb(VGA_INSTAT_READ);
outb(VGA_AC_INDEX, 0x20);
}

28
src/libs/io.rs Normal file
View File

@@ -0,0 +1,28 @@
use core::arch::asm;
#[inline]
pub fn outb(port: u16, value: u8) {
unsafe {
asm!(
"out dx, al",
in("dx") port,
in("al") value,
options(preserves_flags, nomem, nostack)
);
}
return;
}
#[inline]
pub fn inb(port: u16) -> u8 {
let mut value: u8;
unsafe {
asm!(
"in al, dx",
out("al") value,
in("dx") port,
options(preserves_flags, nomem, nostack)
);
}
return value;
}

1
src/libs/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod io;

31
src/main.rs Normal file
View File

@@ -0,0 +1,31 @@
#![no_std]
#![no_main]
mod drivers;
mod libs;
use drivers::{serial, vga};
use libs::io;
#[no_mangle]
pub extern "C" fn _start() -> ! {
serial::init_serial();
// let crash_message = b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
// let garbage_message = b"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
let message = b"A";
for (_i, &byte) in message.iter().enumerate() {
serial::write_serial(byte);
}
vga::init_vga();
loop {}
}
#[panic_handler]
fn panic (_info: &core::panic::PanicInfo) -> ! {
loop {}
}

25
x86_64-unknown-none.json Normal file
View File

@@ -0,0 +1,25 @@
{
"llvm-target": "x86_64-unknown-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"arch": "x86_64",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"executables": true,
"linker-flavor": "ld.lld",
"linker": "rust-lld",
"panic-strategy": "abort",
"disable-redzone": true,
"features": "-mmx,-sse,+soft-float",
"dynamic-linking": false,
"relocation-model": "pic",
"code-model": "kernel",
"exe-suffix": ".elf",
"has-rpath": false,
"no-default-libraries": true,
"position-independent-executables": false,
"pre-link-args": {
"ld.lld": ["--script=linker.ld"]
}
}