Compare commits

..

4 commits

Author SHA1 Message Date
0c4d84f82f
Add files via upload 2026-05-14 18:46:08 +03:00
2587677f25
Delete FloridOS directory 2026-05-14 18:44:08 +03:00
a087cb37e4
Add files via upload 2026-05-14 16:21:33 +03:00
88522a2f34
Delete FloridOS directory 2026-05-14 16:21:03 +03:00
50 changed files with 600 additions and 492 deletions

View file

@ -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
View 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.

View file

@ -1,5 +0,0 @@
TIMEOUT=3
:Florid OS
PROTOCOL=limine
KERNEL_PATH=boot:///kernel

Binary file not shown.

Binary file not shown.

View file

@ -1,5 +0,0 @@
TIMEOUT=3
:Florid OS
PROTOCOL=limine
KERNEL_PATH=boot:///kernel

View file

@ -0,0 +1,3 @@
/Florid OS
protocol: limine
kernel_path: boot():/kernel.elf

View file

@ -1,11 +0,0 @@
ENTRY(_start)
SECTIONS
{
. = 0xffffffff80000000;
.text : { *(.text .text.*) }
.rodata : { *(.rodata .rodata.*) }
.data : { *(.data .data.*) }
.bss : { *(.bss .bss.*) *(COMMON) }
}

View file

@ -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

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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]);
}
}

View file

@ -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

View file

@ -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;

View file

@ -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");
}
}

View file

View 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;
}
}

View 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"); }
}

View file

@ -0,0 +1,11 @@
OUTPUT_FORMAT(elf64-x86-64)
ENTRY(_start)
SECTIONS
{
. = 0xffffffff80000000;
.text : { *(.text*) }
.rodata : { *(.rodata*) }
.data : { *(.data*) }
.bss : { *(.bss*) *(COMMON) }
}

View 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;
}

View 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!
}

View file

@ -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");
}

View file

@ -1,7 +0,0 @@
#ifndef SHELL_H
#define SHELL_H
void shell_init(void);
void interpret_command(char* input);
#endif

View 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"); }
}

View 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;
}

View 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
}
}