Page 1 of 8

Problem on real hardware

Posted: Mon Dec 05, 2011 4:01 pm
by romfox
Hi all,
After a long time trying to make it work by myself, I ask your help...
The problem : my OS works on Bochs, but doesn't work on a real computer.
My bootloader seems to work cause if I put a "jmp $" before the "jmp 0x8:BASE << 4" I can see my bootloader message (which is between kernel copy to RAM and protected mode activation, so it means my kernel is loaded).
But whithout that, my computer restart when it tries to jump to my Kernel.
I don't overwrite the BIOS normally, but probably I do something wrong.
My boot sector :

Code: Select all

%define BASE    0x100  ; 0x0100:0x0 = 0x1000
%define KSIZE   50     ; nombre de secteurs a charger

[BITS 16]
[ORG 0x0]

jmp start
%include "fn_boot.inc"
start:

; initialisation des segments en 0x07C0
    mov ax, 0x07C0
    mov ds, ax
    mov es, ax
    mov ax, 0x8000    
    mov ss, ax
    mov sp, 0xf000

; recuparation de l'unite de boot
    mov [bootdrv], dl    

; charger le noyau
    xor ax, ax
    int 0x13

    push es
initialise_disque: ; Initialise le lecteur de disque
    xor ax, ax
    int 0x13
    jc initialise_disque ; En cas d'erreur on recommence (sinon, de toute façon, on ne peut rien faire)
lire:
    mov ax, BASE ; ES:BX = BASE:0000
    mov es, ax
    xor bx, bx
    mov ah, 2 ; Fonction 0x02 : chargement mémoire
    mov al, KSIZE ; On lit KSIZE secteurs
    xor ch, ch ; Premier cylindre (n° 0)
    mov cl, 2 ; Premier secteur (porte le n° 2, le n° 1, on est dedans, et le n° 0 n'existe pas)
    xor dh, dh ; Tête de lecture n° 0
; Toujours pas d'identifiant de disque, c'est toujours le même.
    int 0x13 ; Lit !
    jc lire ; En cas d'erreur, on recommence
    pop es

; initialisation du pointeur sur la GDT
    mov ax, gdtend    ; calcule la limite de GDT
    mov bx, gdt
    sub ax, bx
    mov word [gdtptr], ax

    xor eax, eax      ; calcule l'adresse lineaire de GDT
    xor ebx, ebx
    mov ax, ds
    mov ecx, eax
    shl ecx, 4
    mov bx, gdt
    add ecx, ebx
    mov dword [gdtptr+2], ecx

   mov si, msgDebut
   call print16            ; This messages is spawned by my computer

; passage en modep
    cli
    lgdt [gdtptr]    ; charge la gdt
    mov eax, cr0
    or  ax, 1
    mov cr0, eax        ; PE mis a 1 (CR0)

    jmp next
next:
    mov ax, 0x10        ; segment de donne
    mov ds, ax
    mov fs, ax
    mov gs, ax
    mov es, ax
    mov ss, ax
    mov esp, 0x9F000    

   ; jmp $     if I do that I see my boot message


    jmp 0x8:0x1000    ; It restart my real computer & works in VMs

;--------------------------------------------------------------------
bootdrv:  db 0
msgDebut: db "Chargement du kernel", 13, 10, 0
;--------------------------------------------------------------------
gdt:
    db 0, 0, 0, 0, 0, 0, 0, 0
gdt_cs:
    db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
gdt_ds:
    db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
gdtend:
;--------------------------------------------------------------------
gdtptr:
    dw 0  ; limite
    dd 0  ; base
;--------------------------------------------------------------------

;; NOP jusqu'a 510
times 510-($-$$) db 144
dw 0xAA55
This is not a kernel problem cause a simple "jmp $" doesn't go executed.

Thanks a lot for reading my bad english.

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 4:51 pm
by DavidCooper
gdt:
db 0, 0, 0, 0, 0, 0, 0, 0
gdt_cs:
db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10011011b, 11011111b, 0x0
gdt_ds:
db 0xFF, 0xFF, 0x0, 0x0, 0x0, 10010011b, 11011111b, 0x0
gdtend:
Try 11001111b instead of 11011111b. I can't remember what bit-4 actually does, but normally it's 0.
; passage en modep
cli
lgdt [gdtptr] ; charge la gdt
mov eax, cr0
or ax, 1
mov cr0, eax ; PE mis a 1 (CR0)

jmp next
next:
I don't know assembler well enough to know, but is that guaranteed to do a far jump? I can't see anything else wrong at the moment, but I'll have another look if you still can't get it to work.

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 5:09 pm
by DavidCooper
I've just remembered something else - I didn't see any sign of you taking 1 away from the GDT size before doing the lgdt part.

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 5:41 pm
by romfox
Thank you for helping me, I changed the bit but this is a free-for-use bit, yes I have correctly modified the size. But now it freezes after displaying the message on my real computer (probably at the "jmp") and still works on VMs...
I don't know for the far jump but I have readen that it's supposed to work.
And I am sure it worked before... Probably a beginner mistake but can't find it :(

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 5:53 pm
by DavidCooper
What are you booting from? If it's a floppy disk, you can't load 50 sectors in one go - you'd need to do 18 instead (or 17 for the first lot as you don't want the boot sector).

[Edit: moved an added question to a new post.]

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 6:00 pm
by romfox
That's an external HDD, and I already tried to change the number of sectors to read...
I have tried a "jmp 0x8:0x1000" after "mov cr0, eax" and then init segments in the kernel but I still freeze after displaying the message, the computer no longer reboot but it doesn't work more :p

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 6:09 pm
by DavidCooper
How are you getting the message below printed?
msgDebut: db "Chargement du kernel", 13, 10, 0
From the form that's in, it looks as if you're going to be sending it to the screen via the BIOS, and yet you make it sound as if it works.

Could the problem be something you're doing after the jump? How about posting a little bit of that?

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 6:14 pm
by romfox
I use the bios to print and I get this string printed yes.

This is my kernel : (dirty I know)

Code: Select all

%define IDTSIZE 50    ; Nombre d'interruptions
%define BASE 0x1000   

; -------------------------------------------------------------

[BITS 32]
[ORG 0x1000]

jmp debut

%include "fn.inc"

debut: 
    call clear
    mov esi, msgKernel01
    call print
    mov esi, msgKernel02
    call print

    lidt [idtptr]
    mov eax, int_clock             ; Init IRQ0
    mov word [idt+32*8], ax            
    mov word [idt+32*8+2], 0x08
    mov word [idt+32*8+4], 0x8e00
    shr eax, 16
    mov word [idt+32*8+6], ax

    mov eax, int_kbd               ; Init IRQ1
    mov word [idt+33*8], ax
    mov word [idt+33*8+2], 0x08
    mov word [idt+33*8+4], 0x8e00
    shr eax, 16
    mov word [idt+33*8+6], ax

    call remap_pic
 
    sti

    jmp $

; -------------------------------------------------------------
; IRQ0 : Timer
; -------------------------------------------------------------

int_clock:
    mov al, 0x20
    out 0x20, al
    iret

; -------------------------------------------------------------
; IRQ1 : Driver Clavier     A chaque fin de ligne la chaine est dans buff_cmd
; -------------------------------------------------------------

int_kbd:
    cli

.wait:
    in al, 0x64
    and al, 1
    jz .wait

    in al, 0x60

    cmp al, 224
    je .wait

    cmp al, 0x3f
    je .refresh

    cmp al, 0x0e
    je .backspace

    cmp al, 0x2a
    je .shift_enable

    cmp al, 0xf0
    jl .release    

    movzx ebx, byte [shift]     ; On converti
    call convert_scan           ; Caractère en ascii maintenant dans esi
    call putc                   ; On affiche

    movzx eax, byte [esi]       
    cmp eax, 0x0a             
    je .end_write

    mov edi, buff_cmd
    add edi, [buff_cmd_size]
    stosb
    add byte [buff_cmd_size], 1
    jmp .end  

.end:
    mov al, 0x20
    out 0x20, al
    sti
    iret 

.refresh:
    call clear
    jmp .end

.shift_enable:
    mov byte [shift], 1
    jmp .end

.shift_disable:
    mov byte [shift], 0
    jmp .end
    
.release:
    sub al, 0x80
    cmp al, 0x2a
    je .shift_disable
    jmp .end

; Backspace, seulement sur la meme ligne pour l'instant
.backspace:
    movzx eax, byte [posx]
    cmp eax, 1
    jl .end
    sub byte [posx], 1
    mov esi, buff_space
    call putc
    sub byte [posx], 1
    call move_cursor
    jmp .end
           
.help:
    mov esi, msgHelp
    call print
    jmp .end   

.end_write:
    movzx edx, byte [buff_cmd_size]
    cmp edx, 0
    je .end
    mov edi, buff_cmd
    add edi, [buff_cmd_size]
    stosb
    mov eax, 0
    stosb
    mov byte [buff_cmd_size], 0
    mov esi, cmd_help
    mov edi, buff_cmd
    mov ecx, 4
    call strncmp
    cmp eax, 0
    je .help
    jmp .end


; -------------------------------------------------------------

msgKernel01: db 'Kernel loaded...', 10, 13, 'Welcome to RomOS 0.1', 10, 0
msgKernel02: db 'Press F5 to refresh sreen.', 10, "Type 'help' for a list of commands availables.", 10, 0
msgHelp: db 'Here is a list of all commands availables : ', 10, 'help', 10, 0

buff_cmd:       times 0xff db 0
buff_cmd_size:  db 0
;--------------------------------------------------------------------

idt:                             ; idt est la table d'interruptions
    times (IDTSIZE*8) db 0       ; 8 * 50 octets aloués (taille_idt_descriptor * nb_interrupt)
        
idtptr:
    dw (IDTSIZE << 3) - 1  ; Nombre de vecteurs d'interruption * 8 - 1
    dd (BASE+idt-$$)    ;  Adresse de la table

; -------------------------------------------------------------

;; NOP jusqu'a 4096
 times 4096-($-$$) db 0x90
And all is working in VMs...

Edit : And a simple kernel doesn't go executed yet...

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 6:19 pm
by DavidCooper
Before I read through that, I need to know if you're using the BIOS to print that message while in protected mode? It shouldn't be possible.

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 6:20 pm
by romfox
No, in protected mode I'm writting to 0xB8000 :p

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 6:36 pm
by guyfawkes
Have try something like this

Code: Select all

; passage en modep
    cli
    lgdt [gdtptr]    ; charge la gdt
    mov eax, cr0
    or  ax, 1
    mov cr0, eax        ; PE mis a 1 (CR0)

    jmp 0x8:next   ;<this
[BITS 32]           ;< this
next:
    mov ax, 0x10        ; segment de donne
    mov ds, ax
    mov fs, ax
    mov gs, ax
    mov es, ax
    mov ss, ax
    mov esp, 0x9F000    

   ; jmp $     if I do that I see my boot message


    jmp 0x8:0x1000    ; It restart my real computer & works in VMs

I do not use nasm so unsure about simtex

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 6:40 pm
by neon
Hello,

gdt limit should be gdtend - gdt - 1, not gdtend - gdt. Unless I messed it (I cannot read the comments) your code appears to use the latter. The other software that sets gdt base appears correct, however.

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 6:41 pm
by DavidCooper
So I assume that it was a mistake when you said:-
I use the bios to print and I get this string printed yes.
[Edit: no it wasn't a mistake - I missed the bit that called "print" and the code that does the printing is hidden at the top as an %include.]

I still can't see the code that's doing the printing, but assuming the fault isn't there, something may be going wrong with the idt code and removing the message from the screen before you get a chance to see it. Could you try doing something really simple first to see if the kernel's being loaded - start the kernel code by sending few bytes directly to the screen and then follow that with a big delay loop. Try:-

mov al,65
mov ah,12 ;(both decimal)
mov edi,b8000h

then send it to the screen with a lodsw (I think that's the right mnemonics - I don't know because I always use machine code numbers directly: 102 171).

After that, use a delay loop like this:-

xor ecx,ecx
dec ecx

then use the loop instruction - I imagine you'd need to jump to a name for that, but I just use 226 254 which is the loop instruction followed by the jump distance back to the loop instruction again.

That should display a red "A" on the screen for a moment - certainly long enough to see it if this code runs.

Edit: confused myself with mnemonics and told OP to use a movsw instead of a lodsw.

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 6:53 pm
by DavidCooper
I've got to disappear for many hours now, but that bit of test code I suggested you add to the top of the kernel should tell you if the jump's working. If it isn't working, you know where to look for the fault, but if it is working you'll know for certain that the fault is after the test code. I may have made the loop too long, so adjust it if necessary. You can move the test code lower down the kernel to see where it first fails, and by trying it in lots of different places it should be easy to isolate the point where an instruction is causing the machine to freeze/crash.

Note correction to previous post (lodsw, not movsw).

Re: Problem on real hardware

Posted: Mon Dec 05, 2011 6:59 pm
by romfox
I was talking about the boot message. Which is spawned by BIOS.
But my kernel's messages don't get spawned, I already have try a verry simple kernel wich directly write to the Video RAM =/

With

Code: Select all

mov cr0, eax

jmp 0x8:next
[BITS 32]
next:
mov ax, 0x10
mov ds, ax
[...]
jmp $
It breaks at "mov ax, 0x10" :s I note that using that I got by Bochs debugger : "Interrupt() : gate descriptor is not a valid sys seg
AND :

CPU protected mode:
CS.mode = 32 bit
SS.mode = 16 bit (?)"

Edit !