The problem in the recreating of linux 0.00

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
hypeboyz
Posts: 8
Joined: Wed Nov 10, 2010 2:29 am

The problem in the recreating of linux 0.00

Post by hypeboyz »

I tried recreating linux 0.00 by as, and when I ran it on bochs it was stuck. Bochs keep reseting:
00066339148i[CPU0 ] | CS:0000( 0004| 0| 0) 00000000 0000ffff 0 0
00066339148i[CPU0 ] | DS:07c0( 0005| 0| 0) 00007c00 0000ffff 0 0
00066339148i[CPU0 ] | SS:07c0( 0005| 0| 0) 00007c00 0000ffff 0 0
00066339148i[CPU0 ] | ES:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00066339148i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00066339148i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00066339148i[CPU0 ] | EIP=00000701 (00000701)
00066339148i[CPU0 ] | CR0=0x60000010 CR2=0x00000000
00066339148i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00066339148i[CPU0 ] 0x00000701>> (invalid) : FFFF
00066339148e[CPU0 ] exception(): 3rd (12) exception with no resolution, shutdown status is 00h, resetting

I can only find exception(13) online, so I post this on the forum
I thought the problem is located in boot.s so I copy codes as following:

Code: Select all

.code16
.text
BOOTSEG = 0x07C0
SYSSEG  = 0x1000
SYSLEN  = 17
.global start
start:
        ljmp    $BOOTSEG, $go
go:
        movw    %cs, %ax        #Initialize ds, ss and sp(>> end of head.s)
        movw    %ax, %ds
        movw    %ax, %ss
        movw    $0x0400, %sp

#Loading system from disk to memory by int 0x13:
Load:
        movw    $0x0000, %dx
        movw    $0x0002, %cx
        movw    $SYSSEG, %ax
        xor     %bx, %bx
        movw    $0x0200+SYSLEN, %ax
        int     $0x13
        jnc     ok_load
die:    jmp     die                       #In case for fault
ok_load:
#Here we copy kernel codes from 0x1000:0 to 0x0000:0
        cli
        movw    $SYSSEG, %ax
        movw    %ax, %ds
        xor     %ax, %ax
        movw    %ax, %es
        sub     %si, %si
        sub     %di, %di
        movw    $0x1000, %cx
        rep     movsw
#Load IDT & GDT
        movw    $BOOTSEG, %ax
        mov     %ax, %ds
        lidt    lidt_48
        lgdt    lgdt_48
#Here we go for the protected mode
        movw    $0x0001, %ax
        lmsw    %ax
        ljmp    $8, $0
gdt:
        .word   0, 0, 0, 0

        .word   0x07ff
        .word   0x0000
        .word   0x9a00
        .word   0x00c0

        .word   0x07ff
        .word   0x0000
        .word   0x9200
        .word   0x00c0
lidt_48:
        .word   0, 0, 0
lgdt_48:
        .word   0x07ff
        .word   0x7c00+gdt, 0

.org    510
.word   0xAA55
Thanks for answer
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: The problem in the recreating of linux 0.00

Post by Brendan »

Hi,

Code: Select all

SYSLEN  = 17
Hard-coding the length of the kernel is a bad idea.

Code: Select all

.global start
Why does "start" need to be global? The BIOS isn't going to be linked to the boot code...

Code: Select all

go:
The first sector of a floppy should have a BIOS Paramater Block (because some OSs can't figure out what format a floppy disk is without one, and think the floppy is borken/corrupt/unusable, which prevents the user from reformatting it after they've used it). Only the fields that describe the media format are really important for this ("bytes per sector", "number of sectors per track", "number of heads", "media format", and maybe "total sectors") - the other fields should be set to dummy values that make it impossible for software to assume it's FAT (e.g. "zero sectors per file allocation tables", "zero file allocation tables", "zero root directory entries", etc), unless it is FAT.

Code: Select all

        movw    $0x0400, %sp
0x0400 is 512 bytes for the boot sector itself and only 512 bytes left for the stack. That's probably too small (I'd allow at least 2 KiB for IRQ handlers and BIOS functions).

Code: Select all

#Loading system from disk to memory by int 0x13:
Load:
        movw    $0x0000, %dx
        movw    $0x0002, %cx
        movw    $SYSSEG, %ax
        xor     %bx, %bx
        movw    $0x0200+SYSLEN, %ax
        int     $0x13
        jnc     ok_load
die:    jmp     die                       #In case for fault
ok_load:
ES hasn't been set to anything specific, but this BIOS function reads sector/s from disk and stores them at ES:BX. This means the code to load sectors could trash anything.

The BIOS tells you the "boot device number" (in DL on entry), and it's better to use that than to assume you're booting from device 0x00. It's normal for the BIOS "read sector/s" function to fail due to temporary causes (especially for floppy), so going into an infinite loop (rather than retrying a few times) is bad. If there's a real problem (not a temporary one) you should tell the user (e.g. print an error message).

It could/should also use values from the BPB instead of assuming (for e.g.) that one track is 18 sectors, and also split reads into "less than one track". This would allow the same boot code to be used for different floppy disk formats (where the "format" utility sets the correct values in the BPB). For e.g. if there's only 9 sectors per track, then it'd nice to read the remaining 8 sectors of the first track, then read the next 9 sectors from the second track (especially when the kernel grows larger than 8.5 KiB).

Code: Select all

#Here we copy kernel codes from 0x1000:0 to 0x0000:0
        cli
        movw    $SYSSEG, %ax
        movw    %ax, %ds
        xor     %ax, %ax
        movw    %ax, %es
        sub     %si, %si
        sub     %di, %di
        movw    $0x1000, %cx
        rep     movsw
The direction flag was never cleared, and nothing guarantees that the BIOS didn't leave it set. This code might copy the wrong 8192 bytes to the wrong location.

Code: Select all

#Load IDT & GDT
#Here we go for the protected mode
Switching to protected mode in the boot sector code is a bad mistake. There simply isn't enough space to do things properly, including loading the kernel properly, and gathering useful information from the BIOS while in real mode to make things easier later (e.g. memory map).


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
Thomas
Member
Member
Posts: 284
Joined: Thu Jun 04, 2009 11:12 pm

Re: The problem in the recreating of linux 0.00

Post by Thomas »

Hi hypeboyz,

You might want to check out : http://oldlinux.org/ and see the sources for yourself. There was one more book floating in the internet, but I cannot find it now. I do not work with linux or windows anymor :mrgreen: e .

Linus himself admits that first version of Linux was not well written but it might still be of educational value.
--Thomas
Last edited by Thomas on Sun Nov 14, 2010 8:10 am, edited 1 time in total.
User avatar
Thomas
Member
Member
Posts: 284
Joined: Thu Jun 04, 2009 11:12 pm

Re: The problem in the recreating of linux 0.00

Post by Thomas »

See : http://pramode2.tripod.com/kerneldocs/ . I did find it out :)

--Thomas
hypeboyz
Posts: 8
Joined: Wed Nov 10, 2010 2:29 am

Re: The problem in the recreating of linux 0.00

Post by hypeboyz »

Brendan wrote:Hi,

Code: Select all

SYSLEN  = 17
Hard-coding the length of the kernel is a bad idea.

Code: Select all

.global start
Why does "start" need to be global? The BIOS isn't going to be linked to the boot code...

Code: Select all

go:
The first sector of a floppy should have a BIOS Paramater Block (because some OSs can't figure out what format a floppy disk is without one, and think the floppy is borken/corrupt/unusable, which prevents the user from reformatting it after they've used it). Only the fields that describe the media format are really important for this ("bytes per sector", "number of sectors per track", "number of heads", "media format", and maybe "total sectors") - the other fields should be set to dummy values that make it impossible for software to assume it's FAT (e.g. "zero sectors per file allocation tables", "zero file allocation tables", "zero root directory entries", etc), unless it is FAT.

Code: Select all

        movw    $0x0400, %sp
0x0400 is 512 bytes for the boot sector itself and only 512 bytes left for the stack. That's probably too small (I'd allow at least 2 KiB for IRQ handlers and BIOS functions).

Code: Select all

#Loading system from disk to memory by int 0x13:
Load:
        movw    $0x0000, %dx
        movw    $0x0002, %cx
        movw    $SYSSEG, %ax
        xor     %bx, %bx
        movw    $0x0200+SYSLEN, %ax
        int     $0x13
        jnc     ok_load
die:    jmp     die                       #In case for fault
ok_load:
ES hasn't been set to anything specific, but this BIOS function reads sector/s from disk and stores them at ES:BX. This means the code to load sectors could trash anything.

The BIOS tells you the "boot device number" (in DL on entry), and it's better to use that than to assume you're booting from device 0x00. It's normal for the BIOS "read sector/s" function to fail due to temporary causes (especially for floppy), so going into an infinite loop (rather than retrying a few times) is bad. If there's a real problem (not a temporary one) you should tell the user (e.g. print an error message).

It could/should also use values from the BPB instead of assuming (for e.g.) that one track is 18 sectors, and also split reads into "less than one track". This would allow the same boot code to be used for different floppy disk formats (where the "format" utility sets the correct values in the BPB). For e.g. if there's only 9 sectors per track, then it'd nice to read the remaining 8 sectors of the first track, then read the next 9 sectors from the second track (especially when the kernel grows larger than 8.5 KiB).

Code: Select all

#Here we copy kernel codes from 0x1000:0 to 0x0000:0
        cli
        movw    $SYSSEG, %ax
        movw    %ax, %ds
        xor     %ax, %ax
        movw    %ax, %es
        sub     %si, %si
        sub     %di, %di
        movw    $0x1000, %cx
        rep     movsw
The direction flag was never cleared, and nothing guarantees that the BIOS didn't leave it set. This code might copy the wrong 8192 bytes to the wrong location.

Code: Select all

#Load IDT & GDT
#Here we go for the protected mode
Switching to protected mode in the boot sector code is a bad mistake. There simply isn't enough space to do things properly, including loading the kernel properly, and gathering useful information from the BIOS while in real mode to make things easier later (e.g. memory map).


Cheers,

Brendan
Thank you sincerely for your reply and detailed comment on my codes. And I'm not programing whole kernel but a simple head.s that has only two tasks running parallelly. So I use 0x17 as the length of the system and jump into protected mode in boot.
hypeboyz
Posts: 8
Joined: Wed Nov 10, 2010 2:29 am

Re: The problem in the recreating of linux 0.00

Post by hypeboyz »

Thomas wrote:Hi hypeboyz,

You might want to check out : http://oldlinux.org/ and see the sources for yourself. There was one more book floating in the internet, but I cannot find it now. I do not work with linux or windows anymor :mrgreen: e .

Linus himself admits that first version of Linux was not well written but it might still be of educational value.
--Thomas
I'm reading the book of that forum, and also posted a topic about this question but the problem still remained unresovled. I've checked codes and read the correct codes from that forum for several times but cannot find the bug.
In addition, I'm in Shanghai and the website quoted by you is blocked... Would you like to post its name?
Thankyou
Post Reply