home *** CD-ROM | disk | FTP | other *** search
- ;****************************************************************************
- ; CMOSSAVE saves the contents of CMOS RAM to a file. Its syntax is:
- ;
- ; CMOSSAVE [d:][path]filename [/nnn]
- ;
- ; where "filename" is the name of the file to which CMOS data will be
- ; saved, and "nnn" specifies the number of bytes to save. Valid values
- ; for "nnn" are 64 to 256. If the /nnn switch is omitted, CMOSSAVE
- ; determines how many bytes of CMOS your PC contains and saves them all.
- ; Use CMOSRSTR to restore CMOS RAM data.
- ;****************************************************************************
-
- CMOS_ADDR equ 70h ;CMOS address port
- CMOS_DATA equ 71h ;CMOS data port
-
- code segment
- assume cs:code,ds:code
- org 100h
- begin: jmp main
-
- copyright db "CMOSSAVE 2.0 Copyright (c) 1993 Jeff Prosise",13,10
- db "From: PC Magazine DOS 6 Memory Management "
- db "with Utilities",13,10,13,10,"$"
-
- helpmsg db "Saves the configuration data stored in CMOS RAM to "
- db "a file.",13,10,13,10
- db "CMOSSAVE [d:][path]filename [/nnn]",13,10,13,10
- db " filename Name of the file to which configuration "
- db "data will be saved.",13,10
- db " /nnn Number of bytes of CMOS RAM to save."
- db 13,10,13,10
- db "Use CMOSRSTR to restore CMOS configuration data."
- crlf db 13,10,"$"
-
- errmsg1 db "Syntax: CMOSSAVE [d:][path]filename [/nnn]",13,10,"$"
- errmsg2 db "The file already exists. Replace it (Y/N)? $"
- errmsg3 db "Invalid path or file name. File could not be "
- db "created.",13,10,"$"
- errmsg4 db "Error writing file to disk",13,10,"$"
- errmsg5 db "Disk full",13,10,"$"
- errmsg6 db "Invalid numeric parameter or value out of range"
- db 13,10,"$"
-
- msg db " bytes were copied from CMOS RAM to disk",13,10,"$"
-
- handle dw ? ;File handle
- filename dw 0 ;Address of file name
- cmoslength dw ? ;Number of bytes to save
- nnn dw 0 ;Value of "nnn" parameter
-
- ;****************************************************************************
- ; Procedure MAIN
- ;****************************************************************************
-
- main proc near
- cld ;Clear direction flag
- mov si,81h ;Point SI to command line
- call scanhelp ;Scan for "/?" switch
- jnc main1 ;Branch if not found
-
- mov ah,09h ;Display help text and exit
- mov dx,offset helpmsg ;with ERRORLEVEL=0
- int 21h
- mov ax,4C00h
- int 21h
- ;
- ; Parse the command line.
- ;
- main1: call findchar ;Find a parameter
- jc main2 ;Branch if end of line
-
- cmp byte ptr [si],"/" ;Branch if the parameter
- je main1a ;starts with a "/"
-
- mov filename,si ;Save the address
- call finddelim ;Find the end of the string
- mov byte ptr [si],0 ;Convert file name to ASCIIZ
- jc main2 ;Branch if end of line
- inc si ;Advance SI
- jmp main1 ;Loop back for more
-
- main1a: inc si ;Skip the "/" character
- call asc2bin ;Read and convert the number
- mov dx,offset errmsg6 ;Error if carry returns set
- jc error
- cmp ax,64 ;Error if number is less
- jb error ;than 64 or greater than
- cmp ax,256 ;256
- ja error
- mov nnn,ax ;Save the value
- jmp main1 ;Loop back for more
-
- main2: cmp filename,0 ;Branch if a file name
- jne main2a ;was entered
-
- mov dx,offset errmsg1 ;Point DX to error message
- error: mov ah,09h ;Display error message
- int 21h
- error_exit: mov ax,4C01h ;Exit with ERRORLEVEL=1
- int 21h
-
- main2a: mov cx,nnn ;Set CMOSLENGTH equal to
- mov cmoslength,cx ;NNN and branch if a number
- or cx,cx ;was entered on the command
- jnz main3 ;line
-
- call getlength ;Get CMOS length
- mov cmoslength,cx ;Save the result
- ;
- ; Create the data file.
- ;
- main3: mov ax,3D00h ;Attempt to open the file
- mov dx,filename ;with DOS function 3Dh
- int 21h
- jc main4 ;Branch if the call failed
-
- mov bx,ax ;Close the file
- mov ah,3Eh
- int 21h
-
- mov ah,09h ;Ask if user wants to
- mov dx,offset errmsg2 ;overwrite it
- int 21h
-
- ask: mov ah,08h ;Get the response
- int 21h
- or al,al
- jnz compare
- mov ah,08h
- int 21h
- jmp ask
-
- compare: cmp al,"Y" ;Ask again if the answer
- je yes ;isn't "Y" or "N"
- cmp al,"y"
- je yes
- cmp al,"N"
- je no
- cmp al,"n"
- jne ask
-
- no: mov ah,02h ;Display "N" and abort
- mov dl,"N"
- int 21h
- mov ah,09h
- mov dx,offset crlf
- int 21h
- jmp error_exit
-
- yes: mov ah,02h ;Display "Y" and continue
- mov dl,"Y"
- int 21h
- mov ah,09h
- mov dx,offset crlf
- int 21h
-
- main4: mov ah,3Ch ;Create the file by calling
- xor cx,cx ;DOS function 3Ch
- mov dx,filename
- int 21h
- mov dx,offset errmsg3 ;Error if the file could
- jc main6a ;not be created
- mov handle,ax ;Save the file handle
- ;
- ; Read the configuration data from CMOS RAM, compute the checksum, and
- ; write both to the file.
- ;
- mov cx,8 ;Copy the CMOSSAVE signature
- mov si,offset copyright ;to the output buffer
- mov di,offset scanhelp
- rep movsb
-
- cld ;Clear direction flag
- xor cx,cx ;Initialize counter
-
- main5: mov al,cl ;Get address in AL
- cli ;Interrupts off
- out CMOS_ADDR,al ;Output CMOS address
- jmp short $+2 ;I/O delay
- jmp short $+2
- in al,CMOS_DATA ;Read one byte of CMOS data
- stosb ;Buffer the byte
- sti ;Interrupts on
- inc cx ;Increment counter
- cmp cx,cmoslength ;Loop if there are more
- jne main5 ;bytes to save
-
- xor al,al ;Compute the checksum
- mov cx,cmoslength
- add cx,8
- mov si,offset scanhelp
- main6: add al,[si]
- inc si
- loop main6
- stosb ;Copy checksum to buffer
-
- mov ah,40h ;Write the data to the file
- mov bx,handle
- mov cx,cmoslength
- add cx,9
- mov dx,offset scanhelp
- int 21h
- mov dx,offset errmsg4
- jc main6a ;Branch on error
-
- cmp ax,cx ;Error if the disk is
- je main7 ;full
- mov dx,offset errmsg5
- main6a: jmp error
- ;
- ; Close the file, display message, and exit.
- ;
- main7: mov ah,3Eh ;Close the data file
- mov bx,handle
- int 21h
-
- mov ah,09h ;Display copyright message
- mov dx,offset copyright
- int 21h
-
- mov ax,cmoslength ;Display the number of
- call bin2asc ;bytes that were saved
- mov ah,09h
- mov dx,offset msg
- int 21h
-
- mov ax,4C00h ;Exit with ERRORLEVEL=0
- int 21h
- main endp
-
- ;****************************************************************************
- ; GETLENGTH returns the number of bytes of CMOS RAM that this PC
- ; contains in CX. GETLENGTH will never return a value less than 64
- ; or greater than 256.
- ;****************************************************************************
-
- getlength proc near
- mov cx,64 ;Initialize counter
-
- gl_loop: cli ;Interrupts off
- mov al,cl ;Get address in AL
- out CMOS_ADDR,al ;Output CMOS address
- jmp short $+2 ;I/O delay
- jmp short $+2
- in al,CMOS_DATA ;Read one byte of CMOS data
- mov bl,al ;Save the byte in BL
- sti ;Interrupts on
-
- mov al,0A5h ;Test this byte with
- call testbyte ;alternating 1s and 0s
- jc gl_exit
-
- mov al,5Ah ;Test this byte with
- call testbyte ;alternating 0s and 1s
- jc gl_exit
-
- mov al,00h ;Test this byte with
- call testbyte ;all 0s
- jc gl_exit
-
- mov al,0FFh ;Test this byte with
- call testbyte ;all 1s
- jc gl_exit
-
- cli ;Interrupts off
- mov al,cl ;Get address in AL
- out CMOS_ADDR,al ;Output CMOS address
- jmp short $+2 ;I/O delay
- jmp short $+2
- mov al,bl ;Get original value in AL
- out CMOS_DATA,al ;Restore the byte
- sti ;Interrupts on
-
- inc cx ;Increment counter
- cmp cx,256 ;Loop back for more if
- jne gl_loop ;CX is less than 256
-
- mov al,80h ;Make sure NMI is enabled
- out CMOS_ADDR,al ;if this happens to be a
- jmp short $+2 ;PS/2
- jmp short $+2
- in al,CMOS_DATA
- gl_exit: ret ;Return to caller
- getlength endp
-
- ;****************************************************************************
- ; TESTBYTE tests a byte of CMOS RAM to see if it really does contain RAM.
- ; On entry, CL holds the CMOS address. On return, carry is clear if the
- ; byte contains RAM, set if it does not.
- ;****************************************************************************
-
- testbyte proc near
- mov ah,al ;Save test value in AH
-
- cli ;Interrupts off
- mov al,cl ;Get address in AL
- out CMOS_ADDR,al ;Output CMOS address
- jmp short $+2 ;I/O delay
- jmp short $+2
- mov al,ah ;Get test value in AL
- out CMOS_DATA,al ;Output the test value
- jmp short $+2 ;I/O delay
- jmp short $+2
-
- mov al,cl ;Get address in AL
- out CMOS_ADDR,al ;Output CMOS address
- jmp short $+2 ;I/O delay
- jmp short $+2
- in al,CMOS_DATA ;Read the test value back
- sti ;Interrupts on
-
- cmp al,ah ;Compare the values
- je tb_exit ;Branch if they're equal
-
- stc ;Set carry and return
- ret
-
- tb_exit: clc ;Clear carry and return
- ret
- testbyte endp
-
- ;****************************************************************************
- ; ASC2BIN converts the text pointed to by SI to a number and returns the
- ; value in AX. Carry returns set if the text contains an invalid character
- ; or if an overflow error occurred.
- ;****************************************************************************
-
- asc2bin proc near
- cld ;Clear direction flag
- sub ax,ax ;Initialize registers
- xor bh,bh
- mov cx,10
-
- a2b_loop: mov bl,[si] ;Get a character
- inc si
- cmp bl,20h ;Exit if space
- je a2b_exit
- cmp bl,09h ;Exit if tab
- je a2b_exit
- cmp bl,2Ch ;Exit if comma
- je a2b_exit
- cmp bl,0Dh ;Exit if carriage return
- je a2b_exit
-
- cmp bl,"0" ;Error if character is not
- jb a2b_error ;a number
- cmp bl,"9"
- ja a2b_error
-
- mul cx ;Multiply the value in AX
- jc a2b_error ;by 10 and exit on overflow
- sub bl,30h ;ASCII => binary
- add ax,bx ;Add latest value to AX
- jnc a2b_loop ;Loop back if no overflow
-
- a2b_error: dec si ;Set carry and exit
- stc
- ret
-
- a2b_exit: dec si ;Clear carry and exit
- clc
- ret
- asc2bin endp
-
- ;****************************************************************************
- ; BIN2ASC converts a binary value in AX to ASCII form and displays it.
- ;****************************************************************************
-
- bin2asc proc near
- mov bx,10 ;Initialize divisor word and
- xor cx,cx ;digit counter
- b2a1: inc cx ;Increment digit count
- xor dx,dx ;Divide by 10
- div bx
- push dx ;Save remainder on stack
- or ax,ax ;Loop until quotient is zero
- jnz b2a1
- b2a2: pop dx ;Retrieve a digit from stack
- add dl,30h ;Convert it to ASCII
- mov ah,2 ;Display it
- int 21h
- loop b2a2 ;Loop until done
- ret
- bin2asc endp
-
- ;****************************************************************************
- ; SCANHELP scans the command line for a /? switch. If found, carry returns
- ; set and SI contains its offset. If not found, carry returns clear.
- ;****************************************************************************
-
- scanhelp proc near
- push si ;Save SI
- scanloop: lodsb ;Get a character
- cmp al,0Dh ;Exit if end of line
- je scan_exit
- cmp al,"?" ;Loop if not "?"
- jne scanloop
- cmp byte ptr [si-2],"/" ;Loop if not "/"
- jne scanloop
-
- add sp,2 ;Clear the stack
- sub si,2 ;Adjust SI
- stc ;Set carry and exit
- ret
-
- scan_exit: pop si ;Restore SI
- clc ;Clear carry and exit
- ret
- scanhelp endp
-
- ;****************************************************************************
- ; FINDCHAR advances SI to the next non-white-space character. On return,
- ; carry set indicates EOL was encountered; carry clear indicates it was not.
- ;****************************************************************************
-
- findchar proc near
- lodsb ;Get the next character
- cmp al,09h ;Loop if tab
- je findchar
- cmp al,20h ;Loop if space
- je findchar
- cmp al,2Ch ;Loop if comma
- je findchar
- dec si ;Point SI to the character
- cmp al,0Dh ;Exit with carry set if end
- je eol ;of line is reached
-
- clc ;Clear carry and exit
- ret
-
- eol: stc ;Set carry and exit
- ret
- findchar endp
-
- ;****************************************************************************
- ; FINDDELIM advances SI to the next white-space character. On return,
- ; carry set indicates EOL was encountered.
- ;****************************************************************************
-
- finddelim proc near
- lodsb ;Get the next character
- cmp al,09h ;Exit if tab
- je fd_exit
- cmp al,20h ;Exit if space
- je fd_exit
- cmp al,2Ch ;Exit if comma
- je fd_exit
- cmp al,0Dh ;Loop back for more if end
- jne finddelim ;of line isn't reached
-
- dec si ;Set carry and exit
- stc
- ret
-
- fd_exit: dec si ;Clear carry and exit
- clc
- ret
- finddelim endp
-
- code ends
- end begin
-