title okdrives.asm 6/25/88 (c) 1988 Bridger Mitchell ; ; ; This rsx sets the vector of valid drives allowed by the bios. ; If called with de == 0, it returns the current valid-drives vector. ; ; usage to set valid drives: ; ; ld c,DRIVEFN ; ld de, ; bit 0 = A:, ..., bit 15 = P: ; call 5 ; ; usage to determine currently-valid drives: ; ; ld c,DRIVEFN ; ld de,0000 ; call 5 ; ; ; We need an extended bdos function number. ; DRIVEFN equ 241 ; 0F1h ABORT equ 0ffh ; ; ; Name the REL image with "RSX" plus 0-3 characters of identification. ; In this case, we've used the rsx's bdos function number (241). name RSX241 ;"RSX" required ; ; All of the code within the bracketed regions is the same for any rsx ; loaded by JetLDR. It can be copied intact when creating a different rsx. ; ; *---------- Plu*Perfect Systems RSX Extended Header----------------* ;/ \ ; ; The rsx code goes in the CSEG (code segment). ; CSEG rsx: jp rsxstart ; 00 jp rsxwb ; +03 jp rsxremove ; +06 rsxwba: dw $-$ ; +09 rsxprot:dw rsx ; +0B dw rsxname ; +0D rsxnext:jp $-$ ; -> next wb or ccp entry ; +0F ; next: jp $-$ ; -> next rsx or bdos ; +12 nextwb: dw $-$ ; +15 ;\ / ; *-----------------------------------------------------------------* ; ; ; The custom code for this rsx begins here. ; ; rsxname:db 'OKDRIVES',0 ; nul-terminated name of rsx. ; vector: dw 1111111111111111b ; <-- set bits for valid drives ; PONMLKJIHGFEDCBA ; <-- must be terminated by 'B' char. ; ; ; This RSX's bdos function. ; ; enter: c = DRIVEFN ; de == 0 to get current ok-drives vector ; de != 0 to set the current vector to de ; return: ; hl = vector of ok drives ; rsxstart: ld a,c cp DRIVEFN ; if not our function jr nz,next ; .. on to the next rsx/bdos ld a,e ; set vector? or d jr nz,set ; ..yes get: ld hl,(vector) ; no, return the drive vector in hl ld a,l ; return a != 0 ret ; set: ex de,hl set 0,l ; ensure drive A: always valid ld (vector),hl ; save the new drive vector ld a,l ; and return it in hl ret ; ; The bios seldsk intercept ; ; enter: c = requested drive ; exit: hl == 0 if drive not allowed ; else continue to bios seldsk ; rsxseldsk: ld hl,(vector) ; shift ok-drives vector left ld a,16 sub c rsxs1: add hl,hl dec a jr nz,rsxs1 ld hl,0000 ; prime error return ret nc ; NC if bit wasn't set jseldsk:jp $-$ ; jmp to bios seldsk routine ; ; ; Restore this rsx's particular patches. ; custom_remove: ld hl,(jseldsk+1) ; restore bseldsk address ld (bios+1ch),hl ; to bios jmp vector ret ; ; *---------------- Standard RSX Code -----------------------------* ;/ \ ; ; The warm-boot intercept. ; rsxwb: .new call fix0001 ; ensure correct page 0 ld hl,(bios+4) ; does bios wb addr ld de,rsx+3 ; point at us? or a sbc hl,de jr nz,rsxwb1 ; no, we're not the bottom rsx ld hl,(rsxprot) ; we are, set our protect address ld (0006),hl rsxwb1: ld bc,(0004h) ; get c = logged du for ccp jp rsxnext ; in case we're top rsx ; ; ; The removal routine. ; rsxremove: call custom_remove ; do extra restoration for this rsx ; ld hl,(nextwb) ; get saved original warmboot addr ld (bios+4),hl ; and restore it to bios jmp vector ; ; When the caller terminates to a warmboot, ; the next module (or bios, if none), will correct 0006. ; ; Set CY flag to inform the removal tool that this routine ; has indeed taken action. (Some RSX's are not self-removing). ; fix0001:ld hl,(rsxwba) ; restore (0001) in case an errant ld (0001h),hl ; application has tampered with it scf ; set CY to signal success ret ; ; ; Before loading an RSX, JetLDR will first check for protected memory. ; If it detects that memory is protected by a non-RSX header (e.g. a debugger) ; it will cancel the load. Otherwise, JetLDR will call any ; code in the _INIT_ named common, after the rsx module has been ; loaded and relocated. This code will be located in non-protected ; memory, and takes no space in the RSX. ; ; Return parameter: A = 0 indicates a good installation ; A = ABORT = 0FFh = not installed ; common /_INIT_/ ; ; Install the rsx. This code is standard for all rsx's, ; except for: ; custom_init ; custom_twin ; init: ld hl,(0006) ; hl = possible rsx, or bdos ld c,0 ; initialize count of rsx's ; initlp: push hl ; stack (possible) rsx base address ld de,09 ; if candidate is an rsx add hl,de ; ..the wbaddr will be here ld e,(hl) ; get address inc hl ld d,(hl) ld hl,(0001) ; and compare or a sbc hl,de pop hl jr nz,inittop ; warmboot addr not there, stop looking ; ; we have an rsx in memory, is it our twin? ; inc c ; count an rsx found push hl call ckname pop hl jr z,twin ; ld de,0Fh+1 ; that rsx was't a twin, check for more add hl,de ; get addr of next rsx's wboot jmp ld a,(hl) inc hl ld h,(hl) ld l,a dec hl ; back up to head of that next rsx dec hl dec hl jr initlp ; now check that rsx ; ; we're at the top of the (possibly empty) rsx chain ; inittop: inc c ; any rsx's found? dec c ld hl,ccp+3 ; prepare to use ccp entry address jr z,setnext ; ..no ; ld hl,(0006) ; yes, use bottom rsx's address ; setnext: ld (rsxnext+1),hl ; save the next addr ; in the rsx chain to bdos/ccp ; ; install the rsx into the running system ; ld hl,(bios+4) ; save the bios's wb addr ld (nextwb),hl ; in the header ld hl,rsx+3 ; point the bios wb jump ld (bios+4),hl ; at the rsx wb vector ld hl,bios+3 ; store wb addr ld (rsx+09),hl ; in rsx header word ld hl,(0006) ; get addr of next rsx or bdos ld (next+1),hl ; and install it ld hl,rsx ; finally, protect the rsx ld (0006),hl ; call custom_init ; take care of extras ret ; ckname: ld de,0dh ; offset to candidate rsx name pointer add hl,de ld a,(hl) ; get address inc hl ld h,(hl) ld l,a ld de,rsxname ; compare to our name ckname1:ld a,(de) cp (hl) ret nz inc (hl) ; candidate must be nul-terminated dec (hl) jr nz,ckname2 or a ; ..at our same byte ret ckname2:inc hl inc de jr ckname1 ; ; Handle the case of a previously-loaded copy of this RSX. ; twin: call custom_twin ret ;\ / ; *-----------------------------------------------------------------* ; ; Custom initialization code goes here. ; ; ; Do the particular patches for this RSX. ; Note: this code is in the _INIT_ segment. custom_init: ld hl,(bios+1ch) ; get bseldsk address ld (jseldsk+1),hl ; install it in rsx ; ld hl,rsxseldsk ; divert bios jump ld (bios+1ch),hl ; to the rsx ret ; ; This particular rsx should not be duplicated. ; A different rsx might wish to query the user here, ; print a warning, or whatever. ; custom_twin: ld a,ABORT ret ; ; Include identification info in the REL image. ; JetLDR will display the bytes up to the first NUL byte ; when the RSX is loaded. ; ; common /_ID_/ ; db 'OKDRIVES: RSX prevents bios logins' db 13,10 db 'Use BDOS function 241 (0F1h) to set de = drive vector',0 ; ; Include whatever other named-commons are needed for this RSX. ; JetLDR will resolve these labels for us. ; common /_BIOS_/ bios equ $ common /_CCP_/ ccp equ $ end ;okdrives.asm