Skip to content

Commit b0f1ab9

Browse files
authored
Paging (#38)
* page entries * rename file * present setter * missspel... * paging unstable identity mapping * add to header * rename to `paging_init` * fix global asm export * dereference esp * add paging init to kernel main * fix kernel logs * bitmap funcs * make multiple page dirs * move init funcs to the bottom & unwrap eaw data from the struct * register page fault * simple frame allocators * high-half kernel mapping * add kernel end symbol * add some defines to `paging.h` * remove transfering func * fix bootstrap end symbol rename * unstatic arrays * add `serial_write_hex_uint32` * make `load_page_directory` auto detect virt addr * remove some unused commented code * pre ebp fix state commit * memmove * fix move stack * gdt * BUGGED add kernel gdt init * fix no irq's * packed improvement * fix gdt incorect init * bootstrap_qemu_serial * remove bootstrap_qemu_serial commented code from `bootstarp/lib` * `bootstrap_dump_mappings` * add intended `sti` before mouse driver init * BUGGED remap vga vram * add comment with useful debug qemu args * messing around in kernel main * add this to separate option * rename it * kernel high half mapping now works I GODDAMN DO IT. * remove static from func that should not * wow, theres was a bug all that time * page/dir alloc and mappinf system * fix missed include * fix warns * Update README * rename `bootstrap_rodata` section * remove generated tag from linker script actualy the lastone i wroteby myself
1 parent 05d9b16 commit b0f1ab9

32 files changed

+1066
-52
lines changed

.gitattributes

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
Makefile linguist-generated
2-
*.ld linguist-generated

Makefile

Lines changed: 6 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
A bare-metal educational operating system project for x86, originally created to implement the classic **Snake** game in protected mode without any external dependencies. The project boots from the **MBR** via BIOS and runs directly on the hardware (or QEMU).
44

5-
Over time it has grown into a small experimental OS with exception handling, keyboard input, VGA text/graphics modes, custom fonts, palette control, a stack guard mechanism, and multiple demo applications.
5+
Over time it has grown into a small experimental OS with exception handling, keyboard input, VGA text/graphics modes, custom fonts, palette control, paging, and multiple demo applications.
66

77
---
88

@@ -19,9 +19,7 @@ Over time it has grown into a small experimental OS with exception handling, key
1919
- VGA driver with support for text mode `0x03` and graphics mode `0x13`.
2020
- DAC palette setup and custom font loading.
2121
- Global settings system
22-
- Expand-down stack segment with **Stack Guard**:
23-
- Warns at 75% stack usage.
24-
- Triggers a custom **Stack Overflow Interrupt** at 100%.
22+
- High-half kernel mapping
2523
- **Red Screen of Death (RSoD)** kernel panic screen.
2624
- No dependency on `libc` or any external libraries.
2725
- Fully freestanding kernel (written in C, C++ and assembly).
@@ -45,14 +43,42 @@ Over time it has grown into a small experimental OS with exception handling, key
4543
## Repository Structure
4644

4745
```
48-
boot/ - Bootloader (boot.asm, MBR)
49-
include/ - Public headers (arch, drivers, kernel, lib)
50-
src/ - Kernel, architecture-specific code, drivers, applications
51-
apps/ - Demo programs (Snake, Sandbox, Roulette, etc.)
52-
arch/x86/ - Interrupt handling, ports, PIC, PIT
53-
kernel/ - Core kernel and drivers
54-
lib/ - Custom C standard library replacement
55-
Makefile - Build system
46+
boot/ - Early boot code (MBR)
47+
48+
include/ - Public kernel headers
49+
arch/x86/ - x86-specific headers
50+
interrupts/ - IDT, ISR, PIC
51+
paging/ - Paging, bootstrap paging, GDT
52+
timer/ - PIT timer
53+
ports.h - I/O port access
54+
drivers/ - Keyboard, mouse, screen, VGA, serial
55+
kernel/ - Diagnostics, memory, settings
56+
lib/ - Custom C library headers
57+
58+
src/ - Kernel sources
59+
apps/ - User-facing demo applications
60+
app_selector/ - Application switcher
61+
mouse_playground/ - Mouse interaction demo
62+
rsod_roulette/ - RSOD roulette easter egg
63+
segment_test/ - Segment register test
64+
settings_manager/ - Kernel settings app
65+
snake/ - Snake game
66+
text_sandbox/ - Text demo sandbox
67+
arch/x86/ - Architecture-specific implementation
68+
diagnostics/ - RSOD and warning routines
69+
interrupts/ - IDT, ISR, PIC, CPU exception handlers
70+
paging/ - Paging system, bootstrap paging
71+
timer/ - PIT implementation
72+
ports.c - port I/O
73+
kernel/ - Core kernel logic and entry point
74+
core/ - Kernel bootstrap and memory init
75+
drivers/ - Driver implementations
76+
kernel_entry.asm - Kernel entry point
77+
linker.ld - Linker script
78+
lib/ - Custom libc-like implementation (string, mem, math, etc.)
79+
80+
Makefile - Build rules
81+
5682
```
5783

5884
---
@@ -126,7 +152,7 @@ sudo apt install nasm qemu-system-i386
126152
make
127153
```
128154

129-
This produces `build/snake.img`, a bootable raw image.
155+
This produces `build/metabar.img`, a bootable raw image.
130156

131157
### Run in QEMU
132158
```bash
@@ -142,9 +168,9 @@ make clean
142168

143169
## Running on Real Hardware
144170

145-
1. Write `build/snake.img` to the beginning of a storage device (e.g. USB stick) since the bootloader is in the MBR:
171+
1. Write `build/metabar.img` to the beginning of a storage device (e.g. USB stick) since the bootloader is in the MBR:
146172
```bash
147-
sudo dd if=build/snake.img of=/dev/sdX bs=512
173+
sudo dd if=build/metabar.img of=/dev/sdX bs=512
148174
```
149175
2. Boot from it using BIOS (legacy boot).
150176
3. A **PS/2 keyboard** is required. If using USB, make sure **USB-PS/2 emulation** is enabled in BIOS/UEFI.
@@ -182,10 +208,15 @@ make clean
182208
## Future Plans
183209

184210
- Dynamic memory allocation.
185-
- Paging support.
186211
- Additional demo applications (possibly **Tetris**).
187212
- Snake AI mode using pre-trained weights.
188213
- Further expansion of VGA graphics features.
214+
- USB driver
215+
- Hard drive driver
216+
- File System driver
217+
- ELF executor
218+
- Paging based Stack Guard
219+
- User mode (CPL3)
189220

190221
---
191222

@@ -200,10 +231,3 @@ External sources:
200231
License: Public domain.
201232

202233
Many theoretical references were taken from [OSDev Wiki](https://wiki.osdev.org).
203-
204-
---
205-
206-
## Disclaimer
207-
208-
This project is experimental and intended as a learning resource.
209-
It runs in **ring 0 only** (CPL0), with no user mode (CPL3).

boot/boot.asm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ init_pm:
172172
jmp $
173173

174174
; ===== STRINGS =====
175-
msg_loading_kernel db "Loading kernel...", 0
175+
msg_loading_kernel db "Loading kernel... ", 0
176176
msg_kernel_loaded db "Kernel loaded!", 0
177177
msg_disk_error db "Disk read error", 0
178178

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#pragma once
2+
3+
#include <lib/types.h>
4+
#include <paging/page_directory.h>
5+
6+
void bootstrap_setup_mapping(void);
7+
void bootstrap_enable_global_pages(void);
8+
void bootstrap_enable_paging(void);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
#include <lib/types.h>
4+
5+
uint8_t bootstrap_inb(uint16_t port);
6+
void bootstrap_outb(uint16_t port, uint8_t data);
7+
int bootstrap_serial_is_transmit_empty();
8+
void bootstrap_serial_write_char(char c);
9+
void bootstrap_serial_write_uint8(uint8_t value);
10+
void bootstrap_serial_write_uint32(uint32_t value);
11+
void bootstrap_serial_write_hex_uint8(unsigned char byte);
12+
void bootstrap_serial_write_hex_uint32(uint32_t value);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
3+
#include <lib/types.h>
4+
5+
void bootstrap_set_bitmap8_val(uint8_t bitmap[], size_t index, bool_t val);
6+
bool_t bootstrap_get_bitmap8_val(uint8_t bitmap[], size_t index);
7+
void *bootstrap_memcpy(void *dest, const void *src, uint32_t n);

include/arch/x86/paging/gdt.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#pragma once
2+
3+
#include <lib/types.h>
4+
5+
typedef enum __attribute__((packed))
6+
{
7+
tss_16_avl = 1,
8+
ldt = 2,
9+
tss_16_busy = 3,
10+
call_gate_16 = 4,
11+
task_gate = 5,
12+
int_gate_16 = 6,
13+
trap_gate_16 = 7,
14+
tss_32_avl = 8,
15+
tss_32_busy = 10,
16+
call_gate_32 = 11,
17+
int_gate_32 = 12,
18+
trap_gate_32 = 13
19+
} system_descriptor_type_t;
20+
21+
typedef struct
22+
{
23+
uint8_t present : 1;
24+
uint8_t cpl : 2;
25+
// should be 0
26+
uint8_t desc_type : 1;
27+
system_descriptor_type_t type : 4;
28+
} __attribute__((packed)) system_access_byte_t;
29+
30+
typedef struct
31+
{
32+
uint8_t present : 1;
33+
uint8_t cpl : 2;
34+
// should be 1
35+
uint8_t desc_type : 1;
36+
// should be 0
37+
uint8_t datacode_desc_type : 1;
38+
uint8_t conforming : 1;
39+
uint8_t readable : 1;
40+
uint8_t accessed : 1;
41+
} __attribute__((packed)) code_access_byte_t;
42+
43+
typedef struct
44+
{
45+
uint8_t present : 1;
46+
uint8_t cpl : 2;
47+
// should be 1
48+
uint8_t desc_type : 1;
49+
// should be 1
50+
uint8_t datacode_desc_type : 1;
51+
uint8_t expand_down : 1;
52+
uint8_t writeable : 1;
53+
uint8_t accessed : 1;
54+
} __attribute__((packed)) data_access_byte_t;
55+
56+
typedef struct
57+
{
58+
// 16 bits
59+
uint16_t limit_low;
60+
// 16 bits
61+
uint16_t base_low;
62+
// 8 bits
63+
uint8_t base_mid;
64+
union
65+
{
66+
system_access_byte_t system;
67+
code_access_byte_t code;
68+
data_access_byte_t data;
69+
} access;
70+
/*
71+
4 bits
72+
1 - Granularity
73+
1 - Default/Big (0 - 16bit, 1 - 32bit)
74+
0 - 64bit
75+
0 - Available for use by system software
76+
*/
77+
uint8_t flags : 4;
78+
// 4 bits
79+
uint8_t limit_high : 4;
80+
// 8 bits
81+
uint8_t base_high;
82+
} __attribute__((packed)) gdt_entry_t;
83+
84+
typedef struct
85+
{
86+
uint16_t limit;
87+
gdt_entry_t *base;
88+
} __attribute__((packed)) gdt_ptr_t;
89+
90+
void gdte_set_limit(gdt_entry_t *inst, uint32_t lim);
91+
void gdte_set_base(gdt_entry_t *inst, uint32_t base);
92+
void gdte_init_code(gdt_entry_t *inst, uint32_t base, uint32_t limit, bool_t conforming, bool_t readable);
93+
void gdte_init_data(gdt_entry_t *inst, uint32_t base, uint32_t limit, bool_t expand_down, bool_t writeable);
94+
void gdte_init_system(gdt_entry_t *inst, uint32_t base, uint32_t limit, system_descriptor_type_t type);
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#pragma once
2+
3+
#include <lib/types.h>
4+
5+
typedef struct
6+
{
7+
union
8+
{
9+
struct
10+
{
11+
uint32_t present : 1; // 0 = not present, 1 = present
12+
uint32_t rw : 1; // 0 = read only, 1 = read/write
13+
uint32_t us : 1; // 0 = kernel, 1 = user
14+
uint32_t pwt : 1; // Write-through
15+
uint32_t pcd : 1; // Cache disable
16+
uint32_t accessed : 1; // CPU sets on access
17+
uint32_t ps : 1; // Page size: 0 = 4 KiB, 1 = 4 MiB
18+
uint32_t reserved : 1; // reserved
19+
uint32_t avl : 4; // available for OS
20+
uint32_t addr : 20; // [31:12] physical address (aligned)
21+
} fields;
22+
uint32_t raw_data;
23+
};
24+
25+
} pde_t;
26+
27+
/* addr format is addrs from 0x00000000 to 0xFFFFF000 range */
28+
inline void pde_set_addr(pde_t *entry, uint32_t phys_addr) { entry->fields.addr = phys_addr >> 12; }
29+
30+
/* set flags (lower 12 bits) */
31+
inline void pde_set_flags(pde_t *entry, uint16_t flags) { entry->raw_data = (entry->raw_data & 0xFFFFF000) | (flags & 0x0FFF); }
32+
33+
/* Present
34+
true = present | false = not present */
35+
inline void pde_set_present_flag(pde_t *entry, bool_t val) { entry->fields.present = val != 0; };
36+
37+
/* ReadWrite
38+
true = read/write | false = readonly */
39+
inline void pde_set_rw_flag(pde_t *entry, bool_t val) { entry->fields.rw = val != 0; }
40+
41+
/* User/Supervisor
42+
false = ring 0 only | true = allow ring 3 */
43+
inline void pde_set_us_flag(pde_t *entry, bool_t val) { entry->fields.us = val != 0; }
44+
45+
/* Page-level Write-Through
46+
false = Write-back(more effective) | true = Write-through(direct ram write) */
47+
inline void pde_set_pwt_flag(pde_t *entry, bool_t val) { entry->fields.pwt = val != 0; }
48+
49+
/* Page-level Cache Disable - used for MMIO
50+
false = caching | true = no caching */
51+
inline void pde_set_pcd_flag(pde_t *entry, bool_t val) { entry->fields.pcd = val != 0; }
52+
53+
/* User/Supervisor
54+
false = ring 0 only | true = allow ring 3 */
55+
inline void pde_set_ps_flag(pde_t *entry, bool_t val) { entry->fields.ps = val != 0; }
56+
57+
/* Available for OS - any info. CPU will ignore that
58+
Any 4(!) bits*/
59+
inline void pde_set_avl_flag(pde_t *entry, uint8_t val) { entry->fields.avl = (val & 0xF); }
60+
61+
inline uint8_t pde_get_avl_flag(pde_t *entry) { return entry->fields.avl; }
62+
inline bool_t pde_get_accesed_flag(pde_t *entry) { return entry->fields.accessed; }
63+
64+
/* addr may be in 0x00000000 to 0xFFFFF000 range */
65+
inline void pde_init(pde_t *entry, uint32_t addr, bool_t rw, bool_t us, bool_t pwt, bool_t pcd, bool_t ps, uint8_t avl)
66+
{
67+
pde_set_addr(entry, addr);
68+
pde_set_rw_flag(entry, rw);
69+
pde_set_us_flag(entry, us);
70+
pde_set_pwt_flag(entry, pwt);
71+
pde_set_pcd_flag(entry, pcd);
72+
pde_set_ps_flag(entry, ps);
73+
pde_set_avl_flag(entry, avl);
74+
pde_set_present_flag(entry, 1);
75+
entry->fields.accessed = 0;
76+
entry->fields.reserved = 0;
77+
}

0 commit comments

Comments
 (0)