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