1 ; -*- fundamental -*- (asm-mode sucks)
2 ; -----------------------------------------------------------------------
4 ; Copyright 1998-2008 H. Peter Anvin - All Rights Reserved
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.
12 ; -----------------------------------------------------------------------
17 ; Small DOS program to copy the boot sector from a drive
20 ; Usage: copybs <drive>: <file>
25 pspNextParagraph: resw
1
28 pspTerminateVector: resd
1
29 pspControlCVector: resd
1
30 pspCritErrorVector: resd
1
32 pspEnvironment: resw
1
38 pspCommandArg: resb
127
41 org 100h ; .COM format
43 mov ax,3000h ; Get DOS version
47 cmp ax,0200h ; DOS 2.00 minimum
49 mov dx,msg_ancient_err
58 ; Scan command line for a drive letter followed by a colon
63 mov cl,[pspCommandLen
]
65 cmdscan1: jcxz bad_usage
; End of command line?
66 lodsb ; Load character
68 cmp al,' ' ; White space
70 or al,020h ; -> lower case
71 cmp al,'a' ; Check for letter
75 sub al,'a' ; Convert to zero-based index
76 mov [DriveNo
],al ; Save away drive index
83 ; Got the leading letter, now the next character must be a colon
85 got_letter: jcxz bad_usage
91 ; Got the colon; now we should have at least one whitespace
92 ; followed by a filename
94 got_colon: jcxz bad_usage
100 skipspace: jcxz bad_usage
113 jmp short got_cmdline
116 ; We end up here if the command line doesn't parse
118 bad_usage: mov dx,msg_unfair
122 msg_unfair: db 'Usage: copybs <drive>: <filename>', 0Dh, 0Ah, '$'
129 ; Parsed the command line OK. Get device parameter block to get the
135 dpbSectorSize: resw
1
136 dpbClusterMask: resb
1
137 dpbClusterShift: resb
1
140 dpbRootEntries: resw
1
141 dpbFirstSector: resw
1
142 dpbMaxCluster: resw
1
145 dpbDriverAddr: resd
1
147 dpbFirstAccess: resb
1
159 xor al,al ; Zero-terminate filename
165 int 21h ; Get Drive Parameter Block
170 mov dx,[bx+dpbSectorSize
] ; Save sector size
172 ; Read the boot sector.
177 diStartSector: dd 0 ; Absolute sector 0
178 diSectors: dw 1 ; One sector
179 diBuffer: dw SectorBuffer
; Buffer offset
180 dw 0 ; Buffer segment
184 mov ax,cs ; Set DS <- CS
187 mov [SectorSize
],dx ; Saved sector size from above
189 cmp word [DOSVersion
],0400h ; DOS 4.00 has a new interface
193 mov cx,1 ; One sector
196 mov [diBuffer
+2],ax ; == DS
200 xor dx,dx ; Absolute sector 0
202 int 25h ; DOS absolute disk read
203 pop ax ; Remove flags from stack
207 ; Open the file and write the boot sector to the file.
210 mov cx,0020h ; Attribute = ARCHIVE
211 mov ah,3Ch ; Create file
220 mov ah,40h ; Write file
227 mov ah,3Eh
; Close file
233 mov ax,4C00h
; exit(0)
240 mov dx,msg_filesystem_err
256 mov ah,09h ; Write string
259 mov ax,4C01h
; Exit error status
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, '$'
271 SectorBuffer: resb
4096