Page 1 of 1

Pmode

Posted: Sat Aug 02, 2008 2:48 am
by System123
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

Re: Pmode

Posted: Sat Aug 02, 2008 3:34 am
by AJ
Hi,
Do i need to set up pmode before i load the kernel from the disk?
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.
The other question is can i use pascal functions to set up my gdt and idt?
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 last one is how do i jump from my boot loader into my kernel
Assuming a flat binary loaded at the 1MiB mark:

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

Posted: Sat Aug 02, 2008 3:42 am
by inflater
Do i need to set up pmode before i load the kernel from the disk?
You can load your kernel either by
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.
The other question is can i use pascal functions to set up my gdt and idt?
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 last one is how do i jump from my boot loader into my kernel
When you have the protected mode fully set up, this can be done
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 :D.

Regards
inflater

Re: Pmode

Posted: Sat Aug 02, 2008 10:46 pm
by System123
I wasnt going to use this with BP. I have already converted my kernel to free pascal

Re: Pmode

Posted: Mon Aug 04, 2008 11:58 am
by jal
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.
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.


JAL

Re: Pmode

Posted: Mon Aug 04, 2008 12:48 pm
by inflater
To the flamebaiter: Now set the GDT and IDT up solely with pascal's declarations and arrays. You sure didn't tried that huh? :roll: 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.

Re: Pmode

Posted: Mon Aug 04, 2008 11:57 pm
by leledumbo
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.

Re: Pmode

Posted: Tue Aug 05, 2008 6:37 am
by System123
My GDT setup function looks very similar to the one above. The only thing is I forgot to use packed records.

Re: Pmode

Posted: Thu Aug 07, 2008 12:45 am
by jal
System123 wrote:My GDT setup function looks very similar to the one above. The only thing is I forgot to use packed records.
You should also check allignment of the actual declared variables.


JAL