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