home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / BOOT2C.ZIP / BOOT2C.ASM next >
Assembly Source File  |  1993-03-02  |  17KB  |  611 lines

  1.         page    66,132
  2. ;====================================================================
  3. ;
  4. ; BOOT2C - A program to force a floppy in A: to boot the C: drive
  5. ;
  6. ; Copyright (c) 1993 Douglas Boling
  7. ;
  8. ;====================================================================
  9.         code    segment
  10.         assume    cs:code
  11.  
  12.         org    100h
  13. ;====================================================================
  14. ;BOOT2C Boot record
  15. ; Entry:     
  16. ;   CS:IP - 0:7C00h
  17. ;      DL - boot drive
  18. ;   ES:SI - Ptr to partition table boot entry (if hard disk.)
  19. ;   All other registers undefined
  20. ;====================================================================
  21.  
  22. bytes_per_sec   equ     word ptr [bp+0bh]
  23. sec_per_cluster equ     byte ptr [bp+0dh]
  24. reserved_sec    equ     word ptr [bp+0eh]
  25. number_of_fats  equ     byte ptr [bp+10h]
  26. root_size       equ     word ptr [bp+11h]
  27. total_sec       equ     word ptr [bp+13h]
  28. media_des_byte  equ     byte ptr [bp+15h]
  29. sec_per_fat     equ     word ptr [bp+16h]
  30. sec_per_track   equ     word ptr [bp+18h]
  31. number_of_heads equ     word ptr [bp+1ah]
  32. num_hidden_sec  equ     word ptr [bp+1ch]
  33. total_sec_long  equ     word ptr [bp+20h]
  34. drive_number       equ     word ptr [bp+24h]
  35. reserved        equ     word ptr [bp+25h]
  36. extended_flag   equ     word ptr [bp+26h]
  37. vol_serial      equ     word ptr [bp+27h]
  38. vol_name        equ     word ptr [bp+2bh]
  39. boot_flag    equ    word ptr [bp+3feh]    ;Offset + 512 needed for code
  40.  
  41. boot_disk       equ     byte ptr [bp + offset boot_disko - offset entry]
  42. reloc_entry    equ    offset boot_2 - offset entry
  43. boot_initmsg    equ    7a00h + offset program - offset entry
  44. boot_chgmsg    equ    7a00h + offset change_msg - offset entry
  45. boot_errmsg     equ    7a00h + offset error_msg - offset entry
  46. boot_rerrmsg    equ     7a00h + offset readerr_msg - offset entry
  47.  
  48. ;--------------------------------------------------------------------
  49. ;Boot sector code
  50. ;--------------------------------------------------------------------
  51. entry:        jmp    initialize
  52. boot_data    db    64 dup (0)        ;Leave room for BPB
  53. boot_dataend    =    $
  54.  
  55. boot_disko    db    80h            ;Disk to boot
  56.  
  57. boot_1:
  58.             cli                ;Disable interrupts
  59.             cld                             ;Set direction UP.
  60.             mov     ax,7a00h
  61.             xor     bx,bx
  62.             mov     ss,bx                   ;SS:SP = 0:7A00
  63.             mov     sp,ax
  64.             sti                ;Interrupts OK
  65.         push    si            ;Save Part table ptr
  66.         push    bp
  67.         mov    bp,ax
  68.  
  69.             mov     ds,bx                   ;DS = 0
  70.             mov     es,bx                   ;ES = 0
  71.             mov     di,ax              ;Move boot code 
  72.         mov    si,7c00h
  73.             mov     cx,100h
  74.             rep     movsw
  75.  
  76.             push    es            ;Push re-entry segment
  77.             mov     al,reloc_entry        ;  and offset on the
  78.             push    ax            ;  stack
  79.             retf                ;Return Far to jump
  80. boot_2:
  81.         mov    si,boot_initmsg        ;Announce we are here
  82.         call    bprint_msg
  83.         xor    ax,ax            ;Read boot sector
  84.         cwd
  85.         mov    bx,7c00h        ;To address 0:7C00
  86.         call    boot_read_disk
  87.         jc    boot_error1
  88.         cmp    boot_flag,0AA55h    ;Check for boot sig
  89.         jne    boot_error
  90.         mov    si,boot_chgmsg        ;Tell user about 
  91.         call    bprint_msg        ;  switch
  92.         pop    bp            ;Restore BP for 
  93.         pop    si            ;  stupid DR-DOS bug
  94.         jmp    bx            ;Jump to new boot rec
  95. boot_error:
  96.         mov    si,boot_errmsg        ;Print err message
  97. boot_error1:
  98.         call    bprint_msg
  99. boot_halt:
  100.         jmp    boot_halt        ;STOP!
  101.  
  102. ;-----------------------------------------------------------------------
  103. ; Read disk - Reads one sector from the disk
  104. ; Entry: DX,AX - Absolute sector to read
  105. ;        BX - address of buffer.
  106. ; Exit:  CF - Clear if read successful.
  107. ;-----------------------------------------------------------------------
  108. boot_read_disk    proc    near
  109.             push    bx
  110.         div    sec_per_track        ;Get sectors per track
  111.             inc     dx
  112. read_2:
  113.         mov    bx,dx            ;Save sector
  114.             cwd
  115.             div     number_of_heads         ;Compute head and cylinder
  116.             xchg    ah,al                   ;Swap cyl low and high bytes
  117.             mov     cl,6
  118.             shl     al,cl                   ;Shift high cyl bits
  119.             xchg    cx,ax                   ;Copy cyl into CX
  120.             or      cl,bl                   ;Combine cyl with sector
  121.             mov     dh,dl                   ;Move head number
  122.             mov     si,5                    ;Try to read 5 times.
  123.             pop     bx
  124. read_3:
  125.             mov     dl,boot_disk            ;Get disk to read
  126.         mov    ax,0201h        ;Read 1 sector
  127.             int     13h                     ;Read/Write disk.
  128.             jnc     read_exit               ;No error, exit
  129.             xor     ax,ax                   ;Reset disk before reading
  130.             int     13h
  131.         dec    si
  132.         jnz    read_3
  133.             mov     si,boot_rerrmsg        ;Read error message
  134.         stc
  135. read_exit:
  136.             ret
  137. boot_read_disk    endp
  138.  
  139. ;--------------------------------------------------------------------
  140. ; Print Msg - Prints a message to the screen
  141. ; Entry: DS:SI - Points to ASCIIZ message
  142. ;--------------------------------------------------------------------
  143. bprint_msg    proc    near
  144.         push    bx
  145.         push    bp
  146. bprint_msg1:
  147.         lodsb
  148.         or    al,al
  149.         je    bprint_exit
  150.         mov    ah,0eh
  151.         mov    bx,7h
  152.         push    si
  153.         int    10h
  154.         pop    si
  155.         jmp    short bprint_msg1
  156. bprint_exit:
  157.         mov    ax,0e0dh        ;Append CR - LF
  158.         int    10h
  159.         mov    ax,0e0ah
  160.         int    10h
  161.         pop    bp
  162.         pop    bx
  163.         ret
  164. bprint_msg    endp
  165. program      db    13,10,"BOOT2C 1.0 Copyright 1993 Douglas Boling"
  166.                 db      13,10,"First published in PC Magazine, " 
  167.         db    "March 30, 1993",13,10,0
  168. change_msg    db    "Redirecting boot to "
  169. change_dest    db    13 dup (0)
  170. error_msg    db    "Error: Target disk not bootable"
  171.         db    13,10,"System halted",0
  172. readerr_msg    db    "Error: reading target drive"
  173.         db    13,10,"System halted",0
  174. bootcode_end    =    $
  175.         org    2feh
  176.         dw    0AA55h            ;Boot signature
  177. boot_end    =    $
  178. ;====================================================================
  179. ;Start of nonresident install code
  180. ;====================================================================
  181. infomsg1    db    "USAGE: BOOT2C x: [nn]",13,10
  182.         db    "x: is the target diskette to "
  183.         db    "modify",13,10
  184.         db    "nn is the disk number that the boot is "
  185.         db    "redirected to.",0
  186.         
  187.  
  188. infomsg2     db    "Boot2C installed on "
  189. msg2_drive    db    "A:",13,10,"Boot will be redirected to ",0
  190. msg2_hard     db    "hard disk ",0
  191. msg2_floppy    db    "diskette ",0
  192.  
  193. errmsg1        db    "Drives not specified",0
  194. errmsg2      db    "Target diskette not a DOS formatted "
  195.         db    "disk",0
  196. errmsg3     db    "Unable to fit BOOT2C code on "
  197.         db    "target disk",0
  198. errmsg4        db    "Illegal redirection disk number",0
  199.  
  200. targ_disk    db    0h            ;Disk to modify
  201.  
  202. doserr_tbl    dw    offset    doserr_00
  203.          dw    offset    doserr_01
  204.         dw    offset    doserr_02
  205.         dw    offset    doserr_03
  206.         dw    offset    doserr_04
  207.         dw    offset    doserr_05
  208.         dw    offset    doserr_06
  209.         dw    offset    doserr_07
  210.         dw    offset    doserr_08
  211.         dw    offset    doserr_09
  212.         dw    offset    doserr_10
  213.         dw    offset    doserr_11
  214.         dw    offset    doserr_12
  215.         dw    offset    doserr_unk
  216. doserr_tblend    =    $
  217.  
  218. doserr_00    db    "Disk Write Protected",0
  219. doserr_01    db    "Unknown Unit",0
  220. doserr_02    db    "Drive not ready",0
  221. doserr_03    db    "Unknown Command",0
  222. doserr_04    db    "CRC Data Error",0
  223. doserr_05    db    "Bad request structure",0
  224. doserr_06    db    "Disk Seek error",0
  225. doserr_07    db    "Not a DOS disk",0
  226. doserr_08    db    "Sector not found",0
  227. doserr_09    db    "Printer out of paper",0
  228. doserr_10    db    "Disk Write fault",0
  229. doserr_11    db    "Disk Read fault",0
  230. doserr_12    db    "General failure",0
  231. doserr_unk    db    "Unknown DOS error",0
  232.  
  233. ;--------------------------------------------------------------------
  234. ; INITIALIZE - Entry point of nonresident code
  235. ;--------------------------------------------------------------------
  236. initialize:
  237.         cld                ;String ops UP
  238.         mov    si,offset program    ;Print copyright msg
  239.         call    print_msg
  240.  
  241.         mov    si,offset infomsg1         ;Syntax msg text
  242.         cmp    byte ptr ds:[80h],0    ;See if any command line
  243.         je    init_1            ;  exists
  244.         
  245.         mov    si,81h            ;Point to cmd line
  246.         call    findnextchar        ;Get first character
  247.         jnc    init_2
  248. init_1:        
  249.         mov    si,offset errmsg1    ;Syntax error message
  250.         jmp    init_error
  251. init_numerr:
  252.         mov    si,offset errmsg4
  253.         jmp    init_error
  254. init_2:
  255.         and    al,0dfh            ;Add drive letter to msg
  256.         mov    msg2_drive,al        ;  text.
  257.         or    al,20h            ;Convert to lower case
  258.         sub    al,'a'            ;See if between a - z
  259.         jb    init_1
  260.         cmp    al,25
  261.         ja    init_1
  262.         mov    ah,al
  263.         lodsb                ;See if trailing :
  264.         cmp    al,':'            ;  present.
  265.         jne    init_1
  266.         mov    targ_disk,ah
  267.  
  268.         call    findnextchar        ;Find next char on line
  269.         jc    init_4
  270.  
  271.         call    make_num        ;Convert to number
  272.         jc    init_numerr
  273.         xor    ah,ah
  274.         cmp    byte ptr [si],' '    ;Check for end of num
  275.         jbe    init_3
  276.         mov    ah,al
  277.         lodsb
  278.         call    make_num        ;Convert to number
  279.         jc    init_numerr
  280.         cmp    byte ptr [si],' '    ;Check for end of num
  281.                 ja    init_numerr
  282.  
  283.         cmp    ah,8               ;Only allow 2 digits
  284.         jne    init_numerr        ;  if 1st indicates
  285.         mov    ah,80h            ;  hard drive.
  286. init_3:
  287.         or    al,ah
  288.         mov    boot_disko,al        ;Save dest boot disk num
  289. init_4:
  290.         mov    al,boot_disko        ;Get dest boot disk num
  291.         mov    di,offset change_dest
  292.         mov    si,offset msg2_floppy
  293.         test    al,80h
  294.         je    init_5
  295.         mov    si,offset msg2_hard
  296. init_5:
  297.         lodsb                ;Copy destination disk msg
  298.         or    al,al            ;  to boot record.
  299.         je    init_6
  300.         stosb
  301.         jmp    short init_5
  302. init_6:
  303.         mov    ah,boot_disko        ;Get redir disk number, convert
  304.         and    ah,0fh            ;  to ASCII and print
  305.         je    init_8
  306.         inc    ah
  307.         mov    al,' '
  308.         add    ah,'0'
  309.         cmp    ah,'9'
  310.         jbe    init_7
  311.         mov    ax,3031h        ;Force 10 as digit
  312. init_7:
  313.         mov    [di],ax
  314. init_8:
  315.         call    install            ;Install Boot2C
  316.         jc    init_error
  317.  
  318.         mov    si,offset infomsg2    ;Print installed msg
  319.         call    print_line
  320.         mov    si,offset change_dest    ;Print destination
  321.         call    print_msg
  322.         xor    ax,ax
  323. init_exit:
  324.         mov    ah,4ch            ;Terminate program
  325.         int    21h
  326. init_error:
  327.         call    print_msg        ;Print error message
  328.         mov    al,1
  329.         jmp    short init_exit
  330.  
  331. ;--------------------------------------------------------------------
  332. ;FINDNEXTCHAR - Finds the next character on the command line
  333. ; Entry: SI - Ptr to command line
  334. ; Exit:  AL - Character
  335. ;        SI - Points to next char
  336. ;        CF - Set if end of line found
  337. ;--------------------------------------------------------------------
  338. findnextchar    proc    near
  339.         lodsb
  340.         cmp    al,13            ;See if end of line
  341.         je    fnchar_err
  342.         cmp    al,20h            ;If space, keep looking
  343.         jbe    findnextchar
  344.         clc
  345. fnchar_exit:
  346.         ret
  347. fnchar_err:
  348.         stc
  349.         jmp    short fnchar_exit
  350. findnextchar    endp
  351.  
  352. ;--------------------------------------------------------------------
  353. ;MAKE NUM - Converts and ASCII digit to a decimal digit
  354. ; Entry: AL - ASCII digit
  355. ; Exit:  AL - decimal digit
  356. ;        CF - Set if invalid number
  357. ;--------------------------------------------------------------------
  358. make_num    proc    near
  359.         sub    al,'0'
  360.         jb    makenum_error
  361.         cmp    al,9
  362.         ja    makenum_error
  363.         clc
  364. makenum_exit:
  365.         ret
  366. makenum_error:
  367.         stc
  368.         jmp    short makenum_exit
  369. make_num    endp
  370.  
  371. ;--------------------------------------------------------------------
  372. ;INSTALL - Installs the BOOT2C boot record on the target diskette
  373. ; Exit:  CF - Set if error
  374. ;        DX - Offset of error message if CF set
  375. ;--------------------------------------------------------------------
  376. install        proc    near
  377.         mov    di,offset entry
  378.         mov    al,0e9h            ;JMP short opcode
  379.         stosb
  380.         mov    ax,offset boot_1 - offset boot_data
  381.         stosw
  382.         mov    al,targ_disk        ;Get target disk
  383.         mov     cx,1            ;read 1 sector
  384.         xor    dx,dx            ;Sector 0
  385.         mov    si,dx
  386.         mov    bx,offset end_of_code
  387.         call    read_absolute        ;Read current boot rec
  388.         jc    install_error
  389.  
  390.         mov    si,bx            ;Copy ptr to boot rec
  391.         lodsb
  392.         mov    dl,al            ;Get opcode
  393.         lodsw
  394.         mov    bx,si
  395.         cmp    dl,0ebh            ;See if short JMP opcode
  396.         jne    install_1
  397.                     
  398.         xor    ah,ah            ;If short JMP, clear 
  399.         jmp    install_2        ;  high byte
  400. install_1:
  401.         mov    si,offset errmsg2
  402.         cmp    dl,0e9h            ;Check for long JMP
  403.         jne    install_error
  404. install_2:
  405.         mov    si,offset errmsg3
  406.         dec    ax
  407.         cmp    ax,offset boot_dataend - offset entry 
  408.         ja    install_error
  409.         mov    si,bx
  410.         mov    di,offset boot_data    ;Copy boot data to 
  411.         mov    cx,ax            ;  BOOT2C boot rec
  412.         rep    movsb
  413.  
  414.         mov    al,targ_disk        ;Get target disk
  415.         mov    bx,offset entry
  416.         mov     cx,1            ;read 1 sector
  417.         xor    dx,dx            ;Sector 0
  418.         xor    si,si
  419.         call    write_absolute        ;Write new boot rec
  420. install_exit:
  421.         ret
  422. install_error:
  423.         stc
  424.         jmp    short install_exit
  425. install        endp
  426.  
  427. ;--------------------------------------------------------------------
  428. ; READ ABSOLUTE - Reads sectors from the disk.
  429. ; Entry:   AL - Drive to read
  430. ;          CX - Number of sectors to read.  
  431. ;       SI,DX - Sector to start read (SI only used on huge disks)
  432. ;       DS:BX - Pointer to data buffer. 
  433. ;--------------------------------------------------------------------
  434. read_abs_hstruc    =    $            ;Needed for >32M disks
  435. read_abs_start    dd    0            ;Starting sector
  436. read_abs_cnt    dw    0            ;Number of sectors to read
  437. read_abs_dbp    dd    0            ;Data buffer ptr
  438.  
  439. read_absolute   proc    near
  440.         push    bx
  441.         push    cx
  442.         push    ds
  443.         call    huge_disk_check
  444.         jc    read_abs_2
  445.         je    read_abs_1
  446.         push    ds            ;Save ptr to data buffer
  447.         push    bx
  448.         push    cs
  449.         pop    ds
  450.         mov    bx,offset read_abs_hstruc
  451.         mov    [bx],dx            ;More than 64K sectors
  452.         mov    [bx+2],si        ;  -> huge disk uses a
  453.         mov    [bx+4],cx        ;  different format
  454.         pop    [bx+6]            ;  than std int 25h.    
  455.         pop    [bx+8]
  456.         mov    cx,-1
  457. read_abs_1:
  458.             int     25h                     ;DOS Absolute Disk Read
  459.             pop     bx                      ;Clean off old flags
  460.         call    seterrmsg
  461.             cld
  462. read_abs_2:
  463.         pop    ds
  464.         pop    cx
  465.         pop    bx
  466.             ret
  467. read_absolute   endp
  468.  
  469. ;--------------------------------------------------------------------
  470. ; WRITE ABSOLUTE - Writes sectors to the disk.
  471. ; Entry:   AL - Drive to write
  472. ;          CX - Number of sectors to write  
  473. ;       SI,DX - Sector to start write (SI only used on huge disks)
  474. ;       DS:BX - Pointer to data buffer. 
  475. ;--------------------------------------------------------------------
  476. write_absolute  proc    near
  477.         push    bx
  478.         push    cx
  479.         push    ds
  480.         call    huge_disk_check
  481.         jc    write_abs_2    
  482.         je    write_abs_1
  483.         push    ds            ;Save data buffer pointer
  484.         push    bx
  485.         push    cs
  486.         pop    ds
  487.         mov    bx,offset read_abs_hstruc
  488.         mov    [bx],dx            ;More than 64K sectors
  489.         mov    [bx+2],si        ;  -> huge disk uses a
  490.         mov    [bx+4],cx        ;  different format
  491.         pop    [bx+6]            ;  than std int 26h.    
  492.         pop    [bx+8]
  493.         mov    cx,-1                
  494. write_abs_1:
  495.             int     26h                     ;DOS Absolute Disk Write
  496.             pop     bx                      ;Clean off old flags
  497.         call    seterrmsg
  498.             cld
  499. write_abs_2:
  500.         pop    ds
  501.         pop    cx
  502.         pop    bx
  503.             ret
  504. write_absolute  endp
  505.  
  506. ;--------------------------------------------------------------------
  507. ; HUGE DISK CHECK - Checks if disk is greater than 32 Meg
  508. ; Entry: AL - Disk to check
  509. ; Exit:  ZF - Clear if > 32 Meg disk
  510. ;        CF - Set if error
  511. ;        DI - Sectors per cluster
  512. ;--------------------------------------------------------------------
  513. last_disk_read    db    -1
  514. last_disk_huge    db    0
  515. last_disk_spc     dw    0
  516. huge_disk_check    proc    near
  517.         push    ax
  518.         push    bx
  519.         push    cx
  520.         push    dx
  521.         cmp    al,last_disk_read    ;Save last disk checked, if
  522.         jne    huge_disk_check_1    ;  same as last disk, just
  523.         mov    di,last_disk_spc    ;  get saved answer.
  524.         cmp    last_disk_huge,0    
  525.         jmp    short huge_disk_check_3
  526. huge_disk_check_1:
  527.         mov    last_disk_read,al
  528.         mov    last_disk_huge,0
  529.         mov    dl,al            ;Copy disk number
  530.         mov    ah,36h            ;DOS Get Free disk space
  531.         inc    dl
  532.         int    21h        
  533.         cmp    ax,-1
  534.         jne    huge_disk_check_2
  535.         mov    last_disk_read,-1
  536.         stc
  537.         jmp    short huge_disk_check_4
  538. huge_disk_check_2:
  539.         mov    di,ax            ;Save sectors per cluster
  540.         mov    last_disk_spc,di
  541.         mul    dx
  542.         or    dx,dx            ;See if more than 64K sectors
  543.         je    huge_disk_check_3
  544.         mov    last_disk_huge,1
  545. huge_disk_check_3:
  546.         clc
  547. huge_disk_check_4:
  548.         pop    dx
  549.         pop    cx
  550.         pop    bx
  551.         pop    ax
  552.         ret
  553. huge_disk_check    endp
  554.  
  555. ;--------------------------------------------------------------------
  556. ; SETERRMSG - Assigns a DOS error message to the value in AL
  557. ; Entry: AL - Error code
  558. ;        CF - Set if error
  559. ; Exit:  SI - Points to error message
  560. ;--------------------------------------------------------------------
  561. seterrmsg    proc    near
  562.         push    bx
  563.         pushf
  564.         jnc    seterrmsg_exit
  565.         mov    bx,ax
  566.         xor    bh,bh
  567.         shl    bx,1
  568.         cmp    bx,offset doserr_tblend - offset doserr_tbl
  569.         jbe    seterrmsg_1
  570.         mov    bx,26
  571. seterrmsg_1:
  572.         mov    si,[bx+doserr_tbl]
  573. seterrmsg_exit:
  574.         popf
  575.         pop    bx
  576.         ret
  577. seterrmsg    endp
  578.  
  579. ;--------------------------------------------------------------------
  580. ; Print Msg - Prints a message to the screen
  581. ; Entry: DS:SI - Points to ASCIIZ message
  582. ;--------------------------------------------------------------------
  583. crlf_msg    db    13,10,0
  584. print_msg    proc    near
  585.         call    print_line
  586.         mov    si,offset crlf_msg
  587.         call    print_line
  588.         ret
  589. print_msg    endp
  590.  
  591. ;--------------------------------------------------------------------
  592. ; Print Line - Prints a line to the screen
  593. ; Entry: DS:SI - Points to ASCIIZ message
  594. ;--------------------------------------------------------------------
  595. print_line    proc    near
  596.         lodsb
  597.         or    al,al
  598.         je    print_lineexit
  599.         mov    dl,al
  600.         mov    ah,02
  601.         int    21h
  602.         jmp    short print_line
  603. print_lineexit:
  604.         ret
  605. print_line    endp
  606.  
  607.         even    
  608. end_of_code    =    $
  609. code        ends
  610. end        entry
  611.