Page 1 of 3

Citadel Design... so far.

Posted: Mon May 22, 2006 8:01 pm
by elderK
Hey all, Im Zeii! *waves*
Im the enigmatic coffee-slurping cigarette snarfing codemonkey that youll see lurking around here often.

Anywho, onto my project - which I have codenamed Citadel.
Ive written a basic Monolithic Citadel kernel, it has basic Exception handling, aswell as being in Protected mode.
It can output text in protected mode, including translating Integer and Hexidecimal numbers into Strings for output.

Anywho, the point im trying to get to is quite simply this...
I dont think my current setup and design is very good.

*screws up Citadel Design A, throws into Cyberspace*
*gets paper, entitled Citadel Design B*

Im going to write a much more advanced bootloader,
this time - I want it to enter protected mode, and setup a decent GDT list.

Im yet to research the GDT fully.
However, Id appreciate it if anyone would explain why there should be a GDT entry for Interrupts?

anywho, onwards.
The bootloader will also establish a basic filesystem (probably Fat12/32 or something).

I want to make a Microkernel.
From research (mainly Wikipedia and OS FAQ), A Microkernel only supplies 'basic' (I use that word... sarcasticly) services.
Thread control, Memory management, Inter process communication?

The rest, apparently, is all done outside of Kernel code through Servers. Obviously, I want my kernel to eventually be Multitasking.

So, for the next couple days these are my goals:
- A new bootloader.
- Bootloader will detect if the floppy-sector-read fails,
(due to lack of floppy disk in the drive, or just a random
read error.
- Setup a 'real' GDT table.
- Null Selector?
- Code Selector?
- Data Selector?
- Interrupt Selector?
- TSS Selector?
- Im not sure what else I need, If someone would
mind teaching me about the other selectors, id be
grateful.
- Maybe setup a LDT?
- Setup a basic filesystem, Im planning on implementing
something I can mount from within Linux.
This is for several reasons, first off - I want to be able
to update the Kernel simply by dragging KERNEL.BIN onto
the floppy. Also, I want to have basic filesystem support
so I can say 'load kernel', then once thats loaded, the
Kernel can simply say 'load XXX server'

Im not entirely sure what functions I should have in the kernel_main(), but I know I need to implement:

kmalloc / kfree
kmemset / kmemcpy
kprintf
ksetcursor
kclrscr
koutportb
kinportb

In order to implement Printf, Ill need to implement a Variable Argument list system. More research!

Anyone interested and would mind helping - what other in kernel functions should I have?

Keyboard input, etc - will be done by the Input Server.

Basically, I wouldnt mind making something along the lines of BeOS, but... simpler.

It doenst matter if its slow... this is primarily a learning excersize.

Thanks!
~zeii
PS: My hotmail is : [email protected].
If you have MSN, and would like to talk to me in real time, feel free to add me!

Re:Citadel Design... so far.

Posted: Mon May 22, 2006 10:49 pm
by Ryu
If you can do that within a couple of days great! But I have been one of those people who didnt know things such as a Interrupt Vector Table from the start of my project. So it has been a rough ride and I know how it will be for your end. Most things you read will have something associated or some sort of constraint to them. The key is to focus on one matter before you move onto the next. For instance, you need to set a descriptor in the IDT for interrupts not GDT. So I suggest throughly reading about GDT's or the IDT before moving on. Doing this will allow you to then model your goals more progressively and leaving less chances of having to redoing things in the future. But this is just my way of doing things.

Its good that you have an idea of what first protocalls you should have within your kernel, however a single call such as kmalloc will lead to ultimatly your memory manager, which is quite a huge topic. Same goes with handling I/O ports and mapped I/O leading to PCI relations and having to enumerate them to find what ports are in use. You may find yourself in a situation that simular to mine where you need to write up some standard C routines such as memcpy, atoi, and etc.. which will further consume time, in fact its quite heart breaking to say, after about 2 months of time I've only just finalizing my memory manager.

Re:Citadel Design... so far.

Posted: Mon May 22, 2006 11:05 pm
by Brendan
Hi,
zeii wrote:The bootloader will also establish a basic filesystem (probably Fat12/32 or something).
The easiest (IMHO best) way to handle this is for the boot loader to load a "boot image" that includes the kernel, device drivers, file system code, etc. The boot image would work like a RAM disk, and means you can load everything into memory using BIOS functions and then switch to protected mode (without needing to use the BIOS or real mode after that).
zeii wrote:From research (mainly Wikipedia and OS FAQ), A Microkernel only supplies 'basic' (I use that word... sarcasticly) services.
Thread control, Memory management, Inter process communication?
It's different for different micro-kernels. Some try to have the absolute minimum possible, while others are larger. The only things that must be in the micro-kernel are IPC and things that require CPL=0 (thread switching code, low level IRQ handlers, exception handlers and not much else). My micro-kernel design has IPC, the scheduler, physical memory management, virtual memory management, low level IRQ handlers, I/O port access, ISA DMA chip access, a timer (PIT), exception handling, critical error handling and a system log.
zeii wrote:So, for the next couple days these are my goals:
How long did you spend designing "Citadel Design A" before you started writing it, and how long did "Citadel Design A" last before it went in the bin? How much time will you spend designing "Citadel Design B" before you start writing it, and how long will "Citadel Design B" last before it goes in the bin?

Most people want to start writing code straight away, but the more time you spend designing (and researching) the less time you'll spend rewriting and the longer it will last before it goes in the bin (and if you spend long enough designing/researching then it might never end up in the bin).

I'd recommend spending the next month (at least) without writing any code.... ;)


Cheers,

Brendan

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 12:38 am
by distantvoices
I 've spent as much as 9 months reading up and sketching (& meanwhile working on some oss project for the linuxprinting ppl) ere I've started to type my first lines of codes.

Well - as soon as all the pieces fit together you'll have a hard time even thinking about throwing away all your design. Instead, you'll go and iterate over it and think about how to make it better - so to say you water it and watch it growing like some fantastic plant.

Stay safe & head up.

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 3:32 am
by paulbarker
Maybe you find this strange, but what works best for me is the exact opposite of what Brendan suggests: I write a dirty implementation in a scratch directory first, then write a proper design and finally re-write the implementation into the main kernel tree.

This helps because I seem to design things which are impossible to implement. The temptation is obviously to merge the quick and dirty code into the main kernel, which I have been known to do but I'm slowly getting the discipline not to.

Obviously this is for large parts of the kernel. For simple functions I just write them without any design (eg. bcd-binary conversion needed no design). Probably not a good idea to completely skip the design phase, but I avoid doing it for anything non-trivial.

And the best advice of all - test, test, test. Whatever testing / development strategy you use, just make sure you test.

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 4:52 am
by mystran
Brendan wrote: My micro-kernel design has IPC, the scheduler, physical memory management, virtual memory management, low level IRQ handlers, I/O port access, ISA DMA chip access, a timer (PIT), exception handling, critical error handling and a system log.
How do you handle virtual memory (specifically swapout and sharing, kernel out-of-memory situations and such) without having a hdd-driver in kernel? Or is that possible in your setup?

I've got about three models so far, I don't quite like any of them... so I'd like to hear what other people do.

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 5:00 am
by Solar
zeii wrote: Im not entirely sure what functions I should have in the kernel_main(), but I know I need to implement:

kmalloc / kfree
kmemset / kmemcpy
kprintf
ksetcursor
kclrscr
koutportb
kinportb

In order to implement Printf, Ill need to implement a Variable Argument list system. More research!
Perhaps you want to check out PDCLib (see my signature). In pre-release v0.4, you will find a working if primitive implementation of malloc() / free() directly based on a page allocator, and a working <stdargs.h> (working, at least, for GCC / x86 - haven't tested other platforms yet).

In a couple of weeks v0.5 will be released, which will come with a complete printf() implementation - all you'd need then is a way to write a character string to screen.

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 7:47 am
by elderK
Thats true, I could use PDCLib, but I Would like to learn how to implement such functions myself.

Hmm. Maybe my friends are right, maybe I AM a massochist ;) lol.

Anywho, Ramdisk seems like a good idea.
And I havent read much up on Virtual Memory or Paging

I realize you need to define descriptors for the IDT, in the IDT.

However, Other sourcecode I have read has an IDT entry in the GDT aswell.
Specifying some segment and selector and such.

Im trying to find out why they would do that.
Perhaps they want it to run on a different ring?
Im unsure as current.

~Zeii

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 7:53 am
by Solar
zeii wrote: Thats true, I could use PDCLib, but I Would like to learn how to implement such functions myself.
In that case, I warmly recommend P.J. Plauger's "The C Standard Library", a book which not only documents the (C90) library, but also gives an introduction to writing one yourself.

Anyway, I hope PDCLib is clear-cut enough to be educational, too - you can replace its functions with your own ones, but you get a working start.

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 8:38 am
by elderK
Im reading through the Intel Documentation, hmm.

Im having a little trouble understanding.
Like, I know that for a Flat layout, you need a Code Selector? and a Data one?

But there are others like Multisegmented layouts.
Im not sure which to use. *sigh*

~zeii

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 9:10 am
by Midas
Taking the prerequisite GDT layout for the Intel fast syscalls (sysenter/sysexit) routines as a vaguely sane recommendation.

0x0 NULL Descriptor
0x8 DPL 0 Code descriptor
0x10 DPL 0 Data descriptor
0x18 DPL 3 Code descriptor
0x20 DPL 3 Data descriptor
[Other segments (TSSes for example)]

If you're using paging then it's probably simplest to hold a flat memory model for code and data segments with base 0GB and limit 4GB. I think this is probably the base-standard upon which people usually stand. You can then use paging to enforce code/privilege protection in here. However, I know that someone's (Candy, maybe; Pype.Clicker, maybe) OS around here uses both. You need at least one code and one data descriptor for every DPL you intend to use.

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 9:14 am
by bluecode
Solar wrote:In that case, I warmly recommend P.J. Plauger's "The C Standard Library", a book which not only documents the (C90) library, but also gives an introduction to writing one yourself.
sry for being off topic, but do you have some recommendation for the C++ Standard (german or english)? Or perhaps a good website that examines the C++ Standard Library from inside (not like cppreference.com)...

I would also keep a flat memory model. It makes things more easy..

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 9:33 am
by elderK
Thanks Midas!
Man, I wish you had IM!
Itd be really awesome to talk to you in real-time.

~Zeii.

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 9:36 am
by elderK
0x8 DPL 0 Code descriptor
0x10 DPL 0 Data descriptor
0x18 DPL 3 Code descriptor
0x20 DPL 3 Data descriptor

This is a horribly rookie question, but I must ask it regardless.

0x8, Is the 'selector'? for DPL0 Code, but... is it hardware that sets it to 0x8, or is it part of the GDT Entry for the DPL0 Code?

~Zeii

Re:Citadel Design... so far.

Posted: Tue May 23, 2006 10:15 am
by elderK
Also, is it ok if the DPL0 / DPL3 Segments have the same BASE and Limit?
Like, they overlap?

Im just curious, because if they overlap, doesnt that mean... that they will overwrite each others data?

Or does the Selector (0x10) for example, change that.
0x10:0x000000 base?
0x10:0xFFFFFF limit?

0x20:0x00000
0x20:0xFFFFF

so, Data at 0x20 is at a different place in RAM then 0x10 Data?

Also, is 0x20:0x0 that same as physical 0x020000?

In my bootloader, I have the code:

    mov ax, 10h ; Our DPL0 Data Descriptor.

    mov ds, ax ; Set Data Segment to point here.

    mov ss, ax ; The DPL0 Data Segment is writable, so set Stack Segment here too.

    mov eax, 0x020000   ; Where we want the stack.
mov esp, eax
mov ebp, eax

Is the Stack Pointer and BasePointer for the Stack, being set 0x20000 relative to the selected Data Segment?

Hmm...

~Zeii.