#FennecOS

1 messages · Page 1 of 1 (latest)

agile bear
#

This is FennecOS, a small 32-bit x86 operating system.

Currently there isn't much to showcase as I'm just getting started, but I'm creating this post here so I can document my progress somewhere :3
I don't plan on making this OS be Unix-like or POSIX-compatible. Also, currently everything runs in ring 0 and I will most likely keep it that way because something about that is just really charming to me.

Current features include:

  • Very basic IDE disk support
  • RAM disk support (currently broken lol)
  • FAT12/16/32 support via the FatFS library (planning on writing my own FAT driver once the rest of the OS is more mature)
  • Very basic ELF binary parsing and executing

Planned features include: (off the top of my head)

  • Event queue system, which will be the main mechanism for passing messages around the OS
  • VFS layer on top of the FAT driver
  • Floppy support

https://github.com/ry755/fennecos

GitHub

FennecOS - a small 32-bit x86 operating system. Contribute to ry755/fennecos development by creating an account on GitHub.

#

also if anyone wants to help convert the horrible build scripts into a more standard makefile, i would really appreciate it 🙏

strong jetty
#

i will do that right now

molten phoenix
#

Cool project, what bootloader are u using

#

wait i will look up into the code

#

my man good old grub

agile bear
#

yeah in my older osdev projects i typically made my own bootloader (since i was using a homemade filesystem) but for this one i decided to just go the easier route so i could focus more on the OS itself :p

molten phoenix
agile bear
#

yeah exactly

molten phoenix
#

i prefer to use grub in all of them

agile bear
#

plus this way i can use multiboot to set a vesa video mode for me

molten phoenix
#

yesss that's very handy

#

anyways cool project i will give a star

agile bear
#

thanks :3

molten phoenix
#

also do you have an psf font loader

#

?

#

nvm see it

agile bear
#

no it currently just loads a bitmap font from a raw binary on disk

molten phoenix
#

wait i really do recognise that font

#

it's smth from gnu i think

agile bear
#

yeah its gnu unifont

molten phoenix
#

got it, i thought about it

strong jetty
#

i havent used a bash build system in so long this looks like witchcraft to me now

agile bear
#

heh yeah its absolutely terrible

#

it was something i quickly hacked together when i was first getting started and i just never changed to a makefile because i dont really know how to use make

#

as in, event queue, cooperative multitasking, and just general code layout

#

this is my first time doing any real osdev in C instead of assembly

strong jetty
#

yeah ive seen fox32

#

it looks pretty good

agile bear
#

oh yeah youre in the discord server

agile bear
#

welp, i just tried booting it on my ThinkPad 390E but it just does this and then reboots after about 30 seconds

strong jetty
#

the joy of real hardware

agile bear
#

and since i dont currently have a way to connect to the ThinkPad's serial port, i have no idea how far it got :p

brave glade
#

oh i've been there

#

made a long delay function and used characters on the screen for seeing how far i got

agile bear
#

the problem here is that grub apparently isnt even setting the video mode correctly :p

#

its still in text mode in that photo

#

maybe this laptop doesnt support 640x480 @ 32bpp?

brave glade
#

pretty sure grub should be trying to use any other mode then

agile bear
#

yeah thats what i thought

#

hmm

brave glade
#

if it can't find any iirc it will spit out an error

brave glade
agile bear
#

oh interesting

glass dove
#

you could try running a simpler hello world multiboot kernel to check if grub is doing something

agile bear
#

i know this laptop supports 640x480 vesa, ive used it before with 256 colors

brave glade
#

you could try booting vix troll

agile bear
#

also the way im attempting to boot this is via a grub floppy disk with the OS's resource files (/res/font.bin, etc) copied to the hard disk

#

this grub floppy is using an old version of grub, like 0.94 or 0.97 or something

brave glade
#

do you ever even get to see the grub menu?

agile bear
#

yeah i get to grub and i use the command line to enter

kernel /boot/fennecos.elf
boot
#

it apparently understands the multiboot header because the kernel command spits out some info like where its loading the kernel in memory, and it looks correct

agile bear
#

eh, i'll keep debugging this later, i want to get back to working on the OS itself :p

bleak quail
#

is booting off a floppy that important to you? because if not i'd run away from grub legacy

#

as fast as possible

agile bear
#

haha

#

i mean, i do want this OS to target older systems, so booting off of a floppy would be nice

bleak quail
#

its honestly possibly a better idea to write a multiboot shim bootsector/loader manually for floppies than it is to use old unmaintained grub

#

one of the few instances when writing a bootloader isn't necessarily a bad idea

agile bear
#

yeah :p

bleak quail
#

that or using some other updated bootloader which supports floppies which doesn't suck, which i don't know any of

agile bear
#

yeah i'll probably just end up making my own little bootloader if/when i eventually add real floppy support

bleak quail
#

nice

agile bear
#

but yeah im one of the weird ones who likes targeting old hardware hehe

#

no uefi for me

agile bear
#

"i love failing to map virtual memory! it's my favorite thing to do in my free time!" - my kernel

woeful thicket
#

i need to get my github clout up

agile bear
#

oh nice, thanks

rare violet
agile bear
#

hi lua :3

#

(this is my gf and shes helping with some parts of the OS)

rare violet
#

i get to watch him suffer to implement paging! hooray!

#

<-- going to write a nice allocator for the kernel

bleak quail
#

cute

amber frost
whole osprey
#

probably could work

amber frost
#

@agile bear where'd you get a cross compiler for this? did you build one yourself?

iprogramincpp@IPROGRAMINCPP:/mnt/z/projects/fennecos$ ./build.sh
./build.sh: line 113: /home/iprogramincpp/opt/cross/bin/i686-elf-as: No such file or directory
iprogramincpp@IPROGRAMINCPP:/mnt/z/projects/fennecos$
amber frost
sudden spire
#

will this become the basis of a port to fox32 for some future fox32os?

whole osprey
#

there's no fox32 c compiler yet

#

atleast a usable one

agile bear
#

feel free to install it to some other location and then just adjust the TOOLCHAIN_PATH variable in the build script

agile bear
strong jetty
#

jt does do that yes

#

but would you not want it as a uint64_t

agile bear
#

but this runs in protected mode, not long mode

amber frost
#

the problem is that you are declaring a variable after a label

#

not sure how this compiles on your end

agile bear
#

ohhhhhhhhh

#

gcc never complained about it :p

strong jetty
amber frost
#

it's probably supported by some GNU extension

#

you'd ideally want to do something like:

case 0xE:
{
    uint32_t virtual_address;
    //...
    break;
}
agile bear
#

yeah, i'll fix that, thanks

agile bear
agile bear
#

doing somewhat cursed things, im making all processes have the framebuffer mapped at 0xF0000000 :)

#

because like. i dont really want to have dedicated sycalls for drawing into the framebuffer

#

this means i can move the font rendering code out of the kernel and into a "userspace" library

#

("userspace" in quotes because everything runs in ring 0)

strong jetty
#

couldnt a process just make the screen always filled with some particular color

agile bear
#

yeah, there would be nothing there to stop that

strong jetty
#

i mean i guess if you have everything in ring0 for whatever reason thats the least of my concerns

agile bear
#

hehe

strong jetty
#

why have everything in ring0?

agile bear
#

two reasons:

  1. simplicity, im still learning how x86 works so this makes things slightly easier
  2. something about having no security is just really charming to me. this is a toy kernel and it doesnt really need to have security
agile bear
#

working on implementing more syscalls, currently i have exit(), yield(), open(), read(), write(), new_event(), and get_next_event()

#

here is the source code for the demo in that screenshot:

#include <user/user.h>
#include <user/framebuffer.h>
#include <user/keyboard.h>

#include <stdbool.h>

event_t event;
file_t file;
bool running = true;

void _start() {
    draw_string("demo - press ESC to exit", 16, 16, 0xFFFFFFFF, 0xFF123456, global_font);

    char file_buffer[512] = { 0 };
    if (open(&file, "1:/res/hello.txt", MODE_READ)) {
        read(&file, file_buffer, 512);
        draw_string(file_buffer, 16, 32, 0xFFFFFFFF, 0xFF123456, global_font);
    } else {
        draw_string("failed to open 1:/res/hello.txt", 16, 32, 0xFFFFFFFF, 0xFF123456, global_font);
    }

    while (running) {
        if (get_next_event(&event)) {
            switch (event.type) {
                case KEY_DOWN:
                    draw_string("key down", 16, 48, 0xFFFFFFFF, 0xFF123456, global_font);
                    keyboard_event(event.arg0);
                    draw_font_tile(scancode_to_ascii(event.arg0), 16, 64, 0xFFFFFFFF, 0xFF123456, global_font);
                    break;

                case KEY_UP:
                    draw_string("key up  ", 16, 48, 0xFFFFFFFF, 0xFF123456, global_font);
                    keyboard_event(event.arg0);
                    draw_font_tile(scancode_to_ascii(event.arg0 & 0x7F), 16, 64, 0xFFFFFFFF, 0xFF123456, global_font);
                    if (event.arg0 == 0x81)
                        running = false;
                    break;
            }
        }
        yield();
    }
    exit();
}
#

discord kinda fucked up the formatting so heres a screenshot instead :p

#

the filesystem calls are abstracted through a (very simple atm) VFS layer

amber frost
#

why a cooperative one?

agile bear
#

its just the style that i like i guess. im very inspired by classic Mac OS

amber frost
#

it's not even that much harder, a basic idea is to just forcefully yield in a timer interrupt

agile bear
#

true

#

i might end up doing that, idk

amber frost
#

the timer interrupt saves your registers anyway because it has to, and you just call yield() within the function as long as you can deal with interrupts being disabled there

agile bear
#

yeah

agile bear
#

it worked well enough in my other OS so i figured i'd try implementing it in this one too, but in C this time

amber frost
#

Win32 and SDL also have event queues

agile bear
#

interesting

#

yeah its probably a lot more common than i realized :p

agile bear
#

also currently experimenting with making an actual console/terminal

amber frost
agile bear
#

update on the ThinkPad situation, i installed grub 2 to the hard disk and now it boots properly, the issue now is that it looks like it doesnt support 32 bit color so its putting it into the closest match video mode

#

(ignore the red line going down the right side of the screen, thats a hardware issue)

#

my kernel assumes 32 bit color so things break here :p

#

i know the multiboot struct passes info about the video mode it set but at the moment im not really sure how to go about supporting multiple framebuffer pitches in a clean way

agile bear
#

alright so i rewrote some of the framebuffer code so that it can support both 32 bpp and 24 bpp, since the ThinkPad is using 24 bpp. i tested it in qemu with both 32 bpp and 24 bpp modes and it works

#

but now the issue is that grub on the ThinkPad is actually reporting it as 240 bpp instead of 24 bpp lol

#

is this like, a known vesa issue with some devices? i cant find anything about this online

agile bear
#

WOOOOO

#

dont mind the weird font aliasing (or whatever its called), thats just a weird artifact of this display's scaling

amber frost
#

also, for my OS I have decided to not bother at all with color that isn't 32-bit. I hate 24-bit color in particular

#

It doesn't "waste" a byte like 32-bit color does but it's much slower because the data isn't aligned

agile bear
#

i'd definitely only support 32 bit color too if all of my test hardware supported it

amber frost
#

I've run into the same issue on 86box but I decided to, again, not bother

#

Since it would make my graphics slower

agile bear
#

starting to work on a simple shell with help from @rare violet
also while taking this screenshot i just ran into a funny bug where the shift key state gets stuck :p

#

there we go, shift bug fixed

amber frost
#

like a "b c" d => "a", "b c", "d"

agile bear
#

yes, i will get to that

agile bear
#

current state

strong jetty
#

do you have a libc?

agile bear
#

at the moment im just rolling my own as i go along but i do want to try porting newlib or mlibc or something

strong jetty
agile bear
#

not yet :p

strong jetty
#

ah i see

glass dove
#

you'd have to ask lapfed

agile bear
#

oh right mlibc is 64 bit only, i forgot about that

whole osprey
#

what about musl

agile bear
#

ive heard musl is really linux-specific

whole osprey
#

it can be customized

#

to be less linux centric

#

some hobby oses did it

#

musl is a pretty solid libc

#

it supports almost every single applications in existence

#

it should be easy enough to make it work for your os

ionic barn
ionic barn
ionic barn
#
_Noreturn void _Exit(int ec)
{
    __syscall(SYS_exit_group, ec);
    for (;;) __syscall(SYS_exit, ec);
}
#

i love some good inline syscalls

sudden spire
warped nimbus
#

alternatively there's glibc

whole osprey
#

💀

amber frost
#

@agile bear what is this

uint8_t *framebuffer = (void *) 0xF0000000;
uint32_t *framebuffer_pitch = (void *) 0xF012C000;
uint8_t *framebuffer_bpp = (void *) 0xF012C004;
whole osprey
#

oh god

#

why

agile bear
#

a dirty hack :)

bleak quail
bleak quail
bleak quail
bleak quail
warped nimbus
#

that's a very low bar tho

bleak quail
#

mlibc is very good at being portable

#

what it isn't good at is at not having a group of people bitch about getting patches merged in (when they touch more than something trivial)

sudden spire
#

tips fedora m'libc

ornate grove
#

lol

jaunty eagle
jaunty eagle
tribal river
agile bear
#

nice!

agile bear
#

oh btw floppy support is now implemented, disk 2: is the floppy drive

agile bear
#

i had a sudden burst of motivation to learn the zig language and tbh i kinda want to try rewriting FennecOS in zig as a way to learn it

#

the codebase is small enough to where i could probably rewrite it in zig in just a couple hours, learning zig along the way

whole osprey
#

cool

#

i'm a kinda experienced zig programmer

#

i have rewritten my os (faruos) in zig too

#

i probably can help

molten phoenix
#

nice work

#

this os will be good i bealive in it

agile bear
#

thank you :3

warped nimbus
#

just way better metaprogramming and fixing a few warts

agile bear
#

yeah

#

zig kinda seems like budget rust in a way

#

i was reading up on it last night and translating a few minor parts of my kernel into zig

#

i do like the fact that its build system is more integrated, similar to rust

warped nimbus
#

though i like the metaprogramming a lot, that i have to say

agile bear
#

im not very familiar with metaprogramming as a concept so i dont really have anything to say about that

ionic barn
#

metaprogramming is great

molten phoenix
#

what's metaprogramming

strong jetty
#

it makes your code write code

agile bear
#

i wish zig's documentation was better. it feels very lacking compared to what im used to with rust

#

but i mean its understandable considering the language is still very young

strong jetty
#

rust is my nemesis

molten phoenix
molten phoenix
strong jetty
#

i just dont really like it

#

i dont see much that it would give me that would help me write code

molten phoenix
#

i know lot's of languages and tbh rust is a good language but u need to know how to use it properly, it have lots of cool features

strong jetty
#

so far i havent really seen any cool features that outweigh the reasons i like c/cpp

agile bear
#

i think my favorite thing about rust is just its syntax tbh, the language itself (borrow checking, etc) is kinda annoying to work with sometimes but it still just feels nice to write

#

(imo)

strong jetty
#

i hate rust syntax tbh

#

c/cpp syntax i much prefer

agile bear
#

anyways, currently im just trying to figure out zig's build system lol

molten phoenix
molten phoenix
strong jetty
#

i dislike the parts that differ from c/cpp

#

like let mut x: &int

#

int& x much nicer

molten phoenix
#

not every language needs to be this same as c/cpp i like when a language looks different

#

like nim it's a cool language i known about it for a while but just tomorrow tested it

strong jetty
#

different doesnt instantly been i like it

#

idk i just dont like rust syntax

#

and also i still fail to see any of the benefit it provides for the programmer

#

but i have only written a few things in it so far

agile bear
#

lets just leave it at the fact that everyone has their own favorite language, different people prefer different things

agile bear
#

or maybe theres a better way to do this. basically what i want is for the kernel elf binary to be copied from the zig-out/bin directory into my sysroot directory for when the disk image gets created

#

this is currently what my build.zig looks like```cpp
pub fn build(b: *Builder) !void {
// define a freestanding x86 cross-compilation target
var target: std.zig.CrossTarget = .{
.cpu_arch = .x86,
.os_tag = .freestanding,
.abi = .none,
};

// disable CPU features that require additional initialization
// like MMX, SSE/2 and AVX. that requires us to enable the soft-float feature
const Features = std.Target.x86.Feature;
target.cpu_features_sub.addFeature(@enumToInt(Features.mmx));
target.cpu_features_sub.addFeature(@enumToInt(Features.sse));
target.cpu_features_sub.addFeature(@enumToInt(Features.sse2));
target.cpu_features_sub.addFeature(@enumToInt(Features.avx));
target.cpu_features_sub.addFeature(@enumToInt(Features.avx2));
target.cpu_features_add.addFeature(@enumToInt(Features.soft_float));

// build the kernel itself
const optimize = b.standardOptimizeOption(.{});
const kernel = b.addExecutable(.{
    .name = "fennecos.elf",
    .root_source_file = .{ .path = "kernel/src/main.zig" },
    .target = target,
    .optimize = optimize,
});
kernel.code_model = .kernel;
kernel.setLinkerScriptPath(.{ .path = "kernel/linker.ld" });
kernel.addAssemblyFile("kernel/src/boot.s");
const kernel_copy_cmd_str = &[_][]const u8{ "/bin/sh", "-c", "cp", "zig-out/bin/fennecos.elf", "base_image/boot/fennecos.elf" };
kernel.step.dependOn(b.addSystemCommand(kernel_copy_cmd_str));
b.installArtifact(kernel);

}

but it says that `kernel.step.dependOn` expects a \*Build.Step, but `b.addSystemCommand` is passing it a \*Build.RunStep instead. and i dont understand the difference lol
#

basically all of the examples that im finding online are outdated because zig changes so frequently (im using 0.11.0-dev, the latest master build)

molten phoenix
#

crazy

agile bear
molten phoenix
#

why the gdt ptr is an extern struct instead of packed

agile bear
#

because in order to export gdt_ptr, the struct needs to be extern. but from what i understand, extern implies packed? at least thats what i gather from the docs. it doesnt allow both extern and packed on the same struct anyways
https://ziglang.org/documentation/master/#extern-struct

#

(gdt_ptr must be exported in order for it to be visible from within boot.s)

whole osprey
whole osprey
molten phoenix
whole osprey
#

repo settings

agile bear
molten phoenix
agile bear
#

alright changing gdt_ptr to a packed struct and moving flush_gdt into the zig file fixed it. i bet the issue was actually just with the struct. extern structs probably dont behave exactly like packed structs like i expected

warped nimbus
#

@agile bear extern structs in zig are repr(C) in rust

#

so they are laid out like c with no packed attribute would

agile bear
#

ohhh

#

that makes sense

#

its interesting that it doesnt let you create an extern and packed struct then

#

only one or the other

whole osprey
#

extern is the equivalent of struct {} type_name in C

#

packed is the equivalent of struct {} __attribute__((packed)) type_name in C

agile bear
#

yeah

agile bear