• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
24pspInt20:		resw 1
25pspNextParagraph:	resw 1
26			resb 1		; reserved
27pspDispatcher:		resb 5
28pspTerminateVector:	resd 1
29pspControlCVector:	resd 1
30pspCritErrorVector:	resd 1
31			resw 11		; reserved
32pspEnvironment:		resw 1
33			resw 23		; reserved
34pspFCB_1:		resb 16
35pspFCB_2:		resb 16
36			resd 1		; reserved
37pspCommandLen:		resb 1
38pspCommandArg:		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
54DOSVersion:	resw 1
55
56		section .text
57;
58; Scan command line for a drive letter followed by a colon
59;
60dosver_ok:
61		xor cx,cx
62		mov si,pspCommandArg
63		mov cl,[pspCommandLen]
64
65cmdscan1:	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
79DriveNo:	resb 1
80
81		section .text
82;
83; Got the leading letter, now the next character must be a colon
84;
85got_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;
94got_colon:	jcxz bad_usage
95		lodsb
96		dec cx
97		cmp al,' '
98		ja bad_usage
99
100skipspace:	jcxz bad_usage
101		lodsb
102		dec cx
103		cmp al,' '
104		jbe skipspace
105
106		mov di,FileName
107copyfile:	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;
118bad_usage:	mov dx,msg_unfair
119		jmp die
120
121		section .data
122msg_unfair:	db 'Usage: copybs <drive>: <filename>', 0Dh, 0Ah, '$'
123
124		section .bss
125		alignb 4
126FileName	resb 256
127
128;
129; Parsed the command line OK.  Get device parameter block to get the
130; sector size.
131;
132		struc DPB
133dpbDrive:	resb 1
134dpbUnit:	resb 1
135dpbSectorSize:	resw 1
136dpbClusterMask:	resb 1
137dpbClusterShift: resb 1
138dpbFirstFAT:	resw 1
139dpbFATCount:	resb 1
140dpbRootEntries:	resw 1
141dpbFirstSector:	resw 1
142dpbMaxCluster:	resw 1
143dpbFATSize:	resw 1
144dpbDirSector:	resw 1
145dpbDriverAddr:	resd 1
146dpbMedia:	resb 1
147dpbFirstAccess:	resb 1
148dpbNextDPB:	resd 1
149dpbNextFree:	resw 1
150dpbFreeCnt:	resw 1
151		endstruc
152
153		section .bss
154		alignb 2
155SectorSize	resw 1
156
157		section .text
158got_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
176DISKIO		equ $
177diStartSector:	dd 0				; Absolute sector 0
178diSectors:	dw 1				; One sector
179diBuffer:	dw SectorBuffer			; Buffer offset
180		dw 0				; Buffer segment
181
182		section .text
183read_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;
239filesystem_error:
240		mov dx,msg_filesystem_err
241		jmp short die
242disk_read_error:
243		mov dx,msg_read_err
244		jmp short die
245file_write_error:
246		mov dx,msg_write_err
247die:
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
263msg_error:		db 'ERROR: $'
264msg_ancient_err:	db 'DOS version 2.00 or later required', 0Dh, 0Ah, '$'
265msg_filesystem_err:	db 'Filesystem not found on disk', 0Dh, 0Ah, '$'
266msg_read_err:		db 'Boot sector read failed', 0Dh, 0Ah, '$'
267msg_write_err:		db 'File write failed', 0Dh, 0Ah, '$'
268
269		section .bss
270		alignb 4
271SectorBuffer:	resb 4096
272