Implementing bootloader

Started by ggnfs000, January 07, 2017, 06:03:04 AM

Previous topic - Next topic

ggnfs000

Implementing bootloader

[html]I have been away from my project for about 3 months and started resuming on the bootloader. 
Basically I have 3 file:
copyraw.exe - copies boot.bin to mbr (without overwriting p-table) and copies exp.exe below to sector 1 and so on. 
boot.bin - bootloader that is less than 512 bytes.
exp.exe - actual executable that is loaded by bootloader.

Initially no concern regarding the FAT, it is all raw stuff. 

To prove the bootloader is loaded successfully to 0000:7c00h, i put small snippet to printed chars starting from 0 incrementing by 2 10 times (02468... ) to beginning of video buffer area 0000:b800h This part works.
After that boot loader should copy exp.exe file starting from sector 1 to 0000:8000h and subsequent sectors to 0000:8200h and so on. 
The exp.exe starts with printing ABCD... 10h times to video buffer area 0000:b820h. This is where it does not seem to work anymore which I am still checking. 

Here I put down source for bootloader (boot.asm), exp.exe (loadable executable) and copyraw (the one that raw copies bootloader and executable into disk and its output log below.

;boot.asm

686p

    include macros.inc

;   re-defined the part of disk.inc here so that no need to include
;   disk.asm,

DAP_OFFSET_SIZE =       0
DAP_OFFSET_UNUSED =     1
DAP_OFFSET_NO_SECTORS = 2
DAP_OFFSET_BUFFER_PTR = 4
DAP_OFFSET_SECTOR_START = 8

sta segment para stack use16 'stack'
sta ends

data segment para public 'data'
data ends

code segment para public use16 'code'
assume cs:code, ds:data,ss:sta

M_EXTERNDEF

;   code to be copied to 1st sector of HDD.
;   this code will do a boot strap by copying main program into another
;   program and will do a jmp.
;   the size of this function must be less than 512 bytes in order to
;   fit onto 1st sector.

    main    proc    far

;    Print a series of char into screen buffer, to verify this code has been reached
;   and been executed by a processor. 

    mov     si, 0b800h
    mov     ds, si
    sub     si, si              ; (DS:SI) = video buffer.
    mov     cx, 10h            ; display 80 times.
    mov     ax, 0e30h         ; char to display byte1: color, byte2: char 0.

loop1:
    mov     ds:[si], al
    inc     al                  ; (AL) = next digit.
    cmp     al, 39h             ; reset to 0 if 9
    jb      @f
    mov     al, 30h
@@:
    add     si, 2               ; (SI) = next char.
    loop    loop1

    mov     dl, 80h             ; disk 0

    mov     si, 7e00h           ;
    mov     ds, si
    sub     si, si              ; (DS:SI) = 0000:7e00h = DAP area.

    mov     byte ptr ds:[si+DAP_OFFSET_SIZE], 10h
    mov     byte ptr ds:[si+DAP_OFFSET_UNUSED], 00h
    mov     word ptr ds:[si+DAP_OFFSET_NO_SECTORS], (400h * 64) ; copy 64k

    mov     word ptr ds:[si+DAP_OFFSET_BUFFER_PTR], 8000h
    mov     word ptr ds:[si+DAP_OFFSET_BUFFER_PTR+2], 00h

    mov     dword ptr ds:[si+DAP_OFFSET_SECTOR_START], eax
    mov     dword ptr ds:[si+DAP_OFFSET_SECTOR_START+4], 0h ; set starting sector No for upper 48 lba.

    mov     ah, 42h             ; (AH) = fcn No. for extended disk read.
    int     13h

    sub     si, si
    mov     ds, si
    mov     si, 8000h           ; (DS:SI) = location, 0:8000h to jump to, pt of no ret.

    jmp     word ptr ds:[si]
   
;   Should never reach here. Also up to this point should better not exceed 512 bytes.

   fileEnd    db  55h, 0aah
    main    endp
code    ends
    end     main

;exp.asm


.686p

    include macros.inc
    include exp.inc

code segment para public use16 'code'
assume cs:code, ds:data,ss:sta
M_EXTERNDEF

main    proc    far
    mov     ax, DATA
    mov     ds, ax
    mov     si, 0b800h
    add     si, 20h             ; Leave bootloader written area behind.
    mov     ds, si
    sub     si, si              ; (DS:SI) = video buffer.
    mov     cx, 10h             ; display 80 times.
    mov     ax, 'A'             ; char to display byte1: color, byte2: char 0.

loop1:
    mov     ds:[si], al
    inc     al                  ; (AL) = next digit.
    cmp     al, 'E'             ; reset to 0 if 9
    jb      @f
    mov     al, 'A'
@@:
    add     si, 2               ; (SI) = next char.
    loop    loop1


; rawcopy.asm:


    include macros.inc
    include disk.inc

;   re-defined the part of disk.inc here so that no need to include
;   disk.asm,

DAP_OFFSET_SIZE =       0
DAP_OFFSET_UNUSED =     1
DAP_OFFSET_NO_SECTORS = 2
DAP_OFFSET_BUFFER_PTR = 4
DAP_OFFSET_SECTOR_START = 8

sta segment para stack use16 'stack'
sta ends

;   here we define variables bootloader.

data segment para public 'data'
fileName    db  "boot.bin", 0
dosHdrBuffer db  512 dup (36h)
mbrBuffer   db  512 dup (37h)   ; mbr write buffer.
mbrReadBuffer db 512 dup (35h)  ; mbr read first and partition table is copied to mbrBuffer
filePointer dw  ?
readSize    dw  ?

;   here we define variables for file being loaded. will be kernel.

fileName1   db  "exp.exe$"
mbrBuffer1  db  512 dup (38h)
filePointer1 dw  ?
readSize1   dw  ?
counter     dd  0

;   disk access packet area.

dap             db  16  dup(31h)
data ends

code segment para public use16 'code'
assume cs:code, ds:data,ss:sta

M_EXTERNDEF

;   code to be copy mbr code to 1st sector of HDD (sector No. 0).
;   this will open boot.bin (bootloader) file and reads first 1024
;   (should read entire file) bytes into pre-defined buffer and will copy
;   the entire file content (minus DOS header) into Disk 80h sector 0.

    main    proc    far

;   do not run from windows, prevent accidental erase of MBR in case it is allowed.

    mov     eax, cr0
    test    eax, 01
    jz      mainLab1

    M_PRINTF "\nCan not run from protected mode."
    jmp     mainExit

mainLab1:

;   Read sector 0 first. Doing so will help preserve the partition table
;   when we write back after loading boot.bin and overwrite first 200h-64 bytes.

    mov     dl, 80h             ; disk 0

    mov     si, DATA
    mov     ds, si
    lea     si, dap             ; (DS:SI) = SEG:OFF pointer to dap.

;   Prepare DAP area.

    mov     cx, 1               ; (CX) = No. of sectors.
    mov     di, DATA
    mov     es, di
    lea     di, mbrBuffer       ; (DS:SI) = SEG:OFF pointer to dap.

    mov     byte ptr ds:[si+DAP_OFFSET_SIZE], 10h
    mov     byte ptr ds:[si+DAP_OFFSET_UNUSED], 00h
    mov     word ptr ds:[si+DAP_OFFSET_NO_SECTORS], cx

    mov     word ptr ds:[si+DAP_OFFSET_BUFFER_PTR], di
    mov     word ptr ds:[si+DAP_OFFSET_BUFFER_PTR+2], es

    mov     dword ptr ds:[si+DAP_OFFSET_SECTOR_START], 0h
    mov     dword ptr ds:[si+DAP_OFFSET_SECTOR_START+4], 0h ; set starting sector No for upper 48 lba.

;   Issue read DOS function to read into region defined by DAP area.

    mov     ah, 42h             ; (AH) = fcn No. for extended disk read.
    int     13h                 ; (AH) = return code if error reading.
    jnc     mainLab1a

    M_PRINTF "\nRead sector 0 failure. Exiting (Error code): "
    M_PRINTBYTE ah
    jmp     mainExit

mainLab1a:
    M_PRINTF "\nRead sector 0 success."
    M_PRINTSTR_1616_NL es, di, 0, 020h

;   Open bootstrap file. Will copy first 512-64 bytes overwriting the DAP area.

    mov     ah, 3dh             ; (AH) = file open int 21h code.
    sub     al, al              ; (AL) = RO mode.
    mov     dx, DATA
    mov     ds, dx
    lea     dx, fileName        ; (DS:DX) = pointer to filename string.

    M_PRINTF "\nbootloader file (boot.bin): "
    M_PRINTSTR_1616_NL ds, dx, 1, 7

    int     21h                 ; (AX) = file handle.
    jnc     mainLab2

    M_PRINTF "\nFailure opening boot.bin file (error code): "
    M_PRINTWORD ax
    jmp     mainExit

;   Read till the end or up to 1024 - 64  (dos header + mbr - partition table size)
;   into buffer if FF pointer is successful.

mainLab2:
    M_PRINTF "\nSuccess opening file boot.bin (fileHandle), reading: "
    M_PRINTWORD ax

    mov     filePointer, ax     ; save file pointer.
    mov     ah, 3fh             ; (AH) = file read int 21h code.
    mov     bx, filePointer     ; (BX) = file pointer.
    mov     cx, 400h - 64       ; (CX) = 1024 - bytes but leave partition table area.
    mov     dx, DATA
    mov     ds, dx
    lea     dx, dosHdrBuffer    ; (DS:DX) = 16:16 buffer to read into.
    int     21h                 ; (AX) = No. of bytes read if success.
    jnc     mainLab3

    M_PRINTF "\nFailed to read boot.bin file (Error code): "
    M_PRINTWORD ax
    jmp     mainExit

;   copy to disk 80h sector 0. Since the first 200h bytes of read is dosheader
;   we point the DS:SI to right after dosHeaderBuffer which is mbrBuffer
;   which itself is 512 bytes.

mainLab3:
    M_PRINTF "\nRead success for boot.bin (No. of bytes): "
    M_PRINTWORD ax

    mov     readSize, ax        ; save read size.
    mov     dl, 80h             ; disk 0

;   Start writing DAP area back to sector 0.

    mov     si, DATA
    mov     ds, si
    lea     si, dap             ; (DS:SI) = SEG:OFF pointer to dap.

    mov     di, DATA
    mov     es, di
    lea     di, mbrBuffer       ; (DS:SI) = SEG:OFF pointer to dap.