Metropoli BBS
VIEWER: cmosrstr.asm MODE: TEXT (ASCII)
;****************************************************************************
; CMOSRSTR restores the contents of CMOS RAM from a file. Its syntax is:
;
;       CMOSRSTR [d:][path]filename
;
; where "filename" is the name of the file from which CMOS data will be
; read. Use CMOSSAVE to save the contents of CMOS RAM to disk.
;****************************************************************************

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      "CMOSRSTR 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      "Restores the configuration data stored in CMOS RAM "
                db      "from a file.",13,10,13,10
                db      "CMOSRSTR [d:][path]filename",13,10,13,10
                db      "  filename  Name of the file from which "
                db      "configuration data will be read.",13,10,13,10
                db      "Use CMOSSAVE to save CMOS configuration data."
                db      13,10,"$"

signature       db      "CMOSSAVE"

errmsg1         db      "Syntax: CMOSRSTR [d:][path]filename",13,10,"$"
errmsg2         db      "Invalid path name or file not found",13,10,"$"
errmsg3         db      "Error reading file",13,10,"$"
errmsg4         db      "File does not contain valid CMOS data",13,10,"$"

msg             db      " bytes were copied from disk to CMOS RAM",13,10,"$"

handle          dw      ?                       ;File handle
cmoslength      dw      ?                       ;Number of bytes to restore

;****************************************************************************
; 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 and read the data file.
;
main1:          call    findchar                ;Advance to next character
                jnc     main2                   ;Branch if found

                mov     dx,offset errmsg1       ;Load error message address
error:          mov     ah,09h                  ;Display error message
                int     21h
                mov     ax,4C01h                ;Exit with ERRORLEVEL=1
                int     21h

main2:          mov     dx,si                   ;Convert the file name to
                call    finddelim               ;ASCIIZ format
                mov     byte ptr [si],0

                mov     ax,3D00h                ;Open the file
                int     21h
                mov     dx,offset errmsg2
                jc      error                   ;Branch if the call failed
                mov     handle,ax               ;Save the file handle

                mov     bx,ax                   ;Read the data from the file
                mov     ah,3Fh
                mov     cx,512
                mov     dx,offset scanhelp
                int     21h
                mov     dx,offset errmsg3
                jc      error                   ;Branch on error

                mov     cx,ax                   ;Save byte count
                mov     ah,3Eh                  ;Close the file
                mov     bx,handle
                int     21h

                mov     dx,offset errmsg4       ;Error if more than
                cmp     cx,73                   ;265 or fewer than 73
                jb      error                   ;bytes were read from
                cmp     cx,265                  ;the file
                ja      error
                sub     cx,9                    ;Compute CMOS length
                mov     cmoslength,cx           ;Save the result

                mov     cx,8                    ;Error if the file does
                mov     si,offset scanhelp      ;not contain a CMOSSAVE
                mov     di,offset signature     ;signature
                repe    cmpsb
                jne     error

                xor     al,al                   ;Error if the file does
                mov     cx,cmoslength           ;not contain a valid
                add     cx,8                    ;checksum
                mov     di,offset scanhelp
main2a:         add     al,[di]
                inc     di
                loop    main2a
                cmp     al,[di]
                jne     error
;
; Write the data from the file to CMOS RAM.
;
                cld                             ;Clear direction flag
                xor     cx,cx                   ;Initialize counter

main3:          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
                lodsb                           ;Get a byte of data
                out     CMOS_DATA,al            ;Write it to CMOS RAM
                sti                             ;Interrupts on
                inc     cx                      ;Increment counter
                cmp     cx,cmoslength           ;Loop if there are more
                jne     main3                   ;bytes to copy

                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
;
; Display message and exit.
;
                mov     ah,09h                  ;Display copyright message
                mov     dx,offset copyright
                int     21h

                mov     ax,cmoslength           ;Display the number of
                call    bin2asc                 ;bytes that were restored
                mov     ah,09h
                mov     dx,offset msg
                int     21h

                mov     ax,4C00h                ;Exit with ERRORLEVEL=0
                int     21h
main            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
[ RETURN TO DIRECTORY ]