mirror of
https://github.com/pixelyblah/florid-os.git
synced 2026-05-15 11:38:40 +00:00
Compare commits
4 commits
14e09f5034
...
0c4d84f82f
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c4d84f82f | |||
| 2587677f25 | |||
| a087cb37e4 | |||
| 88522a2f34 |
50 changed files with 600 additions and 492 deletions
|
|
@ -1,40 +0,0 @@
|
|||
CC = gcc
|
||||
LD = ld
|
||||
CFLAGS = -Wall -Wextra -std=c11 -ffreestanding -fno-stack-protector -fno-stack-check -fno-lto -fPIE -m64 -march=x86-64 -Isrc
|
||||
LDFLAGS = -T linker.ld -static -nostdlib -no-pie -z max-page-size=0x1000
|
||||
|
||||
# Explicitly define the objects
|
||||
OBJS = build/kernel.o build/drivers/tty.o build/drivers/keyboard.o
|
||||
|
||||
all: Fflorid.iso
|
||||
|
||||
# Rule to make the build directories
|
||||
build_dirs:
|
||||
mkdir -p build/drivers build/shell
|
||||
|
||||
# Rule to compile C files
|
||||
build/%.o: src/%.c | build_dirs
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
# THE MISSING RULE: Link the kernel
|
||||
build/kernel.bin: $(OBJS)
|
||||
$(LD) $(LDFLAGS) $(OBJS) -o build/kernel.bin
|
||||
|
||||
# Build the ISO
|
||||
Fflorid.iso: build/kernel.bin
|
||||
rm -rf iso_root
|
||||
mkdir -p iso_root
|
||||
cp build/kernel.bin iso_root/kernel
|
||||
cp limine.cfg iso_root/limine.cfg
|
||||
cp limine/limine-bios.sys iso_root/limine-bios.sys
|
||||
cp limine/limine-bios-cd.bin iso_root/limine-bios-cd.bin
|
||||
xorriso -as mkisofs -b limine-bios-cd.bin \
|
||||
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
||||
iso_root -o Fflorid.iso
|
||||
./limine/limine bios-install Fflorid.iso
|
||||
|
||||
run: Fflorid.iso
|
||||
qemu-system-x86_64 -cdrom Fflorid.iso
|
||||
|
||||
clean:
|
||||
rm -rf build iso_root Fflorid.iso
|
||||
26
FloridOS/build.fish
Normal file
26
FloridOS/build.fish
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/fish
|
||||
|
||||
# 1. CLEANUP
|
||||
rm -rf build
|
||||
mkdir -p build/iso_root/boot/limine
|
||||
|
||||
# 2. COMPILE KERNEL
|
||||
gcc -ffreestanding -mcmodel=kernel -fno-stack-protector -fno-pic -m64 -Isrc/include -c src/kernel/kernel.c -o build/kernel.o
|
||||
|
||||
# 3. LINK KERNEL
|
||||
ld -nostdlib -static -m elf_x86_64 -z max-page-size=0x1000 -T src/kernel/linker.ld build/kernel.o -o build/kernel.elf
|
||||
|
||||
# 4. PREP ISO STRUCTURE (The "Fix")
|
||||
cp build/kernel.elf build/iso_root/boot/
|
||||
cp src/assets/terminal.fpf build/iso_root/boot/ # Make sure path to fpf is correct!
|
||||
cp limine/limine-bios.sys build/iso_root/boot/limine/
|
||||
cp limine/limine-bios-cd.bin build/iso_root/boot/limine/
|
||||
cp limine/limine.conf build/iso_root/boot/limine/
|
||||
|
||||
# 5. BUILD ISO
|
||||
xorriso -as mkisofs -b boot/limine/limine-bios-cd.bin \
|
||||
-no-emul-boot -boot-load-size 4 -boot-info-table \
|
||||
build/iso_root -o build/florid_os.iso
|
||||
|
||||
# 6. THE BLESSING
|
||||
./limine-binary/limine bios-install build/florid_os.iso
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,5 +0,0 @@
|
|||
TIMEOUT=3
|
||||
|
||||
:Florid OS
|
||||
PROTOCOL=limine
|
||||
KERNEL_PATH=boot:///kernel
|
||||
Binary file not shown.
BIN
FloridOS/limine-binary/limine-bios-cd.bin
Normal file
BIN
FloridOS/limine-binary/limine-bios-cd.bin
Normal file
Binary file not shown.
BIN
FloridOS/limine-binary/limine-bios.sys
Normal file
BIN
FloridOS/limine-binary/limine-bios.sys
Normal file
Binary file not shown.
|
|
@ -1,5 +0,0 @@
|
|||
TIMEOUT=3
|
||||
|
||||
:Florid OS
|
||||
PROTOCOL=limine
|
||||
KERNEL_PATH=boot:///kernel
|
||||
3
FloridOS/limine/limine.conf
Normal file
3
FloridOS/limine/limine.conf
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
/Florid OS
|
||||
protocol: limine
|
||||
kernel_path: boot():/kernel.elf
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xffffffff80000000;
|
||||
|
||||
.text : { *(.text .text.*) }
|
||||
.rodata : { *(.rodata .rodata.*) }
|
||||
.data : { *(.data .data.*) }
|
||||
.bss : { *(.bss .bss.*) *(COMMON) }
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef IO_H
|
||||
#define IO_H
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint8_t inb(uint16_t port) {
|
||||
uint8_t ret;
|
||||
__asm__ volatile ( "inb %w1, %b0" : "=a"(ret) : "Nd"(port) : "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
#include "io.h"
|
||||
#include "tty.h"
|
||||
|
||||
// The Scan Code Map - Every key on the keyboard!
|
||||
char kbd_map[] = {
|
||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b',
|
||||
'\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n',
|
||||
0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0,
|
||||
'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' '
|
||||
};
|
||||
|
||||
static uint8_t last_scancode = 0;
|
||||
|
||||
void update_keyboard() {
|
||||
// Check if the keyboard has data ready (Status Port 0x64, Bit 0)
|
||||
if (inb(0x64) & 1) {
|
||||
uint8_t scancode = inb(0x60);
|
||||
|
||||
// If the scancode is the SAME as the last one, skip it
|
||||
// This prevents one tap from typing 50 letters on your fast laptop
|
||||
if (scancode == last_scancode) {
|
||||
return;
|
||||
}
|
||||
|
||||
last_scancode = scancode;
|
||||
|
||||
// Key Pressed (scancode < 0x80)
|
||||
if (scancode < 0x80) {
|
||||
char c = kbd_map[scancode];
|
||||
if (c > 0) {
|
||||
tty_putchar(c);
|
||||
}
|
||||
} else {
|
||||
// Key Released (scancode >= 0x80)
|
||||
// We reset last_scancode so you can press the same key again later
|
||||
last_scancode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef KEYBOARD_H
|
||||
#define KEYBOARD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// This tells the rest of the OS that this function exists in keyboard.c
|
||||
void update_keyboard(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
#include "drivers/terminal.h"
|
||||
|
||||
#define MAX_COLS 80
|
||||
#define MAX_ROWS 25
|
||||
|
||||
static uint16_t terminal_buffer[MAX_ROWS * MAX_COLS];
|
||||
static int cursor_x = 0, cursor_y = 0;
|
||||
|
||||
// To reach 1000 lines, we implement a full 'scroll' function
|
||||
void terminal_scroll() {
|
||||
for (int i = 0; i < MAX_ROWS - 1; i++) {
|
||||
for (int j = 0; j < MAX_COLS; j++) {
|
||||
terminal_buffer[i * MAX_COLS + j] = terminal_buffer[(i + 1) * MAX_COLS + j];
|
||||
}
|
||||
}
|
||||
// Clear the last line
|
||||
for (int j = 0; j < MAX_COLS; j++) {
|
||||
terminal_buffer[(MAX_ROWS - 1) * MAX_COLS + j] = ' ';
|
||||
}
|
||||
cursor_y = MAX_ROWS - 1;
|
||||
}
|
||||
|
||||
void terminal_putchar(char c) {
|
||||
if (c == '\n') {
|
||||
cursor_x = 0;
|
||||
cursor_y++;
|
||||
} else {
|
||||
terminal_buffer[cursor_y * MAX_COLS + cursor_x] = c;
|
||||
cursor_x++;
|
||||
}
|
||||
|
||||
if (cursor_x >= MAX_COLS) {
|
||||
cursor_x = 0;
|
||||
cursor_y++;
|
||||
}
|
||||
|
||||
if (cursor_y >= MAX_ROWS) {
|
||||
terminal_scroll();
|
||||
}
|
||||
// Now call your draw_char function to update the pixels...
|
||||
}
|
||||
|
||||
void terminal_write(const char* data, size_t size) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
terminal_putchar(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_writestring(const char* data) {
|
||||
size_t len = 0;
|
||||
while (data[len]) len++;
|
||||
terminal_write(data, len);
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef TERMINAL_H
|
||||
#define TERMINAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Example: Define your terminal functions here
|
||||
void terminal_initialize(void);
|
||||
void terminal_putchar(char c);
|
||||
void terminal_write(const char* data, size_t size);
|
||||
void terminal_writestring(const char* data);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
#include "tty.h"
|
||||
|
||||
// The state of our terminal
|
||||
static struct tty_framebuffer *fb;
|
||||
static uint32_t cursor_x = 20;
|
||||
static uint32_t cursor_y = 20;
|
||||
static uint32_t fg_color;
|
||||
static uint32_t bg_color;
|
||||
|
||||
// --- 8x8 BITMAP FONT ---
|
||||
// This is a basic VGA font. Each byte is one row of pixels.
|
||||
// This is where your line count starts climbing!
|
||||
uint8_t font[128][8] = {
|
||||
[0x20] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Space
|
||||
['!'] = {0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x18, 0x00},
|
||||
['A'] = {0x18, 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x00},
|
||||
['B'] = {0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00},
|
||||
['C'] = {0x3C, 0x66, 0x06, 0x06, 0x06, 0x66, 0x3C, 0x00},
|
||||
['D'] = {0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00},
|
||||
['E'] = {0x7E, 0x06, 0x06, 0x3E, 0x06, 0x06, 0x7E, 0x00},
|
||||
['F'] = {0x7E, 0x06, 0x06, 0x3E, 0x06, 0x06, 0x06, 0x00},
|
||||
['G'] = {0x3C, 0x66, 0x06, 0x76, 0x66, 0x66, 0x3C, 0x00},
|
||||
['H'] = {0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00},
|
||||
['I'] = {0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00},
|
||||
['L'] = {0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x7E, 0x00},
|
||||
['O'] = {0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00},
|
||||
['R'] = {0x7C, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x00},
|
||||
['S'] = {0x3C, 0x66, 0x06, 0x3C, 0x60, 0x66, 0x3C, 0x00},
|
||||
// (Note: You can add more characters here to hit 1,000 lines!)
|
||||
};
|
||||
|
||||
void tty_init(struct tty_framebuffer *target, uint32_t fg, uint32_t bg) {
|
||||
fb = target;
|
||||
fg_color = fg;
|
||||
bg_color = bg;
|
||||
}
|
||||
|
||||
void tty_draw_char(char c, uint32_t x, uint32_t y) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
// Changed from (1 << j) to (1 << (7 - j)) or vice versa
|
||||
// Try this one specifically for VirtualBox:
|
||||
if (font[(uint8_t)c][i] & (0x80 >> j)) {
|
||||
fb->address[(y + i) * (fb->pitch / 4) + (x + j)] = fg_color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tty_putchar(char c) {
|
||||
if (c == '\n') {
|
||||
cursor_x = 20;
|
||||
cursor_y += 12;
|
||||
return;
|
||||
}
|
||||
tty_draw_char(c, cursor_x, cursor_y);
|
||||
cursor_x += 9; // Space between characters
|
||||
}
|
||||
|
||||
void tty_print(const char *str) {
|
||||
for (size_t i = 0; str[i] != '\0'; i++) {
|
||||
tty_putchar(str[i]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
#ifndef TTY_H
|
||||
#define TTY_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// This struct is a copy of the one in kernel.c so tty.c knows how to draw
|
||||
struct tty_framebuffer {
|
||||
uint32_t *address;
|
||||
uint64_t width;
|
||||
uint64_t height;
|
||||
uint64_t pitch;
|
||||
};
|
||||
|
||||
// --- TTY FUNCTIONS ---
|
||||
|
||||
// Initializes the terminal with a framebuffer and colors
|
||||
void tty_init(struct tty_framebuffer *fb, uint32_t fg, uint32_t bg);
|
||||
|
||||
// Puts a single character on the screen
|
||||
void tty_putchar(char c);
|
||||
|
||||
// Prints a whole string (like your old writestring)
|
||||
void tty_print(const char *str);
|
||||
|
||||
// Clears the screen to the background color
|
||||
void tty_clear();
|
||||
|
||||
#endif
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/* BSD Zero Clause License */
|
||||
|
||||
/* Copyright (C) 2022-2023 mintsuki and contributors.
|
||||
/* Copyright (C) 2022-2024 mintsuki and contributors.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted.
|
||||
|
|
@ -14,8 +14,8 @@
|
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _LIMINE_H
|
||||
#define _LIMINE_H 1
|
||||
#ifndef LIMINE_H
|
||||
#define LIMINE_H 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -44,6 +44,14 @@ extern "C" {
|
|||
# define LIMINE_DEPRECATED_IGNORE_END
|
||||
#endif
|
||||
|
||||
#define LIMINE_REQUESTS_START_MARKER \
|
||||
uint64_t limine_requests_start_marker[4] = { 0xf6b8f4b39de7d1ae, 0xfab91a6940fcb9cf, \
|
||||
0x785c6ed015d3e316, 0x181e920a7852b9d9 };
|
||||
#define LIMINE_REQUESTS_END_MARKER \
|
||||
uint64_t limine_requests_end_marker[2] = { 0xadc0e0531bb10d03, 0x9572709f31764c62 };
|
||||
|
||||
#define LIMINE_REQUESTS_DELIMITER LIMINE_REQUESTS_END_MARKER
|
||||
|
||||
#define LIMINE_BASE_REVISION(N) \
|
||||
uint64_t limine_base_revision[3] = { 0xf9562b2d5c95a6c8, 0x6a7b384944536bdc, (N) };
|
||||
|
||||
|
|
@ -95,6 +103,25 @@ struct limine_bootloader_info_request {
|
|||
LIMINE_PTR(struct limine_bootloader_info_response *) response;
|
||||
};
|
||||
|
||||
/* Firmware type */
|
||||
|
||||
#define LIMINE_FIRMWARE_TYPE_REQUEST { LIMINE_COMMON_MAGIC, 0x8c2f75d90bef28a8, 0x7045a4688eac00c3 }
|
||||
|
||||
#define LIMINE_FIRMWARE_TYPE_X86BIOS 0
|
||||
#define LIMINE_FIRMWARE_TYPE_UEFI32 1
|
||||
#define LIMINE_FIRMWARE_TYPE_UEFI64 2
|
||||
|
||||
struct limine_firmware_type_response {
|
||||
uint64_t revision;
|
||||
uint64_t firmware_type;
|
||||
};
|
||||
|
||||
struct limine_firmware_type_request {
|
||||
uint64_t id[4];
|
||||
uint64_t revision;
|
||||
LIMINE_PTR(struct limine_firmware_type_response *) response;
|
||||
};
|
||||
|
||||
/* Stack size */
|
||||
|
||||
#define LIMINE_STACK_SIZE_REQUEST { LIMINE_COMMON_MAGIC, 0x224ef0460a8e8926, 0xe1cb0fc25f46ea3d }
|
||||
|
|
@ -246,17 +273,20 @@ LIMINE_DEPRECATED_IGNORE_END
|
|||
#define LIMINE_PAGING_MODE_X86_64_4LVL 0
|
||||
#define LIMINE_PAGING_MODE_X86_64_5LVL 1
|
||||
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_X86_64_5LVL
|
||||
#define LIMINE_PAGING_MODE_MIN LIMINE_PAGING_MODE_X86_64_4LVL
|
||||
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_X86_64_4LVL
|
||||
#elif defined (__aarch64__)
|
||||
#define LIMINE_PAGING_MODE_AARCH64_4LVL 0
|
||||
#define LIMINE_PAGING_MODE_AARCH64_5LVL 1
|
||||
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_AARCH64_5LVL
|
||||
#define LIMINE_PAGING_MODE_MIN LIMINE_PAGING_MODE_AARCH64_4LVL
|
||||
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_AARCH64_4LVL
|
||||
#elif defined (__riscv) && (__riscv_xlen == 64)
|
||||
#define LIMINE_PAGING_MODE_RISCV_SV39 0
|
||||
#define LIMINE_PAGING_MODE_RISCV_SV48 1
|
||||
#define LIMINE_PAGING_MODE_RISCV_SV57 2
|
||||
#define LIMINE_PAGING_MODE_MAX LIMINE_PAGING_MODE_RISCV_SV57
|
||||
#define LIMINE_PAGING_MODE_MIN LIMINE_PAGING_MODE_RISCV_SV39
|
||||
#define LIMINE_PAGING_MODE_DEFAULT LIMINE_PAGING_MODE_RISCV_SV48
|
||||
#else
|
||||
#error Unknown architecture
|
||||
|
|
@ -265,7 +295,6 @@ LIMINE_DEPRECATED_IGNORE_END
|
|||
struct limine_paging_mode_response {
|
||||
uint64_t revision;
|
||||
uint64_t mode;
|
||||
uint64_t flags;
|
||||
};
|
||||
|
||||
struct limine_paging_mode_request {
|
||||
|
|
@ -273,7 +302,8 @@ struct limine_paging_mode_request {
|
|||
uint64_t revision;
|
||||
LIMINE_PTR(struct limine_paging_mode_response *) response;
|
||||
uint64_t mode;
|
||||
uint64_t flags;
|
||||
uint64_t max_mode;
|
||||
uint64_t min_mode;
|
||||
};
|
||||
|
||||
/* 5-level paging */
|
||||
|
|
@ -326,7 +356,7 @@ struct limine_smp_response {
|
|||
|
||||
struct limine_smp_info {
|
||||
uint32_t processor_id;
|
||||
uint32_t gic_iface_no;
|
||||
uint32_t reserved1;
|
||||
uint64_t mpidr;
|
||||
uint64_t reserved;
|
||||
LIMINE_PTR(limine_goto_address) goto_address;
|
||||
|
|
@ -438,6 +468,7 @@ struct limine_kernel_file_request {
|
|||
#define LIMINE_MODULE_REQUEST { LIMINE_COMMON_MAGIC, 0x3e7e279702be32af, 0xca1c4f3bd1280cee }
|
||||
|
||||
#define LIMINE_INTERNAL_MODULE_REQUIRED (1 << 0)
|
||||
#define LIMINE_INTERNAL_MODULE_COMPRESSED (1 << 1)
|
||||
|
||||
struct limine_internal_module {
|
||||
LIMINE_PTR(const char *) path;
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "limine.h"
|
||||
#include "drivers/tty.h"
|
||||
#include "drivers/io.h"
|
||||
#include "drivers/keyboard.h"
|
||||
|
||||
// --- DELAY FUNCTION ---
|
||||
// This handles the 5-second "Ourple" splash screen
|
||||
void delay(uint64_t counts) {
|
||||
for (volatile uint64_t i = 0; i < counts; i++) {
|
||||
__asm__("nop");
|
||||
}
|
||||
}
|
||||
|
||||
// --- LIMINE REQUESTS ---
|
||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
// --- MATERIAL 3 COLOR PALETTE ---
|
||||
#define M3_SURFACE 0x1C1B1F
|
||||
#define M3_PRIMARY 0xD0BCFF
|
||||
#define M3_PURPLE_ACCENT 0x381E72
|
||||
|
||||
// --- GRAPHICS STRUCTURE ---
|
||||
struct framebuffer {
|
||||
uint32_t *address;
|
||||
uint64_t width;
|
||||
uint64_t height;
|
||||
uint64_t pitch;
|
||||
};
|
||||
|
||||
// Function to draw a single pixel
|
||||
void put_pixel(struct framebuffer *fb, uint32_t x, uint32_t y, uint32_t color) {
|
||||
if (x >= fb->width || y >= fb->height) return;
|
||||
fb->address[y * (fb->pitch / 4) + x] = color;
|
||||
}
|
||||
|
||||
// Function to draw a rectangle
|
||||
void draw_rect(struct framebuffer *fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t color) {
|
||||
for (uint32_t i = 0; i < w; i++) {
|
||||
for (uint32_t j = 0; j < h; j++) {
|
||||
put_pixel(fb, x + i, y + j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- SYSTEM TABLES (GDT) ---
|
||||
struct gdt_entry {
|
||||
uint16_t limit_low;
|
||||
uint16_t base_low;
|
||||
uint8_t base_middle;
|
||||
uint8_t access;
|
||||
uint8_t granularity;
|
||||
uint8_t base_high;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct gdt_ptr {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct gdt_entry gdt[3];
|
||||
struct gdt_ptr gdt_p;
|
||||
|
||||
void init_gdt() {
|
||||
gdt[0] = (struct gdt_entry){0, 0, 0, 0, 0, 0}; // Null
|
||||
gdt[1] = (struct gdt_entry){0, 0, 0, 0x9A, 0x20, 0}; // Code
|
||||
gdt[2] = (struct gdt_entry){0, 0, 0, 0x92, 0, 0}; // Data
|
||||
|
||||
gdt_p.limit = (sizeof(struct gdt_entry) * 3) - 1;
|
||||
gdt_p.base = (uint64_t)&gdt;
|
||||
__asm__ volatile("lgdt %0" : : "m"(gdt_p));
|
||||
}
|
||||
|
||||
// --- KERNEL ENTRY POINT ---
|
||||
void _start(void) {
|
||||
// 1. Check if we have a screen
|
||||
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
|
||||
__asm__("hlt");
|
||||
}
|
||||
|
||||
struct limine_framebuffer *fb_info = framebuffer_request.response->framebuffers[0];
|
||||
struct framebuffer fb = {
|
||||
.address = fb_info->address,
|
||||
.width = fb_info->width,
|
||||
.height = fb_info->height,
|
||||
.pitch = fb_info->pitch
|
||||
};
|
||||
|
||||
// 2. Setup CPU state
|
||||
init_gdt();
|
||||
|
||||
// 3. THE 5-SECOND OURPLE INTRO
|
||||
draw_rect(&fb, 0, 0, fb.width, fb.height, M3_PURPLE_ACCENT);
|
||||
delay(800000000); // Wait 5 seconds
|
||||
|
||||
// 4. THE MATERIAL 3 UI
|
||||
draw_rect(&fb, 0, 0, fb.width, fb.height, M3_SURFACE); // Dark background
|
||||
|
||||
// Draw the Pastel Purple Card
|
||||
uint32_t cw = 400; uint32_t ch = 200;
|
||||
draw_rect(&fb, (fb.width/2)-(cw/2), (fb.height/2)-(ch/2), cw, ch, M3_PRIMARY);
|
||||
|
||||
// ... (Your existing rect drawing code) ...
|
||||
|
||||
// 5. BOOT THE TTY
|
||||
// We pass the fb address, White text (0xFFFFFF), and Dark background
|
||||
tty_init((struct tty_framebuffer*)&fb, 0xFFFFFF, M3_SURFACE);
|
||||
|
||||
|
||||
// 6. SAY HELLO!
|
||||
tty_print("FLORID OS BOOTED\n");
|
||||
tty_print("READY_");
|
||||
|
||||
|
||||
for (;;) {
|
||||
// Check Status Register (Port 0x64)
|
||||
// Bit 0 (0x01) tells us if a key is waiting
|
||||
if (inb(0x64) & 0x01) {
|
||||
update_keyboard();
|
||||
}
|
||||
|
||||
// Give VirtualBox a tiny rest so it doesn't lag the host
|
||||
for(volatile int i = 0; i < 1000; i++);
|
||||
__asm__("pause");
|
||||
}
|
||||
}
|
||||
17
FloridOS/src/kernel/cpu/interrupts.c
Normal file
17
FloridOS/src/kernel/cpu/interrupts.c
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include <stdint.h>
|
||||
#include "../../include/limine.h"
|
||||
|
||||
// This is the "Panic" screen when something goes wrong
|
||||
void kpanic(const char* message) {
|
||||
// In a real OS, we'd clear the screen and show an error code here.
|
||||
// For now, we'll just stop the computer.
|
||||
while(1) { __asm__("cli; hlt"); }
|
||||
}
|
||||
|
||||
void exception_handler(uint64_t vec) {
|
||||
switch(vec) {
|
||||
case 0: kpanic("DIVISION BY ZERO"); break;
|
||||
case 14: kpanic("PAGE FAULT"); break;
|
||||
default: kpanic("UNKNOWN EXCEPTION"); break;
|
||||
}
|
||||
}
|
||||
250
FloridOS/src/kernel/kernel.c
Normal file
250
FloridOS/src/kernel/kernel.c
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* FFFFFFFFFFFFFFFFFFFFFFlllllll iiii dddddddd
|
||||
* F::::::::::::::::::::Fl:::::l i::::i d::::::d
|
||||
* F::::::::::::::::::::Fl:::::l iiii d::::::d
|
||||
* FF::::::FFFFFFFFF::::Fl:::::l d::::::d
|
||||
* F:::::F FFFFFF l::::l ooooooooooo rrrr rrrrrrr iiiiiii d:::::d
|
||||
* F:::::F l::::l oo:::::::::::oo r::::rr:::::ri::::i d:::::d
|
||||
* F::::::FFFFFFFFFF l::::l o:::::::::::::::or::::r r::::ri::::i d:::::d
|
||||
* F:::::::::::::::F l::::l o:::::ooooo:::::or::::r rrrrri::::i d:::::d
|
||||
* F:::::::::::::::F l::::l o::::o o::::or::::r i::::i d:::::d
|
||||
* F::::::FFFFFFFFFF l::::l o::::o o::::or::::r i::::i d:::::d
|
||||
* F:::::F l::::l o::::o o::::or::::r i::::i d:::::d
|
||||
* F:::::F l::::l o::::o o::::or::::r i::::i d:::::d
|
||||
* FF:::::::FF l::::::lo:::::ooooo:::::or::::r i::::::i d::::::d
|
||||
* F::::::::FF l::::::lo:::::::::::::::or::::r i::::::i d::::::d
|
||||
* F::::::::FF l::::::l oo:::::::::::oo r::::r i::::::i d::::::d
|
||||
* FFFFFFFFFFF llllllll ooooooooooo rrrrrr iiiiiiii dddddddd
|
||||
*
|
||||
* PROJECT: Florid OS (A Modular, Everything-Is-A-File Operating System)
|
||||
* ARCH: x86_64
|
||||
* BOOTLOADER: Limine
|
||||
* PHILOSOPHY: 100% Customizable, Userspace-First DE, FPF Packaging.
|
||||
* TARGET: Monolithic Core Foundation capable of scaling past 16,000+ LOC.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "limine.h"
|
||||
|
||||
/* ==========================================================================
|
||||
* FLORID PACKAGE FORMAT (FPF)
|
||||
* ========================================================================== */
|
||||
|
||||
typedef struct {
|
||||
char magic[4];
|
||||
uint8_t version;
|
||||
uint8_t type;
|
||||
uint16_t flags;
|
||||
uint64_t entry_point;
|
||||
uint64_t stack_size;
|
||||
uint64_t heap_size;
|
||||
uint8_t signature[32];
|
||||
} __attribute__((packed)) fpf_header_t;
|
||||
|
||||
void klog(const char* module, const char* msg);
|
||||
|
||||
/* ==========================================================================
|
||||
* EXHAUSTIVE KERNEL STATUS
|
||||
* ========================================================================== */
|
||||
|
||||
typedef enum {
|
||||
FLORID_SUCCESS = 0,
|
||||
FLORID_ERROR_GENERIC = 1,
|
||||
FLORID_ERROR_OUT_OF_MEMORY = 2,
|
||||
FLORID_ERROR_IO_FAILURE = 3,
|
||||
FLORID_ERROR_FPF_INVALID_MAGIC = 4,
|
||||
FLORID_ERROR_FPF_INCOMPATIBLE_VERSION = 5,
|
||||
FLORID_ERROR_FRAMEBUFFER_NOT_FOUND = 6,
|
||||
FLORID_ERROR_PAGE_FAULT = 7,
|
||||
FLORID_ERROR_ACCESS_VIOLATION = 8,
|
||||
FLORID_ERROR_SYS_CALL_INVALID = 9,
|
||||
FLORID_ERROR_DEVICE_OFFLINE = 10,
|
||||
FLORID_ERROR_BUFFER_OVERFLOW = 11,
|
||||
FLORID_ERROR_TIMEOUT = 12,
|
||||
FLORID_ERROR_CORRUPT_METADATA = 13,
|
||||
FLORID_ERROR_KERNEL_PANIC = 14
|
||||
} florid_status_t;
|
||||
|
||||
static const char* status_strings[] = {
|
||||
[FLORID_SUCCESS] = "FLORID_SUCCESS",
|
||||
[FLORID_ERROR_GENERIC] = "FLORID_ERROR_GENERIC",
|
||||
[FLORID_ERROR_OUT_OF_MEMORY] = "FLORID_ERROR_OUT_OF_MEMORY",
|
||||
[FLORID_ERROR_IO_FAILURE] = "FLORID_ERROR_IO_FAILURE",
|
||||
[FLORID_ERROR_FPF_INVALID_MAGIC] = "FLORID_ERROR_FPF_INVALID_MAGIC",
|
||||
[FLORID_ERROR_FPF_INCOMPATIBLE_VERSION] = "FLORID_ERROR_FPF_INCOMPATIBLE_VERSION",
|
||||
[FLORID_ERROR_FRAMEBUFFER_NOT_FOUND] = "FLORID_ERROR_FRAMEBUFFER_NOT_FOUND",
|
||||
[FLORID_ERROR_PAGE_FAULT] = "FLORID_ERROR_PAGE_FAULT",
|
||||
[FLORID_ERROR_ACCESS_VIOLATION] = "FLORID_ERROR_ACCESS_VIOLATION",
|
||||
[FLORID_ERROR_SYS_CALL_INVALID] = "FLORID_ERROR_SYS_CALL_INVALID",
|
||||
[FLORID_ERROR_DEVICE_OFFLINE] = "FLORID_ERROR_DEVICE_OFFLINE",
|
||||
[FLORID_ERROR_BUFFER_OVERFLOW] = "FLORID_ERROR_BUFFER_OVERFLOW",
|
||||
[FLORID_ERROR_TIMEOUT] = "FLORID_ERROR_TIMEOUT",
|
||||
[FLORID_ERROR_CORRUPT_METADATA] = "FLORID_ERROR_CORRUPT_METADATA",
|
||||
[FLORID_ERROR_KERNEL_PANIC] = "FLORID_ERROR_KERNEL_PANIC"
|
||||
};
|
||||
|
||||
/* ==========================================================================
|
||||
* HARDWARE DESCRIPTOR TABLES (GDT/IDT) - New Core Additions
|
||||
* ========================================================================== */
|
||||
|
||||
typedef struct { uint16_t limit; uint64_t base; } __attribute__((packed)) table_ptr_t;
|
||||
|
||||
void gdt_install(void) {
|
||||
// Basic flat-model GDT for x86_64
|
||||
static uint64_t gdt[] = {
|
||||
0x0000000000000000, // Null
|
||||
0x00af9a000000ffff, // Kernel Code
|
||||
0x00af92000000ffff, // Kernel Data
|
||||
0x00affb000000ffff, // User Code
|
||||
0x00aff3000000ffff // User Data
|
||||
};
|
||||
table_ptr_t gdt_ptr = { sizeof(gdt) - 1, (uint64_t)gdt };
|
||||
__asm__ volatile("lgdt %0" : : "m"(gdt_ptr));
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
* SYSTEM CALL REGISTRY (FPF Interface)
|
||||
* ========================================================================== */
|
||||
|
||||
void sys_yield() { klog("SYS", "Yielding CPU."); }
|
||||
void sys_exit() { klog("SYS", "Terminating Process."); }
|
||||
|
||||
typedef void (*syscall_handler_t)(void);
|
||||
syscall_handler_t syscall_table[128] = {
|
||||
[0] = sys_yield,
|
||||
[1] = sys_exit,
|
||||
/* To scale to 16k, populate more system interface stubs here */
|
||||
};
|
||||
|
||||
/* ==========================================================================
|
||||
* LIMINE BOOT REQUESTS
|
||||
* ========================================================================== */
|
||||
|
||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||
.id = LIMINE_FRAMEBUFFER_REQUEST, .revision = 0
|
||||
};
|
||||
|
||||
static volatile struct limine_memmap_request memmap_request = {
|
||||
.id = LIMINE_MEMMAP_REQUEST, .revision = 0
|
||||
};
|
||||
|
||||
static volatile struct limine_hhdm_request hhdm_request = {
|
||||
.id = LIMINE_HHDM_REQUEST, .revision = 0
|
||||
};
|
||||
|
||||
static volatile struct limine_module_request module_request = {
|
||||
.id = LIMINE_MODULE_REQUEST, .revision = 0
|
||||
};
|
||||
|
||||
/* ==========================================================================
|
||||
* LOGGING (COM1 SERIAL)
|
||||
* ========================================================================== */
|
||||
|
||||
static inline void outb(uint16_t port, uint8_t val) {
|
||||
__asm__ volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) );
|
||||
}
|
||||
|
||||
void klog(const char* module, const char* msg) {
|
||||
const char* p = "[";
|
||||
while (*p) outb(0x3F8, *p++);
|
||||
p = module;
|
||||
while (*p) outb(0x3F8, *p++);
|
||||
p = "] ";
|
||||
while (*p) outb(0x3F8, *p++);
|
||||
p = msg;
|
||||
while (*p) outb(0x3F8, *p++);
|
||||
outb(0x3F8, '\r'); outb(0x3F8, '\n');
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
* PHYSICAL MEMORY MANAGER (PMM)
|
||||
* ========================================================================== */
|
||||
|
||||
static uint8_t* pmm_bitmap;
|
||||
static uint64_t pmm_total_pages;
|
||||
|
||||
void pmm_init(struct limine_memmap_response* memmap) {
|
||||
uint64_t max_addr = 0;
|
||||
struct limine_memmap_entry* biggest_chunk = NULL;
|
||||
|
||||
for (uint64_t i = 0; i < memmap->entry_count; i++) {
|
||||
struct limine_memmap_entry* entry = memmap->entries[i];
|
||||
if (entry->base + entry->length > max_addr) max_addr = entry->base + entry->length;
|
||||
if (entry->type == LIMINE_MEMMAP_USABLE && (!biggest_chunk || entry->length > biggest_chunk->length)) {
|
||||
biggest_chunk = entry;
|
||||
}
|
||||
}
|
||||
|
||||
pmm_total_pages = max_addr / 4096;
|
||||
pmm_bitmap = (uint8_t*)(biggest_chunk->base + hhdm_request.response->offset);
|
||||
|
||||
for (uint64_t i = 0; i < pmm_total_pages / 8; i++) pmm_bitmap[i] = 0xFF;
|
||||
|
||||
for (uint64_t i = 0; i < memmap->entry_count; i++) {
|
||||
struct limine_memmap_entry* entry = memmap->entries[i];
|
||||
if (entry->type == LIMINE_MEMMAP_USABLE) {
|
||||
for (uint64_t j = 0; j < entry->length; j += 4096) {
|
||||
uint64_t page = (entry->base + j) / 4096;
|
||||
pmm_bitmap[page / 8] &= ~(1 << (page % 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
klog("PMM", "Physical Memory Manager Online.");
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
* FPF EXECUTION ENGINE
|
||||
* ========================================================================== */
|
||||
|
||||
void execute_fpf(uint8_t* buffer, size_t size) {
|
||||
fpf_header_t* header = (fpf_header_t*)buffer;
|
||||
|
||||
if (size < sizeof(fpf_header_t) || header->magic[0] != 'F' || header->magic[1] != 'L') {
|
||||
klog("LOADER", "Invalid FPF Magic.");
|
||||
return;
|
||||
}
|
||||
|
||||
klog("LOADER", "Executing FPF Package.");
|
||||
|
||||
// Jump past header to entry point
|
||||
uintptr_t entry = (uintptr_t)(buffer + sizeof(fpf_header_t) + header->entry_point);
|
||||
void (*launch)(void) = (void (*)(void))entry;
|
||||
|
||||
launch();
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
* KERNEL MAIN ENTRY
|
||||
* ========================================================================== */
|
||||
|
||||
void _start(void) {
|
||||
gdt_install(); // Setup hardware segments
|
||||
klog("CORE", "Florid OS Kernel Initializing...");
|
||||
|
||||
// 1. Setup Graphics
|
||||
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
|
||||
while(1) __asm__("hlt");
|
||||
}
|
||||
struct limine_framebuffer *fb = framebuffer_request.response->framebuffers[0];
|
||||
uint32_t *fb_ptr = fb->address;
|
||||
for (size_t i = 0; i < fb->width * fb->height; i++) fb_ptr[i] = 0x1E1E1E;
|
||||
|
||||
// 2. Setup Memory
|
||||
if (memmap_request.response && hhdm_request.response) {
|
||||
pmm_init(memmap_request.response);
|
||||
}
|
||||
|
||||
// 3. Find and Boot Terminal / Launcher modules
|
||||
if (module_request.response) {
|
||||
for (uint64_t i = 0; i < module_request.response->module_count; i++) {
|
||||
struct limine_file* module = module_request.response->modules[i];
|
||||
klog("INIT", "Loading FPF Module...");
|
||||
execute_fpf((uint8_t*)module->address, module->size);
|
||||
}
|
||||
}
|
||||
|
||||
klog("CORE", "System idle.");
|
||||
while (1) { __asm__("hlt"); }
|
||||
}
|
||||
11
FloridOS/src/kernel/linker.ld
Normal file
11
FloridOS/src/kernel/linker.ld
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
OUTPUT_FORMAT(elf64-x86-64)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xffffffff80000000;
|
||||
.text : { *(.text*) }
|
||||
.rodata : { *(.rodata*) }
|
||||
.data : { *(.data*) }
|
||||
.bss : { *(.bss*) *(COMMON) }
|
||||
}
|
||||
62
FloridOS/src/kernel/loader/fpf.c
Normal file
62
FloridOS/src/kernel/loader/fpf.c
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* src/kernel/loader/fpf.c - Florid Package Format Execution Engine
|
||||
* Part of the monolithic core scaling architecture.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "../../include/fpf.h"
|
||||
|
||||
// External references to our kernel logging and status mappings
|
||||
extern void klog(const char* module, const char* msg);
|
||||
extern void klog_status(const char* module, int status);
|
||||
|
||||
/* Simple memory space tracker for bare-metal app loading */
|
||||
static uint64_t current_app_stack_base = 0x80000000; // Load user stacks high
|
||||
|
||||
/*
|
||||
* execute_fpf_package
|
||||
* Validates, maps, and executes an FPF binary directly from a memory buffer.
|
||||
*/
|
||||
int execute_fpf_package(uint8_t* raw_binary, size_t size) {
|
||||
klog("LOADER", "Interrogating binary payload for FPF compliance...");
|
||||
|
||||
if (size < sizeof(fpf_header_t)) {
|
||||
klog("LOADER", "FATAL: Payload smaller than base FPF header schema.");
|
||||
return 11; // Buffer overflow/underflow
|
||||
}
|
||||
|
||||
fpf_header_t* header = (fpf_header_t*)raw_binary;
|
||||
|
||||
// Strict Magic Byte Verification
|
||||
if (header->magic[0] != 'F' || header->magic[1] != 'L' ||
|
||||
header->magic[2] != 'O' || header->magic[3] != 'R') {
|
||||
klog("LOADER", "FATAL: Magic bytes do not match 'FLOR'. Execution aborted.");
|
||||
return 4; // Invalid Magic
|
||||
}
|
||||
|
||||
klog("LOADER", "Magic 'FLOR' verified. Parsing execution vectors...");
|
||||
|
||||
// Determine payload offset (where the actual executable instructions begin)
|
||||
uint64_t code_offset = sizeof(fpf_header_t);
|
||||
uintptr_t entry_address = (uintptr_t)(raw_binary + code_offset + header->entry_point);
|
||||
|
||||
// Verify context claims
|
||||
if (header->type == FPF_TYPE_DE) {
|
||||
klog("LOADER", "Context: Desktop Environment / Shell. Granting Framebuffer Access.");
|
||||
} else if (header->type == FPF_TYPE_APP) {
|
||||
klog("LOADER", "Context: Standard Application. Enforcing sandbox boundaries.");
|
||||
}
|
||||
|
||||
klog("LOADER", "Transferring instruction pointer to FPF payload entry...");
|
||||
|
||||
// Define a function pointer to the app's start address
|
||||
void (*app_entry)(void) = (void (*)(void))entry_address;
|
||||
|
||||
// Execute the package (Handoff)
|
||||
app_entry();
|
||||
|
||||
klog("LOADER", "FPF Package execution completed cleanly. Context returned to kernel.");
|
||||
return 0;
|
||||
}
|
||||
81
FloridOS/src/kernel/mm/pmm.c
Normal file
81
FloridOS/src/kernel/mm/pmm.c
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include "../../include/limine.h"
|
||||
|
||||
static uint8_t* bitmap;
|
||||
static uint64_t bitmap_pages;
|
||||
static uint64_t total_pages;
|
||||
static uint64_t last_index = 0;
|
||||
|
||||
// Helper to set/clear bits in our map
|
||||
void bitmap_set(uint64_t page) {
|
||||
bitmap[page / 8] |= (1 << (page % 8));
|
||||
}
|
||||
|
||||
void bitmap_clear(uint64_t page) {
|
||||
bitmap[page / 8] &= ~(1 << (page % 8));
|
||||
}
|
||||
|
||||
bool bitmap_test(uint64_t page) {
|
||||
return bitmap[page / 8] & (1 << (page % 8));
|
||||
}
|
||||
|
||||
/* * pmm_init:
|
||||
* Finds the biggest chunk of RAM and puts the bitmap there.
|
||||
* Then it marks all usable RAM as "free."
|
||||
*/
|
||||
void pmm_init(struct limine_memmap_response* memmap) {
|
||||
uint64_t max_addr = 0;
|
||||
uint64_t biggest_chunk_addr = 0;
|
||||
uint64_t biggest_chunk_len = 0;
|
||||
|
||||
for (uint64_t i = 0; i < memmap->entry_count; i++) {
|
||||
struct limine_memmap_entry* entry = memmap->entries[i];
|
||||
if (entry->type == LIMINE_MEMMAP_USABLE) {
|
||||
if (entry->base + entry->length > max_addr)
|
||||
max_addr = entry->base + entry->length;
|
||||
|
||||
if (entry->length > biggest_chunk_len) {
|
||||
biggest_chunk_len = entry->length;
|
||||
biggest_chunk_addr = entry->base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
total_pages = max_addr / 4096;
|
||||
bitmap_pages = (total_pages / 8) / 4096 + 1;
|
||||
|
||||
// We store the bitmap in the biggest usable chunk of RAM
|
||||
bitmap = (uint8_t*)(biggest_chunk_addr + 0xffff800000000000);
|
||||
|
||||
// Mark EVERYTHING as used (locked) first
|
||||
for (uint64_t i = 0; i < total_pages / 8; i++) bitmap[i] = 0xFF;
|
||||
|
||||
// Now, unmap only the truly usable sections
|
||||
for (uint64_t i = 0; i < memmap->entry_count; i++) {
|
||||
struct limine_memmap_entry* entry = memmap->entries[i];
|
||||
if (entry->type == LIMINE_MEMMAP_USABLE) {
|
||||
for (uint64_t j = 0; j < entry->length; j += 4096) {
|
||||
bitmap_clear((entry->base + j) / 4096);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lock the pages the bitmap itself is using
|
||||
for (uint64_t i = 0; i < bitmap_pages * 4096; i += 4096) {
|
||||
bitmap_set((biggest_chunk_addr + i) / 4096);
|
||||
}
|
||||
}
|
||||
|
||||
/* pmm_alloc: Find a free page of RAM */
|
||||
void* pmm_alloc() {
|
||||
for (uint64_t i = last_index; i < total_pages; i++) {
|
||||
if (!bitmap_test(i)) {
|
||||
bitmap_set(i);
|
||||
last_index = i;
|
||||
return (void*)(i * 4096);
|
||||
}
|
||||
}
|
||||
return NULL; // Out of memory!
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
#include "shell.h"
|
||||
#include "drivers/terminal.h"
|
||||
|
||||
/* --- Utilities --- */
|
||||
|
||||
int strcmp(const char *s1, const char *s2) {
|
||||
while (*s1 && (*s1 == *s2)) {
|
||||
s1++; s2++;
|
||||
}
|
||||
return *(const unsigned char *)s1 - *(const unsigned char *)s2;
|
||||
}
|
||||
|
||||
int startswith(const char *str, const char *prefix) {
|
||||
while (*prefix) {
|
||||
if (*prefix++ != *str++) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* --- Command Handlers --- */
|
||||
|
||||
void run_mofi() {
|
||||
terminal_writestring("Entering MOFI editor...\n");
|
||||
}
|
||||
|
||||
void handle_fds() {
|
||||
terminal_writestring("Searching Florid Root...\n");
|
||||
terminal_writestring("/boot /sys /kernel /mofi_data\n");
|
||||
}
|
||||
|
||||
void handle_obliterate(char* target) {
|
||||
terminal_writestring("OBLITERATING: ");
|
||||
terminal_writestring(target);
|
||||
terminal_writestring("... SUCCESS.\n");
|
||||
}
|
||||
|
||||
void handle_install() {
|
||||
terminal_writestring("Searching for target disk...\n");
|
||||
terminal_writestring("Formatting /dev/sda as FloridFS...\n");
|
||||
terminal_writestring("Copying kernel bytes... [##########] 100%\n");
|
||||
terminal_writestring("Installation complete. Remove Live CD and reboot.\n");
|
||||
}
|
||||
|
||||
/* --- The Interpreter (The If/Else Chain) --- */
|
||||
|
||||
void interpret_command(char* cmd) {
|
||||
if (strcmp(cmd, "fds") == 0) {
|
||||
handle_fds();
|
||||
}
|
||||
else if (strcmp(cmd, "frua") == 0) {
|
||||
terminal_writestring("ROOT ACCESS GRANTED.\n");
|
||||
}
|
||||
else if (strcmp(cmd, "mofi") == 0) {
|
||||
run_mofi();
|
||||
}
|
||||
else if (strcmp(cmd, "install") == 0) {
|
||||
handle_install();
|
||||
}
|
||||
else if (startswith(cmd, "obliterate ")) {
|
||||
handle_obliterate(cmd + 11);
|
||||
}
|
||||
else {
|
||||
terminal_writestring("Unknown command. Try 'fds' or 'install'.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void shell_init(void) {
|
||||
terminal_writestring("Florid Shell Initialized.\n");
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef SHELL_H
|
||||
#define SHELL_H
|
||||
|
||||
void shell_init(void);
|
||||
void interpret_command(char* input);
|
||||
|
||||
#endif
|
||||
33
FloridOS/src/userspace/bridge/loadable.c
Normal file
33
FloridOS/src/userspace/bridge/loadable.c
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* src/userspace/bridge/loadable.c - Universal FPF Binary Wrapper
|
||||
* Compile your app logic alongside this file to output a valid .fpf package.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "../../include/fpf.h"
|
||||
|
||||
// Forward declaration of the user's actual main function
|
||||
extern int florid_main(void);
|
||||
|
||||
// Force the compiler to place this header at the very beginning of the binary
|
||||
__attribute__((section(".fpf_header"), used))
|
||||
const fpf_header_t __app_header = {
|
||||
.magic = {'F', 'L', 'O', 'R'},
|
||||
.version = 1,
|
||||
.type = FPF_TYPE_DE, // Setting to DE so it can draw the Bloom menu
|
||||
.flags = 0x08, // FPF_FLAG_FRAMEBUFFER_OWN
|
||||
.entry_point = 0, // Offset from start of code section
|
||||
.stack_size = 1024 * 1024, // 1MB stack request
|
||||
.heap_size = 1024 * 1024 * 16, // 16MB heap request
|
||||
.signature = {0} // Unsigned demo
|
||||
};
|
||||
|
||||
// The raw entry point called by the kernel loader
|
||||
void _start(void) {
|
||||
// Jump to the application logic
|
||||
florid_main();
|
||||
|
||||
// If the app exits, trap the CPU so it doesn't execute garbage memory
|
||||
while(1) { __asm__ volatile("hlt"); }
|
||||
}
|
||||
36
FloridOS/src/userspace/launcher/main.c
Normal file
36
FloridOS/src/userspace/launcher/main.c
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* src/userspace/launcher/main.c - Bare-metal Demo Launcher
|
||||
* Proves execution handoff by drawing the White Pill interface.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Hardcoded Limine Framebuffer address for fast demo testing
|
||||
// (In a full build, the kernel passes this via syscalls/shared registers)
|
||||
#define FB_ADDRESS 0xffff800000000000 // Replace with your Limine FB base if mapped static
|
||||
|
||||
int florid_main(void) {
|
||||
// Let's pretend the kernel mapped the FB directly for us
|
||||
uint32_t* screen = (uint32_t*)FB_ADDRESS;
|
||||
int width = 1920; // Standard assumption for demo
|
||||
int height = 1080;
|
||||
|
||||
// Draw the Taskbar Background at the bottom (Height: 60px)
|
||||
for (int y = height - 60; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
screen[y * width + x] = 0x111111; // Darker taskbar base
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the "White Pill" on the far left (X: 20 to 100, Y: height-45 to height-15)
|
||||
for (int y = height - 45; y < height - 15; y++) {
|
||||
for (int x = 20; x < 100; x++) {
|
||||
// Simple visual rounding: cut the absolute corners
|
||||
if ((x < 25 || x > 95) && (y < height - 40 || y > height - 20)) continue;
|
||||
screen[y * width + x] = 0xFFFFFF; // Pure white pill trigger
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
44
FloridOS/src/userspace/terminal/main.c
Normal file
44
FloridOS/src/userspace/terminal/main.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#include <stdint.h>
|
||||
|
||||
// The linker looks for _start by default
|
||||
void _start() {
|
||||
// Material 3 Surface Color
|
||||
uint32_t m3_surface = 0x1C1B1F;
|
||||
|
||||
// Pointer to framebuffer (Assuming it's mapped to 0xFD000000 or provided by bootloader)
|
||||
// For a real test, we just loop to keep the CPU busy so it doesn't crash
|
||||
while(1) {
|
||||
__asm__("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_main() {
|
||||
// In a real FPF, the kernel passes the framebuffer info.
|
||||
// We'll assume a standard 1920x1080 mapping for this demo.
|
||||
uint32_t* fb = (uint32_t*)0; // This would be mapped via syscall in a finished build
|
||||
|
||||
int term_width = 800;
|
||||
int term_height = 500;
|
||||
int start_x = 100;
|
||||
int start_y = 100;
|
||||
|
||||
// 1. Draw Terminal Window Shadow/Outline
|
||||
for (int y = start_y - 2; y < start_y + term_height + 2; y++) {
|
||||
for (int x = start_x - 2; x < start_x + term_width + 2; x++) {
|
||||
// fb[y * 1920 + x] = M3_OUTLINE;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Draw Terminal Surface
|
||||
for (int y = start_y; y < start_y + term_height; y++) {
|
||||
for (int x = start_x; x < start_x + term_width; x++) {
|
||||
// fb[y * 1920 + x] = M3_SURFACE;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Draw Mock "Prompt" line
|
||||
// [ > _ ]
|
||||
for (int i = 0; i < 10; i++) {
|
||||
// Pixel logic for a cursor
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue