;***************************************************************************** ;* .-= The ROMOS Project =-. * ;* ROM Operating System 1.06 by Martin žeh k (C) 2001-2017; rayer@seznam.cz * ;* Started: 27.3.2001 * ;* Last updated: 7.12.2017 * ;* Tested on: Award BIOS 4.51PG (Octek Rhino II ZX-AT, 64kB ISA ROM image) * ;* Award BIOS 6.00PG (Abit BX133-Raid, 15kB and 64kB ISA ROM img) * ;* AMI PnP BIOS 2.53 (ASUS P5LD2, 55kB and 64kB PCI ROM image) * ;* Award BIOS 6.00PG (Gigabyte GA-P31-DS3L 64kB PCI ROM image) * ;* Award BIOS 6.00PG (Gigabyte GA-P67-DS3-B3 64kB PCI ROM image) * ;* Compile with NASM (186 code), recommended segment to load: D000h * ;* Now able to boot FreeDOS from virtual ROMDISK image, see incbin at EOF * ;***************************************************************************** CPU 186 ;code compatability ;%define MAKE_DEBUG_COM ;compile as executable *.COM file / zkompiluje spustitelny *.COM soubor %define MAKE_PCI_MODULE ;create PCI ROM module instead ISA ROM module (needed for new BIOSes) / vytvori ROM jako PCI modul misto ISA modulu (nektere nove BIOSy uz nepodporuji ISA) %define HOOK_INT19H ;hook INT19h firts, finish POST and then boot or if commented boot directly without hooking INT19h / ma-li se napred hooknout INT19h, dokoncit POST a pak az bootovat ROM_IMAGE_SIZE EQU 64 ;size of ROM image in kB / velikost ROM image v kB ROMDISK_DRIVE EQU 0 ;0=A: 1=B: 80h=C: ... emulated drive / emulovana jednotka ROMDISK_CYLS EQU 7 ;number of cylinders of emulated drive [1-255] / pocet cylindru emulovane jednotky ROMDISK_HEADS EQU 1 ;number of heads of emulated drive [1-255] / pocet hlav emulovane jednotky ROMDISK_SECPT EQU 18 ;sectors per track of emulated drive [1-63] / pocet sektoru na stopu emulovane jednotky BS_DRIVE_OFFSET EQU 24h ;offset in bootsector where boot dive number is stored / pozice v bootsektoru, kde je cislo jednotky BS_SEGMENT EQU 0 ;address to load bootsector / adresa spousteni bootsectoru BS_OFFSET EQU 7C00h ROMOS_MSG_DELAY EQU 30 ;delay of MSG1 show in 55ms ticks / doba zobrazeni MSG1 v 55ms ticich ROMOS_HOTKEY EQU 00010000b ;mask for ScrollLock key / maska pro klavesu ScrollLock ;ROMOS_HOTKEY EQU 00100000b ;mask for NumLock key / maska pro klavesu NumLock NEW_SS EQU 04000h ;address of new stack (4000:xxxx should be free for Award BIOS) NEW_SP EQU 0FFFEh ;adresa noveho zasobniku (oblast 4000:xxxx by mela byt v Award BIOSu volna) OLD_INT13H EQU 85h ;INT 85h is used for permanent store of old INT 13h vector (should be free) / puvodni vektor INT 13h se ulozi na misto INT 85h (melo by byt volne) ;%define USE_PCI_REG_PATCH ;compile a piece code to patch a PCI register in specific PCI device (executed on every boot) PPCI_BUS EQU 0 ;PCI to PCI bridge 8086:0101h bus number PPCI_DEV EQU 1 ;PCI to PCI bridge 8086:0101h device number PPCI_FUNC EQU 0 ;PCI to PCI bridge 8086:0101h function number PPCI_REG EQU 3Ch ;PCI to PCI bridge 8086:0101h INTR&BCTRL 32b-aligned register number (3Ch:INTR, 3Eh:BCTRL) PPCI_REG_ORMSK EQU 00100000h ;OR mask to patch Bridge Control Register bit 4-VGA 16-Bit Decode enable (to supress VGA ports aliasing causing conflicts in I/O space) PPCI_REG_ANDMSK EQU 0FFFFFFFFh ;AND mask (not used) ;************** ROM header *************************************************** %ifdef MAKE_DEBUG_COM ORG 100h ;use if compiling .COM file / pouzij pri kompilaci .COM souboru %else ORG 0h ;use if compiling ROM image / pouzij pri kompilaci ROM image DW 0AA55h ;ROM header signature / ROM hlavicka DB ROM_IMAGE_SIZE*2;ROM size in 512B blocks, minimum 8 blocks / velikost ROM v 512B blocich, minimum 8 bloku %endif JMP BEGIN ;jump to begin of code / skok na zacatek kodu DB 'CHKSUM=',0 ;reserved Byte for checksum / rezerva na korekci checksumu ;************** PCI ROM header *********************************************** %ifdef MAKE_PCI_MODULE ;need to insert additional PCI headers / je potreba vlozit pridavne hlavicky PCI TIMES 18h-($-$$) DB 0 ;padding zeros to offset 18h / zarovnani nulami na offset 18h DW PCIHDR ;pointer to PCI Header / ukazatel na hlavicku PCI (musi byt na offsetu 18h) DW PNPHDR ;pointer to PnP Expansion Header / ukazatel na hlavicku PnP (musi byt na offsetu 20h) PCIHDR: DB 'PCIR' ;PCI data structure signature / hlavicka PCI data structury DW 10ECh ;vendor ID-Realtek (must match real PCI device) / ID vyrobce (musi odpovidat existujicimu PCI zarizeni) DW 8168h ;device ID-8168/8111 1Gbit eth. (must match real PCI device) / ID zarizeni (musi odpovidat existujicimu PCI zarizeni) DW 0 ;pointer to vital product data (0=none) / ukazatel na vital product data (0=nic) DW 24 ;PCI data structure length [B] / velikost PCI data structury [B] DB 0 ;PCI data structure revision (0=PCI 2.1)/ revize PCI data structury (0=PCI 2.1) DB 2,0,0 ;PCI device class code (2=notwork ctrl., 0=eth.) / trida PCI zarizeni (musi odpovidat existujicimu PCI zarizeni) DW ROM_IMAGE_SIZE*2;ROM size in 512B blocks / velikost ROM v 512B blocich DW 0 ;revision level of code / revize kodu DB 0 ;code type (0=x86 PC-AT) / typ kodu (0=x86 PC-AT kompatabilni) DB 80h ;last image indicator/indikuje posledni image v ROM DW 0 ;reserved PNPHDR: DB '$PnP' ;PnP data structure signature / hlavicka PnP data structury (PnP BIOS spec. 1.0a str. 17) DB 1 ;PnP structure revision / revize PnP struktury DB 2 ;PnP structure length (in 16B blocks) / velikost PnP struktury v 16B blocich DW 0 ;offset to next header (0-none) / offset na dalsi hlavicku DB 0 ;reserved DB 33h ;PnP structure checksum / kontrolni soucet PnP struktury DD 0 ;device identifier / identifikator zarizeni DW 0 ;pointer to manufacturer string / ukazatel na retezec vyrobce DW 0 ;pointer to productname string / ukazatel na retezec zarizeni DB 2,0,0 ;device class code (2=notwork ctrl., 0=eth.) / trida PCI zarizeni (musi odpovidat existujicimu PCI zarizeni) DB 64h ;device indicators (64h - shadowable,cacheable,not only for boot,IPL device) DW 0 ;boot connection vector (0-none) DW 0 ;disconnect vector (0-none) DW 0 ;bootstrap entry vector (0-none) DW 0 ;reserved DW 0 ;static resource info vector (0-none) %endif ;************** Constants / Konstanty **************************************** MSG1 DB 'Press [ScrollLock] to boot ROMOS !',0 %ifdef MAKE_PCI_MODULE %ifdef HOOK_INT19H MSG2 DB 'Welcome to ROMOS ver. 1.06 PCI by Martin Rehak (C) 2001-2017',0 %else MSG2 DB 'Welcome to ROMOS ver. 1.06 PCI by Martin Rehak (C) 2001-2017; rayer@seznam.cz',0 %endif ; HOOK_INT19H %else MSG2 DB 'Welcome to ROMOS ver. 1.06 by Martin Rehak (C) 2001-2017; rayer@seznam.cz',0 %endif ; MAKE_PCI_MODULE MSG3 DB 'ROMOS has installed virtual ROM DISK drive.',0 MSG4 DB 'Bootsector loaded at ',0 MSG5 DB 'Booting!',0 ;************** Subroutines / Procedury ************************************** DELAY: ;pause, put number of 55ms idle ticks in AH / pauza, do AH vloz pocet 55ms idle tiku STI ;enable interrupts otherwise timer will not be updated / povol preruseni, jinak se neaktualizuje casovac PUSHF ;store flags / uloz flagy PUSH AX ;store / uloz AX PUSH ES ;store / uloz ES PUSH BYTE 0 ;segment of timer / segment casovace 0000 (opcode 6A 00 misto 68 00 00) POP ES ;ikdyz jsme pushli jen Byte, popne se cely Word (vyssi Byte je vzdy 0) ADD AH,[ES:046Ch] ;add ticks to required delay / k pozadovane pauze pricti aktualni pocet tiku z adresy casovace 046C @DLY1: CMP AH,[ES:046Ch] ;compare current and required value / rovnaji se pozadovane a aktualni ? JNE @DLY1 ;if not then repeat / kdyz ne, opakuj POP ES ;restore ES / obnov ES POP AX ;restore AX / obnov AX POPF ;restore flags / obnov flagy RET ;return / navrat ;***************************************************************************** GOTOXY: PUSH AX ;set cursor [x,y] position given in [DL,DH] / nastavi kurzor na pozici [x,y] danou [DL,DH] PUSH BX ;[0,0] is top-left corner / [0,0] je levy horni roh MOV AH,2 ;function number 2 / funkce cislo 2 MOV BH,0 ;videopage / videostranka INT 10h ;execute / proved POP BX POP AX RET ;return / navrat ;***************************************************************************** WHEREXY: PUSH AX ;get cursor [x,y] position into [DL,DH] / precte pozici kurzoru [x,y] do [DL,DH] PUSH BX PUSH CX MOV AH,3 ;function number 3 / funkce cislo 3 MOV BH,0 ;videopage / videostranka INT 10h ;execute / proved POP CX ;waste information about cursor size / zahod informaci o velikosti kurzoru POP BX POP AX RET ;return / navrat ;***************************************************************************** WRITE: PUSHA ;write zero-terminated string from CS:SI pointer / vypis 0-ukonceny retezec z CS:SI atributem v BL PUSHF ;with every character repeated BH-times (low 7bit) / a opakovanim jednotlivych znaku BH-krat PUSH BX ;and write CRLF if MSB of BH is 1 / a odradkuj pokud MSB BH je 1 CALL WHEREXY ;read cursor position to [DL,DH] / precti pozici kurzoru [DL,DH] MOV AH,9 ;function write char 9h (BH=scr_num, AL=char, CX=repeat, BL=attrib) / funkce na vypis znaku 9h XOR CX,CX ;set CH=0, CL=0 XCHG CL,BH ;repeat char. BH-times CH=0, CL=BH, BH=0 / opakovani znaku BH-krat AND CL,7Fh ;set MSB=0, accept only 7-bit value / snuluj MSB, akceptujeme pouze 7-bit hodnotu @WRI1: MOV AL,[CS:SI] ;load char. from zero-terminated string / nacti znak z retezce ukonceneho 0 CMP AL,0 ;if it is 0 / je-li konec - 0 JE @WRI2 ;then end / tak konec INT 10h ;execute / proved INC SI ;increment string index / inkrementuj index znaku ve vete INC DL ;increment X-cursor position / inkrementuj X-ovou pozizi kurzoru CALL GOTOXY ;set cursor to [DL,DH] (need to do myself) / nastav kurzor na [DL,DH] (musim to delat rucne) JMP SHORT @WRI1 ;repeat / opakuj @WRI2: POP BX ;restore BX / obnov BX CMP BH,80h ;if BH<80h (MSB=0) skip / pokud je BH<80h (MSB=0) JS @WRI3 ;jump to end / preskoc na konec POPF ;else write newline / jinak odradkuj POPA ;restore regs because WCRLF store them again / obnov registry protoze WCRLF je opet uklada WCRLF: PUSHA ;write CRLF = newline / vypis CRLF = novy radek PUSHF ;this subfunc. can be called out of WRITE func. / tato podfunkce muze byt volana i mimo fci WRITE MOV AX,0E0Dh ;function 0E - write char as TTY, CR / funkce 0E - pis TTY znak, znak CR XOR BL,BL ;paper color=0 / barva papiru=0 INT 10h ;execute / proved MOV AL,0Ah ;char LF / znak LF INT 10h ;execute / proved @WRI3: POPF ;restore flags (2B) / obnov flagy POPA ;restore regs DI,SI,BP,SP,BX,DX,CX,AX (16B) RET ;return / navrat ;***************************************************************************** WHEXPTR:PUSH BX ;write hexa pointer DX:AX / vypis hexa pointer DX:AX PUSH DX ;store BX,DX / uloz BX,DX XOR BL,BL ;paper color=0 / barva papiru=0 XCHG DX,AX ;swap DX-AX / prohod AX-AX CALL WHEXW ;write segment from AX / vypis segment z AX MOV AX,0E3Ah ;write char ':' / vypis znak ':' INT 10h ;via BIOS / pres BIOS POP AX ;restore segment to AX /obnov segment do AX XCHG DX,AX ;swap back DX-AX / prohod DX-AX tak jak byly puvodne CALL WHEXW ;write offset from AX / vypis offset z AX POP BX ;restore BX / obnov BX RET ;return / navrat ;***************************************************************************** WHEXW: XCHG AH,AL ;write hexa word from DX / vypis hexa word z DX CALL WHEXB ;call WHEXB to write upper Byte / zavolej WHEXB na vypis horniho Byte XCHG AH,AL ;swap AH-AL / prohod AH-AL CALL WHEXB ;call WHEXB to write lower Byte / zavolej WHEXB na vypis dolniho Byte RET ;return / navrat ;***************************************************************************** WHEXB: PUSHF ;write hexa Byte from AL / vypis hexa Byte z AL PUSH AX ;store flags,AX / uloz flagy,AX MOV AH,0Eh ;video BIOS service / sluzba video BIOSu PUSH AX ;store AX again / uloz AX jeste jednou SHR AL,4 ;prepare high nibble / priprav vyssi nibble CALL @WHB1 ;write high nibble / vypis vyssi nibble POP AX ;restore AX / obnov AX AND AL,0Fh ;prepare low nibble / priprav nizsi nibble CALL @WHB1 ;write low nibble / vypis nizsi nibble POP AX ;restore AX / obnov AX POPF ;restore flags / obnov flagy RET ;return / navrat @WHB1: CMP AL,10 ;if x<10, set CF=1 SBB AL,69h ;0-9: 96h..9Fh, A-F: A1h..A6h; 0-9: subtr. 66h -> 30h-39h DAS ;A-F: subtr. 60h -> 41h..46h INT 10h ;write char via BIOS / vypis znak pres BIOS RET ;return / navrat ;***************************************************************************** WREGS: PUSHA ;write register dump line and CRLF / vypis na radku registry a odradkuj PUSH DS ;prepare all regs to stack / priprav vsechny registry do zasobniku PUSH ES ;AX,CX,DX,BX,SP,BP,SI,DI, DS,ES,SS,CS, F PUSH SS PUSH CS PUSHF MOV CX,9 ;loop counter-9x repeat / pocitadlo smycky-9x oparuj MOV SI,REGSTR ;prepare reg name / priprav jmeno registru MOV BP,SP ;set BP=SP for indexing stored regs / priprav BP=SP pro indexaci ulozenych registru @WREGS1:MOV BX,0107h ;seda barva, opakovani 1x CALL WRITE ;write reg name / vypis jmeno registru MOV AX,0E3Dh ;write char function, char '=' / funkce vypisu znaku, znak '=' XOR BL,BL ;paper color=0 / barva papiru=0 INT 10h ;write '=' via BIOS / vypis '=' pres BIOS MOV AX,[SS:BP] ;load reg from stack to AX / nacti registr ze zasobniku do AX CALL WHEXW ;write AX hexa value / vypis hexa hodnotu AX MOV AX,0E20h ;;write char function, char ' ' / funkce vypisu znaku, znak ' ' INT 10h ;via BIOS / pres BIOS INC BP ;go up through the stack data / jdi v zasobniku na dalsi registr INC BP INC SI ;reg name pointer+=3 / nastav pointer na dalsi jmeno registru (+3) INC SI INC SI LOOP @WREGS1 ;repeat until CX is nonzero / opakuj dokud je CX nenulove CALL WCRLF ;newline / odradkuj POPF ;restore regs and flag / obnov registry a flag POP DS ;POP DS instead CS because it crashed under BOCHS POP SS ;anyway CS was not changed during this routine POP ES POP DS POPA RET ;return / navrat REGSTR: DB 'F',0,0 ;strings with regs names (all must be 3 bytes long) / retezce s nazvy registru (kazdy musi byt dlouhy 3 byte) DB 'CS',0 DB 'SS',0 DB 'ES',0 DB 'DS',0 DB 'DI',0 DB 'SI',0 DB 'BP',0 DB 'SP',0 ;************** New INT 13h handler emulating virtual ROM disk, now supports functions 2,3,8 ;************** Nova obsluha INT 13h emulujici virtualni ROM disk, nyni podporuje sluzby 2,3,8 NEW_INT13H: ;INT XX do PUSHF, clear IF,TF, PUSH CS,IP (6B) / INT XX provadi..., SP=x-6 PUSHF ;store flags (2B) / uloz flagy (2B), SP=x-8 CMP DL,ROMDISK_DRIVE;related to our disk ? / tyka se to naseho disku? JE @NEW_INT13H_HUB ;if yes continue below else / pokud ano, pokracuj nize, jinak POPF ;restore flags (2B) / obnov flagy (2B), SP=x-6 INT OLD_INT13H ;call old INT 13h handler / zavolej puvodni preruseni INT 13h, SP=x-6 PUSH BP ;store BP (2B) / uloz BP (2B), SP=x-8 MOV BP,SP ;set BP to current SP / nastav BP na aktualni SP, BP=SP=x-8 PUSH AX ;store AX (2B) / uloz AX (2B), SP=x-10 LAHF ;load flags[7:0] to AH that was returned by old INT 13h handler / vlozi do AH LSB flagu 7:0, ktere vratila puvodni obsluha INT 13h, SP=x-10 MOV [BP+6],AH ;replace previously saved flags[7:0] of INT caller on stack by current flags (SS is implicit) / prepis flagy[7:0] v zasobniku, ktere ulozil program volajici INT aktualnimi flagy (SS je implicitni), SP=x-10 POP AX ;restore AX (2B) / obnov AX (2B), SP=x-8 POP BP ;restore BP (2B) / obnov BP (2B), SP=x-6 IRET ;return from ISR, do POP IP,CS,F (6B) / navrat z obsluhy preruseni provadi..., SP=x-0 @NEW_INT13H_HUB: ;subfunction hub / rozcestnik podfunkci PUSHA ;store regs AX,CX,DX,BX,SP,BP,SI,DI (16B) / uloz registry... PUSH DS ;store DS (2B) / uloz DS (2B) CMP AH,02h ;function ?= 2h - read sectors / sluzba ?= 2h - cti sektory JE @NEW_INT13H_02H CMP AH,03h ;function ?= 3h - write sectors / sluzba ?= 3h - pis sektory JE @NEW_INT13H_03H CMP AH,08h ;function ?= 8h - get drive params / sluzba ?= 8h - vrat parametry disku JE @NEW_INT13H_08H CMP AH,15h ;function ?= 15h - get disk type / sluzba ?= 15h - vrat typ disku JE @NEW_INT13H_15H ADD AH,'A' ;infoflag of unhandled function (cislo 0=A, 1=B,...) / priznak neobslouzeni funkce JMP @NEW_INT13HEND1 ;other? jump to end and let me know / jina? preskoc na konec a dej o tom vedet @NEW_INT13H_02H: ;INT 13h: AH=func, DL=drive, DH=H, CH=C, CL=S, PUSH AX ; AL=S-CNT, ES:BX=buffer of calling program MOV DI,BX ;prepare destination address ES:BX->ES:DI / priprav cilovou adresu... XOR SI,SI ;we prepare linear address to SI step by step / do SI si postupne pripravime linearni adresu AND CL,03Fh ;number of sector is only 6-bit / cislo sektoru je jen 6-bitove (cyl<=80 u FD) DEC CL ;BIOS numbers the sectors from starting 1, we need from 0 / BIOS cisluje sektory o 1, my potebujem od 0 MOV AX,ROMDISK_SECPT;SI=LINSEC=NH*NS*C + NS*H + (S-1) MUL DH ;AX*DH->AX (NS*H) ADD SI,AX ;add to SI (SI=NS*H) / pricti do SI MOV AX,ROMDISK_HEADS;there's no check of CHS validity / neprovadi se zadna kontrola parametru CHS MOV BL,ROMDISK_SECPT;so when CHS overflow it returns invalid data from memory / takze pri prekroceni adr. rozs. vraci nesmyslna data MUL BL ;AX*BL->AX (NH*NS) MUL CH ;AX*CH->AX (NH*NS*C) ADD SI,AX ;add to SI (SI=NS*H + NH*NS*C) / pricti do SI XOR CH,CH ;prepare S to CX / priprav S v CX ADD SI,CX ;add to SI (SI=NH*NS*C + NS*H + (S-1)) / pricti do SI SHL SI,9 ;recalc from sectors to Bytes (SI*512) / prepocti SI ze sektoru na Byty ADD SI,IMG_BEGIN ;prepare source offset (and add offset to image) / priprav zdrojovy offset (jeste pricti offset na image) PUSH CS ;prepare source segment / priprav zdrojovy segment POP DS ;set DS=CS (ROM segment with disk image / segment ROM s image disku) POP CX ;restore number of required sectors to CX / vyber pocet ctenych sektoru do CX SHL CX,9 ;recalc number of sectors to number of Bytes (S-CNT*512) / prepocitej pocet sektoru na Byty REP MOVSB ;copy until CX is nonzero / kopiruj dokud CX neni nulove JMP @NEW_INT13HEND ;end without calling original INT 13h handler / konec bez volani puvodni obsluhy INT 13h @NEW_INT13H_03H: ;ROM disk is read-only so return errorcode AH=3 / ROM disk je read-only, takze vrat chybu AH=3 MOV BP,SP ;set BP=SP / nastav BP=SP OR [BP+24],BYTE 1 ;nastav CARRY bit ve flags (LSB) na zasobniku (adr=2+16+2+2+2 objem dat v zasob. nad F) MOV [BP+17],BYTE 3 ;nastav AH v zasobniku na kod chyby 3 (adr=16+2-1=DS+ALL) JMP @NEW_INT13HEND ;end without calling original INT 13h handler / konec bez volani puvodni obsluhy INT 13h @NEW_INT13H_08H: ;return CHS info about ROM disk geometry / vrat informace CHS o geometrii ROM disku MOV BP,SP ;set BP=SP / nastav BP=SP MOV CH,ROMDISK_CYLS ;set CH to number of cylinders / nastav CH na pocet cylindru MOV CL,ROMDISK_SECPT;set CL to number of sectors per track / nastav CL na pocet sektoru/stopu MOV [BP+13],BYTE ROMDISK_HEADS ;nastav DH v zasobniku - hlavy (adr=2+16-2-2-1=DS+ALL-AX-CX-DL) MOV [BP+14],CX ;nastav CX v zasobniku (adr=2+16-2-2=DS+ALL-AX-CX) JMP @NEW_INT13HEND ;end without calling original INT 13h handler / konec bez volani puvodni obsluhy INT 13h @NEW_INT13H_15H: ;ROM disk is like nonchangeable diskette drive / ROM disk je jako nevymenna disketova jednotka MOV BP,SP ;set BP=SP / nastav BP=SP MOV [BP+17],BYTE 1 ;nastav AH v zasobniku na kod chyby 0 (adr=16+2-1=DS+ALL) MOV [BP+14],WORD 0 ;set CX=0 (total drive sectors high word to 0) / nastav vyssi slovo poctu sektoru na 0 MOV [BP+12],WORD ROMDISK_CYLS*ROMDISK_HEADS*ROMDISK_SECPT ;set DX=total drive sectors / nastav DX=celkovy pocet sektoru JMP @NEW_INT13HEND ;end without calling original INT 13h handler / konec bez volani puvodni obsluhy INT 13h @NEW_INT13HEND: ;INT 13h watcher (work in textmode only / funguje jen v textovem modu) MOV AH,'*' ;flag of handled function / priznak obslouzeni funkce @NEW_INT13HEND1: PUSH WORD 0B800h POP DS ;set DS=B800h (segment of textmode VRAM on VGA / segment textove VRAM u VGA) MOV [DS:79*2],AH ;write flag character to top-right corner from AH / do praveho horniho rohu obrazovky vykresli znak z AH POP DS ;restore DS (2B) / obnov DS (2B) POPA ;restore regs DI,SI,BP,SP,BX,DX,CX,AX (16B) / obnov registry... POPF ;restore flags (2B) / obnov flagy (2B) IRET ;return from ISR, do POP IP,CS,F (6B) / navrat z obsluhy preruseni provadi... ;***************************************************************************** INSTALL_NEW_INT13H: ;install new INT 13h handler / nainstaluj novou obsluhu INT 13h PUSHA ;and write message about vector change + CRLF / a vypis hlaseni o zmene vektoru a odradkuj PUSH DS ;store DS / uloz DS PUSH BYTE 0 ;push 00 POP DS ;pop 0000 (DS=0) / vynuluj DS MOV SI,13h*4 ;set SI at INT 13h IVT entry / nastav SI na polozku IVT vektoru INT 13h MOV DI,OLD_INT13H*4 ;set DI at free INT 85h IVT entry / nastav DI na volnou polozku IVT vektoru INT 85h MOV AX,[SI] ;load original offset of INT 13h handler from IVT to AX (DS is implicit) / nacti do AX offset puvodni obsluhy INT 13h z IVT (DS je implicitni) MOV [DI],AX ;store it to other safe place in IVT (DS is implicit) / uloz ho na jine bezpecne misto v IVT (DS je implicitni) MOV DX,[SI+2] ;load original segment of INT 13h handler from IVT to DX (DS is implicit) / nacti do DX segment puvodni obsluhy INT 13h z IVT (DS je implicitni) MOV [DI+2],DX ;store it to other safe place in IVT (DS is implicit) / uloz ho na jine bezpecne misto v IVT (DS je implicitni) MOV [SI],WORD NEW_INT13H ;set offset of new INT 13h handler (DS is implicit) / nastav offset nove obsluhy INT 13h (DS je implicitni) MOV [SI+2],CS ;set segment of new INT 13h handler (current-ROM, DS is implicit) / nastav segment nove obsluhy INT 13h (aktualni-ROM, DS je implicitni) POP DS ;restore DS / obnov DS MOV SI,IINTSTR ;write hook INT 13h vector message / vypis zpravu o zmene vektoru INT 13h MOV BX,0107h ;grey color, 1-times / seda barva, opakovani 1x CALL WRITE CALL WHEXPTR ;write original vector DX:AX / vypis puvodni vektor DX:AX MOV SI,AROWSTR CALL WRITE ;write / vypis ' -> ' MOV DX,CS ;current code segment MOV AX,WORD NEW_INT13H CALL WHEXPTR ;write new vector DX:AX (CS:NEW_INT13H) / vypis novy vektor DX:AX CALL WCRLF ;newline / odradkuj POPA ;restore regs DI,SI,BP,SP,BX,DX,CX,AX (16B) / obnov registry... RET ;return / navrat IINTSTR:DB 'INT13h vector has been hooked ',0 AROWSTR:DB ' -> ',0 ;************** Initial code - modify carefully! / Pocatecni kod, upravujte s max. opatrnosti! BEGIN: PUSHF ;store flags (2B) / uloz flagy (2B) PUSHA ;store regs AX,CX,DX,BX,SP,BP,SI,DI (16B) / uloz registry... MOV AX,SS ;set AX=original SS / nastav AX=puvodni SS PUSH NEW_SS ;set new bigger stack (BIOS use default SS=0 SP=0Dxx - small) / nastav novy vetsi zasobnik... POP SS ;segment MOV BX,NEW_SP ;offset XCHG BX,SP ;set BX=original SP / nastav BX=puvodni SP PUSH AX ;store configuration of original stack - SS / uloz konfiguraci stareho zasobniku - SS PUSH BX ;store configuration of original stack - SP / uloz konfiguraci stareho zasobniku - SP PUSH ES ;store ES / uloz ES PUSH DS ;store DS / uloz DS ;TEST FOR 1ST RUN-ROMSCAN/2ND RUN-INT19H CALL %ifdef HOOK_INT19H ;only if we want to hook INT 19h otherwise skip this / jen pokud chceme hooknout INT 19h PUSH BYTE 0 ;push 00 POP ES ;pop 0000 (ES=0, segment of IVT) / nastav ES=0, segment IVT CMP [ES:19h*4],WORD BEGIN ;compare if offset match the BEGIN label / porovnej, shoduje-li se offset s labelem BEGIN JNE RUN1ST ;if not it means that's 1st run-ROMSCAN / pokud ne, znamena to, ze bezime poprve-ROMSCAN MOV AX,CS ;set AX=CS (cannot compare CS directly / CS nelze primo porovnavat) CMP [ES:19h*4+2],AX ;compare if segment match the current CS segment / porovnej, shoduje-li se segment s aktualnim CS JNE RUN1ST ;if not it means that's 1st run-ROMSCAN / pokud ne, znamena to, ze bezime poprve-ROMSCAN JMP BOOT ;else continue next phase at BOOT label / jinak pokracuj v dalsi fazi na labelu BOOT %endif ;ASK FOR BOOT ROMOS RUN1ST: CALL WCRLF ;newline / odradkuj MOV SI,MSG1 ;prompt to press HotKey / vyzva ke stisku HotKey MOV BX,810Fh ;white color, 1-times + CRLF / bila barva, opakovani 1x a odradkuj CALL WRITE ;write message / vypis hlasku MOV AH,ROMOS_MSG_DELAY ;wait / pockej CALL DELAY ;EXECUTE OPTIONAL PCI DEVICE REGISTER PATCH CODE %ifdef USE_PCI_REG_PATCH ;only if we need to patch a PCI register in specific PCI device (executed on every boot) CPU 386 ;code compatability raised to 386 CLI ;disable interrupts to perform atomic I/O operation PUSH EAX ;save 32-bit EAX MOV DX,0CF8h ;set PCI Config Address Register I/O address MOV EAX,80000000h|(PPCI_BUS<<16)|(PPCI_DEV<<11)|(PPCI_FUNC<<8)|PPCI_REG ; make PCI address: bit31=1, bit30:24=reserved, bit23:16=bus# [0-255], bit15:11=dev# [0-31], bit10:8=func# [0-7], bit7:0=cfgreg [0-255] OUT DX,EAX ;write PCI address to PCI Config Address Register MOV DX,0CFCh ;set PCI Config Data Register I/O address IN EAX,DX ;read PCI Config Data Register to EAX OR EAX,PPCI_REG_ORMSK ;set required bits to 1 ; AND EAX,PPCI_REG_ANDMSK ;set required bits to 0 OUT DX,EAX ;write modified EAX back to PCI Config Data Register POP EAX ;restore 32-bit EAX STI ;enable interrupts %endif ;TEST FOR SCROLLOCK ;test if HotKey was pressed / otestuj, jestli je stisknuty HotKey PUSH BYTE 0 ;push 00 POP ES ;pop 0000 (ES=0, segment of keyboard flags / segment flagu klavesnice) MOV AL,[ES:0417h] ;offset of keyboard flags / offset flagu klavesnice 0417h MOV AH,AL ;store loaded value to AH / schovej si nactenou hodnotu do AH AND AL,ROMOS_HOTKEY ;mask the HotKey / vymaskuj HotKey CMP AL,ROMOS_HOTKEY ;if it is turned on then / je-li zaply, %ifdef HOOK_INT19H ;if we want to hook INT 19h JE EXIT_AND_HOOK_INT19H ;exit and hook INT 19h / skonci a hookni INT 19h %else ;or if we boot directly without hooking INT 19h / pokud nechcem hooknout INT 19h JE BOOT ;then go to boot ROMOS / pak jdi primo na sekci BOOT %endif ;if we don't want to run ROMOS then MOV [CS:0],ES ;erase 55AAxx (ES=0) ROM header, then BIOS will free this area for UMB / smaz hlavicku ROM 55AAxx (ES=0)... JMP EXIT ;end without hook of INT 19h / skonci bez hooknuti INT 19h ;************** Terminating and restoring, returning controll back to BIOS *** ;************** Ukonceni, obnoveni stavu a predani rizeni zpet BIOSu ********* EXIT_AND_HOOK_INT19H: %ifdef HOOK_INT19H ;only if we want to hook INT 19h otherwise skip this / jen pokud chceme hooknout INT 19h ;here you can place a code which should be executed on 1st run-during ROMSCAN ;zde je jeste mozno pridat kod, ktery se ma provest pri prvnim spusteni-ROMSCAN MOV AL,ROMOS_HOTKEY ;load HotKey bit mask / nacti bitovou masku HotKey NOT AL ;negate HotKey bit mask / zneguj bitovou masku HotKey AND AH,AL ;turn off the HotKey / zhasni HotKey MOV [ES:0417h],AH ;write keyboard flag (ES=0, see above) / zapis flag klavesnice ;HOOK INT 19h MOV [ES:19h*4],WORD BEGIN ;put ROM module address here / vlozime tam adresu ROM modulu, MOV [ES:19h*4+2],CS ;offset first, then segment / napred offset a pak segment %endif EXIT: POP DS ;restore DS (2B) / obnov DS (2B) POP ES ;restore ES (2B) / obnov ES (2B) POP BX ;get BX=original SP / nacti BX=puvodni SP POP SS ;restore SS=original SS / obnov SS=puvodni SS MOV SP,BX ;restore SP=original SP / obnov SP=puvodni SP POPA ;restore regs DI,SI,BP,SP,BX,DX,CX,AX (16B) / obnov registry... POPF ;restore flags (2B) / obnov flagy (2B) %ifdef MAKE_DEBUG_COM INT 20h ;use if compiling *.COM file / pouzij pri kompilaci .COM souboru %else RETF ;CBh - FAR RET %endif ;************** Here you can place your code without risks - it can be skipped when booting ;************** Zde uz je mozno psat kod bez obav, lze ho pri bootu preskocit BOOT: ;this code is executed after POST is finished / tento kod se uz provadi po ukonceni POST ;when INT 19h is invoked ROM area is write protected / pri volani INT19h, ROM pamet je zamcena pro zapis CALL WCRLF ;newline / odradkuj MOV SI,MSG2 MOV BX,810Eh ;yellow color, 1-times + CRLF / zluta barva, opakovani 1x a odradkuj CALL WRITE ;write welcome message / vypis welcome MOV AH,20 ;20*55ms delay / pauza CALL DELAY CALL INSTALL_NEW_INT13H ;install new INT 13h handler / nainstaluj novou obsluhu INT 13h CALL DELAY ;for accessing virtual ROM disk / pro pristup k virtual ROM disku MOV SI,MSG3 MOV BX,8107h ;grey color, 1-times + CRLF / seda barva, opakovani 1x a odradkuj CALL WRITE ;write isntall ROMDISK message / vypis isntall ROMDISK CALL DELAY CALL WCRLF ;newline / odradkuj CALL WREGS ;write registers dump / vypis registry CALL DELAY MOV SI,MSG4 MOV BX,0107h ;grey color, 1-times / seda barva, opakovani 1x CALL WRITE ;write Bootsector loaded at message / vypis Bootsector loaded at MOV DX,BS_SEGMENT ;prepare segment to DX / priprav segment do DX MOV AX,BS_OFFSET ;prepare offset to AX / priprav offset do AX CALL WHEXPTR ;write pointer / vypis pointer CALL WCRLF ;newline / odradkuj MOV SI,MSG5 MOV BX,810Fh ;white color, 1-times + CRLF / bila barva, opakovani 1x a odradkuj CALL WRITE ;write Booting! message / vypis Booting! MOV AH,10 ;10*55ms delay / pauza CALL DELAY ;************** Copy bootsector from virtual ROM disk at starting address **** ;************** Prekopiruje bootsector z virtual ROM disku na spousteci adresu PUSH BYTE 0 ;push 00 POP ES ;pop 0000 (ES=0, segment BIOS data) MOV SI,0410h ;prepare address of equipment Byte (INT11h) / priprav adresu Bytu vybaveni (INT11h) MOV AL,[ES:SI] ;two top bits means number of drives-1 / horni dva bity udavaji pocet mechanik-1 MOV AH,BYTE ROMDISK_DRIVE ;so: any=00, A:=00, A:+B:=01 / tedy: zadna=00, A:=00, A:+B:=01 CMP AH,1 ;if we have to emulate B: drive / pokud mame emulovat jednotku B: JNE SKIP_DRVNUPD ;else leave / jinak nech bejt OR AL,01000000b ;number of drives is needed to be increased / je potreba zvysit pocet mechanik MOV [ES:SI],AL ;write updated equipment Byte / zapis aktualizovany Byte vybaveni SKIP_DRVNUPD: PUSH WORD BS_SEGMENT ;prepare destination segment for bootsector / priprav cilovy segment pro nahrani bootsectoru POP ES ;set ES=BS_SEGMENT / nastav ES=BS_SEGMENT MOV DI,BS_OFFSET ;prepare destination offset for bootsector / priprav cilovy offset pro nahrani bootsectoru PUSH CS ;prepare source segment / priprav zdrojovy segment POP DS ;set DS=CS / nastav DS=CS MOV SI,IMG_BEGIN ;prepare source offset - beginning of the ROMDISK image / priprav zdrojovy offset-zacatek ROMDISK image MOV CX,512 ;1 sector=512B REP MOVSB ;copy until CX is nonzero / kopiruj dokud CX neni nulove MOV [ES:BS_OFFSET+BS_DRIVE_OFFSET], BYTE ROMDISK_DRIVE ;patch bootsector by drive number / patch bootsectoru podle c. drive MOV DL,BYTE ROMDISK_DRIVE ;set bootdrive for bootsector / nastav bootdrive pro bootsector JMP BS_SEGMENT:BS_OFFSET ;jump to beginning of bootsector copy / skoc na zacatek kopie bootsectoru ;************** Include VIRTUAL ROMDISK image / Vloz VIRTUAL ROMDISK image IMG_BEGIN: ;append binary file of romdisk image at the end / nakonec pripoj binarni soubor image disku ; incbin "romd15kb.img" ;FAT12 (1x), C:2, H:1, S:18, S/CL:1, ROOTE:16 ; incbin "romd54kb.img" ;FAT12 (1x), C:6, H:1, S:18, S/CL:1, ROOTE:16 ; incbin "romd64kb.img" ;FAT12 (1x), C:7, H:1, S:18, S/CL:1, ROOTE:16 incbin "romd64kb.ima" ;FAT12 (1x), C:7, H:1, S:18, S/CL:1, ROOTE:16, path modified to use drive A: ; incbin "romdusb.img" ;FAT12 (1x), C:7, H:1, S:18, S/CL:1, ROOTE:16 IMG_END: TIMES ROM_IMAGE_SIZE*1024-($-$$) db 0 ;zero padding to required length / zarovnani nulami na danou velikost END: ;************** Block diagram for HOOK_INT19H option enabled ***************** ; (BEGIN) ; ___________|____________ ; |store regs, old stack...| ; ~~~~~~~~~~~|~~~~~~~~~~~~ ; _________|_________ ; ___________________/' running 1st? `\ ; | go to BOOT N `\ (called by ROMSCAN) /' ; | ~~~~~~~~Y~|~~~~~~~~~~ ; | | RUN1ST: ; | __________|___________ ; | |display HotKey message| ; | ~~~~~~~~~~|~~~~~~~~~~~ ; | __________|___________ ; | |optional PCI reg.patch| ; | ~~~~~~~~~~|~~~~~~~~~~~ ; | _____|_____ ; | /' was HotKey`\_________________________________ ; | \ pressed? / Y go to EXIT_AND_HOOK_INT19H | ; | ~~~~~~|~N~~~~ | ; | __________|___________ | ; | |delete 55AA ROM header| | ; | ~~~~~~~~~~|~~~~~~~~~~~ | ; | | ,----------------------' ; | | | EXIT_AND_HOOK_INT19H: ; | | ___________|____________ ; | | | disable hotkey | ; | | |(exec some 1st-run code)| ; | | | hook INT 19h to ROM | ; | | ~~~~~~~~~~~|~~~~~~~~~~~~ ; | `-----------------| EXIT: ; | ____________|_____________ ; | |restore regs, old stack...| ; | | and RETF to BIOS | ; | ~~~~~~~~~~~~~~~~~~~~~~~~~~ ; `------------->----------------, ; | BOOT: (note: this is right place for user code) ; ________________|_________________ ; | display some messages | ; | install new INT13h handler | ; | look for number of FDDs | ; |copy bootsector from image to RAM | ; |patch bootdrive Byte in bootsector| ; |jump to bootsector (never return) | ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; ;************** Block diagram for HOOK_INT19H option disabled **************** ; (BEGIN) ; ___________|____________ ; |store regs, old stack...| ; ~~~~~~~~~~~|~~~~~~~~~~~~ ; __________|___________ ; |display HotKey message| ; ~~~~~~~~~~|~~~~~~~~~~~ ; _____|_____ ; ________/' was HotKey`\ ; | Y \ pressed? / ; | ~~~~~~|~N~~~~ ; | __________|___________ ; | |delete 55AA ROM header| ; | ~~~~~~~~~~|~~~~~~~~~~~ ; | | EXIT: ; | ____________|_____________ ; | |restore regs, old stack...| ; | | and RETF to BIOS | ; | ~~~~~~~~~~~~~~~~~~~~~~~~~~ ; | ; `------->-------, ; | BOOT: (note: this is right place for user code) ; ________________|_________________ ; | display some messages | ; | install new INT13h handler | ; | look for number of FDDs | ; |copy bootsector from image to RAM | ; |patch bootdrive Byte in bootsector| ; |jump to bootsector (never return) | ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~