Pmode
Pmode
I have just moved my kernel from borland pascal to free pascal(32 bit). Now i want to set up pmode. Do i need to set up pmode before i load the kernel from the disk? (In my case fdd). The other question is can i use pascal functions to set up my gdt and idt? The last one is how do i jump from my boot loader into my kernel
Gizmic OS
Currently - Busy with FAT12 driver and VFS
Currently - Busy with FAT12 driver and VFS
Re: Pmode
Hi,
If you have an ELF format kernel, you need to extract the entry point from the ELF header and JMP to that.
Cheers,
Adam
My preference is to load the kernel using BIOS functions. In this case, you need to load the kernel from disk before switching to PMode. Bear in mind that either your kernel will have to entirely fit in the space before the BIOS area at around 0x90000 or you will have to use unreal mode/PMode to copy the kernel to above 1MiB as you load it. You can then switch to Pmode and jump to your kernel.Do i need to set up pmode before i load the kernel from the disk?
As long as you can directly manipulate bits at known memory locations in Pascal, yes. I believe there is a Pascal barebones on the wiki and/or other people here have written Pascal kernels, so the answer must be yes.The other question is can i use pascal functions to set up my gdt and idt?
Assuming a flat binary loaded at the 1MiB mark:The last one is how do i jump from my boot loader into my kernel
Code: Select all
JMP 0x100000
If you have an ELF format kernel, you need to extract the entry point from the ELF header and JMP to that.
Cheers,
Adam
Re: Pmode
You can load your kernel either byDo i need to set up pmode before i load the kernel from the disk?
1) real mode bootloader,
2) protected mode bootloader.
In first case, you need to put [bits 16] in your kernel's ASM stub and do the whole pmode switch there. Be warned though, you must have a fully working GDT and IDT and the protected mode set up before you call the main() function!
In second case, set up your "final" GDT/IDT/ISRs, since the one from the pmode bootloader is just temporary (i think), then you can start your pascal kernel.
Theoretically yes, but use ASM routines for that, you'll get a faster code plus you'll avoid some number of strange bugs. Really. - This applies only when your kernel is loaded by pmode bootloader!!! (When in real mode you need to set up pmode in asm.)The other question is can i use pascal functions to set up my gdt and idt?
When you have the protected mode fully set up, this can be doneThe last one is how do i jump from my boot loader into my kernel
extern Your_main_function
call Your_main_function
jmp $
like in brans kernel dev. Did you read the wiki?
And, anyways, DON'T EVER THINK of using THESE METHODS in borland pascal or in borland pascal kernel as you'll just mix up 16-bit again. You need to select if your kernel wants to be in real (B. pascal), or protected mode (FP 32-bit).
Plus, when you will be setting up gdt, idt and interrupt service routines: I suggest you code them in assembly. You'll avoid a bunch of problems that way.
BTW set the compiler to the binary format. You can switch to MZ-EXE, PE or ELF when you'll understand what you can do and do not in free pascal (since it's not meant to develop a kernel, thus running without a OS underlying). You'll see quickly what you can't do in "standalone" free pascal .
Regards
inflater
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Re: Pmode
Oh really? First, when setting up a GDT it is absolutely useless to go for 'speed' as it is a one-time thing that'll take a nano-second on a modern CPU, regardless of whether you code in asm or a high-level language, and secondly, what 'strange bugs' are you thinking about? As long as you know your compiler and are able to align everything properly, there shouldn't be any 'strange bugs' (or any bug, for that matter). I've set up my GDT in C++, and it works perfectly well.inflater wrote:Theoretically yes, but use ASM routines for that, you'll get a faster code plus you'll avoid some number of strange bugs. Really.
JAL
Re: Pmode
To the flamebaiter: Now set the GDT and IDT up solely with pascal's declarations and arrays. You sure didn't tried that huh? Theoretically this can be accomplished, but wait until you get the first triple fault by e.g. mis-aligned tables. Therefore it's easier, faster and safer to do it in ASM.
C++ is more portable than Pascal i must say, so there it may work correctly.
C++ is more portable than Pascal i must say, so there it may work correctly.
My web site: http://inflater.wz.cz (Slovak)
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Derrick operating system: http://derrick.xf.cz (Slovak and English )
Re: Pmode
Taken from my OS:
Code: Select all
unit gdt;
interface
type
TGDTEntry = packed record
LowLimit: Word;
LowBase: Word;
MiddleBase: Byte;
Access: Byte;
Granularity: Byte;
HighBase: Byte;
end;
TGDTPtr = packed record
Limit: Word;
Base: LongWord;
end;
var
GDTList: array [0..4] of TGDTEntry;
GDTPtr: TGDTPtr;
procedure SetGDTGate(num: LongInt; base,limit: LongWord; acc,gran: Byte);
procedure InstallGDT;
implementation
uses
console; // Write* routines are defined here
procedure FlushGDT; assembler; nostackframe;
label
flush;
asm
lgdt [GDTPtr]
mov ax,$10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
// jmp $08:flush // don't know the correct syntax in FPC inline assembler, but it works!
flush:
end;
procedure SetGDTGate(num: LongInt; base,limit: LongWord; acc,gran: Byte);
begin
with GDTList[num] do begin
LowBase:=(base and $FFFF);
MiddleBase:=(base shr 16) and $FF;
HighBase:=(base shr 24) and $FF;
LowLimit:=(limit and $FFFF);
Granularity:=((limit shr 16) and $0F);
Granularity:=Granularity or (gran and $F0);
Access:=acc;
end;
end;
procedure InstallGDT;
begin
WriteString('Installing GDT... ');
with GDTPtr do begin
Limit:=SizeOf(GDTList)-1;
Base:=PtrUInt(@GDTList);
end;
SetGDTGate(0,0,0,0,0); // nil descriptor
SetGDTGate(1,0,$FFFFFFFF,$9A,$CF); // Kernel space code
SetGDTGate(2,0,$FFFFFFFF,$92,$CF); // Kernel space data
SetGDTGate(3,0,$FFFFFFFF,$FA,$CF); // User space code
SetGDTGate(4,0,$FFFFFFFF,$F2,$CF); // User space data
FlushGDT;
WriteStrLn('Done.');
end;
end.