Author Topic: 2 Stage Bootloader  (Read 24741 times)

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2361
  • Country: us
Re: 2 Stage Bootloader
« Reply #60 on: July 28, 2014, 07:57:29 PM »
Code: [Select]
mov [jumptarget], ES
mov [jumptarget + 2], DI
jmp far [jumptarget]

Nope. Little-endian.

Code: [Select]
mov [jumptarget], DI
mov [jumptarget + 2], ES
jmp far [jumptarget]

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #61 on: July 28, 2014, 08:01:11 PM »
Thanks for clarifying still wouldn't work but thanks anyway I will keep at it
Thanks in advance, Anonymous

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #62 on: July 28, 2014, 09:15:30 PM »
I tried modifying it by using some of the code that I attached but still no luck am probably gonna switch back to what I was doing before but its attached it you want to see it it is too big to fit in this post also I found this link on the specification of El torito standard here it is : http://bazaar.launchpad.net/~libburnia-team/libisofs/scdbackup/view/head:/doc/boot_sectors.txt , Here as well : http://wiki.osdev.org/El-Torito , I've been reading about a path table which you can use to jump to the address of the file which is probably what I need Ill keep reading  up on this hope this helps you guys help me :D
« Last Edit: July 29, 2014, 04:46:00 AM by Anonymous »
Thanks in advance, Anonymous

Offline gammac

  • Jr. Member
  • *
  • Posts: 71
  • Country: 00
Re: 2 Stage Bootloader
« Reply #63 on: July 29, 2014, 03:30:31 PM »
Sorry, I can't resist, I have to ask. ;)

Are you sure that your image file is a valid image with functional file system?
Please comment your code! It helps to help you.

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #64 on: July 29, 2014, 05:29:37 PM »
Well I am sure that the image is bootable and has a file system, am I sure that the little driver I am writing for it is working no I am not thats why am I here.
Thanks in advance, Anonymous

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #65 on: July 29, 2014, 06:21:28 PM »
Here I this is my most recent try at this if it helps:
EDIT: Updated to new Code so there is no confusion
Code: [Select]
[BITS   16]

[ORG  0x0]

Start: jmp main


;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW:  db 0
LOADSEG equ 0x200 ; ?
LOADOFFS equ 0 ; ?
jumptarget dw LOADOFFS, LOADSEG
;macro for print
%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_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:;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

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

;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],0
ret


Read_Sectors: 
        ;/* Read the sector into memory. */
       
.ForLoop:
mov     ah,042h
xor     al,al
mov     si, DiskAddressPacket
mov     dl, [CDDriveNumber]
int     013h
        jnc    .Success ; /* read error? */

        Print Read_Sector_Error_MSG, RED

cli
hlt

.Success:
Print Progress_MSG , PURPLE
inc WORD[DiskAddressPacket.SectorsToRead]

        loop    .ForLoop
call Print_ln
ret
CHECK_DESC:
Print CHECK_DESC_MSG, TEAL
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]

xor bx, bx
.top:
mov al, BYTE[ES:DI+BX]
mov BYTE[VOLUME+BX], al

inc bx
cmp al, ' '
je .Done
jmp .top
.Done:

;see if the Volume descriptor contains the Signature
xor BX, BX; clear out bx
add BX, 0x01;move into bx the offset
xor cx, cx;clear out cx
.toploop:
xor ax, ax
mov al, BYTE[VOLUME+BX]
cmp al, BYTE[CD_Signature+BX-1]
je .FOUND_IT; Compare the letters Byte by Byte to see if they are the same
jmp .Done2
inc CX;increments if even one letter is wrong
.FOUND_IT:
Print Progress_MSG, PURPLE
inc BX;Increments the offset

jmp .toploop

.Done2:
cmp CX, 0;if signatures don't match then stop the system and print an error Message
jne .FAIL
call Print_ln

Print FOUND_CD, TEAL
jmp .Done3
.FAIL:
Print FILE_NOT_FOUND, RED
cli
hlt
.Done3:
call Print_ln
ret
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL
call Print_ln

mov di, [DiskAddressPacket.Offset]
mov es, [DiskAddressPacket.Segment]


    xor BX, BX;clears out bx
xor si, si ;clears out si
xor cx, cx
    .top:


MOV AL,BYTE[ES:DI+BX] ;moves a byte of a possible start of a file entry
cmp AL,BYTE[STAGE2];compares it with file I want
je .Done;if it is then jump out of loop
INC BX;get ready for next file entry
jmp .top

.Done:
Print Found_Possible_FILE, TEAL;prints it found a possible file
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter
.top2:;compares strings to see if they are the same
;xor ax, ax;clears out acx

;prints out a letter to the screen
MOV AL, BYTE[ES:DI+BX]
MOV AH, 0xE
INT 0x010
;;;;;;;;;;;;;;;;;;

xor ax, ax
MOV AL, BYTE [ES:DI+BX]
cmp AL, BYTE[STAGE2+SI]

je .Success
call Print_ln
jmp .top
.Success:

;Print Progress_MSG, PURPLE;progress message


INC BX;get ready for next character
INC SI;get ready for next character
INC CX; increment counter
cmp CX, WORD[STAGE_2_LEN]
jne .top2
;call clear
call Print_ln
Print File_Found, TEAL;prints found file if found
call Print_ln

Print Reading_Sectors, TEAL;prints reading sector message
;call clear
SUB BX, WORD[STAGE_2_LEN];goes back to the start of the file
ADD DI, BX;adds to the offset
;moves in the new address ES:DI into the DAP
;MOV WORD[DiskAddressPacket.Offset], DI
;MOV WORD[DiskAddressPacket.Segment], ES
;MOV EAX, [ES:DI]
;MOV DWORD[DiskAddressPacket.End],EAX
;MOV WORD[DiskAddressPacket.SectorsToRead], 4
;read all sectors

xor cx, cx;clears out cx
mov cx, 0x01;puts in cx 0x04 for how many sectors to read
call Read_Sectors;calls the read sectors
Print READ_SUCCESS, TEAL;if it gets here that means it was successful
;jump to where the file is located and run it
call Print_ln
MOV AX, ES
call itoa


mov AL, ':'
MOV AH, 0xE
INT 0x010



MOV AX, DI
call itoa

call Print_ln

;call clear
mov [jumptarget], WORD 0x000
    mov [jumptarget + 2], WORD 0x200
    jmp far [jumptarget]
;jmp 000h:0000D800h

;PUSH  0x0200
;PUSH  0x0000
;retf
.FAIL:;it failed so print that the file wasn't found and halt the system
call Print_ln
Print FILE_NOT_FOUND, RED
cli
hlt
         
ret
main:
;first stage of bootloader is loaded at the address 0x07c0:0x0FFFF
;second stage of bootloader is loaded at address 0x9000:0x0FFFF
cli
mov ax, 0x07c0 ;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 ,0x0FFFE
sti

mov     [CDDriveNumber],dl
call clear


Print W_MSG, TEAL;prints the loading message in colour
call Print_ln


;First find the Signature of the CD
Print Reading_Sectors, TEAL
LOAD_SIGNATURE:
mov cx, 0x04
call Read_Sectors

Print READ_SUCCESS, TEAL
call Print_ln
;load the Volume descriptor to the Volume variable
call CHECK_DESC
;Now Load the Root Directory from the Volume Descriptor
LOAD_ROOT:
;Print Reading_Sectors, TEAL
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]

XOR BX, BX
MOV BX, 40 ;move in the offset
VolumeLabelLoop:

MOV CL,[ES:DI+BX]                   ; Grab a letter
CMP CL,' '                          ; Is it a space? (Assumes end of string is space, may run out)
JE .VolumeLabelDone                 ; Yes, we are done

MOV [VOLUME+BX-40],CL
INC BX
JMP VolumeLabelLoop                 ; Need to compare BX to length of Volume Label on CD (32?)

.VolumeLabelDone:
Print Reading_Sectors, TEAL
MOV byte [VOLUME+BX-40],0      ; End the string

MOV EAX,[ES:DI+158]                 ; LBA of root directory, where all things start.
;MOV [DiskAddressPacket.End],EAX     ; Load packet with new address on CD of the root directory

MOV DWORD[DiskAddressPacket.End],EAX     ; Load packet with new address on CD of the root directory
xor cx, cx
mov cx, 0x01
call Read_Sectors
                             

Print READ_SUCCESS, TEAL;if the program gets here it means it was a success
call Print_ln

LOAD_STAGE2:

call READ_STAGE2


.FAILURE:
Print FILE_NOT_FOUND, RED
cli
hlt


Sector_Size: dw   512
CDDriveNumber: db   0x080
CD_Signature:     db    "CD001"
CD_FILE_VER:     db    0x01
CD_FileNameLength: db   0x0
CD_dir_curr_size: db 0x0
Reading_Sectors: db "Reading sectors", 0
CHECK_DESC_MSG: db "Checking for CD Signature",0
LOADING_STAGE2_MSG: db "Loading Stage 2 of boot loader",0
STAGE_2_LEN: DW 0xA
File_Found: db "File for Stage 2 of the bootloader was found!!",0
LOADING_STAGE2_FAILED: db  "Failed to load Stage 2 of the boot loader !!!!!",0
Found_Possible_FILE: db "Found Possible File",0
Colon: db ":",0
FILE_ENTRY: db 0
JolietSig       DB  25h, 2fh, 45h                               ; this is the value of the escape sequence for a Joliet CD
;Disk Address Packet


DiskAddressPacket:          db 0x010,0  
.SectorsToRead:             dw 1                              ; Number of sectors to read (read size of OS)
.Offset:                    dw 0                              ; Offset :0000
.Segment:                   dw 0x0200                         ; Segment 0200
.End:                       dq 0x010                             ; Sector 16 or 10h on CD-ROM

VOLUME: DW 0

W_MSG: db "Loading Z-Boot", 0
STAGE2: db "STAGE2.BIN"
Read_Sector_Error_MSG: db "Error, failed to read sector",0
READ_SUCCESS: db "Sectors read correctly!",0
Progress_MSG: db ".",0
FILE_NOT_FOUND: db "Error, file not found!",0
FOUND_CD: db "Found the CD Signature!", 0
times 2046 - ($ - $$) db 0; padd out the rest of the file to 0
DW 0xAA55; boot signature
BTW Just noticed this is the longest topic in the history of this forum
« Last Edit: July 31, 2014, 03:29:50 AM by Anonymous »
Thanks in advance, Anonymous

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #66 on: July 29, 2014, 09:41:56 PM »
Anyone else have anything I am stuck I really don't know what to do now :-\
Thanks in advance, Anonymous

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #67 on: July 30, 2014, 06:17:36 AM »
Ok So I am now using org 0 because as I have come to find out that's where I would be jumping to if I was jumping to 0x0200:0x000 still no change I also think it might be the way I set up my segments and offsets when creating the stack in both stages in Stage1 of the boot loader the segment:offset address is at 0x07c0:0x0FFFF and the Stage2 address is 0x9000:0x0FFFF Maybe that might be the problem but I have no idea what to change it to.
Thanks in advance, Anonymous

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2361
  • Country: us
Re: 2 Stage Bootloader
« Reply #68 on: July 30, 2014, 07:18:50 AM »
Quote
BTW Just noticed this is the longest topic in the history of this forum
Congratulations! You have won a prize - a FREE COPY of Nasm!

Seriously, I haven't even finished reading the version before last. You are fast approaching the point where you need some version control (git or something) or I won't be the only one who's confused about which version is which.

Your stack is poorly aligned (again), but I doubt if that's the problem. Some systems use the upper part of segment 0x9000 for something (I forget what, if I ever knew). That could be a problem, but I doubt it. Your first stage stack is at 0:0xFFFF (according to the code), not 0x7C0:0xFFFF as you state.

This is almost certainly wrong:
Code: [Select]
        LEA EAX, [ES:DI]
MOV DWORD[DiskAddressPacket.End],EAX

"VOLUME" is defined as "db 0", but you appear to be putting multiple bytes in it.

Code: [Select]
        je .FOUND_IT; Compare the letters Byte by Byte to see if they are the same
jmp .Done2
inc CX;increments if even one letter is wrong
.FOUND_IT:
The "inc cx" is never executed.

In no particular order, those are some things I see wrong in your latest(?) version.

As our friend Betov used to say, "Courage!"

Best,
Frank


Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #69 on: July 30, 2014, 07:28:33 AM »
Ya you are right I accidently posted the wrong code I am Because my Read stage 2 function doesen't look like that anymore other than that I changed the volume to a defined word no change I'll work on Version Control and won't post as much code Maybe I'll find the answer this time, Also I updated the code above to the correct version
« Last Edit: July 31, 2014, 03:30:25 AM by Anonymous »
Thanks in advance, Anonymous

Offline Anonymous

  • Jr. Member
  • *
  • Posts: 78
  • Country: us
Re: 2 Stage Bootloader
« Reply #70 on: August 06, 2014, 07:56:10 AM »
It works now finally after searching and countless nights hacking at my code to figure out what was wrong here is the soulution it is attached if anyone wants to look at the code
Thanks in advance, Anonymous

Offline Tony201500

  • New Member
  • Posts: 1
Re: 2 Stage Bootloader
« Reply #71 on: July 23, 2015, 04:59:45 AM »
hi there,

i am experimenting with developing a 64bit os from the ground up. i have 2 asm files: (stage1.asm, stage2.asm). stage 2 will be the 64bit kernel loader (not quite there yet). at the moment stage 2 will simply display the usual welcome text.

stage 1 simply has to find and load stage 2 from fat32. how do i combine the 2 files so that i can run it in bochs.

my development environment is:
win7 pro 64bit
bochs
nasm

thanks for your help,
tony

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2361
  • Country: us
Re: 2 Stage Bootloader
« Reply #72 on: July 23, 2015, 09:01:12 AM »
Hi Tony,

I'm not really familiar with Bochs. I was under the impression that it came with its own disk image manipulation program, no?

I assume when you want to load Stage2.bin "from FAT32", you mean as a "named file". I don't think you really need to "combine" the files - more like "fake copy" it to "fake disk". It may be somewhat easier, to get started, to put Stage2 in known sectors (right after Stage1, probably) - but you've gotta deal with file systems eventually...

I'd poke around osdev.org and see if you can find examples of getting started with Bochs

http://wiki.osdev.org/Bochs

Best,
Frank