1 ; -*- fundamental -*- (asm-mode sucks)
2 ; $Id: copybs.asm,v 1.4 2004/12/14 23:03:28 hpa Exp $
3 ; -----------------------------------------------------------------------
5 ; Copyright 1998-2004 H. Peter Anvin - All Rights Reserved
7 ; This program is free software; you can redistribute it and/or modify
8 ; it under the terms of the GNU General Public License as published by
9 ; the Free Software Foundation, Inc., 53 Temple Place Ste 330,
10 ; Boston MA 02111-1307, USA; either version 2 of the License, or
11 ; (at your option) any later version; incorporated herein by reference.
13 ; -----------------------------------------------------------------------
18 ; Small DOS program to copy the boot sector from a drive
21 ; Usage: copybs <drive>: <file>
26 pspNextParagraph: resw 1
29 pspTerminateVector: resd 1
30 pspControlCVector: resd 1
31 pspCritErrorVector: resd 1
33 pspEnvironment: resw 1
39 pspCommandArg: resb 127
42 org 100h ; .COM format
44 mov ax,3000h ; Get DOS version
48 cmp ax,0200h ; DOS 2.00 minimum
50 mov dx,msg_ancient_err
59 ; Scan command line for a drive letter followed by a colon
64 mov cl,[pspCommandLen]
66 cmdscan1: jcxz bad_usage ; End of command line?
67 lodsb ; Load character
69 cmp al,' ' ; White space
71 or al,020h ; -> lower case
72 cmp al,'a' ; Check for letter
76 sub al,'a' ; Convert to zero-based index
77 mov [DriveNo],al ; Save away drive index
84 ; Got the leading letter, now the next character must be a colon
86 got_letter: jcxz bad_usage
92 ; Got the colon; now we should have at least one whitespace
93 ; followed by a filename
95 got_colon: jcxz bad_usage
101 skipspace: jcxz bad_usage
114 jmp short got_cmdline
117 ; We end up here if the command line doesn't parse
119 bad_usage: mov dx,msg_unfair
123 msg_unfair: db 'Usage: copybs <drive>: <filename>', 0Dh, 0Ah, '$'
130 ; Parsed the command line OK. Get device parameter block to get the
136 dpbSectorSize: resw 1
137 dpbClusterMask: resb 1
138 dpbClusterShift: resb 1
141 dpbRootEntries: resw 1
142 dpbFirstSector: resw 1
143 dpbMaxCluster: resw 1
146 dpbDriverAddr: resd 1
148 dpbFirstAccess: resb 1
160 xor al,al ; Zero-terminate filename
166 int 21h ; Get Drive Parameter Block
171 mov dx,[bx+dpbSectorSize] ; Save sector size
173 ; Read the boot sector.
178 diStartSector: dd 0 ; Absolute sector 0
179 diSectors: dw 1 ; One sector
180 diBuffer: dw SectorBuffer ; Buffer offset
181 dw 0 ; Buffer segment
185 mov ax,cs ; Set DS <- CS
188 mov [SectorSize],dx ; Saved sector size from above
190 cmp word [DOSVersion],0400h ; DOS 4.00 has a new interface
194 mov cx,1 ; One sector
197 mov [diBuffer+2],ax ; == DS
201 xor dx,dx ; Absolute sector 0
203 int 25h ; DOS absolute disk read
204 pop ax ; Remove flags from stack
208 ; Open the file and write the boot sector to the file.
211 mov cx,0020h ; Attribute = ARCHIVE
212 mov ah,3Ch ; Create file
221 mov ah,40h ; Write file
228 mov ah,3Eh ; Close file
234 mov ax,4C00h ; exit(0)
241 mov dx,msg_filesystem_err
257 mov ah,09h ; Write string
260 mov ax,4C01h ; Exit error status
264 msg_error: db 'ERROR: $'
265 msg_ancient_err: db 'DOS version 2.00 or later required', 0Dh, 0Ah, '$'
266 msg_filesystem_err: db 'Filesystem not found on disk', 0Dh, 0Ah, '$'
267 msg_read_err: db 'Boot sector read failed', 0Dh, 0Ah, '$'
268 msg_write_err: db 'File write failed', 0Dh, 0Ah, '$'
272 SectorBuffer: resb 4096