CD Bootloader

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.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: CD Bootloader

Post by neon »

So what exactly is wrong with the entry point???? Is it not executing the far jump correctly?
It never ends, of course. After call Print_ln within main it will start executing the LOAD_SUCCESS string as code and whatever garbage is after. You need to end it, either with an infinity loop (jmp $) or CLI followed by HLT instruction (since there is no where for it to return to.)

In addition,

1. jmp 0x9000:main is wrong. Use jmp main or jmp 0x200:main.
2. Set ES=DS=SS=FS=GS=0x200 not 0x9000. Not required but will mimic a flat segment memory model and will probably solve the display problem. CS should already be 0x200 set by the boot record.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
AnonymousUser
Posts: 14
Joined: Wed Jul 23, 2014 5:54 pm
Location: Bermuda Triangle

Re: CD Bootloader

Post by AnonymousUser »

Thank you so much it worked!!! :D
AnonymousUser
Posts: 14
Joined: Wed Jul 23, 2014 5:54 pm
Location: Bermuda Triangle

Re: CD Bootloader

Post by AnonymousUser »

I have one last question
After I move onto the second stage I try to enter protected mode and what happens is that It crashes when I try and make the jump to the protected mode here is what I have done:

Code: Select all

main:		
;first stage of bootloader is loaded at the address 0x07c0:0x0FFFE
	;second stage of bootloader is loaded at address 0x9000:0x0FFFF
	
	
	cli
	mov ax, 0x200	;adjust the segment registers
	mov ds, ax
	mov gs, ax
	mov fs, ax


Create_Stack:
	xor ax, ax
	mov es, ax
	mov ss, ax
	mov sp ,0x0FFFF
	sti

	mov [CDDriveNumber], dl
	
	
	
	
	call clear
	Print LOAD_SUCCESS, TEAL
	call Print_ln
	
	SwitchToProtectedMode:
	cli
	lgdt [GDT]

	
	mov eax, cr0
	or eax, 1
	mov cr0, eax
	
	
	;enable 32 bit mode
	jmp 0x8:Protected_Mode
	
	[BITS 32]
	
	Protected_Mode:
	;set up stack
	xor ax, ax
	MOV   AX, 0x10 ; 0x10 points at the new data selector
	MOV   DS, AX
	MOV   ES, AX
	MOV   FS, AX
	MOV   GS, AX
	MOV   SS, AX
	MOV ESP, 0x900000
	mov edi, VIDEO_MEM
	mov BYTE[edi], 'A'
	mov BYTE[edi+1], TEAL
	
	cli
	hlt
	

	
Entered_PMODE: db "YOu have succcessfully entered Protected Mode :D", 0
LOAD_SUCCESS:	db "Stage 2 Loaded Successfully",0
CDDriveNumber:  db 0
GDT_START:
;null descriptor
dd 0
dd 0
;data descriptor
dw 0xFFFF
dw 0
db 0
db 10011010b
db 11001111b
db 0
;code descriptor
dw 0xFFFF
dw 0
db 0
db 10010010b
db 11001111b
db 0
GDT_END:


GDT:
dw GDT_END - GDT_START - 1
dd GDT_START


I was looking at the disassembly of the code and It looks like it jumps but it doesent stop after the cli hlt Why would that be???
here it is :

Code: Select all

00000200  EA8D000002        jmp word 0x200:0x8d
00000205  0000              add [bx+si],al
00000207  60                pushaw
00000208  8A360600          mov dh,[0x6]
0000020C  B402              mov ah,0x2
0000020E  B700              mov bh,0x0
00000210  FEC6              inc dh
00000212  B200              mov dl,0x0
00000214  CD10              int 0x10
00000216  88360600          mov [0x6],dh
0000021A  C606050000        mov byte [0x5],0x0
0000021F  61                popaw
00000220  C3                ret
00000221  EB0C              jmp short 0x22f
00000223  F7D8              neg ax
00000225  50                push ax
00000226  B02D              mov al,0x2d
00000228  B40E              mov ah,0xe
0000022A  CD10              int 0x10
0000022C  58                pop ax
0000022D  EB0A              jmp short 0x239
0000022F  31DB              xor bx,bx
00000231  B90A00            mov cx,0xa
00000234  83F800            cmp ax,byte +0x0
00000237  7CEA              jl 0x223
00000239  31D2              xor dx,dx
0000023B  F7F1              div cx
0000023D  52                push dx
0000023E  43                inc bx
0000023F  85C0              test ax,ax
00000241  75F6              jnz 0x239
00000243  58                pop ax
00000244  83C030            add ax,byte +0x30
00000247  B40E              mov ah,0xe
00000249  CD10              int 0x10
0000024B  4B                dec bx
0000024C  83FB00            cmp bx,byte +0x0
0000024F  75F2              jnz 0x243
00000251  C3                ret
00000252  B409              mov ah,0x9
00000254  B90100            mov cx,0x1
00000257  AC                lodsb
00000258  84C0              test al,al
0000025A  740C              jz 0x268
0000025C  CD10              int 0x10
0000025E  B402              mov ah,0x2
00000260  B700              mov bh,0x0
00000262  FEC2              inc dl
00000264  CD10              int 0x10
00000266  EBEA              jmp short 0x252
00000268  C3                ret
00000269  B40F              mov ah,0xf
0000026B  B000              mov al,0x0
0000026D  CD10              int 0x10
0000026F  B400              mov ah,0x0
00000271  CD10              int 0x10
00000273  B402              mov ah,0x2
00000275  B701              mov bh,0x1
00000277  B600              mov dh,0x0
00000279  B200              mov dl,0x0
0000027B  CD10              int 0x10
0000027D  88360600          mov [0x6],dh
00000281  88160500          mov [0x5],dl
00000285  C3                ret
00000286  E492              in al,0x92
00000288  0C02              or al,0x2
0000028A  E692              out 0x92,al
0000028C  C3                ret
0000028D  FA                cli
0000028E  B80002            mov ax,0x200
00000291  8ED8              mov ds,ax
00000293  8EE8              mov gs,ax
00000295  8EE0              mov fs,ax
00000297  31C0              xor ax,ax
00000299  8EC0              mov es,ax
0000029B  8ED0              mov ss,ax
0000029D  BCFFFF            mov sp,0xffff
000002A0  FB                sti
000002A1  88165001          mov [0x150],dl
000002A5  E8C1FF            call word 0x269
000002A8  60                pushaw
000002A9  31C0              xor ax,ax
000002AB  31D2              xor dx,dx
000002AD  8A360600          mov dh,[0x6]
000002B1  8A160500          mov dl,[0x5]
000002B5  31DB              xor bx,bx
000002B7  B303              mov bl,0x3
000002B9  BE3401            mov si,0x134
000002BC  E893FF            call word 0x252
000002BF  88160500          mov [0x5],dl
000002C3  61                popaw
000002C4  E840FF            call word 0x207
000002C7  FA                cli
000002C8  0F01166901        lgdt [0x169]
000002CD  E8B6FF            call word 0x286
000002D0  0F20C0            mov eax,cr0
000002D3  6683C801          or eax,byte +0x1
000002D7  0F22C0            mov cr0,eax
000002DA  EADF000800        jmp word 0x8:0xdf
000002DF  6631C0            xor eax,eax
000002E2  66B810008ED8      mov eax,0xd88e0010
000002E8  8EC0              mov es,ax
000002EA  8EE0              mov fs,ax
000002EC  8EE8              mov gs,ax
000002EE  8ED0              mov ss,ax
000002F0  BC0000            mov sp,0x0
000002F3  90                nop
000002F4  00BF0080          add [bx-0x8000],bh
000002F8  0B00              or ax,[bx+si]
000002FA  C60741            mov byte [bx],0x41
000002FD  C6470103          mov byte [bx+0x1],0x3
00000301  FA                cli
00000302  F4                hlt
00000303  59                pop cx
00000304  4F                dec di
00000305  7520              jnz 0x327
00000307  686176            push word 0x7661
0000030A  65207375          and [gs:bp+di+0x75],dh
0000030E  636363            arpl [bp+di+0x63],sp
00000311  657373            gs jnc 0x387
00000314  66756C            o32 jnz 0x383
00000317  6C                insb
00000318  7920              jns 0x33a
0000031A  656E              gs outsb
0000031C  7465              jz 0x383
0000031E  7265              jc 0x385
00000320  64205072          and [fs:bx+si+0x72],dl
00000324  6F                outsw
00000325  7465              jz 0x38c
00000327  637465            arpl [si+0x65],si
0000032A  64204D6F          and [fs:di+0x6f],cl
0000032E  6465203A          and [gs:bp+si],bh
00000332  44                inc sp
00000333  005374            add [bp+di+0x74],dl
00000336  61                popaw
00000337  67652032          and [gs:edx],dh
0000033B  204C6F            and [si+0x6f],cl
0000033E  61                popaw
0000033F  646564205375      and [fs:bp+di+0x75],dl
00000345  636365            arpl [bp+di+0x65],sp
00000348  7373              jnc 0x3bd
0000034A  66756C            o32 jnz 0x3b9
0000034D  6C                insb
0000034E  7900              jns 0x350
00000350  0000              add [bx+si],al
00000352  0000              add [bx+si],al
00000354  0000              add [bx+si],al
00000356  0000              add [bx+si],al
00000358  00FF              add bh,bh
0000035A  FF00              inc word [bx+si]
0000035C  0000              add [bx+si],al
0000035E  9ACF00FFFF        call word 0xffff:0xcf
00000363  0000              add [bx+si],al
00000365  0092CF00          add [bp+si+0xcf],dl
00000369  17                pop ss
0000036A  005101            add [bx+di+0x1],dl
0000036D  0000              add [bx+si],al
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: CD Bootloader

Post by neon »

Hello,

There are a few notes on the provided code,

Code: Select all

;first stage of bootloader is loaded at the address 0x07c0:0x0FFFE
;second stage of bootloader is loaded at address 0x9000:0x0FFFF
;enable 32 bit mode
;0x10 points at the new data selector
1. All of these comments are wrong. It is highly recommend to write correct comments that describe the intent of the code. Incorrect comments are worse then no comments at all and will greatly make it harder to follow your code. This is why your original code was so hard to follow (that and the unnecessary output and some useless code.)

a. The boot record (first stage) is loaded at 0x7c0:0 (most cases) or 0:0x7c00 (not very often.) Both are 0x7c00 linear.
b. The boot loader (second stage) is loaded at 0x200:0 or 0x2000 linear.
c. The third comment is also wrong. The far jump is only there to flush the old value of CS to 8 which is the GDT offset of the code descriptor. The code descriptor in your GDT is what tells the CPU to enable 32 bit protected mode.
d. 0x10 does not point to anything. Its the GDT entry of your data selector.

The point here is to be careful with your commenting and make sure your code actually does what the comments claim.

2. Your provided boot record only loaded the first 4 sectors. This should be resolved as soon as possible using the formula I provided earlier.
I was looking at the disassembly of the code and It looks like it jumps but it doesent stop after the cli hlt Why would that be???
Many disassemblers only take a binary image as input and since your image lacks symbolic information and is flat binary, everything within it must be taken as possible code. In other words, the disassembler has no way to determine what is data or code.

The disassembled file is expected given the above. What would be more useful is the following :

1. What is the value of GDTR?
2. What is the actual in memory contents of that address and is it expected?
3. What does CS:EIP become after the far jump and is it expected code?
4. The GDT should be 4 byte aligned.

Given what you described its probably a general protection fault. The provided GDT appears correct so I would resort to the use of an actual debugger. We can test it here if requested however really recommend practicing with your debugger while things are still simple.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
AnonymousUser
Posts: 14
Joined: Wed Jul 23, 2014 5:54 pm
Location: Bermuda Triangle

Re: CD Bootloader

Post by AnonymousUser »

Ya I wan't to be able to debug but when I compile the bochs debugger using cygwin it just doesen't work like it's supposed to It spits out the same 4 lines of code over and over even when I change the software Almost as if it wasn't compiled the right way. It Might be cygwin thats the reason I haven't been able to debug it at all the only way for me that works for certain is dissasembly and that only goes so far. As far of the comments go sorry I forgot to change the comments when you corrected me earlier. The only way to get the value of the CS:EIP registers would be print them out after the jump but the thing is I won't be able to see them because it crashes before it does anything after the jump to the Protected_Mode Label. Same goes for the value of the GDTR. I have tried looking for a similar problem with bochs but none have come up, If you could test it there that would be great I'll keep trying to see what is wrong with bochs My guess is it's probably Cygwin but I could be wrong.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: CD Bootloader

Post by neon »

Hello,

We have rewritten your current boot loader to the way we would have wrote it (note consistent spacing and comments to improve readability.) The real problem with your boot loader was the loading of the wrong offset due to the use of the org directive in between execution modes. We rewritten your loader with this fixed.

Code: Select all

;
; Execution mode is 16 bit real mode
;
bits 16

;
; Must be loaded at 0x2000. We use ORG here to avoid weird offset calcs between modes
;
org 0x2000

;
; jump to entry point
;
jmp  main

;=======================================;
;                                       ;
; Constants                             ;
;                                       ;
;=======================================;

; colors
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05

;=======================================;
;                                       ;
; Print macro                           ;
;                                       ;
;=======================================;

COL: db 0
ROW:  db 0
%macro Print 2
	pusha
	xor ax, ax
	xor dx, dx
	mov dh, BYTE[ROW];puts the row into the dh register
	mov dl, BYTE[COL]
	xor bx, bx
	mov bl, %2
	mov si, %1
	call cPrint
	mov BYTE[COL], dl
	; saves the rows for the next time we need to print
	popa
%endmacro

;=======================================;
;                                       ;
; Print line                            ;
;                                       ;
;=======================================;

Print_ln:
	pusha   
	mov dh, BYTE[ROW]  
	mov ah, 0x02            ;set cursor pos
	mov bh, 0x00            ;page 00
	inc dh                  ;row 00
	mov dl, 0x00            ;col. 00    
	int 0x10
	mov BYTE[ROW], dh
	mov BYTE[COL], 0
	popa
	ret

;=======================================;
;                                       ;
; itoa - Integer to string              ;
;                                       ;
;=======================================;

itoa:				;number is passed into ax
	jmp .beggining
.negate:
	neg ax
	push ax
	mov al, '-'
	mov ah, 0xe 
	int 0x10
	pop ax
	jmp .top
.beggining:
	xor bx , bx
	mov cx, 10			;mov into cx 10
	cmp ax, 0
	jl .negate
.top:
	;
	; divide by 10 and push remainder onto stack 
	;
	xor dx, dx			;clear out remainder
	div cx				;divide ax by 10
	push dx				;push the remainder onto the stack for later
	inc bx				;count the number of digits
	test ax,ax			;if ax = 0 then stop
	jne .top
.loop:
	pop ax				;restore the remainder
	add ax, '0'			;convert to ASCII
	mov ah, 0xe			;print
	int 0x10
	dec bx				;get ready for the next digit
	cmp bx, 0			;if not zero then jump to .loop   
	jne .loop
	ret
	
;=======================================;
;                                       ;
; Print string                          ;
;                                       ;
;=======================================;

cPrint:                   ; Routine: output string in SI to screen
.top:
   ;Paramaters for Input 
    mov ah, 09h             ; Must be 9 to print color
    mov cx, 0x01          ;x position
    lodsb                   ; Get character from string
    test al, al
    je .done                ; If char is zero, end of string
    int 0x10                 ; Otherwise, print it
    mov ah, 0x02         ;set cursor position
    mov bh, 0x00         ;page
    inc dl       ;column
    int 0x10            ;changes the cursor position so the next char can be written at the new location
    jmp .top
.done:
    ret
	
;=======================================;
;                                       ;
; Clear display                         ;
;                                       ;
;=======================================;

;clears the screen and sets the cursor position to the top left 
clear:
    mov ah, 0x0F            ;get current video mode
    mov al, 0x00            ;reset register
    int 0x10                ;get video mode
    mov ah, 0x00            ;set video mode
    int 0x10                ;reset screen
    mov ah, 0x02            ;set cursor pos
    mov bh, 0x01         ;page 00
    mov dh, 0x00            ;row 00
    mov dl, 0x00            ;col. 00
    int 0x10                ;set pos
	MOV BYTE[ROW], DH
	MOV BYTE[COL], DL
	ret

;=======================================;
;                                       ;
; Entry point                           ;
;                                       ;
;=======================================;

main:
	;
	; initialize segments to a flat memory model (all same segment)
	;
	cli
	xor ax, ax			; All segments set to 0, flat memory model
	mov ds, ax
	mov es, ax
	mov gs, ax
	mov fs, ax
	mov ss, ax
	;
	; Set stack top SS:0xffff
	;
	mov sp, 0x0FFFF
	;
	; Initialize GDTR
	;
	lgdt [_gdtr]
	;
	; Enable protected mode
	;
	mov eax, cr0
	or eax, 1
	mov cr0, eax
	;
	; Flush CS and set code selector
	;
	jmp 8:.pmode_entry

bits 32

.pmode_entry:
	;
	; disable hardware interrupts and halt
	;
	cli
	hlt
	
;=======================================;
;                                       ;
; Data                                  ;
;                                       ;
;=======================================;

struc gdt_descr
	.limitLo      resw 1
	.baseLo       resw 1
	.baseMiddle   resb 1
	.access       resb 1
	.grandularity resb 1
	.baseHi       resb 1
endstruc

struc gdtr_descr
	.limit        resw 1
	.base         resd 1
endstruc

;
; Global descriptor table
;
_gdt_start :
	;
	; null descriptor
	;
	istruc gdt_descr
		at gdt_descr.limitLo,      dw 0
		at gdt_descr.baseLo,       dw 0
		at gdt_descr.baseMiddle,   db 0
		at gdt_descr.access,       db 0
		at gdt_descr.grandularity, db 0
		at gdt_descr.baseHi,       db 0
	iend
	;
	; 32 bit protected mode code descriptor
	;
	istruc gdt_descr
		at gdt_descr.limitLo,      dw 0xffff
		at gdt_descr.baseLo,       dw 0
		at gdt_descr.baseMiddle,   db 0
		at gdt_descr.access,       db 10011010b
		at gdt_descr.grandularity, db 11001111b
		at gdt_descr.baseHi,       db 0
	iend
	;
	; 32 bit protected mode data selector
	;
	istruc gdt_descr
		at gdt_descr.limitLo,      dw 0xffff
		at gdt_descr.baseLo,       dw 0
		at gdt_descr.baseMiddle,   db 0
		at gdt_descr.access,       db 10010010b
		at gdt_descr.grandularity, db 11001111b
		at gdt_descr.baseHi,       db 0
	iend
_gdt_end :

;
; GDT Register Descriptor
;
_gdtr :
istruc gdtr_descr
	at gdtr_descr.limit, dw _gdt_end - _gdt_start - 1
	at gdtr_descr.base,  dd _gdt_start
iend
Please try to improve your coding style by using structure declarations and more consistency next time as it will greatly make it easier to read.

We use a different build environment then you however under Windows you can just use the Windows version of the debugger if you think Cygwin is the problem (note that we do not use Cygwin so cannot confirm anything with regards to it.)

Do not go any farther until you have a good machine level debugger and know how to use it. Everything so far could have easily been found with a debugger and I assure you that it is only going to get much more complicated. This is why I emphasize readability and good use of a debugger as you will not stand a chance without them. You might eventually be able to port or write a source level debugger for the kernel or boot loader later on, but until then the Bochs debugger is really the only good option.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
SpyderTL
Member
Member
Posts: 1074
Joined: Sun Sep 19, 2010 10:05 pm

Re: CD Bootloader

Post by SpyderTL »

You can download Bochs already compiled for windows. I would recommend doing that for now.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Post Reply