Page 1 of 2

[SOLVED]I might just need the best bootloader in the world..

Posted: Mon Jan 19, 2015 5:15 pm
by bashcommando
Hello everybody, I am in a bit of a pickle. I need a bootloader that will load a filesystem(I don't care which) and then load a file called kernel.bin. Kernel.bin will expect to be in 32-bit mode so that is another problem. Is this even possible? -bashcommando

Re: I might just need the best bootloader in the world...

Posted: Mon Jan 19, 2015 5:43 pm
by Nable
I wonder if you've never heard about GRUB and multiboot specification. I think that these things are enough for your needs (including the 32-bit mode).
You can start here: http://wiki.osdev.org/Multiboot

> that will load a filesystem (I don't care which)
What did you mean by this?
Did you mean that bootloader should load some image of filesystem (i.e. initramfs/initrd) ? GRUB is able to do it.
Or did you mean that it should load kernel.bin _from_ some filesystem? Of course it's possible, that's one of key features of loaders.

Re: I might just need the best bootloader in the world...

Posted: Mon Jan 19, 2015 6:23 pm
by bashcommando
Nable wrote:I wonder if you've never heard about GRUB and multiboot specification. I think that these things are enough for your needs (including the 32-bit mode).
You can start here: http://wiki.osdev.org/Multiboot

> that will load a filesystem (I don't care which)
What did you mean by this?
Did you mean that bootloader should load some image of filesystem (i.e. initramfs/initrd) ? GRUB is able to do it.
Or did you mean that it should load kernel.bin _from_ some filesystem? Of course it's possible, that's one of key features of loaders.
I want to make my own. Maybe I can reverse engineer grub? Obviously I would need GDT to go into 32-bit mode, but I can't figure that out. I didn't care about the filesystem because I was worried that I would pass the 512 bytes limit. Yep, I want kernel.bin loaded from a filesystem, it is coded in complete i686 binary. I have seen projects like MikeOS and stuff like that but can't figure out how they call 32-bit binaries from assembly.

Re: I might just need the best bootloader in the world...

Posted: Tue Jan 20, 2015 1:20 am
by Brendan
Hi,
bashcommando wrote:Hello everybody, I am in a bit of a pickle. I need a bootloader that will load a filesystem(I don't care which) and then load a file called kernel.bin. Kernel.bin will expect to be in 32-bit mode so that is another problem. Is this even possible? -bashcommando
Are you sure you meant "a bootloader that will load a filesystem"? Typically you'd leave the file system on disk and wouldn't try to load several TiB of data into several GiB of RAM... ;)

Also note that I define "best boot loader in the world" quite differently (e.g. boot loader is only the first part of a "multi-stage" process, where other stages do a significant amount of work before the kernel is needed).


Cheers,

Brendan

Re: I might just need the best bootloader in the world...

Posted: Tue Jan 20, 2015 2:38 am
by iansjack
I want to make my own. Maybe I can reverse engineer grub? Obviously I would need GDT to go into 32-bit mode, but I can't figure that out.
Curb your ambition a little. If you are unable to figure out the GDT, how it works, and what the entries in it mean then you are not going to be able to write a bootloader that will load and run a 32-bit kernel. It's fine as a long-term ambition but you need to understand what you are doing first. There is a host of information on the web to help with this. And you could do worse than reading the Intel Programmers Manuals.

I would start by writing a simple kernel that is loaded by Grub. Resources on this Wiki show you how to do that.

Re: I might just need the best bootloader in the world...

Posted: Tue Jan 20, 2015 3:32 am
by bubach
I find it kind of paradoxical that you are looking for a bootloader that does it all for you,
and yet don't want to use GRUB because you "want ot do it yourself". :lol:

Anyway, here's one I wrote years ago, where I basically managed to cram in FAT12 loading,
A20 setting & Pmode into one. For obvious reasons, this isn't really a good idea - error
handling is basically non-existent.

Code: Select all

;------------------------------------------------------------;
;                 BOS - FAT12 bootsector                     ;
;------------------------------------------------------------;
;  - FAT12 compatible.                                       ;
;  - Loads a binary file from the floppy, max ~576kb.        ;
;  - Sets A20 and protected mode.                            ;
;                                                            ;
;  Thanks to: Petroff Heroj and John S. Fine for examples.   ;
;                                                            ;
;          by: Christoffer Bubach, 2003-2005                 ;
;                                                            ;
;------------------------------------------------------------;

; other notes:
;  this code is public domain, and you can use it for
;  anything you want. but if you do, please act polite and
;  give credit. ;-)
;
;            mem map
;  0x0000:0x0000 -> 0x0000:0x0500  BIOS stuff
;  0x0000:0x0500 -> 0x0000:0x2100  root
;  0x0000:0x2100 -> 0x0000:0x3300  fat
;  0x0000:0x3300 -> 0x0000:0x7c00  18,25kb free space
;  0x0000:0x7c00 -> 0x0000:0x7e00  bootsector
;  0x0000:0x7e00 <- 0x0000:0xffff  32,5kb stack
;  0x1000:0x0000 -> 0x9000:0xffff  576kb free space
;  0xa000:0x0000 -> .............  VGA mem etc.

use16
org 0x7C00

boot:     jmp     near start
          nop

;------------------------------------------;
;  Standard BIOS Parameter Block, "BPB".   ;
;------------------------------------------;
          bpbOEM          db  'BOS 0.03'
          bpbSectSize     dw  512
          bpbClustSize    db  1
          bpbReservedSec  dw  1
          bpbFats         db  2
          bpbRootSize     dw  224
          bpbTotalSect    dw  2880
          bpbMedia        db  240
          bpbFatSize      dw  9
          bpbTrackSect    dw  18
          bpbHeads        dw  2
          bpbHiddenSect   dd  0
          bpbLargeSect    dd  0
     ;---------------------------------;
     ;  extended BPB for FAT12/FAT16   ;
     ;---------------------------------;
          bpbDriveNo      db  0
          bpbReserved     db  0
          bpbSignature    db  0                       ; 0 = nothing more. 41 = three more (below)..
;          bpbID           dd  1
;          bpbVolumeLabel  db  'BOOT FLOPPY'
;          bpbFileSystem   db  'FAT12   '


;----------------------------------------;
;   starting point of bootsector code    ;
;----------------------------------------;
start:
          cli

          xor     ax, ax                              ; initialize all the necessary
          mov     ds, ax                              ; registers.
          mov     es, ax
          mov     ss, ax
          mov     sp, 0xFFFF                          ; Stack..

          mov     [bpbDriveNo], dl

          sti


;----------------------------------;
;   clear screen and print some    ;
;----------------------------------;
          mov     ax, 3                               ; Set mode 0x03
          int     0x10

          mov     bp, loading                         ; Print loading message.
          mov     ax, 0x1301
          mov     bx, 7
          mov     cx, 12
          mov     dx, 0x0102
          int     0x10

          mov     bl, 2                               ; Set cursor.
          mov     ah, 2
          mov     dx, 0x0201
          int     0x10

          mov     ah, 9                               ; Print 14 green dots.
          mov     al, '.'
          mov     cx, 14
          int     0x10


;---------------------------;
;    load FAT and root      ;
;---------------------------;
          mov     di, 0x0050                          ; Load the root to
          mov     ax, 19                              ; 0x0000:0x0500 (0x500/0x10)
          mov     cx, 14
          call    read_sectors

          mov     di, 0x0210                          ; Load the fat to
          mov     ax, 1                               ; 0x0000:0x2100
          mov     cx, 9
          call    read_sectors


     ;------------------------;
     ;  search for the file   ;
     ;------------------------;
          mov     dx, [bpbRootSize]
          mov     bx, 0x0500
     filesearch:
          cld
          mov     si, filename
          mov     cx, 11
          mov     di, bx
          repe    cmpsb
          je      found
          add     bx, 32
          dec     dx
          jz      error
          jmp     filesearch


;-----------------------------------;
;      variables & functions        ;
;-----------------------------------;
          loading         db  'Starting BOS'
          filename        db  'KERNEL  SYS'
          failure         db  'Read error!'
          a20_on          db  1


     ;-----------------------------------------------;
     ;   read a number of sectors (one at a time)    ;
     ;-----------------------------------------------;
     ;  in:                                          ;
     ;    di = segment to save at                    ;
     ;    ax = sector to read                        ;
     ;    cx = number of sectors                     ;
     ;  out:                                         ;
     ;    di = updated (added for next read)         ;
     ;    ax = updated (added for next read)         ;
     ;-----------------------------------------------;
     read_sectors:
          pusha
          mov     bl, byte [bpbTrackSect]             ; bl = number of sectors per track
          div     bl                                  ; al = ax / bl
          mov     cl, ah                              ; cl = real sector number
          add     cl, 1

          xor     ah, ah                              ; del the rest of the div before
          mov     bl, byte [bpbHeads]                 ; bl = number of heads
          div     bl                                  ; ah = rest of ( ax / bx ), al = ax / bx
          mov     ch, al                              ; ch = number of track
          mov     dh, ah                              ; dh = the head number

          mov     ax, cx                              ; save cx in ax
          mov     cx, 6                               ; try it 6 times
     .next_try:
          push    es
          push    cx
          mov     cx, ax                              ; restore cx
          push    cx

          xor     ax, ax
          mov     dl, [bpbDriveNo]                    ; reset drive
          push    dx
          int     0x13
          jc      .failed

          pop     dx
          pop     cx
          xor     bx, bx
          mov     es, di
          mov     ax, 0x0201                          ; function 2, 1 sector
          int     0x13
          jnc     .ok                                 ; if it was ok, check next..

     .failed:
          pop     dx
          pop     ax

          pop     cx
          pop     es
          loop    .next_try                           ; else try once again if there is an error
          jmp     error                               ; if cx = 0 and the read operation always failed, halt
     .ok:
          pop     cx                                  ; from the next_try loop
          pop     es
          popa
          add     di, 32                              ; add 32 (512/16) to segment
          inc     ax                                  ; add sector counter
          loop    read_sectors
          ret


     ;----------------------------------------------------;
     ;  show a message and wait for a key before reboot   ;
     ;----------------------------------------------------;
     error:
          ;push    0x0000
          ;pop     es
          mov     bp, failure
          mov     ax, 0x1301
          mov     bx, 4
          mov     cx, 43
          mov     dx, 0x0401
          int     0x10

          mov     ah, 0
          int     0x16
          int     0x19


;-----------------------------------;
;   the file is found, load it.     ;
;-----------------------------------;
found:
          mov     bp, [bx+26]                         ; bp=cluster number from directory entry
          mov     di, 0x1000                          ; 1000 (segment)

     .next_block:
          xor     cx, cx
          mov     cl, [bpbClustSize]                  ; reset sector count to 1 cluster
          mov     si, bp                              ; si=next should-be cluster for
                                                      ; contiguous reads
     .next_contiguous:
          mov     ax, 3                               ; 3
          mul     si                                  ; multiply cluster number by 3
                                                      ; dx assumed to be 0, it's a floppy!
          shr     ax, 1                               ; divide by two
          push    bp
          xchg    bp, ax                              ; bp=ax
          mov     ax, word [0x2100+bp]                ; ax=FAT element with junk
                                                      ; (addressing with bp)
          pop     bp
          jc      byte .odd_cluster                   ; jump if the value was odd

     .even_cluster:
          and     ax, 0x0FFF                          ; leave only lower 12 bits
          jmp     .got_cluster                        ; got it

     .odd_cluster:
          push    cx                                  ; preserve sector count
          mov     cl, 4                               ; shift four bits right
          shr     ax, cl                              ; (leave only bits 4-15)
          pop     cx                                  ; restore sector count

     .got_cluster:
          inc     si                                  ; si=current cluster+1
          cmp     ax, si                              ; next cluster=current cluster+1?
          jne     byte .force_read                    ; is it still contiguous?

          add     cl, [bpbClustSize]                  ; increase sector count by 1 cluster
          adc     ch, 0
          jmp     .next_contiguous

     .force_read:
          xchg    bp, ax                              ; ax=bp (base cluster), bp=new cluster
          dec     ax                                  ; decrease by 2 to get the actual... (1)
          dec     ax                                  ; ...cluster number (2)

          xor     dx, dx
          mov     dl, [bpbClustSize]
          mul     dx                                  ; multiply by sectors per cluster
                                                      ; (dx ignored)
          add     ax, 33                              ; assume data-area start at sector 33
          call    read_sectors                        ; read cx sectors at ax to es:0 :)

          cmp     bp, 0x0FF8                          ; the new cluster is EOF (FF8-FFF)?
          jb      byte .next_block                    ; if not in this range, read next block

;-----------------------;
;  the file is loaded   ;
;-----------------------;
quit:
a20:                                                  ; Enable A20
          in      al, 0x64
          test    al, 2
          jnz     a20
          mov     al, 0xD1
          out     0x64, al
     .d6:
          in      al, 0x64
          and     ax, 2
          jnz     .d6
          mov     al, 0xDF
          out     0x60, al

     .a20_check:
          mov     al, byte [fs:0]                     ; check a20, is it on?
          mov     ah, al
          not     al
          xchg    al, byte [gs:0x10]
          cmp     ah, byte [fs:0]
          mov     [gs:0x10], al
          jz      floppy_off
          mov     [a20_on], 0                         ; it's not on save for file..

floppy_off:
          mov     dx, 0x3F2                           ; turn of the floppy motor.
          mov     al, 0
          out     dx, al

pmode:
          cli                                         ; set protected mode (32-bit)
          lgdt    [gdtr]
          mov     eax, cr0
          or      eax, 1
          mov     cr0, eax

          jmp     0x08:flush


;----------------------------------------;
; start of 32-bit area.                  ;
;     flush segments and jump to kernel  ;
;----------------------------------------;
use32
flush:
          mov     eax, 0x10                           ; refresh all segment registers
          mov     ds, eax
          mov     es, eax
          mov     fs, eax
          mov     gs, eax
          mov     ss, eax
          mov     esp, 0xfffc

          mov     eax, 0xB05B007                      ; report "BOSboot".. ;-)
          mov     bl, [a20_on]                        ; report if a20 is on.
          jmp     0x08:0x10000                        ; jump to loaded file (64kb in mem)



;--------------------------------;
;  global descriptor table (gdt) ;
;--------------------------------;
gdt:                      dw  0x0000, 0x0000, 0x0000, 0x0000
codesel:                  dw  0xFFFF, 0x0000, 0x9800, 0x00CF
datasel:                  dw  0xFFFF, 0x0000, 0x9200, 0x00CF
gdt_end:

gdtr:                     dw  gdt_end - gdt - 1
                          dd  gdt

;-------------------------------------;
; set the BOOT-signature at byte 510. ;
;-------------------------------------;
          rb boot+512-2-$
          dw 0xAA55

Re: I might just need the best bootloader in the world...

Posted: Tue Jan 20, 2015 1:10 pm
by bashcommando
bubach wrote:I find it kind of paradoxical that you are looking for a bootloader that does it all for you,
and yet don't want to use GRUB because you "want ot do it yourself". :lol:

Anyway, here's one I wrote years ago, where I basically managed to cram in FAT12 loading,
A20 setting & Pmode into one. For obvious reasons, this isn't really a good idea - error
handling is basically non-existent.
Oh thanks, that looks great!

Re: I might just need the best bootloader in the world...

Posted: Tue Jan 20, 2015 1:44 pm
by Combuster
bashcommando wrote:

Code: Select all

300 nasm errors, roughly one for each line
Looks like you haven't even learned how to properly copy-paste. Do we need to put that in the required knowledge as well? :evil:

(There should be one error, only because RB isn't nasm-proof.)

Re: I might just need the best bootloader in the world...

Posted: Tue Jan 20, 2015 1:49 pm
by bashcommando
Combuster wrote:Looks like you haven't even learned how to properly copy-paste. Do we need to put that in the required knowledge as well? :evil:

(There should be one error, only because RB isn't nasm-proof.)
I might have deleted a line by mistake or something. Lesson learned.

Re: I might just need the best bootloader in the world...

Posted: Tue Jan 20, 2015 1:50 pm
by bashcommando
Combuster wrote:Looks like you haven't even learned how to properly copy-paste. Do we need to put that in the required knowledge as well? :evil:

(There should be one error, only because RB isn't nasm-proof.)
Oh by the way, can the rb line be replaced with times? Besides you realize some lines are commented, without editing it shows one error. (the rb line)

Re: I might just need the best bootloader in the world...

Posted: Tue Jan 20, 2015 2:42 pm
by bashcommando
Combuster wrote:Looks like you haven't even learned how to properly copy-paste. Do we need to put that in the required knowledge as well? :evil:

(There should be one error, only because RB isn't nasm-proof.)
No seriously what does rb do? It looks kind of like times but what do I replace it with? I looked it up and nothing. No opcodes relating to rb?

Re: I might just need the best bootloader in the world...

Posted: Tue Jan 20, 2015 6:19 pm
by Bender
bashcommando wrote:
Combuster wrote:Looks like you haven't even learned how to properly copy-paste. Do we need to put that in the required knowledge as well? :evil:

(There should be one error, only because RB isn't nasm-proof.)
No seriously what does rb do? It looks kind of like times but what do I replace it with? I looked it up and nothing. No opcodes relating to rb?
RB is the FASM equivalent of NASM's resb. It basically stands for "reserve bytes". It is same as "times db X" but it leaves the region uninitialized, not even random numbers, it is left as nothing. It usually is used for page alignment, declaring data in the BSS and stuff like that. In this case however, it's same as "times db" since there's data (0xAA55) after the reserved region, which makes the assembler place 0's (hopefully) in there.

And here's the official reference: http://www.nasm.us/doc/nasmdoc3.html

EDIT: I just realised that the mechanism may differ between formats. But since this is binary it should be pretty okay.

Re: I might just need the best bootloader in the world...

Posted: Wed Jan 21, 2015 11:08 am
by bashcommando
Bender wrote:RB is the FASM equivalent of NASM's resb. It basically stands for "reserve bytes". It is same as "times db X" but it leaves the region uninitialized, not even random numbers, it is left as nothing. It usually is used for page alignment, declaring data in the BSS and stuff like that. In this case however, it's same as "times db" since there's data (0xAA55) after the reserved region, which makes the assembler place 0's (hopefully) in there.

And here's the official reference: http://www.nasm.us/doc/nasmdoc3.html

EDIT: I just realised that the mechanism may differ between formats. But since this is binary it should be pretty okay.
So in this case do I replace rb with resb?

Re: I might just need the best bootloader in the world...

Posted: Wed Jan 21, 2015 5:44 pm
by bubach
It probably would have taken you less time to try that for yourself then to come here and ask us..... Also I forgot to mention that I used fasm but if the padding code to make it 512 bytes is the only thing that keeps you from using nasm... and you can't even find a nasm bootloader to copy the syntax from? You might be beyond all hope of ever getting somewhere. Sorry.

Re: I might just need the best bootloader in the world...

Posted: Wed Jan 21, 2015 7:08 pm
by bashcommando
bubach wrote:It probably would have taken you less time to try that for yourself then to come here and ask us..... Also I forgot to mention that I used fasm but if the padding code to make it 512 bytes is the only thing that keeps you from using nasm... and you can't even find a nasm bootloader to copy the syntax from? You might be beyond all hope of ever getting somewhere. Sorry.
Earlier I found the MikeOS bootloader which does everything but load 32-bit mode. Why didn't you say you used fasm? That would have made my life easier but I learned something from it. I am not hopeless, I have much to learn.