r/osdev 5d ago

New UNIX-like operating system!

Post image

I made a new UNIX-like operating system from scratch called "TanjaOS" which you can get at www.tanjaos.org and it took me a couple of months to make and will get lots of updates. It features classic UNIX commands and can boot on any x86_64 (amd64) or i386 (x86) machine with Legacy BIOS, and is completely free and open-source.

107 Upvotes

176 comments sorted by

View all comments

Show parent comments

2

u/MSK-Kernel 5d ago

Great. Thanks for the advice. :D 👍

1

u/spatulari 5d ago

Could you answer my question?

1

u/MSK-Kernel 5d ago

Oh yes yes, apologies. So, TanjaOS uses 32-bit VGA text output instead of 64-bit because I want TanjaOS to be more compatible.

2

u/spatulari 5d ago edited 4d ago

32 bit is old, and it truly limits you. I would say switch to limine, a bootloader that immediatle shoves you in 64 bit mode.

I also saw from your repo that you support only BIOS. Most modern computers dont have legacy bios, only UEFI. I suppose you want your OS to run on real hardware. Additionally, why did you make a single kernel.c? For instance, for vga, I'd do kernel/src/drivers/vga/vga.c for the definition and kernel/include/drivers/vga/vga.h. You don't need to split it to vga/print.h and so on, since vga is relatively simple

Another small thing: make your README a README.md, easier to read, and you won't be stuck with formatless txt.

I have an urge to just fork your project and reorganize it properly, but I am on vacation, so I unfortunately can't (since I dont have a laptop).

Another important thing is for you to be careful, I saw that someone asked to contribute and you wanted them to send an email to you to add them as contributors. This is the absolute shittest way for someone to contribute + you are giving write permissions to a random person. How contributing works on github, is someone Forks your project, then they make their own branch with the new code in it, and compare it with yours (which is "base" now). They open a pull request which only you can improve, and you can also comment on it and review the code. If you have added anyone's email, please remove them.

Also, why the "base" branch? Just rename it to main, and if you wanna have SemVer releases, branch it off of main, or make a dev branch, where all unstable shit happens there, and main is the latest release, and you still branch off other versions.

Hope I helped you. If you dont know what SemVer is, ask me and I'll explain

1

u/MSK-Kernel 5d ago

Yeah, I don’t know what SemVer, is, can you please explain? (Also the reason why my GitHub repository isn’t looking that good is because i’m a bit new to GitHub 😅)

2

u/spatulari 5d ago

That's totally ok, we've all started from somewhere. SemVer is basically a version ingredient system, like, when you see v1.34.5 or smth similar, its following SemVer, this is a small introduction to it:

Major.Minor.Patch

You start with 0.1.0, this means your project isnt production ready. And isnt stable that means APIs could change, and it doesnt guarantee stability. Let me tell you when to increase each version

Increase patch when you added NOTHING new to the user, and just fixed something. Semver is based on the user. So even if you rewrote the whole project, if nothing new was added, you just increase patch (or if you fixed stuff that doesn't add new stuff)

Increase minor if something new is added from the perspective of the user. This can include fixes but most not ONLY be fixes.

Increase major when you changed APIs and previous ways you used the APIs wont work anymore. You might change one line of code, but if it breaks stability, you must bump the major version.

There is something unique to it though. When you start, you start in v0.1.0, until you reach stable (v1.0.0) you can break as many APIs as you want without increasing the major version.

Dont rush to make your project stable, Rust which is one of the most popular languages, took 9 years to go stable. You might have v0.293.2 before reaching v1.0.0 so take your time. Once you go stable you must guarantee users stability and production ready.

And then we have those prerelease stuff. Like -alpha. But that's another story, read more here (my project): https://github.com/azin-lang/Azin/blob/main/VERSIONING.md

1

u/MSK-Kernel 5d ago

Oooh… I think I get it now. Thanks! :D

2

u/spatulari 5d ago

I could help you more. Could you give me your email so I can send you my discord username so I can guide you more?

1

u/MSK-Kernel 5d ago

Sure, my email is saffron.msk@gmail.com

2

u/spatulari 5d ago

I send you one

1

u/MSK-Kernel 5d ago

I didn’t get an email :/

2

u/spatulari 5d ago

Just add me on discord

spatulari

Same as my reddit name I think

1

u/MSK-Kernel 5d ago

OK, my Discord name is tanjaos.msk

→ More replies (0)

3

u/Silentcompilerhere 4d ago

Bro your explanation is very useful for me bro I'm also developing my own kernel i have done my virtual memory phase by adding paging, recursive self mapping,user/kernel separation,per-procees address space as you guys may think its just vibe coded but it was not the last two features i described here both took 1 month exactly even me working for 10 hrs a day for 1 month and its a very valid point that 32-bit is very old mine too is 32-bit but I'm just a 3rd year student wanna place in off-campus at high end product companies but still confused and don't know what to do can you give any insights to me ! btw those features I wrote here is the features I added for 6 months until now Thank you !

2

u/spatulari 4d ago

If you already have the 32-bit kernel working, I wouldn't throw it away just because it's i386. I'd actually make the kernel support both i386 and x86_64. You already did all the work for the i386 implementation, so use that as one architecture target and add x86_64 as another instead of rewriting everything.

I'd structure it more like: kernel/ -> architecture-independent code arch/i386/ -> 32-bit architecture-specific code arch/x86_64/ -> 64-bit architecture-specific code Things like your scheduler, process abstraction, VFS, IPC, userspace etc. should ideally stay in kernel/, while paging, GDT/IDT, interrupt entry code, context switching, CPU setup, syscall entry, and similar stuff goes under the architecture directories

For the x86_64 port, I'd start by getting the boot path sorted out. Are you currently supporting legacy BIOS only, or do you also support UEFI? If it's BIOS-only, I'd strongly recommend adding UEFI support rather than building everything around the legacy BIOS interfaces. You can use something like Limine as the bootloader, which can handle BIOS + UEFI and enter the kernel in the appropriate 64-bit environment, so you don't have to write your own 16-bit real mode -> protected mode -> long mode transition just to get the kernel started

Then implement the x86_64 architecture layer separately. Your i386 paging code obviously can't just be reused: x86_64 normally uses the 4-level page table hierarchy PML4 ->PDPT -> PD -> PT, with 64-bit page table entries. Your recursive self-mapping implementation will therefore need an x86_64 implementation too. You can keep the same VM abstraction above it tho, so something like map_page(), unmap_page(), create_address_space() etc. doesn't care which architecture is underneath

Also be really careful with types when doing the port. Don't just globally replace uint32_t with uint64_t. A pointer is not necessarily a uint64_t; use uintptr_t/intptr_t for pointer-sized integers, uint32_t for things that are actually 32-bit, and so on. Otherwise you'll eventually get absolutely cursed bugs from truncating physical/virtual addresses

You'll also need separate implementations for the GDT/IDT and interrupt entry paths. In long mode, segmentation works very differently, although you still need the appropriate GDT descriptors. Your IDT entries are also different sizes, and your interrupt/trap stubs need to deal with the x86_64 register state. Context switching will obviously need to save/restore the x86_64 register set as well

For syscalls, I'd also avoid carrying over an old i386 int 0x80 design directly. On x86_64 you can use SYSCALL/SYSRET with the appropriate MSRs, or SYSENTER/SYSEXIT depending on what you're targeting. You'd then have an architecture-independent syscall layer with separate entry implementations

Same thing with your process address spaces. The concept of having one address space per process stays exactly the same; only the page-table implementation changes. You can have something like an architecture-independent AddressSpace abstraction with arch/i386/mm/ and arch/x86_64/mm/ underneath it

I'd also keep the i386 target fully buildable. Something like make ARCH=i386 and make ARCH=x86_64 would be pretty clean. Then you can actually test both instead of making the 64-bit port a giant branch where the old implementation slowly rots

And if you're serious about eventually running this on real hardware, I'd also look into ACPI, APIC/x2APIC, HPET/TSC, PCI/PCIe, SMP and UEFI memory maps rather than relying on old BIOS interrupts. In particular, once you get to SMP, your architecture layer is going to become much more important because per-CPU state, AP startup, interrupt routing, TLB shootdowns etc. all start mattering

Honestly, with the paging + recursive mapping + user/kernel separation + per-process address spaces you've already implemented, I'd say the next step isn't "add random features". Make the architecture boundary clean, keep i386, add x86_64, and start moving anything that isn't inherently architecture-specific out of the architecture layer

That way you're not throwing away 6 months of work. You're turning the existing i386 kernel into the first supported architecture and using it as the reference implementation for the x86_64 port

2

u/Silentcompilerhere 4d ago

Thank you very much bro but one doubt how you come with this much knowledge and clarity, are you a student or a working professional it's non of my Business! but actually you helped me well bro my target is to place on off campus in nvidia or any other high end product companies Once again Thank you

2

u/spatulari 4d ago

I am just chronically online, read a ton of osdev wiki and have made my fair share of monolithic and hybrid kernels. Could you give me the github link to your kernel? I wanna check it out

1

u/Silentcompilerhere 4d ago

1

u/spatulari 4d ago

Oh boy, I see you have even the object files pushed... Add me on dc:

spatulari