www.pudn.com > bootany.zip > BSTRAP.ASM


        page    61,132 
        title   Bstrap - update fixed disk bootstrap 
        subttl  Code 
        page    + 
Code    segment 
        assume  cs:Code, ds:Code, es:Code, ss:Code 
        org     80h 
parmLen db      ? 
parm    db      ? 
        org     100h 
        include bootany.inc 
Bstrap  proc    far 
        mov     SI,DS                           ; Get data segment 
        mov     ES,SI                           ; Make sure the same 
; 
;       Read current bootstrap record 
; 
        mov     AX,201h                         ; read 1 sector 
        lea     BX,Boot                         ; buffer address 
        mov     CX,1                            ; cyl 0, sector 1 
        mov     DX,80h                          ; head 0, drive 0 
        int     13h                             ; read fixed disk boot 
        jnc     ReadOk                          ; Go on if ok 
        mov     bx,2                            ; write to stderr 
        mov     cx,Err1l                        ; length of message 
        lea     dx,Err1                         ; message address 
        mov     ah,40h                          ; write to stream 
        int     21h                             ; send message 
        jmp     Exit                            ; Exit program 
ReadOk: 
; 
;       Read in file named as parm (boot program) 
;       First find the program name 
; 
        sub     CX,CX                           ; clear register 
        sub     SI,SI                           ; clear register 
        mov     CL,parmLen                      ; Get length of parm 
        cmp     CL,0                            ; Better be there 
        jbe     NameError                       ; its not 
        lea     DI,parm                         ; get name address 
        mov     AL,' '                          ; what we will ignore 
        repe scasb 
        jcxz    NameError                       ; No parm - write msg 
        jmp     NameThere                       ; it is 
NameError: 
        mov     bx,2                            ; write to stderr 
        mov     cx,NameErrl                     ; length of message 
        lea     dx,NameErr                      ; message address 
        mov     ah,40h                          ; write to stream 
        int     21h                             ; send message 
        jmp     Exit 
; 
;       Found the name - Open and Read the file 
; 
NameThere: 
        dec     DI                              ; Point to first byte 
        inc     CX                              ; Correct the count 
        mov     BX,CX                           ; get bytes left 
        mov     [BX+DI],BYTE PTR 0              ; move in terminator 
        mov     DX,DI                           ; Get file name start 
        sub     AL,AL                           ; Open for read 
        mov     AH,3dh                          ; Open function 
        int     21h                             ; Call DOS 
        jc      FileError 
        lea     DX,Boot                         ; buffer address 
        mov     CX,PartAddr                     ; maximum boot length 
        mov     BX,AX                           ; read from file 
        mov     AH,3fh                          ; read from stream 
        int     21h                             ; dos service 
        jnc     FileOk                          ; continue if file ok 
FileError: 
        mov     AH,3Eh                          ; Close the file 
        int     21h                             ; dos service 
        mov     BX,2                            ; write to stderr 
        mov     CX,Err2l                        ; length of message 
        lea     DX,Err2                         ; message address 
        mov     AH,40h                          ; write to stream 
        int     21h                             ; send message 
        jmp     Exit                            ; Exit program 
; 
;       The new boot program is not in our "in-memory" copy of the 
;       boot sector 
; 
FileOk: 
; 
;       Close the file 
; 
        mov     AH,3Eh                          ; Close the file 
        int     21h                             ; dos service 
; 
;       Update the boot sector with User Data 
;       Put out first message 
; 
        mov     bx,2                            ; write to stderr 
        mov     cx,Msg1l                        ; length of message 
        lea     dx,Msg1                         ; message address 
        mov     ah,40h                          ; write to stream 
        int     21h                             ; send message 
 
        mov     CX,max_partitions               ; get loop count 
 
PartLoop: 
; 
;       Find out what partition this Function Key will be for 
; 
        mov     Index,CX                        ; Save index 
        sub     CL,max_partitions+1             ; get negative index 
        neg     CL                              ; turn positive 
        add     CL,Numeric                      ; make displayable 
        mov     Q1FKey,CL                       ; move into message 
        mov     Q2FKey,CL                       ; move into message 
        mov     Q3FKey,CL                       ; move into message 
        mov     AL,max_partitions               ; get max value 
        add     AL,Numeric                      ; make displayable 
        mov     Q1Max,AL                        ; move into message 
        mov     BX,2                            ; write to stderr 
        mov     CX,Q1l                          ; length of message 
        lea     DX,Q1                           ; message address 
        mov     AH,40h                          ; write to stream 
        int     21h                             ; send message 
        call    GetChar                         ; Get the number 
        cmp     AL,'0'                          ; See if '0' 
        jne     NoExit                          ; If not continue 
        jmp     TestNumLock                     ; Exit loop 
NoExit: 
        cmp     AL,'1'                          ; See if valid value 
        jl      PartError                       ; No - reprompt 
        cmp     AL,Numeric+max_partitions       ; Check max value 
        ja      PartError                       ; Too big - reprompt 
        mov     Q2Pnum,AL                       ; Save part number 
        mov     Err3P,AL                        ; Save part number 
        sub     AL,Numeric+1                    ; Turn into index 
        push    AX                              ; Save for later 
        mov     AH,SIZE PartData                ; Get entry size 
        mul     AH                              ; Get offset into table 
        mov     Data,AX                         ; Get data address 
        mov     BX,AX                           ; Get data address 
        pop     AX                              ; Restore value 
        mov     AH,SIZE PartitionEntry          ; Get entry size 
        mul     AH                              ; Get offset into table 
        mov     Entry,AX                        ; Get entry address 
        cmp     part.partition[BX],0            ; Already in use? 
        je      BootTest                        ; No - use it 
        mov     BX,2                            ; write to stderr 
        mov     CX,Err3l                        ; length of message 
        lea     DX,Err3                         ; message address 
        mov     AH,40h                          ; write to stream 
        int     21h                             ; send message 
PartError: 
        mov     CX,Index                        ; restore index 
        jmp     Partloop 
 
BootTest: 
;       Check to see if the partition is marked bootable - 
;       If not, see if it should be made bootable 
; 
        mov     BX,Entry                        ; Get Entry address 
        cmp     partitionTable.BootIndicator[BX],0 ; Can partition boot 
        jne     PartBoot                        ; Yes - use it 
        push    AX                              ; Save for later 
        mov     BX,2                            ; write to stderr 
        mov     CX,Q2l                          ; length of message 
        lea     DX,Q2                           ; message address 
        mov     AH,40h                          ; write to stream 
        int     21h                             ; send message 
        call    GetChar                         ; Get the number 
        pop     CX                              ; Restore value 
        and     AL,0DFh                         ; Convert to upper case 
        cmp     AL,'Y'                          ; See if 'Y' 
        je      MakeBoot                        ;  Make it bootable 
        cmp     AL,'N'                          ; See if 'N' 
        jne     BootTest                        ;  Bad reply 
        jmp     PartError                       ;  Don't make it boot 
MakeBoot: 
        mov     partitionTable.BootIndicator[BX],80h ; Turn on boot flag 
        mov     AX,CX                           ; Restore part # 
 
PartBoot: 
        mov     BX,Data                         ; Get table offset 
        mov     AL,Q2Pnum                       ; Get part number 
        sub     AL,Numeric                      ; Convert to binary 
        mov     part.partition[BX],AL           ; Save partition # 
 
PartBootLoop: 
; 
;       Get partitition description from user 
; 
        mov     BX,2                            ; write to stderr 
        mov     CX,Q3l                          ; length of message 
        lea     DX,Q3                           ; message address 
        mov     AH,40h                          ; write to stream 
        int     21h                             ; send message 
 
        mov     CX,part_text_len                ; set to text length 
        cld                                     ; copy forward 
        lea     DI,part.text                    ; Get base 
        add     DI,Data                         ; Add entry offset 
        mov     AL,' '                          ; Get data start 
        rep stosb                               ; Copy the data 
        lea     DX,TextBuffer                   ; get input area addr 
        mov     AH,10                           ; Buffered Input Code 
        int     21h                             ; Get data 
        sub     CX,CX                           ; Clear register 
        mov     CL,TextBuffer+1                 ; Get length entered 
        jcxz    PartBootLoop                    ; Reprompt if null 
        cld                                     ; copy forward 
        lea     DI,part.text                    ; Get base 
        add     DI,Data                         ; Add entry offset 
        lea     SI,TextBuffer+2                 ; Get data start 
        rep movsb                               ; Copy the data 
        mov     CX,Index                        ; Restore loop index 
        loop    NextPart                        ; Set up next partition 
        jmp     TestNumLock 
NextPart: 
        jmp     PartLoop 
; 
;       See if Num Lock should be turned off 
; 
TestNumLock: 
        mov     bx,2                            ; write to stderr 
        mov     cx,Q4l                          ; length of message 
        lea     dx,Q4                           ; message address 
        mov     ah,40h                          ; write to stream 
        int     21h                             ; send message 
        call    GetChar                         ; Get the number 
        and     AL,0DFh                         ; Convert to upper case 
        cmp     AL,'Y'                          ; See if 'Y' 
        je      ResetTable                      ;  Off is default 
        cmp     AL,'N'                          ; See if 'N' 
        jne     TestNumLock                     ;  Bad reply 
        mov     AL,NumLockOn                    ; Get NumLock on mask 
        mov     bootOpts.numlockMask,AL         ; Reset Mask 
; 
;       Swap the BootIndicator with the System Id to insure that there 
;       will be only one bootable partition at a time. 
; 
ResetTable: 
        mov     CX,max_partitions               ; Get number of parts 
        sub     BX,BX                           ; Clear index 
ResetTableLoop: 
        mov     AL,partitionTable.BootIndicator[BX] ; get indicator 
        cmp     AL,80h                          ; bootable partition? 
        jne     PartOk                          ; don't mess with it 
        mov     AL,partitionTable.SystemId[BX]  ; Get System ID 
        mov     partitionTable.BootIndicator[BX],AL ; Save here 
        mov     partitionTable.SystemId[BX],80h ; Make System ID inv. 
PartOk: 
        add     BX,SIZE PartitionEntry          ; Next Entry 
        loop    ResetTableLoop 
; 
;       Rewrite the boot record 
; 
        lea     BX,Boot                         ; buffer address 
        mov     CX,1                            ; cyl 0, sector 1 
        mov     DX,80h                          ; head 0, drive 0 
        mov     AX,301h                         ; write 1 sector 
        int     13h                             ; update boot record 
        jc      Exit                            ; exit if error 
; 
;       Write out message 
; 
        mov     BX,2                            ; write to stderr 
        mov     CX,Msgl                         ; length of message 
        lea     DX,Msg                          ; message address 
        mov     AH,40h                          ; write to stream 
        int     21h                             ; send message 
Exit: 
        int     20h                             ; exit program 
 
TextBuffer db   16,0 
        db      16 dup(0) 
 
Msg1    db      13,10,' may be used to end the install ' 
        db      'at any time',10 
Msg1l   equ     $-Msg1 
 
Q1      db      13,10,'What partition should be assigned to F' 
Q1Fkey  db      '#? (1-' 
Q1Max   db      '#, 0 to end) ' 
Q1l     equ     $-Q1 
 
Q2      db      13,10,'Partition ' 
Q2Pnum  db      '# is not bootable.',13,10 
        db      '      Reply Y to make it bootable, ' 
        db      'N to assign F' 
Q2Fkey  db      '# to a new partition. ' 
Q2l     equ     $-Q2 
 
Q3      db      13,10,'Enter partition description to be assigned to F' 
Q3Fkey  db      '# (15 chars max) ' 
Q3l     equ     $-Q3 
 
Q4      db      13,10,'Do you want Num Lock turned off at boot? ' 
        db      '(Y or N) ' 
Q4l     equ     $-Q4 
 
Err1    db      13,10,'Error Reading Boot Sector' 
Err1l   equ     $-Err1 
 
NameErr db      13,10,'Invalid file name for new boot program' 
NameErrl equ    $-NameErr 
 
Err2    db      13,10,'Error Reading New Boot Program' 
Err2l   equ     $-Err2 
 
Err3    db      13,10,'Partition ' 
Err3P   db      '# is already defined' 
Err3l   equ     $-Err3 
 
msg     db      13,10,'Boot record updated.',13,10 
msgl    equ     $-msg 
 
Index   dw     0 
Entry   dw     0 
Data    dw     0 
 
Boot           db      DataAddr dup(?) 
part           PartData max_partitions dup(<>) 
bootOpts       BootData <> 
partitionTable PartitionEntry 4 dup(<>) 
Validation     db      2 dup(0) 
 
Bstrap  endp 
 
GetChar proc    near 
        mov     AH,1                   ; Get keyboard input 
        int     21h 
        cmp     AL,0 
        jne     GetCharRet 
        mov     AH,1                   ; Get extended code 
        int     21h 
        sub     AL,AL                  ; show bad, not ASCII 
GetCharRet: 
        ret 
GetChar endp 
 
Code    ends 
        end     Bstrap