Ok finally it works and the partition bootloader is loaded correctly and runs. I'd like to summarize the whole process in one post for any future readers.
First I created a partition image and add any needed file with this lines:
Code: Select all
dd if=/dev/zero of=partition.dd bs=512 count=65536 # count = [ K = megabyte; K*(1024)^2/512 ]
mkfs.vfat -F 16 -n "MyOS" partition.dd
#mcopy -i partition.dd path/to/file.eg ::/
Then I loaded the bootloader in the partition paying attention to not override the BPB:
Code: Select all
dd if=bin/boot/boot.bin of=partition.dd seek=0 count=1 conv=notrunc bs=3
dd if=bin/boot/boot.bin of=partition.dd seek=83 seek=83 skip=83 count=$[512-83] conv=notrunc bs=1 # 83 is the end address of the 7.1 FAT32 BPB
Then I create the actual disk image:
Code: Select all
dd if=/dev/zero of=disk.dd bs=512 count=$[2048+65536] #65536 is the K value from above
echo -e "n \n p \n \n \n \n t \n 6\n a \n w" | fdisk -H 16 -S 63 disk.dd
Then I added the MBR to the image paying attention to not override the partition table:
Code: Select all
dd if=bin/boot/mbr.bin of=disk.dd seek=0 count=1 conv=notrunc bs=436
And finally add the partition to the disk:
Code: Select all
dd if=partition.dd of=disk.dd conv=notrunc bs=512 seek=2048
I'll also post the minimal code for the MBR and the partition bootloader:
MBR code: (This code make some assumption in the ReadSectors function so it should be changed for a normal use)
Code: Select all
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:
call ReadSectors ; Read Sector
jc error.diskReadFailed
mov si, Message.Status.VBRLoaded
call BiosPrint
.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
.diskReadFailed:
mov si, Message.Error.DiskReadFailed
call BiosPrint
jmp hang
.noBootablePartition:
mov si, Message.Error.NoBootablePartition
call BiosPrint
jmp hang
hang:
cli
hlt
jmp hang
;***********************************;
; Reads a series of sectors ;
; Returns: ;
; cf => set if error ;
;***********************************;
ReadSectors:
.init:
mov dl, [bootDrive]
mov ah, 0x00
int 0x13
jc .init
.readSec:
mov bx, 0x7C00 ; address
mov al, 1 ; Number of Sectors
mov dl, [bootDrive]
mov ch, 0x02 ; cylinder 0x02
mov dh, 0x00 ; head 0x00
mov cl, 0x21 ; disk sector number
mov ah, 0x02
int 0x13 ; Invoke BIOS
jc .readSec
ret
;************************;
; Parameters: ;
; si => string pointer ;
;************************;
BiosPrint:
pusha
.loop:
lodsb
or al, al
jz .done
mov ah, 0x0E
int 0x10
jmp .loop
.done:
popa
ret
times (218 - ($-$$)) nop ; Pad for disk time stamp
DiskTimeStamp times 8 db 0 ; Disk Time Stamp
Message.Error.NoBootablePartition db "No bootable partition found.", 13, 10, 0
Message.Error.DiskReadFailed db "Disk read failed", 13, 10, 0
Message.Status.VBRLoaded db "VBR loaded!", 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
Partition bootloader code:
Code: Select all
org 0x7C00
bits 16
jmp short boot
nop
biosParameterBlock:
times 0x52-($-$$) db 0 ; BPB 7.1 FAT32 ends at 0x52.
boot:
.init:
cli
; adjust segment registers
mov ax, cs
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
; create stack
xor ax, ax
mov ss, ax
mov sp, 0x7C00
sti
mov si, String.HelloWorld
call BiosPrint
hang:
cli
hlt
jmp hang
String.HelloWorld db "Hello, World!", 13, 10, 0
BiosPrint:
pusha
.loop:
lodsb
or al, al
jz .done
mov ah, 0x0E
int 0x10
jmp .loop
.done:
popa
ret
times 510-($-$$) db 0
dw 0xAA55
Finally I'd like to thank
PeterX,
MichaelPetch,
BenLunt (and his tool) and
bzt for helping me out.