problems entering protected mode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Seven11
Member
Member
Posts: 25
Joined: Mon Oct 30, 2006 12:48 pm

problems entering protected mode

Post by Seven11 »

My second bootloader is loaded from a FAT12 disk by the bootsector to the addr 10000h and it uses this code:

Code: Select all

cli
o32 lgdt[gdtr]
o32 lidt[idtr]
mov eax,cr0
or al,1
mov cr0,eax
jmp code32sel:pmode
bits32
pmode:
jmp $
To get into pmode, this code has always worked but now when I changed the bootloader addr from 7e00h (right after the bootsector) to 10000h it stopped working. Also I can say that all the segments are cleared before running the above code except CS which is 1000h.


Also, bochs tells me this:
"fetch_raw_descriptor: GDT: index (f)1 > limit (0)"

Looking at the NASM output for the lgdt and lidt instructions:
000023A2 660F0116[D621] o32 lgdt[gdtr]
000023A8 660F011E[F421] o32 lidt[idtr]
makes me think that the cpu never get's the GDT or IDT table since they are located att addr 121D6h (GDT) and 121F4h (IDT)...

any good solutions?
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: problems entering protected mode

Post by Brendan »

Hi,

Which assembler are you using, what do you use for "ORG", what is in DS when this code is run and what data is at gdtr and idtr?


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
Dex
Member
Member
Posts: 1444
Joined: Fri Jan 27, 2006 12:00 am
Contact:

Post by Dex »

First are you setting any org in your second stage and if so, what is it ?
Next bubach had a problem like this, with BOS have a look at that code to see how he fixed it. http://bos.asmhackers.net/downloads.php

I think he had to do something like this:

Code: Select all

	  lgdt	  [gdtr - 0x10000]		      ; Load the GDT descriptor
	  lidt	  [idtr - 0x10000]		      ; Load the IDT descriptor
PS: Whats the "o32" ?
Seven11
Member
Member
Posts: 25
Joined: Mon Oct 30, 2006 12:48 pm

Post by Seven11 »

brendan: as I wrote, the base addr och the bootloader is 10000h and "all the segments are cleared before running the above code except CS which is 1000h." => DS = 0. The assembler is NASM.

Dex: "o32" tells NASM to use 32-bits operand (in other words adding the instruction prefix 66h), look in the Instruction Set Reference from Intel on the instruction "LGDT/LIDT".

The GDT table looks like this:

Code: Select all

%macro GDT_ENTRY 6
  %%LIMIT_15_0 dw %1
  %%BASE_15_0 dw %2
  %%BASE_23_16 db %3
  %%OPT_1 db %4
  %%OPT_2_LIMIT_19_16 db %5
  %%BASE_31_24 db %6
%endmacro

gdtr
  dw gdt_end-gdt-1
  dd gdt
gdt
   nullseg equ ($-gdt)
   GDT_ENTRY 0h, 0h, 0h, 0h, 0h, 0h ;nullseg
   code32sel equ ($-gdt)
   GDT_ENTRY 0FFFFh, 0h, 0h, 9ah, 0cfh, 0h ;Kernel Code
   data32sel equ ($-gdt)
   GDT_ENTRY 0FFFFh, 0h, 0h, 92h, 0cfh, 0h ;Kernel
gdt_end
PS! I have removed the "lidt" instruction for now to make debugging easier, it will be added again when the lgdt thing works.

PS #2! BOS seems to be entering Pmode in the bootsector, this is not an option for me because the bootloader probes the BIOS for VESA, APM and Memory information...

One last option is to move back the bootloader to under the 10000h mark, but shouldn't it be possible to get into Pmode when your above 10000h???
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Post by Brendan »

Hi,
Seven11 wrote:brendan: as I wrote, the base addr och the bootloader is 10000h and "all the segments are cleared before running the above code except CS which is 1000h." => DS = 0. The assembler is NASM.
The "o32" will change the operand size, but won't change the address size. To do that you'd need:

Code: Select all

     o32 lgdt   [dword gdtr]          ; Load the GDT descriptor
In this case, NASM should generate an "o32 lgdt [0x0001????] instruction, which is what you want (because DS base is zero), but will also cause a general protection fault (because the address is above the 64 KB limit for DS).

To fix this, either:

Code: Select all

     mov ax,0x1000
     mov ds,ax
     o32 lgdt   [gdtr]          ; Load the GDT descriptor
Or perhaps:

Code: Select all

     o32 lgdt   [cs:gdtr]          ; Load the GDT descriptor
You should also have a problem with your far jump, which probably needs to be:

Code: Select all

     jmp dword code32sel:pmode

Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Seven11
Member
Member
Posts: 25
Joined: Mon Oct 30, 2006 12:48 pm

Post by Seven11 »

for some reason:

Code: Select all

o32 lgdt   [dword gdtr]          ; Load the GDT descriptor
doesn't work... however...

Code: Select all

 jmp dword code32sel:pmode
did it :D

so If anybody else has the problem here is the code to solve it:

Code: Select all

;Enter Pmode from above 10000h
cli
o32 lgdt[gdtr] ;assumes BASE(DS)*16+gdtr points to GDT structure.
o32 lgdt[idtr]  ;BASE(DS)*16+idtr should point to the IDT structure.
mov eax,cr0
or al,1
mov cr0,eax
jmp dword code32sel:pmode ;where "code32sel" is your 32-bit kernel code seg.
bits 32
pmode:
mov ax,data32sel ;where "data32sel" is your 32-bit kernel data seg.
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax
Thanks for the help!
Post Reply