;***************************************************************************** ;* .-= The ROMOS Project =-. * ;* ROM Operating System 0.94 by Martin žeh k (C) 2001-2004; rayer@seznam.cz * ;* Started: 27.3.2001 * ;* Last updated: 22.2.2004 * ;* Tested on: Award BIOS 4.51PG, Octek Rhino II ZX * ;* Compile with NASM, recommended segmet to load: D000h, see ROM_SEGMENT * ;* Now able to boot FreeDOS from virtual ROMDISK image, see incbin at EOF * ;***************************************************************************** ;%define MAKE_DEBUG_COM ;zkompiluje spustitelny *.COM soubor ;%define HOOK_INT18_BY_ROMOS ;presmeruje INT18h (ROM-BASIC) na adresu ROMOSu ROM_SEGMENT EQU 0D000h ;segment ROM modulu ROMDISK_DRIVE EQU 1 ;0=A: 1=B: 80h=C: ... emulovana jednotka ROMDISK_CYLS EQU 7 ;pocet cylindru emulovane jednotky [1-256] ROMDISK_HEADS EQU 1 ;pocet hlav emulovane jednotky [1-256] ROMDISK_SECPT EQU 18 ;pocet sektoru na stopu em. jed. [1-64] BS_DRIVE_OFFSET EQU 24h ;pozice v bootsektoru, kde je cislo jednotky BS_SEGMENT EQU 0 ;adresa spousteni bootsectoru BS_OFFSET EQU 07C00h ROMOS_MSG_DELAY EQU 30 ;doba zobrazeni MSG1 v 55ms ticich %ifdef MAKE_DEBUG_COM ORG 100h ;use if compiling .COM file %else ORG 0h ;use if compiling ROM image DW 0AA55h ;ROM header signature DB 80h ;ROM size in 512B blocks, minimum 8 blocks %endif JMP BEGIN ;skok na zacatek kodu DB 'CHKSUM=' DB 00h ;rezerva na korekci checksumu ;*************** need to be manualy relocated in compiled image ************** OLDSS DW 05353h ;puvodni SS -pro ulozeni konfigurace zasobniku OLDSP DW 05053h ;puvodni SP OLDINT13 DB 0EAh ;opcode JMP FAR (dynamicky menena instrukce) OLDINT13O DW 03331h ;offset puvodni obsluhy INT13h (0:004C) OLDINT13S DW 03331h ;segment puvodni obsluhy INT13h (0:004E) MSG1 DB 'Press [ScrollLock] to boot ROMOS !',0 MSG2 DB 'Welcome to ROMOS ver. 0.94 by Martin Rehak (C) 2001-2004; rayer@seznam.cz',0 MSG3 DB 'ROMOS will install virtual ROMDISK drive and boot FreeDOS.',0 MSG4 DB 'Bootsector loaded at ',0 MSG5 DB 'Booting!',0 ;***************************************************************************** DELAY: ;pauza, do AH vloz pocet 55ms idle tiku STI ;povol preruseni, jinak se neaktualizuje casovac PUSH BX ;schovej BX PUSH ES ;schovej ES PUSHF XOR BX,BX ;segment casovace 0000 MOV ES,BX MOV AL,[ES:046Ch] ;offset casovace 046C ADD AH,AL ;pauza AH*55ms @DELAY: MOV AL,[ES:046Ch] ;precti tiky CMP AH,AL ;rovnaji se pozadovane a aktualni ? JNE @DELAY ;kdyz ne, opakuj POPF POP ES ;obnov ES POP BX ;obnov BX CLI ;opet zakaz preruseni RET ;navrat ;***************************************************************************** GOTOXY: PUSH AX ;nastavi kurzor na pozici [x,y] danou [DL,DH] PUSH BX MOV AH,2 ;funkce cislo 3 MOV BH,0 ;stranka INT 10h ;proved POP BX POP AX RET ;***************************************************************************** WHEREXY: PUSH AX ;precte pozici kurzoru [x,y] do [DL,DH] PUSH BX PUSH CX MOV AH,3 ;funkce cislo 3 MOV BH,0 ;stranka INT 10h ;proved POP CX POP BX POP AX RET ;***************************************************************************** WRITE: PUSHA ;vypis vety z CS:SI atributem v BL (musi byt ukoncena 0) PUSHF ;a opakovanim jednotlivych znaku BH-krat CALL WHEREXY ;precti pozici kurzoru [DL,DH] MOV AH,9 ;funkce na vypis znaku 9h XOR CX,CX ;snuluj CX, CH=0, CL=0 XCHG CL,BH ;opakovani znaku BH-krat, CH=0, CL=BH, BH=0 @WRI1: MOV AL,[CS:SI] ;nacti znak z retezce ukonceneho 0 CMP AL,0 ;je-li konec - 0 JE @WRI2 ;tak konec INT 10h ;proved INC SI ;inkrementuj index znaku ve vete INC DL ;inkrementuj X-ovou pozizi kurzoru CALL GOTOXY ;nastav kurzor na [DL,DH] (musim to delat rucne) JMP @WRI1 ;opakuj @WRI2: POPF ;obnov registry POPA RET ;navrat ;***************************************************************************** WCRLF: PUSH AX ;vypis CRLF = novy radek PUSH BX MOV AX,0E0Dh ;funkce 0E - pis TTY znak, znak CR XOR BL,BL ;barva papiru 0 INT 10h ;proved MOV AL,0Ah ;znak LF INT 10h ;proved POP BX POP AX RET ;***************************************************************************** WHEXW: XCHG BH,BL ;vypis word z BX na obrazovku v hexa CALL WHEXB ;zavolej WHEXB na vypis horniho byte XCHG BH,BL CALL WHEXB ;zavolej WHEXB na vypis dolniho byte RET ;***************************************************************************** WHEXB: PUSH AX ;vypis byte z BL na obrazovku v hexa PUSH BX PUSHF MOV BH,BL AND BL,00Fh ;vymaskuj dolni cislici AND BH,0F0h ;vymaskuj horni cislici ROR BH,4 ;posun horni cislici o 4 bity vpravo ADD BL,48 ;pricti offset '0' ADD BH,48 CMP BL,58 ;je cislice vetsi nebo rovna A ? JC @WHB1 ;kdyz ne preskoc ADD BL,7 ;kdyz jo, pricti jeste offset 'A' @WHB1: CMP BH,58 JC @WHB2 ADD BH,7 @WHB2: MOV AH,0Eh ;vypis znak MOV AL,BH ;z AL INT 10h ;prez BIOS MOV AL,BL INT 10h POPF POP BX POP AX RET ;***************************************************************************** WREGS: PUSH SI ;vypis na radku registry a odradkuj PUSH BX MOV SI,CSSTR MOV BX,0107h ;seda barva, opakovani 1x CALL WRITE MOV BX,CS ;vypis CS CALL WHEXW MOV SI,SSSTR MOV BX,0107h ;seda barva, opakovani 1x CALL WRITE MOV BX,SS ;vypis SS CALL WHEXW MOV SI,SPSTR MOV BX,0107h ;seda barva, opakovani 1x CALL WRITE MOV BX,SP ;vypis SP ADD BX,6 ;proved korekci vypisu SP, (kvuli PUSH SI,SP a navratove adrese tj 6B) CALL WHEXW MOV SI,ESSTR MOV BX,0107h ;seda barva, opakovani 1x CALL WRITE MOV BX,ES ;vypis ES CALL WHEXW MOV SI,DSSTR MOV BX,0107h ;seda barva, opakovani 1x CALL WRITE MOV BX,DS ;vypis DS CALL WHEXW MOV SI,BPSTR MOV BX,0107h ;seda barva, opakovani 1x CALL WRITE MOV BX,BP ;vypis BP CALL WHEXW CALL WCRLF ;odradkuj POP BX POP SI RET CSSTR DB 'CS=',0 SSSTR DB ' SS=',0 SPSTR DB ' SP=',0 ESSTR DB ' ES=',0 DSSTR DB ' DS=',0 BPSTR DB ' BP=',0 ;***************************************************************************** SET_KBD_FAST: ;nastavi max. opakovaci rychlost klavesnice PUSH AX PUSH BX MOV AX,0305h ;INT16h func. 3 set_kbd_speed XOR BX,BX ;BL=repeat rate, BH=delay INT 16h ;set it POP BX POP AX RET ;***************************************************************************** NEW_INT13: ;nova obsluha INT13h emulujici virtual drive B: CLI ;zakaz preruseni PUSHF ;store flags CMP DL,ROMDISK_DRIVE;tyka se to naseho disku? JNE @NEW_INT13END ;jina nas to nezajima CMP AH,02h ;sluzba 02 = cti sektory? JNE @NEW_INT13END1 ;jina nas nezajima, jen dame vedet ze byla volana PUSHA ;store regs AX,BX,CX,DX,SI,DI,BP,SP (16B) PUSH DS ;INT13h: AH=sluzba, DL=drive, DH=H, CH=C, CL=S, PUSH AX ; AL=S-CNT, ES:BX=buffer volajiciho programu MOV DI,BX ;priprav cilovou adresu ES:BX->ES:DI XOR SI,SI ;do SI si postupne pripravime linearni adresu AND CL,03Fh ;cislo sektoru je jen 6-bitove (cyl<=80 u FD) DEC CL ;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 ;pricti do SI (SI=NS*H) MOV AX,ROMDISK_HEADS;neprovadi se zadna kontrola parametru CHS MOV BL,ROMDISK_SECPT;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 ;pricti do SI (SI=NS*H + NH*NS*C) XOR CH,CH ;priprav S v CX ADD SI,CX ;pricti do SI (SI=NH*NS*C + NS*H + (S-1)) SHL SI,9 ;prepocti SI na Byty (SI*512) ADD SI,IMG_BEGIN ;priprav zdrojovy offset (jeste pricti offset na data) MOV BX,ROM_SEGMENT MOV DS,BX ;priprav zdrojovy segment POP CX ;vyber pocet ctenych sektoru SHL CX,9 ;prepocitej pocet sektoru na Byty (S-CNT*512) REP MOVSB ;kopiruj dokud CX neni nulove MOV SI,0B800h ;INT13h watcher MOV DS,SI ;do praveho horniho rohu obrazovky vykresli * MOV SI,158 ;pokud bylo preruseni obslouzeno MOV [DS:SI],BYTE 42 ;'*' POP DS ;restore all regs and flags POPA POPF STI ;povol preruseni IRET ;navrat z preruseni-nevolame dal starou obsluhu @NEW_INT13END1: PUSH SI PUSH DS MOV SI,0B800h ;INT13h watcher MOV DS,SI ;do praveho horniho rohu obrazovky vykresli ! MOV SI,158 ;pokud nebylo preruseni obslouzeno MOV [DS:SI],BYTE 33 ;'!' POP DS POP SI @NEW_INT13END: POPF ;restore flags STI ;povol preruseni JMP OLDINT13 ;skoc na stare preruseni ;***************************************************************************** INSTALL_NEW_INT13: ;nainstaluj novou obsluhu INT13h PUSHA ;vypise hlaseni o zmene vektoru a odradkuje PUSH ES XOR SI,SI ;0->SI MOV ES,SI ;0->ES MOV SI,4Ch ;4C->SI vektor INT13h zacina na adrese 0:004C MOV CX,[ES:SI] ;uloz offset puvodni obsluhy INT13h MOV DX,[ES:SI+2] ;uloz segment puvodni obsluhy INT13h MOV [ES:SI],WORD NEW_INT13 ;nastav offset nove obsluhy INT13 MOV [ES:SI+2],WORD ROM_SEGMENT ;nastav segment nove obsluhy INT13 MOV SI,WORD ROM_SEGMENT MOV ES,SI ;nastav ES:SI do prostoru ROM modulu MOV SI,OLDINT13O MOV [ES:SI],CX ;uloz offset puvodni obsluhy INT13h do pameti MOV [ES:SI+2],DX ;uloz segment puvodni obsluhy INT13h do pameti MOV SI,IINTSTR ;vypis zpravu o zmene vektoru INT13h MOV BX,0107h ;seda barva, opakovani 1x PUSH BX ;uloz nastaveni barvy a opakovani CALL WRITE MOV BX,DX CALL WHEXW ;vypis stary segmnet MOV AX,0E3Ah ;vypis znak : INT 10h ;prez BIOS MOV BX,CX CALL WHEXW ;vypis stary offset MOV SI,AROWSTR POP BX ;obnov nastaveni barvy a opakovani CALL WRITE MOV BX,WORD ROM_SEGMENT CALL WHEXW ;vypis novy segmnet INT 10h ;vypis znak : prez BIOS (AX zustava stejny) MOV BX,WORD NEW_INT13 CALL WHEXW ;vypis novy offset CALL WCRLF ;odradkuj POP ES POPA RET IINTSTR DB 'INT13h vector has been hooked ',0 AROWSTR DB ' -> ',0 ;***************************************************************************** BEGIN: MOV [CS:OLDSS],SS ;nejprve uloz konfiguraci stareho zasobniku MOV [CS:OLDSP],SP ;BIOS ma defaultne SS=0 SP=0Dxx - malo MOV SP,01FE0h ;nastav novy vetsi zasobnik MOV SS,SP ;segment = 1FE0 MOV SP,07C00h ;offset = 7C00 (fyzicky: 27A00h tj 162304B) PUSHA ;store regs AX,BX,CX,DX,SI,DI,BP,SP (16B) PUSHF ;store flags PUSH DS ;store DS PUSH ES ;store ES ;ASK FOR BOOT MOV SI,MSG1 MOV BX,010Fh ;bila barva, opakovani 1x CALL WCRLF ;odradkuj CALL WRITE ;vypis CALL WCRLF ;odradkuj MOV AH,ROMOS_MSG_DELAY ;pockej CALL DELAY ;TEST FOR SCROLLOCK XOR AX,AX ;otestuj, jestli je stisknuty ScrollLock MOV ES,AX ;segment flagu klavesnice 0000 MOV AL,[ES:0417h] ;offset flagu klavesnice 0417 AND AL,00010000b ;vymaskuj ScrollLock CMP AL,16 ;je-li zaply, JE @DOBOOT ;pokracuj v bootu ROMOSu JMP EXIT ;jinak skonci (je potreba dlouhy JMP) @DOBOOT:MOV AL,[ES:0417h] ;znova nacti flag klavesnice AND AL,11101111b ;zhasni ScrollLock OR AL,00100000b ;rosvit NumLock MOV [ES:0417h],AL ;zapis flag klavesnice ;************** Zde uz je mozno psat kod bez obav, lze ho pri POSTu preskocit BOOT: MOV SI,MSG2 MOV BX,010Eh ;zluta barva, opakovani 1x CALL WRITE ;vypis welcome CALL WCRLF ;odradkuj MOV AH,20 CALL DELAY MOV SI,MSG3 MOV BX,0107h ;seda barva, opakovani 1x CALL WRITE ;vypis isntall ROMDISK CALL WCRLF ;odradkuj MOV AH,20 CALL DELAY CALL WCRLF ;odradkuj CALL WREGS ;vypis registry MOV AH,20 CALL DELAY CALL SET_KBD_FAST ;nastav rychlou klavesnici ;************** Instalace nove obsluhy INT13h emulujici virtualni ROMDISK *** CALL INSTALL_NEW_INT13 MOV AH,20 ;20*55ms CALL DELAY MOV SI,MSG4 MOV BX,0107h ;seda barva, opakovani 1x CALL WRITE ;Bootsector loaded at MOV BX,BS_SEGMENT CALL WHEXW ;vypis segment MOV AX,0E3Ah ;vypis znak : INT 10h ;prez BIOS MOV BX,BS_OFFSET ;vypis offset CALL WHEXW CALL WCRLF ;odradkuj MOV SI,MSG5 MOV BX,010Fh ;bila barva, opakovani 1x CALL WRITE ;Booting! CALL WCRLF ;odradkuj MOV AH,10 ;10*55ms CALL DELAY ;************** Prekopiruje bootsector z virtual ROMDISKu na spousteci adresu XOR SI,SI MOV ES,SI MOV SI,0410h ;priprav adresu Bytu vybaveni (INT11h) MOV AL,[ES:SI] ;horni dva bity udavaji pocet mechanik-1 MOV AH,BYTE ROMDISK_DRIVE ;tedy: zadna=00, A:=00, A:+B:=01 CMP AH,1 ;pokud mame emulovat jednotku B: JNE SKIP_DRVNUPD ;jinak nech bejt OR AL,01000000b ;je potreba zvysit pocet mechanik MOV [ES:SI],AL ;zapis aktualizovany Byte vybaveni SKIP_DRVNUPD: MOV SI,BS_SEGMENT ;priprav cilovy segment pro nahrani bootsectoru MOV ES,SI MOV DI,BS_OFFSET ;priprav cilovy offset pro nahrani bootsectoru MOV SI,ROM_SEGMENT ;priprav zdrojovy segment MOV DS,SI MOV SI,IMG_BEGIN ;priprav zdrojovy offset-zacatek ROMDISK image MOV [DS:SI+BS_DRIVE_OFFSET], BYTE ROMDISK_DRIVE ;patch bootsectoru podle drive MOV CX,512 ;1 sektor=512B REP MOVSB ;kopiruj dokud CX neni nulove MOV DL,BYTE ROMDISK_DRIVE ;nastav bootdrive pro bootsector STI ;povol preruseni JMP BS_SEGMENT:BS_OFFSET ;skoc na zacatek kopie bootsectoru ;*************** Ukonceni, obnoveni stavu a predani rizeni zpet BIOSu ******** EXIT: %ifdef HOOK_INT18_BY_ROMOS XOR SI,SI ;hook INT18h (INT19h) MOV ES,SI MOV SI,60h ;vektor INT18h zacina na adrese 0:0060, INT19h na 0:0064 MOV [ES:SI],WORD 3 ;vlozime tam adresu ROM modulu, napred offset MOV [ES:SI+2],WORD ROM_SEGMENT ;a pak segment %else MOV SI,WORD ROM_SEGMENT ;na zaver smaz hlavicku ROM 55AAxx MOV ES,SI ;BIOS pak uvolni tuto oblast pro UMB MOV [ES:0],DWORD 0 %endif POP ES ;restore ES POP DS ;restore DS POPF ;restore flags POPA ;restore regs AX,BX,CX,DX,SI,DI,BP,SP (16B) MOV SS,[CS:OLDSS] ;obnov konfiguraci stareho zasobniku MOV SP,[CS:OLDSP] %ifdef MAKE_DEBUG_COM INT 20h ;use if compiling *.COM file %else RETF ;CBh - FAR RET %endif ;***************************************************************************** IMG_BEGIN incbin "romdisk.img" ;nakonec pripoj binarni soubor image disku IMG_END ;FAT12 (1x), C:7, H:1, S:18, S/CL:1, ROOTE:16 END