ref: 4d7c195804991b9c762f9a859679282c7014bbbb
dir: /sys/src/boot/pc/pbs.s/
#include "x16.h" #include "mem.h" #define RELOC 0x7c00 TEXT _magic(SB), $0 BYTE $0xEB; BYTE $0x58; /* jmp .+ 0x58 (_start0x5A) */ BYTE $0x90 /* nop */ TEXT _version(SB), $0 BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 TEXT _sectsize(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _clustsize(SB), $0 BYTE $0x00 TEXT _nresrv(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _nfats(SB), $0 BYTE $0x00 TEXT _rootsize(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _volsize(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _mediadesc(SB), $0 BYTE $0x00 TEXT _fatsize(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _trksize(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _nheads(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _nhiddenlo(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _nhiddenhi(SB), $0 BYTE $0x00; BYTE $0x00; TEXT _bigvolsize(SB), $0 BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; /* FAT32 structure, starting @0x24 */ TEXT _fatsz32lo(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _fatsz32hi(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _extflags(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _fsver(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _rootclust(SB), $0 BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 TEXT _fsinfo(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _bkboot(SB), $0 BYTE $0x00; BYTE $0x00 TEXT _reserved0(SB), $0 BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 TEXT _driveno(SB), $0 BYTE $0x00 TEXT _reserved1(SB), $0 BYTE $0x00 TEXT _bootsig(SB), $0 BYTE $0x00 TEXT _volid(SB), $0 BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; TEXT _label(SB), $0 BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 BYTE $0x00; BYTE $0x00; BYTE $0x00 TEXT _type(SB), $0 BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00; BYTE $0x00 _start0x5A: CLI CLR(rAX) MTSR(rAX, rSS) /* 0000 -> rSS */ MTSR(rAX, rDS) /* 0000 -> rDS, source segment */ MTSR(rAX, rES) LWI(0x100, rCX) LWI(RELOC, rSI) MW(rSI, rSP) LWI(_magic(SB), rDI) CLD REP; MOVSL /* MOV DS:[(E)SI] -> ES:[(E)DI] */ MW(rSP, rBP) PUSHR(rCX) PUSHI(start16(SB)) BYTE $0xCB /* FAR RET */ TEXT start16(SB), $0 STI LWI(hello(SB), rSI) CALL16(print16(SB)) STB(rDL, _driveno(SB)) CLR(rDX) LW(_fatsize(SB), rAX) CLR(rCX) LB(_nfats(SB), rCL) MUL(rCX) OR(rAX, rAX) JNE _fatszok /* zero? it's FAT32 */ LW(_fatsz32hi(SB), rBX) IMUL(rCX, rBX) LW(_fatsz32lo(SB), rAX) MUL(rCX) ADD(rBX, rDX) _fatszok: LW(_nhiddenlo(SB), rCX) ADD(rCX, rAX) LW(_nhiddenhi(SB), rCX) ADC(rCX, rDX) CLR(rBX) LW(_nresrv(SB), rCX) ADD(rCX, rAX) ADC(rDX, rBX) SW(rAX, _volid(SB)) /* save for later use */ SW(rBX, _volid+2(SB)) PUSHR(rBP) LW(_sectsize(SB), rCX) SUB(rCX, rSP) MW(rSP, rBP) MW(rSP, rSI) _nextsect: CALL16(readsect16(SB)) LW(_sectsize(SB), rCX) SHRI(5, rCX) _nextdir: PUSHR(rCX) PUSHR(rSI) /* save for later if it matches */ LWI(bootname(SB), rDI) LW(bootnamelen(SB), rCX) CLD REP CMPSB POPR(rSI) POPR(rCX) JEQ _found ADDI(0x20, rSI) LOOP _nextdir ADDI(1, rAX) ADC(rCX, rBX) JMP _nextsect _found: CLR(rBX) LW(_rootsize(SB), rAX) /* calculate and save Xrootsz */ LWI(0x20, rCX) MUL(rCX) LW(_sectsize(SB), rCX) DEC(rCX) ADD(rCX, rAX) ADC(rBX, rDX) INC(rCX) DIV(rCX) PUSHR(rAX) /* Xrootsz */ CLR(rCX) LXW(0x1a, xSI, rAX) /* start cluster low */ LXW(0x14, xSI, rBX) /* start cluster high */ SUBI(2, rAX) /* cluster -= 2 */ SBB(rCX, rBX) LB(_clustsize(SB), rCL) /* convert to sectors (AX:DX) */ IMUL(rCX, rBX) MUL(rCX) ADD(rBX, rDX) LW(_volid(SB), rCX) /* Xrootlo */ ADD(rCX, rAX) LW(_volid+2(SB), rCX) /* Xroothi */ ADC(rCX, rDX) CLR(rBX) POPR(rCX) /* Xrootsz */ ADD(rCX, rAX) ADC(rBX, rDX) PUSHR(rAX) /* calculate how many sectors to read (CX) */ PUSHR(rDX) LXW(0x1c, xSI, rAX) LXW(0x1e, xSI, rDX) LW(_sectsize(SB), rCX) DEC(rCX) ADD(rCX, rAX) ADC(rBX, rDX) INC(rCX) DIV(rCX) MW(rAX, rCX) POPR(rBX) POPR(rAX) LWI(RELOC, rSI) PUSHR(rSI) /* entry */ _loadnext: CALL16(readsect16(SB)) LW(_sectsize(SB), rDX) ADD(rDX, rSI) CLR(rDX) ADDI(1, rAX) ADC(rDX, rBX) LOOP _loadnext LWI(ok(SB), rSI) CALL16(print16(SB)) LB(_driveno(SB), rDL) CLI RET TEXT print16(SB), $0 PUSHA CLR(rBX) _printnext: LODSB ORB(rAL, rAL) JEQ _printret LBI(0x0E, rAH) BIOSCALL(0x10) JMP _printnext _printret: POPA RET /* * in: * AX:BX lba32, * 0000:SI buffer */ TEXT readsect16(SB), $0 _retry: PUSHA CLR(rDX) PUSHR(rDX) /* qword lba */ PUSHR(rDX) PUSHR(rBX) PUSHR(rAX) PUSHR(rDX) /* dword buffer */ PUSHR(rSI) INC(rDX) PUSHR(rDX) /* word # of sectors */ PUSHI(0x0010) /* byte reserved, byte packet size */ MW(rSP, rSI) LB(_driveno(SB), rDL) LWI(0x4200, rAX) BIOSCALL(0x13) JCC _readok LWI((0x0E00|'!'), rAX) BIOSCALL(0x10) ADDI(0x10, rSP) POPA JMP _retry _readok: LWI((0x0E00|'.'), rAX) BIOSCALL(0x10) ADDI(0x10, rSP) POPA RET TEXT bootnamelen(SB), $0 WORD $8 TEXT bootname(SB), $0 BYTE $'9'; BYTE $'B'; BYTE $'O'; BYTE $'O'; BYTE $'T'; BYTE $'F'; BYTE $'A'; BYTE $'T'; BYTE $0 TEXT hello(SB), $0 BYTE $'p'; BYTE $'b'; BYTE $'s'; BYTE $0 TEXT ok(SB), $0 BYTE $'o'; BYTE $'k'; BYTE $'\r'; BYTE $'\n'; BYTE $0