home *** CD-ROM | disk | FTP | other *** search
- * safram.asm Roy Lipscomb
- * Version 1.0 Aug 1, 1982
- *
- * Creates a "safe" partition below BDOS. Modules residing
- * in the partition are safe from destruction until the
- * the next system reset.
- *
- * Copyright 1982 by Roy Lipscomb, Logic Associates, Chicago
- *
- * Original distributor: HP/RCPM, (312) 955-4493
- *
- *
- ********************************************************************
- *
- * Description of this program is contained in SAFRAM.DOC and
- * in SAFRAM.H.
- *
- * Before attempting to assemble this source, please read the
- * ASSEMBLING section in SAFRAM.DOC.
- *
- *********************************************************
- * service/loader routines *
- *********************************************************
-
- if copy1 ;service routines
- org 100h
- jmp begin
-
-
- no equ 0
- yes equ 1
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; customizing variables ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- boot equ 0 ;lowest address within CP/M
-
- notify equ yes ;at each ^C, notify of secure addr
-
- hotboot equ 0 ;set to 0 to deactivate.
- ;hotboot gives displacement from start
- ; of bios to first instruction after
- ; code that loads CCP/BDOS/BIOS.
- ; See document SAFRAM.H for information.
-
- pagebnd equ no ;to force all secure addresses
- ;to page boundary, change to "yes"
-
- ;nothing below this point needs to be customized.
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- bell equ 7
- coutdsp equ 12-3 ;displacement of charout from wboot
- bdosjmp equ boot+5
- pstr equ 9
- deffcb equ boot+5ch
- tbuff equ boot+80h
-
- tab equ 9
- cr equ 13
- lf equ 10
- blank equ ' '
-
- pageopt equ (not pagebnd)/100h ;if pagebnd = no, pageopt = 0ffh
- secaddr dw 0 ;highest available RAM excluding CCP
- loadpnt dw 0
- modbase dw 0 ;starting point of module
- ;(different from loadpnt if old module)
-
- ;values used in setting traps
- biosdsp dw 0
- biosav dw 0
- trapent dw 0
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;values used in manipulating the ccp
-
- doslen1 equ 0d00h ;length of cpm 1.x bdos
- doslen2 equ 0e00h ;length of cpm 2.x bdos
-
- ccplen equ 800h ;length of ccp
- ccpclen equ 7 ;ccp command-length byte
- ccpcchr equ 88h ;ccp current-char displacement
- ccp dw 0 ;ccp entry point
-
- curdrv equ 4 ;current drive in pg zero
- ccpstrt dw 0 ;pointer to first char in ccp buff
-
-
-
- ;messages
- eom equ '$'
-
- baddr db cr,lf
- db bell
- db 'Abort: Valid address range at present is '
- badad1 db '....H through '
- badad2 db '....H.'
- db cr,lf
- db '$'
-
- ccpmess db 'Abort: unable to locate CCP'
- db bell,cr,lf,cr,lf,eom
-
- helpmes db cr,lf
- db ' SAFRAM'
- db ' Copyright 1982 by Roy Lipscomb, Logic Associates'
- db cr,lf
- db ' Version 1.0 Aug, 1982'
- db cr,lf
- db cr,lf
- db ' Assigns safe partition (removed only by system'
- db ' reset) below BDOS.'
- db cr,lf
- db ' (Multiple executions of SAFRAM are permitted).'
- db cr,lf
- db cr,lf
- db ' [] To secure the CCP or the boot+6 address, '
- db 'type "SAFRAM".'
- db cr,lf
- db ' [] To secure a lower address, type "SAFRAM xxxx",'
- db ' where'
- db cr,lf
- db ' "xxxx" is address in hex.'
- db cr,lf
- db cr,lf
- db ' ',eom
-
- crlf db cr,lf
- db eom
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; mainline ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- begin call signon ;print signon message
-
- call getbase ;compute load address: just below CCP
- cz ccperr ;ccp not found
- jz exit
-
- ;test for explicit address on command line. Abort if bad.
- call expladr
- jnz exit ;quit if error
-
- ;if already loaded and active, don't load again (just update it)
- call tstact
- cz active
- cnz instal
-
- ;if ddt executing, do restart 7; else return to cpm
- exit lxi h,0
- dad sp ;if stack pointer <= 100,
- mov a,h ; then ddt active
- cpi 2
- rnc ;stack pointer >1ff, so must be cpm
-
- rst 7 ;ddt active; do restart 7
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; compute load address ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;if ccp not found, return with zero set
-
- ;first try to find ccp: standard method
- getbase lhld boot+6
- shld secaddr ;secure-address if ccp already
- ; secured (default)
- lxi d,0
- call tstccp ;add de and hl for candidate ccpbase
- jz ccpnosc ;ccp found, not secured
-
- ;second try: via cbios entry point of cpm 2.x
- lhld boot+1
- lxi d,-doslen2
- call tstccp ;add de and hl for candidate ccpbase
- jz ccpsec ;ccp found, secured
-
- ;last try: via cbios entry point of cpm 1.x
- lhld boot+1
- lxi d,-doslen1
- call tstccp ;add de and hl for candidate ccpbase
- jz ccpsec ;ccp found, secured
-
- ;ccp not found
- xra a
- ret ;set zero flag ("not found")
-
- ;ccp secured/not-secured
- ccpnosc lhld ccp ;(really contains bdos addr here)
- shld secaddr ;set to secure ccp
-
- ccpsec ori 1
- ret
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;test for explicit address on command line. Abort if error
- ;if no error, return with z flag = yes
-
- ;get parm length and address
- expladr lxi d,tbuff ;get parm length
- ldax d
- mov b,a ;save parm length byte
- inr b
-
- ;skip leading blanks, exit if nothing left
- expl4 dcr b
- jz expl9
-
- inx d
- ldax d
- call blnktab ;test for blank or tab
- jz expl4
-
- ;digest the parm
- lxi h,0 ;initialize hex value
-
- expl6 call asc2hex ;build hex value in hl
- jnz expl8 ;exit if error
-
- dcr b
- jz expl7
-
- inx d
- ldax d
- call blnktab ;test for blank or tab
- jnz expl6
-
- ;value digested: verify it's acceptable
- expl7 xchg ;save in de
- lxi h,progend+2
- call neghl
- dad d
- jnc expl8 ;error if below end of this prog...
-
- lhld secaddr
- inx h
- call neghl
- dad d
- jc expl8 ; ...or if higher than available top
-
- ;value ok: substitute it for implicit address
- xchg
- shld secaddr
-
- xra a ;set z = "no error"
- jmp expl9
-
- ;error exit: display acceptable addr range, then exit.
- expl8 lxi h,progend+3
- call hex2asc ;put value in de and hl
- lxi h,badad1
- call put2bad
-
- lhld secaddr
- call hex2asc
- lxi h,badad2
- call put2bad
-
- lxi d,baddr
- mvi c,pstr
- call bdosjmp
-
- ori 1 ;set z = "error"
-
- expl9 ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;test for blank or tab in a; if yes, return z = yes
- blnktab cpi blank
- rz
-
- cpi tab
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;put address into error message
- put2bad mov m,b
- inx h
-
- mov m,c
- inx h
-
- mov m,d
- inx h
-
- mov m,e
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;convert ascii characters into hex (using hl)
- asc2hex sui '0'
- rc ;exit if invalid char
-
- cpi 10
- jc asc2b
- sui 7
-
- cpi 16
- jnc asc2x
-
- asc2b dad h
- dad h
- dad h
- dad h
-
- add l
- mov l,a
-
- xra a ;set z = "no error"
-
- ret
-
- ;error exit
- asc2x ori 1 ;set z = "error"
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;convert hex value to ascii
- hex2asc call hex2b
- mov b,d
- mov c,e
-
- hex2b call hex2c
- mov d,a
-
- call hex2c
- mov e,a
-
- ret
-
- hex2c mov a,h
-
- dad h
- dad h
- dad h
- dad h
-
- rar
- rar
- rar
- rar
-
- ani 0fh
- adi '0'
-
- cpi '9'+1
- rc
-
- adi 7
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;convert hl to its negative
- neghl push psw
-
- mov a,h
- cma
- mov h,a
-
- mov a,l
- cma
- mov l,a
-
- inx h
-
- pop psw
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;test if this location has ccp
-
- ;compute tentative ccpbase
- tstccp mvi l,0
- dad d ;compute tentative bdos entry point
-
- lxi d,-ccplen
- dad d ;tentative bdos entry minus ccp length
-
- shld ccp ; ...gives tentative ccp entry
-
- ;test for the two leading jumps in the ccp
- mvi a,jmp
- lxi b,3
-
- cmp m
- rnz
-
- dad b
- cmp m
- rnz
-
- ;test for standard "maximum buffer length" value
- dad b
- mov a,m
-
- cpi 7fh ;standard ccp maxbuff len
- jz tstcc4
-
- cpi 50h ;standard zcp maxbuff len
- rnz
-
- ;test for "buffer length" < "maximum buffer length"
- tstcc4 inx h
- cmp m
- rc ;give up if bufflen > maxbufflen
-
- xra a ;looks ok
-
- ret
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; test if module already active ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;check address in bios table for wboot
- tstact lhld boot+1
- inx h
- mov e,m
- inx h
- mov d,m
- xchg
- shld modbase ;save it
-
- ;test if "secure" message present where expected
- lxi d,wb2mess ;get adjustment for message
- dad d
-
- ;compare to unmoved module message
- lxi d,message+module1
- mvi b,testlen
- tstmess ldax d
- cmp m
- jnz failtst
- inx h
- inx d
- dcr b
- jnz tstmess
-
- ;active already
- xra a
- ret
-
- failtst ori 1 ;set flag
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; module already active: process only stub ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;determine where to install bypass
- active lhld secaddr
- lxi d,-3
- dad d
- mvi a,pageopt
- ana l
- mov l,a
- shld loadpnt
-
- ;determine old module's start
- lhld modbase
- lxi d,-beforwb
- dad d
- shld modbase
-
- ;secure, then update message and savearea
- call doprot
-
- ;set for display of current secured address
- lhld modbase
- lxi d,bootflg
- dad d
- mvi m,on ;set flag to "on"
-
- ;set to bypass "not active" module
- xra a
-
- ret
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; module not active: load from scratch ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;if hotboot option requested, set it now
- instal call sethot
-
- ;compute load point
- lhld secaddr
- lxi d,-length
- dad d
- mvi a,pageopt
- ana l
- mov l,a
- shld loadpnt
- shld modbase ;modbase = new module entry
-
- ;move it
- call chgaddr ;convert to true addresses
- call movemod ;move module to load address
- call traps ;install traps
- call doprot ;do secure, and update message
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;overlay warmboot jmptable entry with hotboot, if hotboot > bdos.
- sethot lxi b,hotboot
- mov a,b
- ora c
- jz noacex ;hotboot option not in effect, so exit.
-
- lhld boot+1 ;put warmstart jmptab entry into hl
- mov d,h
- mov e,l ; point de to warmboot jmp addr
- inx d
-
- dcx b ;normalize bc for warmstart, not cold
- dcx b
- dcx b
- dad b ;compute hl = hotboot jump address
-
- mov a,l ;substitute hot for warm boot address
- stax d
- inx d
-
- mov a,h
- stax d
-
- noacex ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; convert module1 to true addresses ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ; change pseudo addresses to true addresses
- chgaddr lxi b,length
- lxi d,module1
- lxi h,module2
- truloop ldax d
- cmp m
- cnz convert
-
- inx h
- inx d
- dcx b
-
- mov a,b
- ora c
- jnz truloop
-
-
- ret
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; convert displacement into address ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- convert push b ;length of module not yet processed
- push h ;module2 character position
-
- ; get displacement from instruction, put into bc.
- ldax d
- mov b,a
- dcx d
- ldax d
- mov c,a
-
- lxi h,-module1 ;normalize displacement to zero
- dad b
- push h
- pop b
-
- lhld loadpnt ;add load point for true addr
- dad b
-
- ; move true address to instruction
- mov a,l
- stax d
- inx d
- mov a,h
- stax d
-
- pop h
- pop b
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; move module into place ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- movemod lhld loadpnt
- xchg ;de=destination
- lxi h,module1 ;hl=source
- lxi b,length
-
- call move
-
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; install security, describe in message ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;move the new secured address to de, then store wherever needed
-
- ; secure the module
- doprot lhld 6
- xchg
- lhld loadpnt
- shld 6
-
- ;install bypass at base of secured RAM
- push h ;save new secured address
- mvi m,jmp
- inx h
- mov m,e
- inx h
- mov m,d
- pop d ;restore new secured address
-
- ;store new secured address in module
- lhld modbase
- lxi b,savbase
- dad b
- mov m,e
- inx h
- mov m,d
-
- ;convert hex address at location 6 to ascii, put in message
- lhld modbase ;address message
- lxi b,messadr
- dad b ;pointer to message into hl
-
- ;output hi and lo bytes of address to message
- call hilo
- hilo mov a,d
- mov d,e ;get next byte
- push psw
- rar
- rar
- rar
- rar
- call hexbyte
- pop psw
-
- hexbyte ani 0fh
- adi '0'
- cpi '9'+1
- jc movhex
- adi 7
- movhex mov m,a
- inx h
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; set all traps ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;set trap for wboot
- traps lxi h,toboot+1
- shld biosav
- lxi h,beforwb
- shld trapent
- lxi h,0
- shld biosdsp
-
- call settrap
-
- ;set trap for conout
- lxi h,jmpcout+1
- shld biosav
- lxi h,pentry
- shld trapent
- lxi h,coutdsp
- shld biosdsp
-
- call settrap
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; set a trap ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- settrap lhld modbase ;get address of moved module
- push h
- pop b ;save in bc
-
- lhld biosdsp ;get displace for bios jmptable into de
- push h
- pop d
-
- ;get contents of bios jumptable entry
- lhld boot+1
- dad d ;address bios jumptable entry
- inx h
- push h ;...save pointer to table entry
-
- mov e,m ;...and get contents
- inx h
- mov d,m
-
- ;store bios entry into trap savearea
- lhld biosav ;save bios contents into trap mod
- dad b
- mov m,e
- inx h
- mov m,d
-
- ;set bios entry to trap entry
- lhld trapent ;get addr of appropriate trap into de
- dad b
- xchg
-
- pop h ;store trap addr in bios jmptab
- mov m,e
- inx h
- mov m,d
-
- ret
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; print messages ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- signon lxi d,helpmes
- jmp domess
-
- ccperr lxi d,ccpmess
-
- domess mvi c,pstr
- call bdosjmp
- xra a ;set zero flag (for ccperr return)
- ret
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; move block of data ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ;source in hl, destination in de, length in bc.
-
- move mov a,b
- ora c
- rz
- mov a,m
- stax d
- inx d
- inx h
- dcx b
- jmp move
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ; end of service routines ;
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- endif
-
-
-
-
- *********************************************************
- *********************************************************
- * beginning of movable module *
- *********************************************************
- *********************************************************
-
-
- org ($+0ffh)/100h*100h ;must be page boundary
- adjust set $
-
- if copy1
- module1 equ $
- endif
-
- if not copy1
- module2 equ $
- endif
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- address equ 0ffffh ;various address to fill at runtime
- on equ 0 ;do resecure
- off equ 0ffh
- pflag equ on ;harden security as soon as loaded
-
- pbase equ $-adjust
- jmp address ;security base: "address" set at run
- ;time to jump to previous pbase
-
- notiflg equ $-adjust
- db notify ;yes/no for message at each ^C
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;maintrap: perform setup if wboot (or trap just loaded)
-
- pentry equ $-adjust
- bootflg equ pentry+1
- mvi a,pflag ;"on" for wboot
- cpi on ;test for "on"
- cz afterwb+adjust
- jmpcout equ $-adjust
- jmp address ;from bios conout jmptable entry
- ;("address" set at runtime)
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;pre-wboot action: set flag
- beforwb equ $-adjust
- mvi a,on
- sta bootflg+adjust
- toboot equ $-adjust
- jmp address ;on to wboot (address set at runtime)
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;post-wboot action: reset flag, restore security, rearm boot trap
- afterwb equ $-adjust
- mvi a,off
- sta bootflg+adjust ;turn off flag
-
- savbase equ $-adjust+1
- lxi h,address ;restore secured address to 5h
- shld 6 ;("address" filled at runtime)
-
- ;if display option set, notify that security still in effect
- lda notiflg+adjust
- cpi yes
- rnz
-
- push b
- lxi d,message+adjust ;notify of current pbase
-
- display equ $-adjust
- ldax d
- inx d
- cpi eom
- jz dispend+adjust
-
- mov c,a
- push d
- call jmpcout+adjust
- pop d
-
- jmp display+adjust
-
-
- dispend equ $-adjust
- pop b
-
- ret
-
-
-
- ;don't remove the message below; used to test if module already present
-
- message equ $-adjust
-
- ;(number of blanks below is arbitrary)
- db ' '
- db '(Safram at '
- messadr equ $-adjust
- db '....)',cr,lf,eom
-
- wb2mess equ message-beforwb ;distance from wboot trap
- testlen equ messadr-message
-
-
- *********************************************************
- * end of relocatable routines *
- *********************************************************
-
- ;get length of relocatable routines
- length equ $-adjust
-
- ;flip the copy1/copy2 toggle
- copy1 set not copy1
-
- ;assemble address of end of this program
- if copy1
- progend equ $
- endif
-
- ;link a second copy, if this was the first copy
- if not copy1
- link safram
- endif
- ram
- if copy1
- p