Home | History | Annotate | Download | only in dosutil
      1 ; -*- fundamental -*- (asm-mode sucks)
      2 ; -----------------------------------------------------------------------
      3 ;
      4 ;   Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
      5 ;
      6 ;   This program is free software; you can redistribute it and/or modify
      7 ;   it under the terms of the GNU General Public License as published by
      8 ;   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
      9 ;   Boston MA 02111-1307, USA; either version 2 of the License, or
     10 ;   (at your option) any later version; incorporated herein by reference.
     11 ;
     12 ; -----------------------------------------------------------------------
     13 
     14 ;
     15 ; copybs.asm
     16 ;
     17 ; Small DOS program to copy the boot sector from a drive
     18 ; to a file
     19 ;
     20 ; Usage: copybs <drive>: <file>
     21 ;
     22 
     23 		absolute 0
     24 pspInt20:		resw 1
     25 pspNextParagraph:	resw 1
     26 			resb 1		; reserved
     27 pspDispatcher:		resb 5
     28 pspTerminateVector:	resd 1
     29 pspControlCVector:	resd 1
     30 pspCritErrorVector:	resd 1
     31 			resw 11		; reserved
     32 pspEnvironment:		resw 1
     33 			resw 23		; reserved
     34 pspFCB_1:		resb 16
     35 pspFCB_2:		resb 16
     36 			resd 1		; reserved
     37 pspCommandLen:		resb 1
     38 pspCommandArg:		resb 127
     39 
     40 		section .text
     41 		org 100h			; .COM format
     42 _start:
     43 		mov ax,3000h			; Get DOS version
     44 		int 21h
     45 		xchg al,ah
     46 		mov [DOSVersion],ax
     47 		cmp ax,0200h			; DOS 2.00 minimum
     48 		jae dosver_ok
     49 		mov dx,msg_ancient_err
     50 		jmp die
     51 
     52 		section .bss
     53 		alignb 2
     54 DOSVersion:	resw 1
     55 
     56 		section .text
     57 ;
     58 ; Scan command line for a drive letter followed by a colon
     59 ;
     60 dosver_ok:
     61 		xor cx,cx
     62 		mov si,pspCommandArg
     63 		mov cl,[pspCommandLen]
     64 
     65 cmdscan1:	jcxz bad_usage			; End of command line?
     66 		lodsb				; Load character
     67 		dec cx
     68 		cmp al,' '			; White space
     69 		jbe cmdscan1
     70 		or al,020h			; -> lower case
     71 		cmp al,'a'			; Check for letter
     72 		jb bad_usage
     73 		cmp al,'z'
     74 		ja bad_usage
     75 		sub al,'a'			; Convert to zero-based index
     76 		mov [DriveNo],al		; Save away drive index
     77 
     78 		section .bss
     79 DriveNo:	resb 1
     80 
     81 		section .text
     82 ;
     83 ; Got the leading letter, now the next character must be a colon
     84 ;
     85 got_letter:	jcxz bad_usage
     86 		lodsb
     87 		dec cx
     88 		cmp al,':'
     89 		jne bad_usage
     90 ;
     91 ; Got the colon; now we should have at least one whitespace
     92 ; followed by a filename
     93 ;
     94 got_colon:	jcxz bad_usage
     95 		lodsb
     96 		dec cx
     97 		cmp al,' '
     98 		ja bad_usage
     99 
    100 skipspace:	jcxz bad_usage
    101 		lodsb
    102 		dec cx
    103 		cmp al,' '
    104 		jbe skipspace
    105 
    106 		mov di,FileName
    107 copyfile:	stosb
    108 		jcxz got_cmdline
    109 		lodsb
    110 		dec cx
    111 		cmp al,' '
    112 		ja copyfile
    113 		jmp short got_cmdline
    114 
    115 ;
    116 ; We end up here if the command line doesn't parse
    117 ;
    118 bad_usage:	mov dx,msg_unfair
    119 		jmp die
    120 
    121 		section .data
    122 msg_unfair:	db 'Usage: copybs <drive>: <filename>', 0Dh, 0Ah, '$'
    123 
    124 		section .bss
    125 		alignb 4
    126 FileName	resb 256
    127 
    128 ;
    129 ; Parsed the command line OK.  Get device parameter block to get the
    130 ; sector size.
    131 ;
    132 		struc DPB
    133 dpbDrive:	resb 1
    134 dpbUnit:	resb 1
    135 dpbSectorSize:	resw 1
    136 dpbClusterMask:	resb 1
    137 dpbClusterShift: resb 1
    138 dpbFirstFAT:	resw 1
    139 dpbFATCount:	resb 1
    140 dpbRootEntries:	resw 1
    141 dpbFirstSector:	resw 1
    142 dpbMaxCluster:	resw 1
    143 dpbFATSize:	resw 1
    144 dpbDirSector:	resw 1
    145 dpbDriverAddr:	resd 1
    146 dpbMedia:	resb 1
    147 dpbFirstAccess:	resb 1
    148 dpbNextDPB:	resd 1
    149 dpbNextFree:	resw 1
    150 dpbFreeCnt:	resw 1
    151 		endstruc
    152 
    153 		section .bss
    154 		alignb 2
    155 SectorSize	resw 1
    156 
    157 		section .text
    158 got_cmdline:
    159 		xor al,al			; Zero-terminate filename
    160 		stosb
    161 
    162 		mov dl,[DriveNo]
    163 		inc dl				; 1-based
    164 		mov ah,32h
    165 		int 21h				; Get Drive Parameter Block
    166 
    167 		and al,al
    168 		jnz filesystem_error
    169 
    170 		mov dx,[bx+dpbSectorSize]	; Save sector size
    171 ;
    172 ; Read the boot sector.
    173 ;
    174 		section .data
    175 		align 4, db 0
    176 DISKIO		equ $
    177 diStartSector:	dd 0				; Absolute sector 0
    178 diSectors:	dw 1				; One sector
    179 diBuffer:	dw SectorBuffer			; Buffer offset
    180 		dw 0				; Buffer segment
    181 
    182 		section .text
    183 read_bootsect:
    184 		mov ax,cs			; Set DS <- CS
    185 		mov ds,ax
    186 
    187 		mov [SectorSize],dx		; Saved sector size from above
    188 
    189 		cmp word [DOSVersion],0400h	; DOS 4.00 has a new interface
    190 		jae .new
    191 .old:
    192 		mov bx,SectorBuffer
    193 		mov cx,1			; One sector
    194 		jmp short .common
    195 .new:
    196 		mov [diBuffer+2],ax		; == DS
    197 		mov bx,DISKIO
    198 		mov cx,-1
    199 .common:
    200 		xor dx,dx			; Absolute sector 0
    201 		mov al,[DriveNo]
    202 		int 25h				; DOS absolute disk read
    203 		pop ax				; Remove flags from stack
    204 		jc disk_read_error
    205 
    206 ;
    207 ; Open the file and write the boot sector to the file.
    208 ;
    209 		mov dx,FileName
    210 		mov cx,0020h			; Attribute = ARCHIVE
    211 		mov ah,3Ch			; Create file
    212 		int 21h
    213 		jc file_write_error
    214 
    215 		mov bx,ax
    216 		push ax				; Handle
    217 
    218 		mov cx,[SectorSize]
    219 		mov dx,SectorBuffer
    220 		mov ah,40h			; Write file
    221 		int 21h
    222 		jc file_write_error
    223 		cmp ax,[SectorSize]
    224 		jne file_write_error
    225 
    226 		pop bx				; Handle
    227 		mov ah,3Eh			; Close file
    228 		int 21h
    229 		jc file_write_error
    230 ;
    231 ; We're done!
    232 ;
    233 		mov ax,4C00h			; exit(0)
    234 		int 21h
    235 
    236 ;
    237 ; Error routine jump
    238 ;
    239 filesystem_error:
    240 		mov dx,msg_filesystem_err
    241 		jmp short die
    242 disk_read_error:
    243 		mov dx,msg_read_err
    244 		jmp short die
    245 file_write_error:
    246 		mov dx,msg_write_err
    247 die:
    248 		push cs
    249 		pop ds
    250 		push dx
    251 		mov dx,msg_error
    252 		mov ah,09h
    253 		int 21h
    254 		pop dx
    255 
    256 		mov ah,09h			; Write string
    257 		int 21h
    258 
    259 		mov ax,4C01h			; Exit error status
    260 		int 21h
    261 
    262 		section .data
    263 msg_error:		db 'ERROR: $'
    264 msg_ancient_err:	db 'DOS version 2.00 or later required', 0Dh, 0Ah, '$'
    265 msg_filesystem_err:	db 'Filesystem not found on disk', 0Dh, 0Ah, '$'
    266 msg_read_err:		db 'Boot sector read failed', 0Dh, 0Ah, '$'
    267 msg_write_err:		db 'File write failed', 0Dh, 0Ah, '$'
    268 
    269 		section .bss
    270 		alignb 4
    271 SectorBuffer:	resb 4096
    272