This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
|
my_mbr [2017/03/06 07:31] admin |
my_mbr [2017/03/27 10:36] (current) admin |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| =====My MBR===== | =====My MBR===== | ||
| - | I'm using NASM to write my [[real mode]] code, and I use file extension "nasm" to separate them from other assembler files. This makes the build process able to automatically select the correct assembler. | + | I'm using NASM to write my [[real mode]] code, and I use file extension "nasm" to separate them from other assembler files. This makes the build process able to automatically select the correct assembler.\\ |
| + | \\ | ||
| + | **Current state:**\\ | ||
| + | 1. Copy 512 bytes to new location.\\ | ||
| + | 2. Load 64-bit set-up code.\\ | ||
| + | 3. Load kernel loader.\\ | ||
| + | 4. Execute 64-bit set-up code.\\ | ||
| + | |||
| + | Function ''seek'': Convert absolute sector number into CHS values directly acceptable for INT13h (AH=02). | ||
| <file asm> | <file asm> | ||
| [bits 16] | [bits 16] | ||
| Line 32: | Line 40: | ||
| mov es, cx ; Extra Segment | mov es, cx ; Extra Segment | ||
| mov ss, cx ; Stack Segment | mov ss, cx ; Stack Segment | ||
| - | mov sp, loc_MBR ; Top of stack is bottom of relocation point | + | mov sp, loc_STACK ; Top of stack |
| mov ds, cx ; Data Segment | mov ds, cx ; Data Segment | ||
| - | mov di, sp ; Destination for stream | + | mov di, loc_MBR ; Destination for stream |
| mov si, bootpoint ; Source of stream | mov si, bootpoint ; Source of stream | ||
| cld ; Clear direction flag (stream increment) | cld ; Clear direction flag (stream increment) | ||
| mov ch, 1 ; cx = 256 | mov ch, 1 ; cx = 256 | ||
| rep movsw ; word move = 512 bytes copy, one HD sector | rep movsw ; word move = 512 bytes copy, one HD sector | ||
| - | jmp 0x0000:continue ; JMP to copy of self | + | jmp 0x0000:continue ; far JMP to copy of self |
| - | + | ||
| - | ;bootdisk db 0 | + | |
| SEGMENT MAIN align=16 ;At 0:7A00 + START.length | SEGMENT MAIN align=16 ;At 0:7A00 + START.length | ||
| continue: | continue: | ||
| - | ; mov [bootdisk], dl | + | mov [drive.disk], dl |
| sti ; enable interrupts | sti ; enable interrupts | ||
| - | mov si, 3 ;Three tries | + | ; grab drive geometry for LBA/CHS conversion |
| + | mov ah, 8 ; check drive parameters | ||
| + | xor di, di | ||
| + | int 13h | ||
| + | mov [drive.H], dh ; last head | ||
| + | mov al, cl | ||
| + | and al, 0x3F ; mask sectors | ||
| + | mov [drive.S], al ; sectors per track | ||
| + | xchg ch, cl ; swap ch/cl - 76543210.98xxxxxx -> 98xxxxxx.76543210 | ||
| + | shr ch, 6 ; shift ch - xxxxxx98.76543210 | ||
| + | mov [drive.C], cx ; last cylinder | ||
| + | mov al, [drive.H] ; grab last head | ||
| + | inc al ; make head-count | ||
| + | mul byte [drive.S] ; make sectors per cylinder | ||
| + | mov [drive.HSmpx], ax ; sectors per cylinder | ||
| + | |||
| + | |||
| + | load64: | ||
| + | mov si, 3 ; three tries | ||
| + | try64: | ||
| + | mov ax, 1 ; sector 1 | ||
| + | call seek ; grab CHS -> dx 0080, cx 0002, ax 0000 | ||
| + | mov ah, 02h ; "read CHS" | ||
| + | mov al, 20 ; 20 = space between loader point and stack (20 x 512 = 10240) | ||
| + | mov bx, loc_LOADER ; mem | ||
| + | int 13h ; 'dl' contains boot disk from MBR entry | ||
| + | jnc loadloader ; success | ||
| + | dec si ; retry count | ||
| + | jnz try64 | ||
| + | jmp fail | ||
| + | |||
| + | loadloader: | ||
| + | mov si, 3 ; three tries | ||
| try: | try: | ||
| - | mov bx, loc_LOADER ;Read it into 0x7C00 | + | mov ax, 21 ; sector 21 |
| - | mov ax, 0x0210 ;Command to read 16 sectors | + | call seek ; grab CHS |
| - | mov cx, 0x0002 ;Sector 2 / Cylinder 1 | + | mov ah, 02h ; "read CHS" |
| + | mov al, 40 ; 10 sectors | ||
| + | mov bx, loc_ELF ; mem | ||
| int 13h ; 'dl' contains boot disk from MBR entry | int 13h ; 'dl' contains boot disk from MBR entry | ||
| - | jnc ok ;Success | + | jnc ok ; success |
| - | dec si ;retry count | + | dec si ; retry count |
| jnz try | jnz try | ||
| + | jmp fail | ||
| + | |||
| fail: | fail: | ||
| mov bx, 0x15 ; bold attribute | mov bx, 0x15 ; bold attribute | ||
| Line 65: | Line 107: | ||
| hlt | hlt | ||
| jmp crap | jmp crap | ||
| + | |||
| ok: | ok: | ||
| cli | cli | ||
| jmp loc_LOADER ; set up for 64-bit, long mode, and bootloader | jmp loc_LOADER ; set up for 64-bit, long mode, and bootloader | ||
| + | |||
| + | ; input: | ||
| + | ; ax: zero-based sector to find | ||
| + | ; output: (int13-02 compatible) | ||
| + | ; dl: drive | ||
| + | ; dh: head | ||
| + | ; cx: cyl.sec - C 76543210.98xxxxxx - S xxxxxxxx.xx543210 | ||
| + | ; example | ||
| + | ; dh: 02 H:0-2 3 heads per cylinder | ||
| + | ; cx: 0802 C:0-8 S:1-2 9 cylinders, 2 sectors per track | ||
| + | ; makes sector 21: C/H/S = 3/1/2 = 3x6+2x1+(2-1) | ||
| + | ; mov cx, 0x0302 ; C=3 / S=2 | ||
| + | ; mov dh, 1 ; H=1 | ||
| + | seek: | ||
| + | push bx | ||
| + | xor dx, dx ; DIV input DX:AX | ||
| + | div word [drive.HSmpx] ; operation DX:AX / HSmpx = AX.DX | ||
| + | xchg ah, al ; xxxxxx98.76543210 -> 76543210.xxxxxx98 | ||
| + | shl al, 6 ; 76543210.98xxxxxx | ||
| + | mov cx, ax ; set cylinder | ||
| + | mov ax, dx ; set remainder - ((LBA/mpx)*mpx) -> AX | ||
| + | xor dx, dx ; zero DX (DX:AX) | ||
| + | xor bh, bh ; zero | ||
| + | mov bl, byte [drive.S] ; grab sectors per track | ||
| + | div bx ; remainder / S | ||
| + | mov dh, al ; set head | ||
| + | inc dl ; remainder is sector, sector is 1-based | ||
| + | or cl, dl ; insert sector | ||
| + | mov dl, [drive.disk] ; set disk | ||
| + | pop bx | ||
| + | ret | ||
| + | |||
| + | drive: | ||
| + | .disk db 0 ; BIOS-supplied drive number | ||
| + | .C dw 0 ; last cylinder, 0-> | ||
| + | .H db 0 ; last head, 0-> | ||
| + | .S db 0 ; sector per track, 1-> | ||
| + | .HSmpx dw 0 ; HxS per cylinder | ||
| + | |||
| + | |||
| + | |||
| ; put segment FINAL at the end of the sector | ; put segment FINAL at the end of the sector | ||