NASM - The Netwide Assembler

NASM Forum => Programming with NASM => Topic started by: Anonymous on July 21, 2014, 08:27:35 PM

Title: 2 Stage Bootloader
Post by: Anonymous on July 21, 2014, 08:27:35 PM
I have been following this tutorial in programming your own OS but for now I wanna just focus on the bootloader how it works what tools I need to create one etc.. So Now I have created the first part of the bootloader and I have modified it from the tutorial by adding my own itoa and atoi functions and creating my own version of the print string function here is my code for stage 1 and the link to the tutorial : Link: http://www.brokenthorn.com/Resources Code :
Code: [Select]
[BITS 16]
[ORG 0x7c00]

jmp Start


Start:
;set up the stack
xor ax, ax;set ax to zero remember that the when both value are the same in the exclusive or operation the both cancel out to zero
mov ds, ax
mov ss, ax

mov sp, 0x9c00
mov es, ax

;pass in the message into si Register
mov si, MSG
;then call the String print function
call sPrint

xor ax, ax;clear out ax for use
int 0x12;returns amount of ram in ax

call itoa


.Reset:
mov ah, 0 ; reset floppy disk function
mov dl, 0 ; drive 0 is floppy drive
int 0x13 ; call BIOS
jc .Reset ; If Carry Flag (CF) is set, there was an error. Try resetting again
 .Read:
mov ax, 0x1000 ; we are going to read sector to into address 0x1000:0
mov es, ax
xor bx, bx
 
mov ah, 0x02 ; read floppy sector function
mov al, 1 ; read 1 sector
mov ch, 1 ; we are reading the second sector past us, so its still on track 1
mov cl, 2 ; sector to read (The second sector)
mov dh, 0 ; head number
mov dl, 0 ; drive number. Remember Drive 0 is floppy drive.
int 0x13 ; call BIOS - Read the sector

 
jmp 0x1000:0x0 ; jump to execute the sector!



cli;clear interrupts
hlt;halt the system






%include "itoa_atoi.asm"
Input db 0
BootDrive dw 0
MSG: db "This is my OS! The number is : ",13,10,0

;vars

bpbOEM db "My OS   "

bpbBytesPerSector:  DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs:     DB 2
bpbRootEntries:     DW 224
bpbTotalSectors:     DW 2880
bpbMedia:             DB 0xF0
bpbSectorsPerFAT:     DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors:     DD 0
bpbTotalSectorsBig:     DD 0
bsDriveNumber:         DB 0
bsUnused:             DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber:         DD 0xa0a1a2a3
bsVolumeLabel:         DB "MOS FLOPPY "
bsFileSystem:         DB "FAT12   "


;vars

times 510 - ($-$$) db 0
dw 0xAA55




Stage 2 boot loader :
Code: [Select]
; Note: Here, we are executed like a normal
; COM program, but we are still in Ring 0.
; We will use this loader to set up 32 bit
; mode and basic exception handling
 
; This loaded program will be our 32 bit Kernel.
 
; We do not have the limitation of 512 bytes here,
; so we can add anything we want here!
 
org 0x0 ; offset to 0, we will set segments later
 
bits 16 ; we are still in real mode
 
; we are loaded at linear address 0x10000
 
jmp main ; jump to main
 
 
;*************************************************;
; Second Stage Loader Entry Point
;************************************************;
 
main:
cli ; clear interrupts
push cs ; Insure DS=CS
pop ds
 
mov si, Msg
call sPrint
 
cli ; clear interrupts to prevent triple faults
hlt ; hault the system
 
;*************************************************;
; Data Section
;************************************************;
%include "itoa_atoi.asm"
Msg db "Preparing to load operating system...",13,10,0

Here is the include file don't know why I didn't put it here in the first place
Code: [Select]

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



atoi:

xor ax, ax;clear out ax for the result
mov cx, 10;mov into cx 10
add bx, 80
mov byte[bx], 0;null terminate the number
sub bx, 80
xor dx, dx;clear out dx for use

.top:
mov dl, byte[bx]
cmp dl, 0;if end of string then out
je .done

sub dl, '0';convert to number
push dx;save the number

xor dx, dx
mul cx;multiply by ten

pop dx;restore the number

add ax, dx;add to the result


inc bx;get ready for the next digit


jmp .top
.done:;finished
ret

sPrint:
.loop:
lodsb;move to the next letter in the string
mov ah, 0xe;print it
int 0x10
test al, al;if the register al is not equal to zero then jump back to the top
jne .loop


ret; return back to after where you where called


Where I run into a problem is I have no idea how to run the second stage, Also I am using Virtual box instead of bochs and VFD and I assemble the file as a .img for floppy disks
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 21, 2014, 10:56:09 PM
Well... first, your link to BrokenThorn doesn't work because of the semicolon. I could edit that for you, but I'll leave it for you. (that cryptic icon just above "report to moderator" if you haven't figured that out)

What's the problem? You jump to stage2 at the end of stage1 - it should just run. Contrary to the comment in stage2, you only load 1 sector in stage1, so you're limited to 512 bytes. I don't think that's a problem. I don't know why your BPB is in stage2 - shouldn't that be in stage1?

While I do have a real floppy in my current machine, I can't easily test this - no include file. I could probably write my own - I think I see what it needs to do, but not in the mood right now. I have no experience with emulators, so can't help you with that part...

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 21, 2014, 11:23:47 PM
Sorry about that I changed the icon I thought that icon just ment' question and I am trying to copy the file to the floppy image without overwriting the image in the tutorial it says to do this
Code: [Select]
nasm -f bin Stage2.asm -o STAGE2.SYS
copy STAGE2.SYS  A:\STAGE2.SYS
The problem with that is that I only have the .img file not a Drive at all and I am not using Bochs or VFD and I wan't to avoid using them unless There is no other way to do so, Instead I do this :
Code: [Select]
nasm -f bin Stage2.asm -o STAGE2.SYS
copy STAGE2.SYS  Boot.img
And then it asks me if I wan't to overwrite it and I say no because if I do it won't boot it will just try to run at 0x0 and it will give me a fatal error.(I edited the code to have the BPB in Stage 1)
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 22, 2014, 12:06:44 AM
I think copying stage2 to "A:stage2.bin" would require a filesystem to load it - that's where the BPB would come in. Your stage1 seems to assume stage2 is in the second sector. I think what I used to do is something like "copy /b stage1.bin + stage2.bin img.bin" and then write "img.bin" to floppy with... "rawrite" or John Fine's "partcopy" or DEBUG will do it, or it's easy to write your own. ASSuming that stage1 is exactly 512 bytes, that should put stage2 in the second sector, where stage1 expects it. Your stage1 loads the second sector to segment 1000 offset 0 and jumps to it. Your "push cs / pop ds" in stage2 should fix up ds so it can find your message. I don't know how all this would work out in an emulator.

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 22, 2014, 02:32:59 AM
I try to copy both onto the image file but for some reason it only copies one of the files. This is what I have tried.
Code: [Select]
copy /b Boot.bin + Boot2.bin BootLoader.bin
copy /b BootLoader.bin BootLoader.img
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 22, 2014, 03:24:36 AM
Perhaps I misremember. What's the size of the presumed combined file look like? Maybe, with the include file now, I'll give it a shot. Not right this minute...

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 22, 2014, 03:28:26 AM
Well Boot.asm which is the first stage is 2kb and Stage2.asm is 2kb so 4kb
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 22, 2014, 03:35:47 AM
That seems way too big. Oh, wait - size of the binary, not the source.

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 22, 2014, 04:12:24 AM
1kb each so 2kb
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 22, 2014, 04:59:45 AM
If stage1 doesn't assemble to 512 bytes exactly, something is dreadfully wrong! Lemee download your files and see what I can see. After I eat. Maybe before I sleep, but no promises...

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 22, 2014, 06:55:34 AM
Okay...
Code: [Select]
[BITS 16]
[ORG 0x7c00]

jmp Start


Start:
;set up the stack
xor ax, ax;set ax to zero remember that the when both value are the same in the exclusive or operation the both cancel out to zero
mov ds, ax
mov ss, ax

mov sp, 0x9c00
mov es, ax

;pass in the message into si Register
mov si, MSG
;then call the String print function
call sPrint

xor ax, ax;clear out ax for use
int 0x12;returns amount of ram in ax

call itoa


.Reset:
mov ah, 0 ; reset floppy disk function
mov dl, 0 ; drive 0 is floppy drive
int 0x13 ; call BIOS
jc .Reset ; If Carry Flag (CF) is set, there was an error. Try resetting again
 .Read:
mov ax, 0x1000 ; we are going to read sector to into address 0x1000:0
mov es, ax
xor bx, bx
 
mov ah, 0x02 ; read floppy sector function
mov al, 1 ; read 1 sector
; mov ch, 1 ; we are reading the second sector past us, so its still on track 1
        mov ch, 0 ; sectors start with 1, tracks start with 0!
mov cl, 2 ; sector to read (The second sector)
mov dh, 0 ; head number
mov dl, 0 ; drive number. Remember Drive 0 is floppy drive.
int 0x13 ; call BIOS - Read the sector

 
jmp 0x1000:0x0 ; jump to execute the sector!



cli;clear interrupts
hlt;halt the system






%include "itoa_atoi.asm"
Input db 0
BootDrive dw 0
MSG: db "This is my OS! The number is : ",13,10,0

;vars

bpbOEM db "My OS   "

bpbBytesPerSector:  DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs:     DB 2
bpbRootEntries:     DW 224
bpbTotalSectors:     DW 2880
bpbMedia:             DB 0xF0
bpbSectorsPerFAT:     DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors:     DD 0
bpbTotalSectorsBig:     DD 0
bsDriveNumber:         DB 0
bsUnused:             DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber:         DD 0xa0a1a2a3
bsVolumeLabel:         DB "MOS FLOPPY "
bsFileSystem:         DB "FAT12   "


;vars

times 510 - ($-$$) db 0
dw 0xAA55

I think that's your main problem. Confusing that cylinders and heads start with 0 but sectors start with 1!

Initially, I was getting your message (from stage1) and the number three times(!) so I fiddled with your include file, too (wrongly, the first two times!). You were/are checking for zero (end of string) after the interrupt - I'm not sure al will still be zero after the interrupt, so I put the test first (and then forgot to jump back to ".loop"!). That may or may not have been the problem there. I think the main thing was the wrong cylinder/track number.

What I did, for the record, was:
Code: [Select]
nasm -f bin stage1.asm -o stage1.bin
nasm -f bin stage2.asm -o stage2.bin
cat stage1.bin stage2.bin>img.bin
dd if=img.bin of=/dev/fd0
"copy /b" ought to work the same as "cat". Dunno what you do then to get it to work with VirtualBox instead of a real floppy. I should check out that or some emulator - all that rebootin' gets old quick!

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 22, 2014, 09:06:34 AM
Well What I tried to do was to cat in Linux in virtual box email it to myself then copying the img.bin to my Boot.img and then try and run but still no luck will keep trying though I know I am close
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 22, 2014, 09:14:32 AM
Any help here?

https://forums.virtualbox.org/viewtopic.php?t=1426

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 22, 2014, 09:51:40 AM
Here's a crazy thought:

Code: [Select]
; nasm -f bin fakeflop.asm -o fakeflop.img

bits 16 ; just for clarity
incbin "stage1.bin"
incbin "stage2.bin"
times (512 * 2880) - ($ - $$) db 0

Makes a big file - 1474560 - is that right? - that you might be able to persuade VirtualBox is a bootable floppy?

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 22, 2014, 06:08:21 PM
Wow It worked How does that work exactly It looks like a file with just two includes but it works like copy or cat
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 22, 2014, 09:05:35 PM
Yeah, that's about right. "%include" essentially does a   "cut and paste" of the included file - right where the "%include" occurs - and Nasm assembles it as if it were all one file. You already use this. If we'd done "%include 'stage1.asm'" and "%include 'stage2.asm'" Nasm would have complained about duplicate symbols. (I didn't even try this - "experience" is the ability to recognize mistakes when you make 'em again). But "incbin" (equivalent to "%incbin" I think) pastes a file in "as is" without any attempt to assemble it. Since I had the two files already assembled, I figured it would work better here. (you can specify a starting point and how much to include, too - doesn't have to be the whole file)

What got me started thinking about it was the references in the VirtualBox forum about using "/dev/zero" to fill a file with zeros. Nasm will do that without "/dev/zero" - we already use it to pad the bootsector out to 510 bytes before the signature. (incidentally, that signature isn't "supposed" to be required for a floppy boot sector - only for a hard drive - but some "buggy" BIOSes look for it, so we have to put it in).

After reading a little more about VirtualBox, I didn't see where we tell it "boot from this". Glad to hear you got it to work!

If, by any chance, you have further problems, feel free to ask!

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 23, 2014, 05:53:14 AM
I don't know if its better to make another topic for this or not so I will be posting here I have gone through and created the first stage with a FAT32 file system but the thing is when it boots it does nothing except print the welcome message I have the full code right here:

Code: [Select]

BITS 16

ORG 0x0

%DEFINE RED 0x04
%DEFINE PURPLE 0x05
%DEFINE BLUE 0x03


Start:
jmp main
;BIOS Paramater Block for the File Allocation Table(F.A.T. For short)
OEM_ID                db "OS-Z"
BytesPerSector        dw 0x0200
SectorsPerCluster     db 0x08
ReservedSectors       dw 0x0020
TotalFATs             db 0x02
MaxRootEntries        dw 0x0000
NumberOfSectors       dw 0x0000
MediaDescriptor       db 0xF8
SectorsPerFAT         dw 0x0000
SectorsPerTrack       dw 0x003D
SectorsPerHead        dw 0x0002
HiddenSectors         dd 0x00000000
TotalSectors         dd 0x00FE3B1F
BigSectorsPerFAT      dd 0x00000778
FSVersion             dw 0x0000
RootDirectoryStart    dd 0x00000002
FSInfoSector          dw 0x0001
BackupBootSector      dw 0x0006
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TIMES 13 DB 0 ;jumping to next offset

DriveNumber           db 0x00
Signature             db 0x29
VolumeID              dd 0xFFFFFFFF
VolumeLabel           db "OS-Z BIN"
SystemID              db "FAT32   "

sPrint:                   ; Routine: output string in SI to screen


 .repeat:
  ;Paramaters for Input
    mov ah, 09h             ; Must be 9 to print color
  xor bh, bh ;Must be set to zero
    mov bl, BLUE ;The Color
    mov cx, 01h ;The counter I guess QQ
   
    lodsb                   ; Get character from string
    test al, al ;If end of string jump to done
    je .done                ; If char is zero, end of string
    int 10h                 ; Otherwise, print it
    mov ah, 02h
    mov bh, 00h
    inc dl    ;Cursor Position maybe?????
    int 10h ;takes ah and bh and acts on their values
    jmp .repeat

 .done:
    ret



     ;*************************************************************************
     ; PROCEDURE ClusterLBA
     ; convert FAT cluster into LBA addressing scheme
     ; FileStartSector = ((X ? 2) * SectorsPerCluster(0x08))
     ;*************************************************************************
Cluster_TO_LBA:
sub ax, 0x02
xor cx, cx
mov cl, BYTE[SectorsPerCluster]; move the Sectors per cluster into cl to multiply by
mul cx;convert to LBA
add ax, WORD[datasector];add the offset to the register ax
ret


;*************************************************************************
; PROCEDURE LBACHS
; convert ?ax? LBA addressing scheme to CHS addressing scheme
; absolute sector = (logical sector / sectors per track) + 1
; absolute head   = (logical sector / sectors per track) MOD number of heads
; absolute track  = logical sector / (sectors per track * number of heads)
;*************************************************************************

;ax == logical sector
LBA_TO_CHS:
xor cx, cx;clear out cx
xor dx, dx;clear out dx for arithmetic
mov cx, ax;mov the logical sector into cx

Absolute_Sector:
;calculate the absolute sector
div WORD[SectorsPerTrack]
inc ax
mov WORD[absoluteSector], ax

xor ax, ax
mov ax, cx
xor dx, dx

Absolute_Head:
;calculate the absolute Head
div WORD[SectorsPerTrack]
div WORD[SectorsPerHead]
mov WORD[absoluteHead], dx


xor ax, ax
xor bx, bx
xor dx, dx

Absolute_Track:
;calculate the absolute track
mov ax, WORD[SectorsPerTrack]
mov bx, WORD[SectorsPerHead]
mul bx

xor bx, bx
xor dx, dx
mov bx, ax

xor ax, ax
mov ax,cx

div bx
mov WORD[absoluteTrack], ax


ret

Read_Sector:
.MAIN:
     mov     di, 0x0005                          ; five retries for error
.SECTORLOOP:
push ax
push bx
push cx
call LBA_TO_CHS
mov ah, 0x02
mov al, 0x01
mov ch, BYTE[absoluteTrack]; Track = Cylinder
mov cl, BYTE[absoluteSector];load in sector
mov dh, BYTE[absoluteHead]; Load in the head
mov dl, BYTE[DriveNumber];load in the drive number
int 0x13 ; access the bios

jnc .SUCCESS ; check to see if there was an overflow(ERROR)

xor     ax, ax                              ; BIOS reset disk
    int     0x13                                ; invoke BIOS
    dec     di                                  ; decrement error counter
    pop     cx ;resets everything
    pop     bx
    pop     ax
    jnz     .SECTORLOOP                         ; attempt to read again
   
    int     0x18 ; Do not know what this does

    .SUCCESS:
   
    mov si, MSG_Progress
    call sPrint
    ;restore counter and other registers
    pop cx
    pop bx
    pop ax

    add     bx, WORD [BytesPerSector]           ; queue next buffer
    inc     ax                                      ; queue next sector

    test cx, cx
    jnz .MAIN; loops through 8 times


ret
main:
;----------------------------------------------------
; code located at 0000:7C00, adjust segment registers
;----------------------------------------------------
     
          cli           ; disable interrupts
          mov     ax, 0x07C0        ; setup registers to point to our segment
          mov     ds, ax
          mov     es, ax
          mov     fs, ax
          mov     gs, ax

     ;----------------------------------------------------
     ; create stack
     ;----------------------------------------------------
     
          mov     ax, 0x0000        ; set the stack
          mov     ss, ax
          mov     sp, 0xFFFF
          sti           ; restore interrupts
          mov si, MSG
  call sPrint


  ;Calculate The Start of the datasector
  mov al, BYTE[TotalFATs];moves the start of the Directory into ax
  mul WORD[BigSectorsPerFAT]
  add ax, WORD[ReservedSectors]
  mov WORD[datasector], ax;Start of datasector into datasector

  LOAD_ROOT:
  mov ax, WORD[RootDirectoryStart]
  call Cluster_TO_LBA

  mov bx, Sector_Size
  call Read_Sector;Read in the first sector


  mov di, Sector_Size + 0x20; adds the offset to the sector size to point the destination index register to the first File

  mov     dx, WORD [di + 0x001A]; point the dx register to where all the information in that file is stored
          mov     WORD [cluster], dx ;mov the information into cluster
          LOAD_STAGE2:
          ;Set up the segments where the Second Stage needs to be loaded

            mov ax, 0100h       ; set ES:BX = 0100:0000
            mov es, ax         
            mov bx, 0


            ;Read the cluster which contains the Second Stage
            mov cx, 0x0008
            mov ax, WORD[cluster]
            call Cluster_TO_LBA
            call Read_Sector   

            Stage2:;jumps to stage2 of the boot loader

            push    WORD 0x0100
          push    WORD 0x0000
          retf


            Failed:
            ;An error has occured if this part is executed
          mov     si, FAILURE
          call    sPrint
          mov     ah, 0x00
          int     0x16                                ; await keypress
          int     0x19                                ; warm boot computer
     







MSG: db "Welcome to OS-Z!",0
absoluteSector db 0x00
absoluteHead    db 0x00
absoluteTrack  db 0x00
cluster      dw 0x0000
datasector  dw 0x0000
Sector_Size dw 0x0200   
MSG_Progress: db ".", 0
FAILURE: db "The Bootloader has Failed to load...........", 0


TIMES 510 - ($-$$) DB 0

DW 0xAA55



Here is the stage 2 bootloader
Code: [Select]
BITS  16
ORG 0x0100


jmp main
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
%DEFINE BLUE 0x03

sPrint:                   ; Routine: output string in SI to screen


 .repeat:
  ;Paramaters for Input
    mov ah, 09h             ; Must be 9 to print color
  xor bh, bh ;Must be set to zero
    mov bl, BLUE ;The Color
    mov cx, 01h ;The counter I guess QQ
   
    lodsb                   ; Get character from string
    test al, al ;If end of string jump to done
    je .done                ; If char is zero, end of string
    int 10h                 ; Otherwise, print it
    mov ah, 02h
    mov bh, 00h
    inc dl    ;Cursor Position maybe?????
    int 10h ;takes ah and bh and acts on their values
    jmp .repeat

 .done:
    ret


main:


cli ; clear interrupts
xor ax, ax ; null segments
mov ds, ax
mov es, ax
mov ax, 0x9000 ; stack begins at 0x9000-0xffff
mov ss, ax
mov sp, 0xFFFF
sti ; enable interrupts

;-------------------------------;
;   Print loading message ;
;-------------------------------;

mov si, LoadingMsg
call sPrint



LoadingMsg: db "Preparing to load Kernel.....", 0
And here is what I use to boot with both of the files
Code: [Select]
[BITS 16]


incbin "Stage1.bin"
incbin "Stage2.bin"

times (512 * 2880) - ($ - $$) db 0
I think the problem is when I start to load the root directory and read the first sector because its supposed to print the progress message if it does read it though there are no errors , I tried to do this without a tutorial and figure it out on my own and it has really helped me in understanding how to read the sector and converting to LBA and from LBA to CHS and using the segment offset model used in the 16 bit part of the bootloader , that being said there may be a bunch of errors but like you said " "experience" is the ability to recognize mistakes when you make 'em again ". And I have little to no experience with bootloaders but I have been at assembly for about a month now.
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 23, 2014, 08:19:49 AM
Wow! Big step! This is going to take some studying, and I'll probably try it. Let me take a quick guess at what "might" be wrong. You seem to be loading your stage2 at segment 0x100 offset 0, and jumping to segment 0x100 offset 0, but your stage2 says "org 0x100". This will (I think) cause stage2 to fail to find its data. Changing that to "org 0" would be an easy thing to try, to see if it helps any...

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 23, 2014, 06:23:49 PM
I have changed the function LBA_TO_CHS because apparently I was doing it wrong still trying to figure out what I did wrong when converting but any way now that I fixed that (I think) it now gives me an INT18 BOOT FAILURE message after my welcome pops up.
Code: [Select]

LBA_TO_CHS:
   xor     dx, dx                              ; prepare dx:ax for operation
   div     WORD [SectorsPerTrack]              ; calculate
   inc     dl                                  ; adjust for sector 0
   mov     BYTE [absoluteSector], dl
   xor     dx, dx                              ; prepare dx:ax for operation
   div     WORD [SectorsPerHead]                     ; calculate
   mov     BYTE [absoluteHead], dl
   mov     BYTE [absoluteTrack], al
ret

Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 24, 2014, 12:42:47 AM
Hi Anonymous,

I didn't get far with this before realizing that your numbers for FAT32 obviously aren't going to work for my floppy drive. I'm not sure what it's doing for you, either. I can see you're reading the root directory into memory (where?), but from what? Do you have a FAT32 drive to read from?

Anyway, starting from "main:" (not that ".MAIN:", the other "main:"), 0xFFFF is a horrible alignment for your stack. Zero is a fine number for sp (if you want the whole segment) - it'll wrap around to 0xFFFE on the first push or call. Or start at 0xFFFE if that makes you nervous.

Then you print the message using a different sPrint. The int 10h/9 looks okay, but the int 10h/2 looks like it's setting the cursor to a random dx - starts off at zero (boot drive in dl... might be 80h?) so okay the first time. As I recall, to use int 10h/9, we need to "get cursor" first (int 10h/3?), then inc dl and do the int 10h/2. There's an int 10h/13h that will do colored text and advance the cursor (or not) - unusual parameters, the message goes in es:bp. It looks like you're "guessing" on these BIOS interrupts. Get RBIL (Ralf Brown's Interrupt List). The online versions are okay for interrupts, but if you download the whole thing you get ports.lst and memory.lst (plus other goodies) which will come in handy later. The int 18h loads ROM-BASIC, which isn't likely to be there unless you've got a genuine IBM... and probably not then, these days.

In any case, you return from sPrint with ah non-zero, then load al with [TotalFATs] and multiply by a word. This isn't going to give you a useful value. A little later, you do "mov bx, Sector_Size". This is the address of Sector_Size, not the [contents]. Is that what you intend? It seems to be the buffer into which Read_Sector reads sectors. The very first thing this is going to do is overwrite your "progress dot", so that may be why you don't see them. I get confused after that...

You may need to back up and take smaller steps, although I applaud your trying to figure out the LBA_TO_CHS thing - you'll probably need it eventually.

If I'm feeling ambitious I may try to rework your stage1 and see if I can get it to load stage2 from floppy again.  I never worked much with FAT32. As I recall, we know the (maximum) size of the root directory for FAT12 and FAT16, but for FAT32 we don't. This may not be a problem from a bootloader since all the memory is "yours" anyway. My brain is turning to mush. Thunderstorm coming and the lights are beginning to flicker.

Later,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 24, 2014, 01:09:42 AM
I made changes to the print function so here it is and Now I actually get how to move the cursor around and which registers are the row column and page and I actually started over well not over I am re-using the old code because now that I look back it's a little messy here it is :
Code: [Select]
BITS   16

ORG  0x00





Start:


jmp main

;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05

;macro for print
%macro Print 2

xor bx, bx
mov bl, %2
mov si, %1
call cPrint

mov ah, 0x02;moves to a new line in the middle of the screen
mov dh, 0x01
xor bh, bh
mov dl, 22
int 10h
%endmacro

;*************************************;
;                                     ;
;         OEM PARAMETER BLOCK         ;
;                                     ;
;                                     ;
;*************************************;

BPB_OEM      DB "Zeroth OS   " ;Name of the OS
BPB_BytesPerSector:    DW 512   ;Size of the Sector
BPB_SectorsPerCluster:    DB 1
BPB_ReservedSectors:    DW 1
BPB_NumberOfFATs:  DB 2
BPB_RootEntries:    DW 224
BPB_TotalSectors:  DW 2880
BPB_Media:      DB 0xf0  ;; 0xF1
BPB_SectorsPerFAT:    DW 9
BPB_SectorsPerTrack:    DW 18
BPB_HeadsPerCylinder:  DW 2
BPB_HiddenSectors:    DD 0
BPB_TotalSectorsBig:      DD 0
BS_DriveNumber:          DB 0
BS_Unused:      DB 0
BS_ExtBootSignature:    DB 0x29
BS_SerialNumber:          DD 0xa0a1a2a3
BS_VolumeLabel:          DB "Z-OS FLOPPY "
BS_FileSystem:            DB "FAT32   "



cPrint:                   ; Routine: output string in SI to screen


 .top:
  ;Paramaters for Input
    mov ah, 09h             ; Must be 9 to print color
    mov cx, 01h ;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:
    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, 0x00            ;page 00
    mov dh, 0x00            ;row 00
    mov dl, 0x00            ;col. 00
    int 0x10                ;set pos
ret




main:

cli; disable interrupts
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 ; enable interrupts

call clear

;move the cursor to the middle of the screen
mov ah, 0x02
xor dh, dh
xor bh, bh
mov dl, 22
int 0x10

Print W_MSG, TEAL

LOAD_STAGE2:





W_MSG: db "Welcome to the Zeroth-OS!", 0
Progress_MSG: db ".",0
TIMES 510 - ($-$$) DB 0
DW 0xAA55

EDIT: I know this may be ambitious and maybe your right that I should be taking it slow or one thing at a time but I just realized that if I continue to create this bootloader then make it really complex I would never actually be able to test it on real hardware because ... well I don't have a floppy or anything that uses a floppy. So I wen't around tying to find even some code on how to write boot off of CD and I found some and it is in AT&T syntax T_T, now I have to go translate that, and I think that may change the way I approach the file system am I right?
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 24, 2014, 09:02:40 AM
AT&T syntax shouldn't make much difference - looks wildly different, but should do the same thing. I think CDs have bigger sectors - 2k? - but there's a way to boot off CD "as if" it were a floppy. I don't know how to do it. I vaguely recall something about "El Torito spec"? Max mentions something about booting off a USB device to test his "painter" bootsector (in the Examples section). He might give us some clues if we asked him. That would have the advantage that it could be reused. http://www.osdev.org has a lot of info about this kind of thing. If you get advanced enough you could dedicate a hard drive to it...

Haven't tried your latest code yet...

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 24, 2014, 11:29:14 AM
AT&T code like this, you mean? No idea if it's right. It assembles.
Code: [Select]
;/* ISO-9660 boot sector
 ;* --------------------
 ;*
 ;* Copyright (c) 2008-2009 Frédéric Feret
 ;* All rights reserved.
 ;*
 ;* Features:
 ;*      - supports ISO-9660 filesystem ("El Torito")
 ;*      - supports multiples burning session
 ;*      - no floppy emulation
 ;*
 ;* Limitations:
 ;*      - supports only Joliet format
 ;*/
BITS  16
ORG 0x00

;/*
; * This is the main function of the boot sector, which loads the OS image
 ;* into memory at 1000:0000.
 ;*
 ;* Parameters:
 ;*      DL = boot disk number.
 ;*/
;MISMATCH: "        .global _start"
;_start:
        cli

 ;       /* The BIOS has loaded our boot sector at 0000:7C00. We move the code
  ;         of this boot sector at 9000:0000. */
        xor     ax,ax
        mov     ds,ax
        mov     si,07C00h                        ; /* DS:SI = 0000:7C00. */
        mov     ax,09000h
        mov     es,ax
xor     di,di                            ; /* ES:DI = 9000:0000. */
        mov     cx,00800h                        ; /* 2048 bytes. */
        rep movsb                                ; /* do the relocation. */

        ;/* Jump to the new address. */
;MISMATCH: "        ljmp    $0x9000, $1f"

jmp 0x9000:here

here:

 ;       /* Setup segment registers. */
        mov     ax,cs
        mov     ds,ax                                  ; /* DS = CS = 9000. */
        xor     ax,ax
        mov     es,ax
        mov     ss,ax                                   ;/* SS = ES = 0000. */
        mov     sp,07C00h                               ;/* SS:SP = 0000:7C00. */

       ; /* Save the boot disk number. */
        mov     [drive_number],dl

   ;     /* Clear the screen. */
        mov     ax,003h
        int     010h

        mov     si, msg_loading
        call    print_string

        sti

  ;      /* Check if the processor is a 386. */
        pushf
        pop     ax                                    ;  /* FLAGS -> AX */
        or      ax,03000h                              ; /* try to set IOPL bits. */
        push    ax
        popf                                            ;/* AX -> FLAGS */

        pushf
        pop     ax                                      ;/* FLAGS -> AX */
        test    ax,03000h                               ;/* check if IOPL bits are always set */
        jnz     short .l1                               ;/* it's a 386, or a higher model. */

        ;/* The processor is a 286 or even older model. We display an error message on the
         ;  screen and then prompts the user to press a key on the keyboard to restart
          ; the computer. */
        mov     si, msg_no_386
        call    print_string
        jmp     reboot

.l1:
        ;/* Get the size in bytes of a sector from the BIOS. Normally, the size of
         ;  a sector on a CD-ROM is 2048 bytes. */
        mov     word [disk_packet],01Ah
        mov     ah,048h
        xor     al,al
        mov     si, disk_packet
        mov     dl, [drive_number]
        int     013h
        jc      assume_2k_sector

        mov    ax, disk_packet + 0x18
        mov     [bytes_per_sect],ax
        jmp     .l1

assume_2k_sector:
        ;/* An error occured while retrieving the size of a sector. We will display
         ;  a warning message on the screen, then we assume that a sector on the
          ; disk makes 2 kilobytes. */
        mov     word [bytes_per_sect],00800h
        mov     si, msg_assume_2k_sector
        call    print_string

.l1:
        ;/* To load the OS image (which is located at the root directory of the disk),
         ;  we have to look at all sessions of the disk. We will retrieve information
          ; on the root directory (its size and location) of each session, load the
           ;directory into memory and see if the OS image filename is in this directory.
           ;If the file isn't found, we move on to the next session. If all sessions
           ;were covered and that the filename wasn't found, we conclude that the OS
           ;image isn't on the disk. The first volume descriptor is the 17th sector of
           ;the disk. */
        mov     eax,16

get_next_desc:
        ;/* Read the sector in memory at 0000:1000. */
        mov     [desc_sector],eax
        mov     bx,01000h
        mov     cx,1
        call    read_sectors

        ;/* Check for the signature "\2CD001" at the beginning of the descriptor. */
        mov     si, cd_signature
        mov     di,01000h
        mov     cx,6
        cmpsb
        je      found_desc

        ;/* Check if we have looked in all the descriptors of volume. */
        cmp     byte [es:0x1000],0FFh
        jne     next_desc

        ;/* We looked in all sessions of the disk, and the OS image wasn't found.
        ;   We display an error message on the screen and then prompts the user to
         ;  press a key to restart the computer. */
        mov     si, msg_file_not_found
        call    print_string
        jmp     reboot

next_desc:
        ;/* Compute the next sector number to load. */
        mov     eax, [desc_sector]
        inc     eax
        jmp     get_next_desc

found_desc:
        ;/* We have to load a volume descriptor of a session in memory. We will check
         ;  if the session supports the Joliet format for storing filenames and
          ; directories. Otherwise, the session is unknown. */
        mov     di,01058h
        mov     si, joliet_signature
        mov     cx,3
        cmpsb
        jne     next_desc

        ;/* We found a session that supports Joliet format. We can find the size and
         ;  the location of the root directory. */
        mov     eax, [es:0x109E]
        mov     [root_dir_start],eax
        mov     eax, [es:0x10A6]
        mov     [root_dir_size],eax

        ;/* Compute the number of sectors to load. */
        movzx   ebx,word [bytes_per_sect]
        div     ebx
        cmp     edx,0
        je      .l1
        inc     eax
.l1:
        mov     [root_dir_sectors],ax

        ;/* Read the root directory in memory at 0000:1000. */
        mov     eax, [root_dir_start]
        mov     bx,01000h
        mov     cx, [root_dir_sectors]
        call    read_sectors

        ;/* We will look into the root directory the OS image filename. If the file has
         ;  been found, we save the sector number where that file ans its size in bytes.
          ; Otherwise, we move to the next session. */
        mov     di,01000h

search_file:
        add     di,25

        ;/* Check if this entry refers to a file. */
        cmp     byte [es:+di],0
        jne     next_entry

        push    di
        add     di,8
        mov     si, osimage
        mov     cx,14
        cmpsb
        pop     di
        je      found_file                            ;  /* file found? */

next_entry:
        add     di,7
        movzx   ax,byte [es:+di]
        add     di,ax

.l1:
        inc     di
        cmp     byte [es:+di],0
        je      1b

        ;/* Check if we have check all the entries of the root directory. */
        mov     eax, [root_dir_size]
        add     eax,01000h
        cmp     di,ax
        jb      search_file

        ;/* The OS image wasn't found in the root directory. We go to the next
         ;  session of the disk. */
        jmp     next_desc

found_file:
        sub     di,25

        ;/* Get the location of this file. */
        mov     eax, [es:2+di]
        mov     [file_start],eax

        ;/* Get the size of this file. */
        mov     eax, [es:10+di]
        mov     [file_size],eax

        ;/* Compute the number of sectors to load. */
        movzx   ebx,word [bytes_per_sect]
        div     ebx
        cmp     edx,0
        je      .l1
        inc     eax
.l1:
        mov     [file_sectors],ax

        ;/* Read the OS image in memory at 1000:0000. */
        mov     eax, [file_start]
        mov     bx,01000h
        mov     es,bx
        xor     bx,bx
        mov     cx, [file_sectors]
        call    read_sectors

        mov     dl, [drive_number]
        xor     si,si

        ;/* Run the OS loader... */
        jmp    0x1000:0x0000

;/*
; * This function loads one or more sectors in memory.
; *
; * Parmaeters:
; *      EAX             first sector to load.
; *      CX              number of sectors to load.
; *      ES:BX           destination address.
; */
read_sectors:
;        /* To request the BIOS to load the sectors, we need to build a data
 ;          packet that contains the number or sectors to load, the first
  ;         logical sector to load and destination address. The address of
   ;        this packet will then be given to the BIOS, which loads these
    ;       sectors into memory. */
        mov     byte [disk_packet],010h

     ;   /* We don't read one single sector at a time. */
         mov [disk_packet + 2], word 0x01

       ; /* Write the destination address. */
         mov     [disk_packet + 4], bx
         mov     [disk_packet + 6], es

        ;/* Write the logical sector to load. */
        mov     [disk_packet + 8], eax
        mov     [disk_packet + 12], dword 0x0

read_one_sector:
        ;/* Read the sector into memory. */
        mov     ah,042h
        xor     al,al
        mov     si, disk_packet
        mov     dl, [drive_number]
        int     013h
        jnc     short .l1                              ; /* read error? */

        mov     si, msg_read_error
        call    print_string
        jmp     reboot

.l1:
      ;  /* Updates the next sector to load. */
       inc    dword [disk_packet + 8]

       ; /* Updates the destination address. Rather than incrementing the offset, we
        ;   will increase the segment. */
        mov     ax, [bytes_per_sect]
        shr     ax,4
        add [disk_packet + 6], ax
        loop    read_one_sector

        ret

;/*
 ;* This function displays a string to the screen, at the current cursor
 ;* position.
 ;*
 ;* Parameters:
 ;*      DS:SI           null-terminated string.
 ;*/
print_string:
  ;      /* Read a character. */
        repe lodsb

   ;     /* Check if we reached the end of the string. */
        cmp     al,0
        je      short .l1

    ;    /* Displays the character on screen. */
        mov     ah,00Eh
        mov     bx,007h
        int     010h

        jmp     print_string

.l1:
        ret

;/*
; * This function reboots the computer.
; */
reboot:
        mov     si, msg_reboot
        call    print_string

 ;       /* Wait for a key. */
        xor     ax,ax
        int     016h

  ;      /* Rebooting... */
        int     019h

;/*
; * Messages
; */
msg_loading:            db     `\n\rLoading...\n\n\r`, 0
msg_no_386:             db     `Error: 386 or higher processor required.\n\r`, 0
msg_assume_2k_sector:   db     `Error: failed to get sector size, assume 2 Kb.\n\r`, 0
msg_file_not_found:     db     `Error: OS image not found.\n\r`, 0
msg_read_error:         db     `Error: cannot read on disk.\n\r`, 0
msg_reboot:             db     `Press any key to restart your computer.\n\r`, 0

;/*
; * Datas
; */
cd_signature:           db    002h
                        db     'CD001'
joliet_signature:       db    025h,02Fh,045h
osimage:                db    0, 'o', 0, 's', 0, 'i', 0, 'm', 0, 'a', 0, 'g', 0, 'e'
drive_number:           db    0
bytes_per_sect:         dw    0
root_dir_size:          dd    0
root_dir_sectors:       dw    0
root_dir_start:         dd    0
file_size:              dd    0
file_sectors:           dw    0
file_start:             dd    0
desc_sector:            dd    0
disk_packet:            times   020h db 0

;/*
 ;* Boot sector signature
 ;*/
; ORG 2046
times 2046 - ($ - $$) db 0


dw    0AA55h

Best,
Frank


Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 24, 2014, 05:44:57 PM
Thanks frank It does assemble but when I try to put it into virtual box it says format not recognized and gives me an error message I think its because of what the Developer stated at the top:
Code: [Select]
Limitations:
 ;*      - supports only Joliet format
I have been studying it and apparently I will have to Put The Descriptors for the Master Boot record into the first sector of the CD_ROM (I think) Each sector is still 512 bytes and the size of an ISO is 2 kilo-bytes or 2,048 bytes. This is as far As I have gotten Not much but I guess I have the structure right so far:
Code: [Select]
BITS   16

ORG  0x00

Start: jmp main


;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05

;macro for print
%macro Print 2

xor bx, bx
mov bl, %2
mov si, %1
call cPrint

mov ah, 0x02;moves to a new line in the middle of the screen
mov dh, 0x01
xor bh, bh
mov dl, 22
int 10h
%endmacro


cPrint:                   ; Routine: output string in SI to screen


 .top:
  ;Paramaters for Input
    mov ah, 09h             ; Must be 9 to print color
    mov cx, 01h ;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, 0x00            ;page 00
    mov dh, 0x00            ;row 00
    mov dl, 0x00            ;col. 00
    int 0x10                ;set pos
ret




main:

cli; disable interrupts
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 ; enable interrupts

call clear

;move the cursor to the middle of the screen
mov ah, 0x02
xor dh, dh
xor bh, bh
mov dl, 22
int 0x10

Print W_MSG, TEAL;prints the welcome message in teal



INIT_MBR:













cd_signature: db "CD001"
cd_Version:   db 0x01



W_MSG: db "Welcome to the Zeroth-OS!", 0
Progress_MSG: db ".",0
times 2048 - ($ - $$) db 0; padd out the rest of the file to 0
DW 0xAA55


Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 24, 2014, 09:13:12 PM
Code: [Select]
Limitations:
 ;*      - supports only Joliet format
Quote
Tell me the trouble
Tell once to my ear
Turn, turn, turn again
Joliet prison
And ninety-nine years
Turn, turn to the rain
And the wind
- Bob Dylan

After "What's a Joliet format, mama?", my next question would have been "How do I write stage1.bin and stage2.bin to CD in the right places?". Will dd do it, if I can figure out "/dev/***", or do I have to make an iso and use "cdrecord"? There are answers to these questions, of course. I'd start looking around osdev.org and follow on from there. In your case, the VirtualBox docs may be more to the point. I thought the idea of a CD bootsector was to get away from VirtualBox. In my case, a USB device is probably what I want to boot from, failing a real floppy.

Once when my buddy was out of town, I grabbed what I thought was a "pen drive" off his desk. I could recognise the device, but couldn't read or write anything to it. Turned out what I had was a "card reader" - I didn't notice the little door on the side. I've never gotten around to trying an actual storage device. That's the extent of my experience with USB devices. I'm a floppy kinda guy. :)

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 24, 2014, 09:43:14 PM
Well It looks like I am so close to actually jumping to the next stage correctly
here is my Code:
Code: [Select]
BITS   16

ORG  0x00

Start: jmp main


;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW:  db 0

;macro for print
%macro Print 2
xor dx, dx
mov dh, BYTE[ROW];puts the row into the dh register
xor bx, bx
mov bl, %2
mov si, %1
call cPrint

             
    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;saves the rows for the next time we need to print
%endmacro


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, 0x00            ;page 00
    mov dh, 0x00            ;row 00
    mov dl, 0x00            ;col. 00
    int 0x10                ;set pos
ret




Read_Extended_Sector:
pusha
xor ax, ax
xor dx, dx
xor bx, bx
;read in the sector


.ForLoop:
MOV DL,BYTE[CDDriveNumber]              ; Set it up again
MOV AH,42h                          ; Read from drive function
MOV SI,DiskAddressPacket            ; Load SI with address of the Disk Address Packet
INT 13h   
jnc .Success


Print Read_Sector_Error_MSG, PURPLE
cli
hlt

.Success:
Print READ_SUCCESS, TEAL
cmp ah, Stage2
jz .DONE
Print FILE_NOT_FOUND, RED
cli
hlt
.DONE:
popa
ret


main:

cli; disable interrupts
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 ; enable interrupts

call clear


Print W_MSG, TEAL;prints the loading message in colour


call Read_Extended_Sector; Reads the first sector of the drive
;the read in data is stored in AH














cd_signature: db "CD001"
cd_Version:   db 0x01
CDDriveNumber: db 80h

;Disk Address Packet


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



W_MSG: db "Loading Z-Boot...........", 0
Stage2: db "STAGE2 BIN"
Read_Sector_Error_MSG: db "Failed to read sector ......",0
READ_SUCCESS: db "Reading the first sector was a success .......",0
FILE_NOT_FOUND: db "Error, File not found......."
times 2046 - ($ - $$) db 0; padd out the rest of the file to 0
DW 0xAA55


I am still unsure that this will work but I know I am going in the Right direction I started reading the documentation on int 0x13 here is the link :

http://en.wikipedia.org/wiki/INT_13H#INT_13h_AH.3D42h%3a_Extended_Read_Sectors_From_Drive
I now can assemble using mkisofs which copies it to a .iso file which I can probably burn to a disk if I wanted to now all i have to figure out is how to actually read the sector because the carry flag was set after I ran this so it printed the error message
EDIT:


just fixed it I realized that upon setting up the segments I have to save the CD_Drive number and put it correctly into the function here
Code: [Select]
    Create_Stack:
    xor ax, ax
    mov es, ax
    mov ss, ax
    mov sp ,0x0FFFE
    sti
        mov [CDDrivenumber], dl
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 25, 2014, 01:00:05 PM
Does "byte value exceeds bounds" ring any bells? It isn't clear to me what you expect to be in ah in Read_Extended_Sector. You compare it with "Stage2" which is the address of a variable containing "STAGE2  BIN", which looks like how the name would be displayed in a (FAT) directory entry... but I think CD directory names are in UTF16. :(

In any case, you pusha/popa around Read_Extended_Sector, so ah is going to be whatever it was going into it - 2 from the print routine would be my guess... It is the carry-flag that will tell you if the interrupt suceeded. If it did, whatever you read from... sector 16(?)... should be at 200h:0. You might want to look for it there before blindly jumping.

I like your version better, though. It doesn't say "all rights reserved"... :)

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 25, 2014, 03:34:16 PM
I am trying now to find the Volume descriptor and it is proving to be a rial PITA it's supposed to be in the 16th sector but there are only 4 sectors on the CD so I am at a loss
here it is
Code: [Select]
BITS   16

ORG  0x00

Start: jmp main


;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW:  db 0

;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

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, 0x00            ;page 00
    mov dh, 0x00            ;row 00
    mov dl, 0x00            ;col. 00
    int 0x10                ;set pos
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


main:

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

LOAD_ROOT:
;first calculate the start of the Root directory
;mov ax, WORD[DiskAddressPacket.End]
mov WORD[DiskAddressPacket.SectorsToRead],16
;xor ax, ax
mov cx, 0x01
call Read_Sectors

Print READ_SUCCESS, TEAL
call Print_ln




 














Sector_Size: dw 512
CDDriveNumber: db 80h
CD_bytes_per_sect:         dw    0
CD_root_dir_size:          dd    0
CD_root_dir_sectors:       dw    0
CD_root_dir_start:         dd    0
CD_file_size:              dd    0
CD_file_sectors:           dw    0
CD_file_start:             dd    0
CD_desc_sector:            dd    0
CD_Signature:    db "CD001"
CD_FILE_VER:    db 0x01

;Disk Address Packet


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

RETURN: DB 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: db "Found", 0
times 2046 - ($ - $$) db 0; padd out the rest of the file to 0
DW 0xAA55


Without the volume descriptor I cannot find the root directory which without it I can't really do anything any Ideas?
Also I am trying to register to OS Dev but it won't send me the activation email any idea on how to contact their admins?
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 25, 2014, 05:53:00 PM
How would I read in whats at the address of 0x0200:0 to I just use a JMP instruction to jump there and read in whats at ES and SI? I think I am getting it I have put the segment and offset of the DAP into ES:SI and now I am trying to print it to see if its there but no luck nothing printed here is what I tried right under my read sector code
Code: [Select]
mov es, WORD[DiskAddressPacket.Segment]
mov si, WORD[DiskAddressPacket.Offset]

mov dl, BYTE[ES:SI]
mov ah, 0xE
int 0x010
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 25, 2014, 06:37:46 PM
al not dl, but otherwise looks about right.

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 25, 2014, 06:53:26 PM
Thanks Frank I found the boot signature well I printed it with the code here it is :
Code: [Select]
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]

xor bx, bx
.top
mov al, BYTE[ES:di+bx]
cmp al, ' '
je .Done
mov ah, 0xE
int 0x010
inc bx
jmp .top

.Done:

Now onto finding the root directory Apparently its not in the Volume descriptor so I have to go look for it in memory but yet again no idea how I'm Gonna go keep studying
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 26, 2014, 01:30:15 AM
I think I found the root but when I try and print it out I get these weird symbols is it a problem with my cPrint Function or Is it supposed to be like that?
I attached an image to my post to show you what it looks like.
here is the code:
Code: [Select]
BITS   16

ORG  0x00

Start: jmp main


;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW:  db 0

;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

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, 0x00            ;page 00
    mov dh, 0x00            ;row 00
    mov dl, 0x00            ;col. 00
    int 0x10                ;set pos
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


main:

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
LOAD_SIGNATURE:
mov cx, 0x04
call Read_Sectors

Print READ_SUCCESS, TEAL
call Print_ln

;load the Volume descriptor to the Volume variable
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
add BX, 0x01
xor cx, cx
.toploop:
xor ax, ax
mov al, BYTE[VOLUME+BX]
cmp al, BYTE[CD_Signature+BX-1]
je .FOUND_IT
jmp .Done2
inc CX
.FOUND_IT:
Print Progress_MSG, PURPLE
inc BX

jmp .toploop

.Done2:
cmp CX, 0
jne FAIL
call Print_ln

Print FOUND_CD, TEAL
jmp LOAD_ROOT
FAIL:
Print FILE_NOT_FOUND, RED

;Now Load the Root Directory from the Volume Descriptor
LOAD_ROOT:
mov es, WORD[DiskAddressPacket.Segment]
mov di, WORD[DiskAddressPacket.Offset]

call Print_ln
MOV AL,[ES:DI]                      ; Length of the current directory entry
MOV [CD_dir_curr_size],AL
Print CD_dir_curr_size, TEAL
call Print_ln

MOV EAX,[ES:DI+2]                   ; Starting sector of directory entry
MOV [CD_root_dir_start],EAX
Print CD_root_dir_start, TEAL
call Print_ln
MOV EAX,[ES:DI+10]                  ; Size of directory entry on CD/DVD/BD
MOV [CD_root_dir_size],EAX
Print CD_root_dir_size, TEAL
call Print_ln

MOV AL,[ES:DI+32]                   ; File's name length (see El Torito of ISO:9660 or CDROM.ASM)
MOV [CD_FileNameLength],AL

Print CD_FileNameLength, TEAL


call Print_ln

XOR BX,BX                           ; Initialize BX
XOR CX,CX                           ; Initialize CX
MOV SI,DI









Sector_Size: dw   512
CDDriveNumber: db   0x080
CD_bytes_per_sect:          dw    0
CD_root_dir_size:          dd    0
CD_root_dir_sectors:        dw    0
CD_root_dir_start:          dd    0
CD_file_size:              dd    0
CD_file_sectors:            dw    0
CD_file_start:              dd    0
CD_desc_sector:            dd    0
CD_Signature:     db    "CD001"
CD_FILE_VER:     db    0x01
CD_FileNameLength: db   0x0
CD_dir_curr_size: db 0x0
joliet_signature:        db    025h,02Fh,045h
;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: DB 0

W_MSG: db "Loading Z-Boot", 0
KERNEL: db "KRNL.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







Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 26, 2014, 05:28:35 AM
NeverMind I found out I needed to use the right offsets in order to find the Root
Here is what I did to solve it
Code: [Select]
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL
call Print_ln
mov es, [DiskAddressPacket.Segment]
mov di, [DiskAddressPacket.Offset]

    xor BX, BX
xor si, si

    .top:

MOV AL,[ES:DI+BX] ;starting address
cmp AL,BYTE[STAGE2]
je .Done
cmp AL,BYTE[STAGE2]
je .FAIL
INC BX
jmp .top

.Done:
Print Found_Possible_FILE, TEAL
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter

.top2:
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


INC BX
INC SI
INC CX
cmp CX, WORD[STAGE_2_LEN]
jne .top2
call clear

Print File_Found, TEAL
call Print_ln

;call clear
SUB BX, 10
ADD DI, BX

;jump to where the file is located and run it
JMP [ES:DI]

.FAIL:
call Print_ln
Print FILE_NOT_FOUND, RED
cli
hlt


ret

Now I am trying to jump to the file because I found it and run the code there but its not working But at least I found the file :D
here is the stage2 code:
Code: [Select]
[BITS 16]
[ORG 0x500]

Start: jmp main

%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
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_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

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, 0x02         ;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





main:
cli ; clear interrupts
xor ax, ax ; null segments
mov ds, ax
mov es, ax
mov ax, 0x9000 ; stack begins at 0x9000-0xffff
mov ss, ax
mov sp, 0xFFFF
sti
;call clear
               ;set pos
call Print_ln
Print LOAD_SUCCESS, TEAL
call Print_ln





LOAD_SUCCESS: db "Stage 2 of the bootloader has loaded successfully!",0






Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 27, 2014, 11:51:15 AM
I'll take your word for it that you've found the file...

Code: [Select]
;jump to where the file is located and run it
JMP [ES:DI]
A near indirect jump to a word found at [es:di]? I doubt it.

Try...
Code: [Select]
    push es
    push di
    retf

Why is stage2 "org 0x500"? Is that where the file is loaded?

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 27, 2014, 04:57:41 PM
Here is the updated code for it It still isn't jumping to it correctly:
Code: [Select]
[BITS   16]

[ORG  0x00]

Start: jmp main


;Colors for text
%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
COL: db 0
ROW:  db 0

;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 eax
push eax

mov al, '-'
mov ah, 0xe
int 0x10
pop ax
jmp .top
.beggining:
xor ebx , ebx
mov ecx, 10;mov into cx 10
cmp eax, 0
jl .negate


.top:
;divide by 10 and push remainder onto stack
xor edx, edx;clear out remainder
div ecx ;divide ax by 10
push edx;push the remainder onto the stack for later
inc ebx;count the number of digits
test eax,eax;if ax = 0 then stop
jne .top

.loop:
pop eax;restore the remainder
add eax, '0';convert to ASCII
mov ah, 0xe;print
int 0x10
dec ebx;get ready for the next digit
cmp ebx, 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;prints the loading message
call Print_ln
;the adress is already stored in ES:DI

MOV ES, WORD[DiskAddressPacket.Segment]
MOV DI, WORD[DiskAddressPacket.Offset]
    xor BX, BX;initialize bx
xor si, si ;initialize si

    .top:

MOV AL,BYTE[ES:DI+BX] ;moves in letter of file name into al
cmp AL,BYTE[STAGE2];compares chars
je .Done;if the same then jump to the next label
cmp AL,BYTE[STAGE2];if not the same then the file wasn't found
je .FAIL
INC BX
jmp .top

.Done:
Print Found_Possible_FILE, TEAL;Prints the possible file found message
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 match
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


INC BX
INC SI
INC CX
cmp CX, WORD[STAGE_2_LEN]
jne .top2
call clear

Print File_Found, TEAL
call Print_ln


SUB BX, 10
ADD DI, BX

LEA EAX, [ES:DI];gets the address of the start of the file

call itoa;prints it
call Print_ln

Print Reading_Sectors, TEAL;Print the reading sectors message

;loads the address into the DAP
    MOV WORD[DiskAddressPacket.Segment], ES
MOV WORD[DiskAddressPacket.Offset], DI
;reads the sectors with the new address
;XOR AX, AX
;MOV AX, WORD[DiskAddressPacket.End]

;MOV WORD[DiskAddressPacket.SectorsToRead], 0
mov cx, 0x04
call Read_Sectors

Print READ_SUCCESS, TEAL;Prints that read was a success
call Print_ln

mov     dl, [CDDriveNumber];puts the drive number into dl for the next stage to use
;xor     si,si

push ES
push DI
retf;jumps to the next stage or tries to jump error here

.FAIL:
call Print_ln
Print FILE_NOT_FOUND, RED;print file not found
cli;halt the system
hlt


ret


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, 0x07c0 ;adjust the segment registers
mov ds, ax
mov gs, ax; stack begins at 0x9000-0xffff
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:

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

xor cx, cx
mov cx, 0x01
Print Reading_Sectors, TEAL
call Read_Sectors                          ; Call read sector from drive
           
Print READ_SUCCESS, TEAL;if the program gets here it means it was a success
call Print_ln
LOAD_STAGE2:
call READ_STAGE2






Sector_Size: dw   512
CDDriveNumber: db   0x080
CD_bytes_per_sect:          dw    0
CD_root_dir_size:          dd    0
CD_root_dir_sectors:        dw    0
CD_root_dir_start:          dd    0
CD_file_size:              dd    0
CD_file_sectors:            dw    0
CD_file_start:              dd    0
CD_desc_sector:            dd    0
CD_Signature:     db    "CD001"
CD_FILE_VER:     db    0x01
CD_FileNameLength: db   0x0
CD_dir_curr_size: db 0x0
joliet_signature:        db    025h,02Fh,045h
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: db 0xA
File_Found: db "File for Stage 2 of the bootloader was successfully loaded!!",0
LOADING_STAGE2_FAILED: db  "Failed to load Stage 2 of the boot loader !!!!!",0
Found_Possible_FILE: db "Found Possible File",0
;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: DB 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
Updated code for Second stage
Code: [Select]
[BITS 16]
[ORG 0x0100]

Start: jmp main

%DEFINE TEAL 0x03
%DEFINE RED 0x04
%DEFINE PURPLE 0x05
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_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], DL
ret





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, 0x9000 ;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

               
call Print_ln
Print LOAD_SUCCESS, TEAL
call Print_ln





LOAD_SUCCESS: db "Stage 2 of the bootloader has loaded successfully!",0






Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 27, 2014, 05:06:42 PM
Hmmm maybe I haven't found the file because whenever I jump to it it does print some code but its not supposed to be printed here let me attach the png am I going through the root incorrectly ??? It is jumping somewhere because it is executing code it shouldn't be once it makes that jump it should be out of the file. By the way the number not in color is the address at [ES:DI]
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 27, 2014, 09:21:12 PM
OK I have changed it to see the real adress where it is reading and it looks like it is way off here is the code for the read stage 2 function:
Code: [Select]
READ_STAGE2:
        Print LOADING_STAGE2_MSG, TEAL;prints the loading message
        call Print_ln
;the adress is already stored in ES:DI
        ;add DI, 158
xor BX, BX;initialize bx
        xor si, si ;initialize si
         
    .top:
                 
                MOV AL,BYTE[ES:DI+BX] ;moves in letter of file name into al
                cmp AL,BYTE[STAGE2];compares chars
                je .Done;if the same then jump to the next label
                cmp AL,BYTE[STAGE2];if not the same then the file wasn't found
                je .FAIL
                INC BX
        jmp .top
         
        .Done:
        Print Found_Possible_FILE, TEAL;Prints the possible file found message
        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 match
                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
                                                 
                         
                        INC BX
                        INC SI   
                        INC CX
        cmp CX, WORD[STAGE_2_LEN] 
        jne .top2
        call clear
         
        Print File_Found, TEAL
        call Print_ln
         
         
        SUB BX, 10
        ADD DI, BX
         
     
     

        Print Reading_Sectors, TEAL;Print the reading sectors message
         
        ;loads the address into the DAP
MOV WORD[DiskAddressPacket.Segment], ES
MOV WORD[DiskAddressPacket.Offset],  DI
        ;reads the sectors with the new address
xor cx, cx
mov cx, 0x04
call Read_Sectors     
         
        Print READ_SUCCESS, TEAL;Prints that read was a success
        call Print_ln
         
        mov     dl, [CDDriveNumber];puts the drive number into dl for the next stage to use
        ;xor     si,si
       

;Prints out the segment and offset ES:DI for debugging
mov ax ,es
       
        call itoa;prints it
       
mov al, BYTE[Colon]
mov ah, 0xe
int 0x010

mov ax ,di;gets the address of the start of the file
       
        call itoa;prints it
        call Print_ln
jmp  0x0200:0x0;jumping here


        .FAIL:
        call Print_ln
        Print FILE_NOT_FOUND, RED;print file not found
        cli;halt the system
        hlt
         
         
ret
Here is what the output looks like :
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 27, 2014, 10:27:22 PM
Judging from the number you print, the sector you read (if success) goes at 0x200:0x1CE. Then you jump to 0x200:0. This looks like it could be a problem.

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 27, 2014, 10:43:31 PM
So I tried jumping to 0x0200:0x1CE and no change for some reason, I am jumping to that location because that is where the result of the read sectors is stored or at least it should be I might check it again
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 27, 2014, 11:04:41 PM
Seems it would make more sense to load it at 0x200:0... or perhaps at 0x200:0x100 since that seems to be your latest (apparently random) "org" in stage2.

Best,
Frank

Title: Re: 2 Stage Bootloader
Post by: gammac on July 27, 2014, 11:11:09 PM
I didn't had a close look at your code but I saw this:

Code: [Select]
    .top:
                 
                MOV AL,BYTE[ES:DI+BX] ;moves in letter of file name into al
                cmp AL,BYTE[STAGE2];compares chars
                je .Done;if the same then jump to the next label
                cmp AL,BYTE[STAGE2];if not the same then the file wasn't found
                je .FAIL
                INC BX
        jmp .top

and it looks senseless to me. What are you doing here? Two identical cmp instructions followed by identical jcc instructions to different locations??



btw:

Code: [Select]
MOV AL,BYTE[ES:DI+BX] ;moves in letter of file name into al
If you hadn't told me that you move something into al .... ;)
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 27, 2014, 11:13:44 PM
I tried loading to that too and it still is giving me the same output hmmm Should I give it a new origin? I thought you could give it whatever you want according to the memory map of course and I think thats ok right?
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 27, 2014, 11:16:17 PM
Gammac I am comparing the the file name to the string of the file name I wan't to find if it is the same then I have found the file subtract the offset by the length of the file name and add it to DI.
Also I got a different output this time there is no random prints after I print there address but there is nothing after it at all which still means I failed to jump to it I tried jmp [ES:DI] still didn't work Man this is a real conundrum isn't it im gonna keep hacking at it to see what I get.
Title: Re: 2 Stage Bootloader
Post by: gammac on July 27, 2014, 11:19:52 PM
but this branch

Code: [Select]
je .FAIL
will never happened
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 27, 2014, 11:24:22 PM
Almost forgot to post output here it is:
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 27, 2014, 11:26:23 PM
Wow I didn't even notice that *face palm* thanks gammac now I realize why its doing this I messed up so bad :P I'm gonna go ahead and fix that
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 27, 2014, 11:58:30 PM
Ok here is my code it is printing out what is at ES:DI+BX and it prints out the file that I wan't but it moves on :( I might have missed something here is the code
Code: [Select]
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL
call Print_ln
mov es, [DiskAddressPacket.Segment]
mov di, [DiskAddressPacket.Offset]

    xor BX, BX
xor si, si

    .top:

MOV AL,[ES:DI+BX] ;starting address
cmp AL,BYTE[STAGE2]
je .Done
cmp AL,BYTE[STAGE2]
je .FAIL
INC BX
jmp .top

.Done:
Print Found_Possible_FILE, TEAL
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter

.top2:
xor ax, ax

MOV AL, BYTE[ES:DI+BX]
MOV AH, 0xE
INT 0x010
MOV AL, BYTE [ES:DI+BX]
cmp AL, BYTE[STAGE2+SI]

je .Success
call Print_ln
jmp .top
.Success:

Print Progress_MSG, PURPLE


INC BX
INC SI
INC CX
cmp CX, WORD[STAGE_2_LEN]
jne .top2
;call clear

Print File_Found, TEAL
call Print_ln

;call clear
SUB BX, 10
ADD DI, BX

;jump to where the file is located and run it
JMP 0x00:0x0200

.FAIL:
call Print_ln
Print FILE_NOT_FOUND, RED
cli
hlt


ret
Here is the output:
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 28, 2014, 12:48:32 AM
Now its just going crazy its like its skipping everything and going straight to printing that the file was found but it wasn't
Here is the new code:
Code: [Select]
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL
call Print_ln
mov es, [DiskAddressPacket.Segment]
mov di, [DiskAddressPacket.Offset]

    xor BX, BX
xor si, si
xor cx, cx
.top3:
add BX, 12
    .top:

MOV AL,[ES:DI+BX] ;starting address
cmp AL,BYTE[STAGE2]
je .Done
cmp AL,BYTE[STAGE2]
jne .top3
INC BX
jmp .top

.Done:
Print Found_Possible_FILE, TEAL
call Print_ln
XOR SI, SI;Clear out for use
;INC BX
;INC SI
xor cx, cx;clear out for use as counter

.top2:
xor ax, ax

MOV AL, BYTE[ES:DI+BX]
MOV AH, 0xE
INT 0x010

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

je .Success
call Print_ln
jmp .top
.Success:

Print Progress_MSG, PURPLE


INC BX
INC SI
INC CX
cmp CX, WORD[STAGE_2_LEN]
jne .top2
;call clear
call Print_ln
Print File_Found, TEAL
call Print_ln

;call clear
SUB BX, 10
ADD DI, BX

;jump to where the file is located and run it
JMP 0x0200:0x00

.FAIL:
call Print_ln
Print FILE_NOT_FOUND, RED
cli
hlt


ret
Here is the output:
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 28, 2014, 01:52:45 AM
Here is what the root looks like if you need it at all:
Code: [Select]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         "             r8ð     "             r8ð    ,             r5ð     
BOOT.CAT;1 .       Π     Îr5ð      STAGE2.BIN;1 0             r5ð     ZEROTHST.BIN;1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ªUUªˆ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             éƒ  `Š6 ´· þƲ ͈6 Æ  aô ¹ ¬„Àt Í´· þÂÍëêô° Í´ Í´· ¶ ² ÍôB0À¾‡Š–Ís`1À1ÒŠ6 Š 1Û³¾±è®ÿˆ aúô`1À1ÒŠ6 Š 1Û³¾æèÿˆ aÿ‰â±èhÿÃ`1À1ÒŠ6 Š 1Û³¾Ìèjÿˆ aŽ‹>‹1Û&Šˆ‡—C< tëò1ÛƒÃ1É1ÀŠ‡—:‡°të A`1À1ÒŠ6 Š 1Û³¾æè ÿˆ aCëÒƒù u!èöþ`1À1ÒŠ6 Š 1Û³¾ÿèùþˆ aë`1À1ÒŠ6 Š 1Û³¾èèÛþˆ aúôè·þÃ`1À1ÒŠ6 Š 1Û³¾æè¹þˆ aè—þ1Û1ö&Š´Í&Š<;tCëïúôÃú¸ÀŽØŽèŽà1ÀŽÀŽÐ¼þÿûˆ–è•þ`1À1ÒŠ6 Š 1Û³¾˜ègþˆ aèEþ`1À1ÒŠ6 Š 1Û³¾¼èHþˆ a¹ èiþ`1À1ÒŠ6 Š 1Û³¾Îè&þˆ aèþèšþŽ‹>‹1Û»( &Š €ù tˆoCëñƇo &f‹…ž f£1ɹ `1À1ÒŠ6 Š 1Û³¾¼èÔýˆ aèøý`1À1ÒŠ6 Š 1Û³¾Îèµýˆ aè“ýèÚþ`1À1ÒŠ6 Š 1Û³¾Cè“ýˆ aèqý €                          CD001  %/EReading sectors Checking for CD Signature Loading Stage 2 of boot loader
File for Stage 2 of the bootloader was successfully loaded!! Failed to load Stage 2 of the boot loader !!!!! Found Possible File
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 28, 2014, 04:39:57 AM
I don't know if this is important but it looks like stage 2 comes before zerothstage in the root I don't know if that matters at all just wanted to point that out
Title: Re: 2 Stage Bootloader
Post by: gammac on July 28, 2014, 09:02:56 AM
Code: [Select]
    xor BX, BX
xor si, si
xor cx, cx
.top3:
add BX, 12 ; What happens if bx is incremented elsewhere?
    .top:

MOV AL,[ES:DI+BX] ;starting address ; address of a filename in your list of names?
cmp AL,BYTE[STAGE2] ; STAGE2 is the address of given filename?
je .Done
cmp AL,BYTE[STAGE2] ; useless, previous branch do not alter flags
jne .top3 ; test next filename?
INC BX ; ATTENTION: never reached
jmp .top ; never reached

.Done:
; OK, we are here that means the first character matches.
; What are you doing now?
...


please explain your whole filesearching algorithm in pseudocode and try to write well commented code.

Code: [Select]
XOR SI, SI;Clear out for use
...
xor cx, cx;clear out for use as counter

this types of comments are useless, only the word counter is an information

Code: [Select]
INT 0x010
what does this interupt?
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 28, 2014, 04:25:54 PM
Sorry about the undocumented code I will fix that ASAP as for INT 0x010 that is to write to the video memory to output things on the screen basically a print thats how I know that it passes it file I wan't here is the code:
Code: [Select]
READ_STAGE2:
Print LOADING_STAGE2_MSG, TEAL
call Print_ln
;mov es, [DiskAddressPacket.Segment]
;mov di, [DiskAddressPacket.Offset]

    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, 10;goes back to the start of the file
ADD DI, BX;adds to the offset
;moves in the new adress ES:DI into the DAP
MOV WORD[DiskAddressPacket.Segment], ES
MOV WORD[DiskAddressPacket.Offset], DI
xor cx, cx;clears out cx
mov cx, 0x04;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
;Print File_Found, TEAL
JMP [ES:DI] ;jumps to the file

.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
EDIT: I finally fixed the string compare it wasn't working because the STAGE2_LEN was a defined BYTE instead of a DEFINED WORD :D now I still have the problem of going to the next file. I will post Output to show what it looks like the code above was updated to the new code.
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 28, 2014, 04:36:32 PM
Here is the output:
Title: Re: 2 Stage Bootloader
Post by: gammac on July 28, 2014, 05:47:42 PM
sorry Anonymous, your code is an 'eye-pain' and I bet it won't work correct. Searching for two identical letters and then comparing the rest will produce false positives e.g. if you have files named 'oldstage2' and 'stage2'.
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 28, 2014, 05:54:20 PM
But I don't have files named oldstage2 because filenames can't be longer than 10 6 for the name 1 for the . and 3 for the extension because it is an El torrito standard ISO that's why I am not checking for files that might have an identical name.
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 28, 2014, 06:27:15 PM
I have been using the code for CD bootloader to help me out if this helps anyone see what I am trying to do and yes it is in fasm but it is the only one that I could find that is closest to nasm and booting off of a CD
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler on July 28, 2014, 06:58:16 PM
I notice you're back to the near jump. I'm really quite sure that isn't going to do what you want.
Code: [Select]
LOADSEG equ 0x200 ; ?
LOADOFFS equ 0 ; ?

; some ways to do a far jump
    jmp LOADSEG:LOADOFFS
; this needs to be "immediate"
; note that segment comes first in this syntax
; in contrast to the usual little-endian arrangement

; jmp es:bx will not work (more's the pity)
; but you can do...
push es
push bx
retf
; with the same result

; or you could use an indirect jump
; it jumps to the address found at the address you provide

;...
    jumptarget dw LOADOFFS, LOADSEG
;...
    jmp far [jumptarget]

; if you don't know 'em in advance, you can...
    mov [jumptarget], bx
    mov [jumptarget + 2], es
    jmp far [jumptarget]

; but...
    jmp [jumptarget]
; or
    jmp [es:bx]
; is going to take just the offset
; and jmp there - in the same segment

Hope that helps...

Best,
Frank

EDIT: Well how does the Fasm file do it? Fine assembler! Why not just use it?

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 28, 2014, 07:18:36 PM
I tried everything you said and it is still not going there the fasm file uses some drive geometry but the only thing is that it won't work because my iso will only read 4 sectors anything higher it will freeze because it is not able to ready anything else probably because the files I have on there only occupy 4 sectors
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 28, 2014, 07:19:47 PM
Here is the output of this far jump:
Code: [Select]
mov [jumptarget], ES
mov [jumptarget + 2], DI
jmp far [jumptarget]
The print below the printed segment offset address is not supposed to happen so it is jumping somewhere just maybe not far enough??? 
Title: Re: 2 Stage Bootloader
Post by: gammac on July 28, 2014, 07:28:50 PM
I have been using the code for CD bootloader to help me out if this helps anyone see what I am trying to do and yes it is in fasm but it is the only one that I could find that is closest to nasm and booting off of a CD

Interesting, thank you for sharing this file. :)
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler 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

Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 28, 2014, 08:01:11 PM
Thanks for clarifying still wouldn't work but thanks anyway I will keep at it
Title: Re: 2 Stage Bootloader
Post by: Anonymous 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
Title: Re: 2 Stage Bootloader
Post by: gammac 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?
Title: Re: 2 Stage Bootloader
Post by: Anonymous 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.
Title: Re: 2 Stage Bootloader
Post by: Anonymous 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
Title: Re: 2 Stage Bootloader
Post by: Anonymous on July 29, 2014, 09:41:56 PM
Anyone else have anything I am stuck I really don't know what to do now :-\
Title: Re: 2 Stage Bootloader
Post by: Anonymous 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.
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler 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

Title: Re: 2 Stage Bootloader
Post by: Anonymous 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
Title: Re: 2 Stage Bootloader
Post by: Anonymous 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
Title: Re: 2 Stage Bootloader
Post by: Tony201500 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
Title: Re: 2 Stage Bootloader
Post by: Frank Kotler 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

Title: Re: 2 Stage Bootloader
Post by: timryazthunder on January 29, 2021, 08:35:44 PM
Tried to make an OS using the two stage CD bootloader and it miserably fails whenever the system is trying to read from BIOS,
Used 86Box as an emulator.
Throws up every time with a sector error.
It shows the same message as that anonymous coder with the CD boot.