com32/chain: make raw handover use total sectors info
[syslinux.git] / dosutil / copybs.asm
blob26407148b2511ce69120204d712bbafe6df49f71
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 ; -----------------------------------------------------------------------
15 ; copybs.asm
17 ; Small DOS program to copy the boot sector from a drive
18 ; to a file
20 ; Usage: copybs <drive>: <file>
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
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
52 section .bss
53 alignb 2
54 DOSVersion: resw 1
56 section .text
58 ; Scan command line for a drive letter followed by a colon
60 dosver_ok:
61 xor cx,cx
62 mov si,pspCommandArg
63 mov cl,[pspCommandLen]
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
78 section .bss
79 DriveNo: resb 1
81 section .text
83 ; Got the leading letter, now the next character must be a colon
85 got_letter: jcxz bad_usage
86 lodsb
87 dec cx
88 cmp al,':'
89 jne 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
95 lodsb
96 dec cx
97 cmp al,' '
98 ja bad_usage
100 skipspace: jcxz bad_usage
101 lodsb
102 dec cx
103 cmp al,' '
104 jbe skipspace
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
116 ; We end up here if the command line doesn't parse
118 bad_usage: mov dx,msg_unfair
119 jmp die
121 section .data
122 msg_unfair: db 'Usage: copybs <drive>: <filename>', 0Dh, 0Ah, '$'
124 section .bss
125 alignb 4
126 FileName resb 256
129 ; Parsed the command line OK. Get device parameter block to get the
130 ; sector size.
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
153 section .bss
154 alignb 2
155 SectorSize resw 1
157 section .text
158 got_cmdline:
159 xor al,al ; Zero-terminate filename
160 stosb
162 mov dl,[DriveNo]
163 inc dl ; 1-based
164 mov ah,32h
165 int 21h ; Get Drive Parameter Block
167 and al,al
168 jnz filesystem_error
170 mov dx,[bx+dpbSectorSize] ; Save sector size
172 ; Read the boot sector.
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
182 section .text
183 read_bootsect:
184 mov ax,cs ; Set DS <- CS
185 mov ds,ax
187 mov [SectorSize],dx ; Saved sector size from above
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
207 ; Open the file and write the boot sector to the file.
209 mov dx,FileName
210 mov cx,0020h ; Attribute = ARCHIVE
211 mov ah,3Ch ; Create file
212 int 21h
213 jc file_write_error
215 mov bx,ax
216 push ax ; Handle
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
226 pop bx ; Handle
227 mov ah,3Eh ; Close file
228 int 21h
229 jc file_write_error
231 ; We're done!
233 mov ax,4C00h ; exit(0)
234 int 21h
237 ; Error routine jump
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
256 mov ah,09h ; Write string
257 int 21h
259 mov ax,4C01h ; Exit error status
260 int 21h
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, '$'
269 section .bss
270 alignb 4
271 SectorBuffer: resb 4096