Search code examples
assemblyx86nasmbootloaderminix

Loading old bootloader in assembly x86


I am writing my own bootloader in NASM x86 on x86_64 architechture, for starters I am just trying to copy the existing bootloader into second sector by using dd, then copy it back and run it from assembly.

file.asm

org 0x7c00

jmp 0:start

start:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0x8000

mov           ah, 0x02
mov           al, 1
mov           dl, 0x80
mov           ch, 0
mov           dh, 0
mov           cl, 3
mov           bx, 0x7e00
int           0x13

jmp 0x7e00
times 510-($-$$) db 0
dw 0xaa55

times (1024 - ($ - $$)) db 0x00
third_sector:
mov           ah, 0x02
mov           al, 1
mov           dl, 0x80
mov           ch, 0
mov           dh, 0
mov           cl, 2
mov           bx, 0x7c00
int           0x13

jmp           0x7c00

The code sets up the stack, then pats itself to 1024 bytes with zeroes to have the last bit of code in third sector of the disk, then it loads the second sector from the disk into the first one and jumps to the first sector.

src.sh

#!/bin/bash
dd bs=1 count=512 if=/dev/c0d0 of=tmp
nasm -f bin file.asm -o file 
dd bs=1 count=1200 if=file of=/dev/c0d0
dd bs=1 count=512 seek=512 if=tmp of=/dev/c0d0

What I am doing is copying the original bootloader into temporary file called tmp, then compiling my programme and putting it into old bootloader's place (/dev/c0d0 since I am working on MINIX 3.3.0), then moving old bootloader into second sector.

The result is "Booting from hard disk" string, which is fine, and then I get "NetBSD MBR boot Error P" which corresponds to "no netBSD partition".

Edit: Pasted the wrong asm file. Second edit: Error changed, but still persists.


Solution

  • The NetBSD volume boot record (called a partition boot record or PBR by NetBSD) reads the first block of the disk it was booted from and checks to see if its the same as itself. If it's not then it assumes the disk has an MBR and tries to find the NetBSD boot partition in the MBR. It does this check by a simple comparison of the first 4 bytes of itself as loaded in memory, and the first four bytes of the first sector on disk.

    Since your replacement boot sector doesn't start with the exact same 4 bytes its interpreted as an MBR with a partition table. Since your boot sector doesn't actually have an MBR partition table the NetBSD VBR isn't able to find the NetBSD partition and so prints error P (maybe or error no slice, depending on how it was configured).

    To solve this problem you'll need to copy your disk's partition table into your replacement MBR. Note this also necessary because NetBSD itself (or whatever you're booting) will also want to read the partition table.

    If your disk doesn't have an MBR with a partition table, and instead starts with the NetBSD VBR (PBR) then there isn't much you can do to fix the problem. In that case when the NetBSD VBR boots normally, it loads the first 15 sectors into memory at 0000:1000, checks that the first four bytes match itself as described above, and if so jumps to the code loaded at 0000:1000. Since you're changing the first 3 sectors of the disk you're also overwriting the NetBSD disk label at sector 2 and the start of what NetBSD calls the phase 1 bootstrap (bootxx) at sector 3.