OSDev.org

The Place to Start for Operating System Developers
It is currently Mon Jun 14, 2021 11:05 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 98 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7  Next
Author Message
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 9:58 am 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
The first sector of a FAT disk/partition is a mix of code and file system data.
1.) In the code you must skip over the data (the BIOS Parameter block) and continue after the BPB.

2.) In the script/makefile you must write only the code to the disk image. Otherwise you erase the FAT file system data.


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 10:06 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 19, 2020 1:08 pm
Posts: 154
Location: Italy
PeterX wrote:
In the code you must skip over the data (the BIOS Parameter block) and continue after the BPB

How large is the BPB? does it depends on the file system? From where should I should start adding code?

PeterX wrote:
Otherwise you erase the FAT file system data.

Is this also in the BPB or is some other part of the disk to not override?

_________________
Greetings, Bonfra.


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 10:12 am 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
Bonfra wrote:
PeterX wrote:
In the code you must skip over the data (the BIOS Parameter block) and continue after the BPB

How large is the BPB? does it depends on the file system? From where should I should start adding code?

PeterX wrote:
Otherwise you erase the FAT file system data.

Is this also in the BPB or is some other part of the disk to not override?

Yes, it depends on the file system. Here is a list of the different DOS versions and their BPB:
https://en.wikipedia.org/wiki/BIOS_parameter_block
I suggest you take the DOS 7.1 FAT32 structure which goes from offset 3 to offset 95. So from offset 96 on it's ok to write code.
No, there is no other data that should not be overwritten. When I talk about FAT file system data and BPB I mean the same.


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 10:15 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 19, 2020 1:08 pm
Posts: 154
Location: Italy
PeterX wrote:
I suggest you take the DOS 7.1 FAT32 structure which goes from offset 3 to offset 95. So from offset 96 on it's ok to write code.

7.1 Is for FAT32, by now I'm using FAT12. Do you think I should just switch to FAT32 or use a FAT12 BPB for now?

Or I just ignore that part of the disk to leave compatibiliy for FAT32 and continue using FAT12?

_________________
Greetings, Bonfra.


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 10:17 am 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
Bonfra wrote:
Or I just ignore that part of the disk to leave compatibiliy for FAT32 and continue using FAT12?

I suggest yes. But it's up to you. All three options should work (somehow).


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 10:35 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 19, 2020 1:08 pm
Posts: 154
Location: Italy
So in the bootloader file I do something like this:

Code:
jmp 0x7C00 : boot

biosParameterBlock:
times 0x52-($-$$) db 0 ; BPB 7.1 FAT32 ends at 0x52.

boot:
  ; Actual boot code


And I need to copy the jump and the boot in the partition.dd excluding the biosParameterBlock.
The problem is that even if I copy only the first byte the partition is no more recognized:
Code:
dd if=bin/boot/boot.bin of=partition.dd seek=0 count=1 conv=notrunc bs=1


This is the partition before copy:
Code:
EB 3C 90 6D 6B 66 73 2E-66 61 74 00 02 04 04 00 [...]

This is the partition after copy:
Code:
EA 3C 90 6D 6B 66 73 2E-66 61 74 00 02 04 04 00 [...]

_________________
Greetings, Bonfra.


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 10:47 am 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
Code:
jmp 0x7C00 : boot

No, that's a far jump. It takes 5 bytes. But you have only room of 3 bytes. So use a near jump
Code:
jmp boot

or a short jump
Code:
jmp short boot
nop


I recommend the short JMP.


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 10:52 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 19, 2020 1:08 pm
Posts: 154
Location: Italy
In the bootloader:
Code:
jmp short boot


In the terminal:
Code:
dd if=bin/boot/boot.bin of=partition.dd seek=0 count=1 conv=notrunc bs=3


And the image results in:
Code:
EB 5E 00 6D 6B 66 73 2E-66 61 74 00 02 04 04 00 [...]


But the image is still marked as unknown

_________________
Greetings, Bonfra.


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 10:54 am 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
Bonfra wrote:
In the bootloader:
Code:
jmp short boot


In the terminal:
Code:
dd if=bin/boot/boot.bin of=partition.dd seek=0 count=1 conv=notrunc bs=3


And the image results in:
Code:
EB 5E 00 6D 6B 66 73 2E-66 61 74 00 02 04 04 00 [...]

Add the "nop". Some BIOS check for that NOP.


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 11:06 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 19, 2020 1:08 pm
Posts: 154
Location: Italy
PeterX wrote:
Add the "nop". Some BIOS check for that NOP.


It was this! Now the image is valid. I'll do some testing to load the bootloader and I'll let you know. Thanks

_________________
Greetings, Bonfra.


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 12:00 pm 
Offline
Member
Member
User avatar

Joined: Wed Feb 19, 2020 1:08 pm
Posts: 154
Location: Italy
Ok the partition works perfectly. It is created with this script:
Code:
#Create the partition
dd if=/dev/zero of=partition.dd bs=512 count=65536 # count = [ K = megabyte; K*(1024)^2/512 ]
mkfs.vfat -F 16 partition.dd

#Add file to the partition
mcopy -i partition.dd path/to/file.eg ::/

#Add the bootloader to the partition
dd if=path/to/boot.bin of=partition.dd seek=0 count=1 conv=notrunc bs=3
dd if=path/to/boot.bin of=partition.dd seek=83 seek=83 skip=83 count=$[512-83] conv=notrunc bs=1


Then I Create the disk image and copy the partition in it:
Code:
#Create the Disk image
dd if=/dev/zero of=disk.dd bs=512 count=$[2048+65536]
echo -e "n \n p \n \n \n \n t \n 6\n a \n w" | fdisk disk.dd

#Load the MBR
dd if=bin/boot/mbr.bin of=disk.dd seek=0 count=1 conv=notrunc bs=436

#Add the partition to the disk
dd if=partition.dd of=disk.dd conv=notrunc bs=512 seek=2048


If I boot just the partition.dd with:
Code:
qemu-system-x86_64 partition.dd

It prints "Hello, World!" but if i boot the disk.dd it prints nothing, instead it clears the screen (which I think is not a good thing).

Is it something with the disk reading part?
This is the code for the MBR:
Code:
bits 16
org 0x0600

start:
    cli                         ; We do not want to be interrupted
    xor ax, ax                  ; 0 AX
    mov ds, ax                  ; Set Data Segment to 0
    mov es, ax                  ; Set Extra Segment to 0
    mov ss, ax                  ; Set Stack Segment to 0
    mov sp, ax                  ; Set Stack Pointer to 0
    .CopyLower:
        mov cx, 0x0100            ; 256 WORDs in MBR
        mov si, 0x7C00            ; Current MBR Address
        mov di, 0x0600            ; New MBR Address
        rep movsw                 ; Copy MBR
    jmp 0:LowStart              ; Jump to new Address

LowStart:
    sti                         ; Start interrupts

    mov BYTE [bootDrive], dl    ; Save BootDrive
    .CheckPartitions:           ; Check Partition Table For Bootable Partition
        mov bx, PT1               ; Base = Partition Table Entry 1
        mov cx, 4                 ; There are 4 Partition Table Entries
        .CKPTloop:
            mov al, BYTE [bx]       ; Get Boot indicator bit flag
            test al, 0x80           ; Check For Active Bit
            jnz .CKPTFound          ; We Found an Active Partition
            add bx, 0x10            ; Partition Table Entry is 16 Bytes
            dec cx                  ; Decrement Counter
            jnz .CKPTloop           ; Loop
            jmp error.noBootablePartition ; ERROR!
        .CKPTFound:
            mov WORD [PToff], bx    ; Save Offset
            add bx, 8               ; Increment Base to LBA Address
    .ReadVBR:
        mov EBX, DWORD [bx]       ; Start LBA of Active Partition
        mov di, 0x7C00            ; We Are Loading VBR to 0x07C0:0x0000
        mov cx, 1                 ; Only one sector
        call ReadSectors          ; Read Sector
   
    .jumpToVBR:
        cmp WORD [0x7DFE], 0xAA55 ; Check Boot Signature
        jne error                 ; Error if not Boot Signature
        mov si, WORD [PToff]      ; Set DS:SI to Partition Table Entry
        mov dl, BYTE [bootDrive]  ; Set DL to Drive Number
        jmp 0x7C00                ; Jump To VBR
       
error:
    jmp hang

    .noBootablePartition:
        mov si, Message.Error.NoBootablePartition
        call BiosPrint
        jmp hang

hang:
    cli
    hlt
    jmp hang

absoluteSector  db 0x00
absoluteHead    db 0x00
absoluteTrack   db 0x00

datasector  dw 0x0000
cluster     dw 0x0000

bpbSectorsPerCluster:   DB 1
bpbSectorsPerTrack:     DW 18
bpbHeadsPerCylinder:    DW 2
bpbBytesPerSector:      DW 512


;********************;
; Convert CHS to LBA ;
; Parameters:        ;
;   ax => CHS        ;
; Returns:           ;
;   ax => LBA        ;
;********************;
CHSLBA:
    sub ax, 0x0002                          ; zero base cluster number
    xor cx, cx
    mov cl, BYTE [bpbSectorsPerCluster]     ; convert byte to word
    mul cx
    add ax, WORD [datasector]               ; base data sector
    ret

;********************;
; Convert LBA to CHS ;
; Parameters:        ;
;   ax => LBA        ;
; Returns:           ;
;   ax => CHS        ;
;********************;
LBACHS:
    xor dx, dx                              ; prepare dx:ax for operation
    div WORD [bpbSectorsPerTrack]           ; calculate
    inc dl                                  ; adjust for sector 0
    mov BYTE [absoluteSector], dl
    xor dx, dx                              ; prepare dx:ax for operation
    div WORD [bpbHeadsPerCylinder]          ; calculate
    mov BYTE [absoluteHead], dl
    mov BYTE [absoluteTrack], al
    ret

;***********************************;
; Reads a series of sectors         ;
; Parameters:                       ;
;   cx => Number of sectors to read ;
;   ax => Starting sector           ;
;   es:ebx => Buffer to read to     ;
;***********************************;
ReadSectors:
    pusha
    .start:
        mov di, 0x0005                          ; five retries for error
    .sectorloop:
        call LBACHS                             ; convert starting sector to CHS
        mov ah, 0x02                            ; BIOS read sector
        mov al, 0x01                            ; read one sector
        mov ch, BYTE [absoluteTrack]            ; track
        mov cl, BYTE [absoluteSector]           ; sector
        mov dh, BYTE [absoluteHead]             ; head
        mov dl, BYTE [bootDrive]                ; drive
        int 0x13                                ; invoke BIOS
        jnc .success                            ; test for read error
        xor ax, ax                              ; BIOS reset disk
        int 0x13                                ; invoke BIOS
        dec di                                  ; decrement error counter
        jnz .sectorloop                         ; attempt to read again
    .success:
        push cx                                  ; queue next segment
        mov cx, WORD [bpbBytesPerSector]
        shr cx, 4
        mov dx, es
        add dx, cx
        mov es, dx
        pop cx

        inc ax                                  ; queue next sector
        loop .start                             ; read next sector
        popa
        ret

;************************;
; Parameters:            ;
;   si => string pointer ;
;************************;
BiosPrint:
    pusha
    .loop:
        lodsb
        or al, al
        jz .done
        mov ah, 0x0E
        int 0x10
        jmp .loop
    .done:
    popa
    ret

Message.Error.NoBootablePartition db "No bootable partition found.", 13, 10, 0
Message.cazzo db "CAZZO", 13, 10, 0

bootDrive db 0                ; Our Drive Number Variable
PToff dw 0                    ; Our Partition Table Entry Offset

times (0x1b4 - ($-$$)) nop    ; Pad For MBR Partition Table

UID times 10 db 0             ; Unique Disk ID
PT1 times 16 db 0             ; First Partition Entry
PT2 times 16 db 0             ; Second Partition Entry
PT3 times 16 db 0             ; Third Partition Entry
PT4 times 16 db 0             ; Fourth Partition Entry

dw 0xAA55                     ; Boot Signature

_________________
Greetings, Bonfra.


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 12:25 pm 
Offline
Member
Member

Joined: Fri Nov 22, 2019 5:46 am
Posts: 590
I don't know if this is the reason, but it is wrong:

Code:
       int 0x13                                ; invoke BIOS
        jnc .success                            ; test for read error
        xor ax, ax                              ; BIOS reset disk
        int 0x13                                ; invoke BIOS
        dec di                                  ; decrement error counter
        jnz .sectorloop                         ; attempt to read again
    .success:

This means, it counts down (via DI) and if it still fails, it continues with success.
There should be some error output and halt between "jnz .sectorloop" and ".success"

Also I have the impression you take too advanced code. You kind of copy code from somewhere without truely understanding it. It would be better for your coding success if you try something "smaller" first.
For example you can assume that partition bootsector is at sector 2048 (because FDISK does so). This is not good for a real OS, but you can concentrate more on the disk read subroutine.
Have you looked at Ralph Brown's Interrupt List for disk read routines?

Greetings
Peter


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 1:15 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 778
Location: USA
PeterX wrote:
Also I have the impression you take too advanced code. You kind of copy code from somewhere without truly understanding it.

I am going to agree with Peter here.

The FAT file system occupies certain parts of the partition. This is a must. Therefore, you *must* preserve these areas when writing boot code to the partition.

The first sector of the partition, sometimes called a Logical Sector Number of zero, must contain a valid BPB for the FAT type it uses. The FAT-12 and FAT-16 use the same data region, while FAT-32 occupies a little more of the first sector. As long as you preserve these areas, you are free to add code to the rest.

Please note that the utility that is writing the code to LSN 0 will already know if it is a FAT-12, -16, or -32 file system and will act accordingly.

For FAT-12 and -16 file systems, as long as you use a short jump plus a NOP as the first three bytes of LSN 0, and skip over the BPB, you can use the remaining part of the sector as code, minus the last two bytes, which must be the 0xAA55 signature. In fact, the FAT-12 and -16 file systems allow you to use additional sectors for code starting at LSN 1. However, since the MBR code only loaded 1 sector, your code within the LSN 0 *must* load any remaining sectors to memory.

For FAT-32, LSN 1 through x are used for the file system and must be preserved. This includes a INFO sector.

However, with all three types, as long as you preserved these areas, you can have many sectors worth of code for your boot code.

As with Peter's suggestion, I suggest that you study how the FAT file system works *before* you try to write boot code for it.

As for the code you posted, it makes a lot of assumptions that a newbie will completely miss. One huge example will be the ORG 0x0600 line. Yes, this is correct, given the code doesn't make any memory references until after it moves to 0x00600, but a quick glance over and one might assume too much about this assumption.

Ben
- http://www.fysnet.net/osdesign_book_series.htm


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Sun Nov 01, 2020 1:42 pm 
Offline
Member
Member
User avatar

Joined: Thu Oct 13, 2016 4:55 pm
Posts: 1514
Bonfra wrote:
It prints "Hello, World!" but if i boot the disk.dd it prints nothing, instead it clears the screen (which I think is not a good thing).

Is it something with the disk reading part?
This is the code for the MBR
PeterX and BenLunt gave good advice. However I would also recommend to try it with a known to work MBR code first, before you write your own MBR code.

Under Windows, just use "FDISK.EXE /MBR". Under Linux, use "ms-sys --mbrdos". The code for this MBR sector can be found here (sadly just a byte array), but there's a detailed disassembly with fully commented source code here.

In theory the MBR code does nothing else than chainloading the VBR sector to 0:7C00h. If your image works with the standard code, then the problem is with your MBR code. If it still doesn't work, then the problem is with your disk image creation. FYI this site also contains all MS boot sectors (MBR and VBR alike). You can find a FAT boot sector for floppies as well as for exFAT disks.

Cheers,
bzt


Top
 Profile  
 
 Post subject: Re: Making a bootable image
PostPosted: Mon Nov 02, 2020 2:28 am 
Offline
Member
Member
User avatar

Joined: Wed Feb 19, 2020 1:08 pm
Posts: 154
Location: Italy
Yea you are right, I should start easy implementing my own stuffs.
I tried implementing this ReadSector function:
Code:
ReadSectors:
    mov bx, 0x7C00  ; address
    mov al, 1       ; Number of Sectors
   
    mov dl, [bootDrive]
    mov ch, 0x00   ; cylinder 0
    mov dh, 0x20   ; head 0
    mov cl, 0x21   ; disk sector number

    mov ah, 0x02
    int 0x13    ; Invoke BIOS

    ret

Which relies on this datas:
Image
But the carry flag is setted by the BIOS function so it fails and I don't understand the reason

_________________
Greetings, Bonfra.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 98 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6, 7  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 10 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group