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 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 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 54 DOSVersion: resw 1 55 56 section .text 57 ; 58 ; Scan command line for a drive letter followed by a colon 59 ; 60 dosver_ok: 61 xor cx,cx 62 mov si,pspCommandArg 63 mov cl,[pspCommandLen] 64 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 77 78 section .bss 79 DriveNo: resb 1 80 81 section .text 82 ; 83 ; Got the leading letter, now the next character must be a colon 84 ; 85 got_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 ; 94 got_colon: jcxz bad_usage 95 lodsb 96 dec cx 97 cmp al,' ' 98 ja bad_usage 99 100 skipspace: jcxz bad_usage 101 lodsb 102 dec cx 103 cmp al,' ' 104 jbe skipspace 105 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 114 115 ; 116 ; We end up here if the command line doesn't parse 117 ; 118 bad_usage: mov dx,msg_unfair 119 jmp die 120 121 section .data 122 msg_unfair: db 'Usage: copybs <drive>: <filename>', 0Dh, 0Ah, '$' 123 124 section .bss 125 alignb 4 126 FileName resb 256 127 128 ; 129 ; Parsed the command line OK. Get device parameter block to get the 130 ; sector size. 131 ; 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 152 153 section .bss 154 alignb 2 155 SectorSize resw 1 156 157 section .text 158 got_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 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 181 182 section .text 183 read_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 ; 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 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 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, '$' 268 269 section .bss 270 alignb 4 271 SectorBuffer: resb 4096 272