diff options
author | hpa <hpa> | 1998-05-07 06:11:10 +0000 |
---|---|---|
committer | hpa <hpa> | 1998-05-07 06:11:10 +0000 |
commit | 29456d6e5107613d3c8ab88f05c7f3909712db0d (patch) | |
tree | 86a5bc23563a46aa89286c19393ef0c14b7b139e /copybs.asm | |
parent | 6f5359aa7065210af374bf0d3576f04b1967aacd (diff) | |
download | syslinux-29456d6e5107613d3c8ab88f05c7f3909712db0d.tar.gz |
Update the DOS installers to use the new INT 25h/26h interface if
DOS >= 4.0; should now work on hard disks.
New "copybs" utility.
Diffstat (limited to 'copybs.asm')
-rw-r--r-- | copybs.asm | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/copybs.asm b/copybs.asm new file mode 100644 index 00000000..784096eb --- /dev/null +++ b/copybs.asm @@ -0,0 +1,269 @@ +; -*- fundamental -*- (asm-mode sucks) +; $Id$ +; ----------------------------------------------------------------------- +; +; Copyright 1998 Transmeta Corporation - All Rights Reserved +; +; This source module contains confidential and proprietary information +; of Transmeta Corporation. It is not to be disclosed or used except +; in accordance with applicable agreements. This copyright notice does +; not evidence any actual or intended publication of such source code. +; +; ----------------------------------------------------------------------- + +; +; copybs.asm +; +; Small DOS program to copy the boot sector from a drive +; to a file +; +; Usage: copybs <drive>: <file> +; + + absolute 0 +pspInt20: resw 1 +pspNextParagraph: resw 1 + resb 1 ; reserved +pspDispatcher: resb 5 +pspTerminateVector: resd 1 +pspControlCVector: resd 1 +pspCritErrorVector: resd 1 + resw 11 ; reserved +pspEnvironment: resw 1 + resw 23 ; reserved +pspFCB_1: resb 16 +pspFCB_2: resb 16 + resd 1 ; reserved +pspCommandLen: resb 1 +pspCommandArg: resb 127 + + section .text + org 100h ; .COM format +_start: + mov ax,3000h ; Get DOS version + int 21h + xchg al,ah + mov [DOSVersion],ax + cmp ax,0200h ; DOS 2.00 minimum + jae dosver_ok + mov dx,msg_ancient_err + jmp die + + section .bss + alignb 2 +DOSVersion: resw 1 + + section .text +; +; Scan command line for a drive letter followed by a colon +; +dosver_ok: + xor cx,cx + mov si,pspCommandArg + mov cl,[pspCommandLen] + +cmdscan1: jcxz bad_usage ; End of command line? + lodsb ; Load character + dec cx + cmp al,' ' ; White space + jbe cmdscan1 + or al,020h ; -> lower case + cmp al,'a' ; Check for letter + jb bad_usage + cmp al,'z' + ja bad_usage + sub al,'a' ; Convert to zero-based index + mov [DriveNo],al ; Save away drive index + + section .bss +DriveNo: resb 1 + + section .text +; +; Got the leading letter, now the next character must be a colon +; +got_letter: jcxz bad_usage + lodsb + dec cx + cmp al,':' + jne bad_usage +; +; Got the colon; now we should have at least one whitespace +; followed by a filename +; +got_colon: jcxz bad_usage + lodsb + dec cx + cmp al,' ' + ja bad_usage + +skipspace: jcxz bad_usage + lodsb + dec cx + cmp al,' ' + jbe skipspace + + mov di,FileName +copyfile: stosb + jcxz got_cmdline + lodsb + dec cx + cmp al,' ' + ja copyfile + jmp short got_cmdline + +; +; We end up here if the command line doesn't parse +; +bad_usage: mov dx,msg_unfair + jmp die + + section .data +msg_unfair: db 'Usage: copybs <drive>: <filename>', 0Dh, 0Ah, '$' + + section .bss + alignb 4 +FileName resb 256 + +; +; Parsed the command line OK. Get device parameter block to get the +; sector size. +; + struc DPB +dpbDrive: resb 1 +dpbUnit: resb 1 +dpbSectorSize: resw 1 +dpbClusterMask: resb 1 +dpbClusterShift: resb 1 +dpbFirstFAT: resw 1 +dpbFATCount: resb 1 +dpbRootEntries: resw 1 +dpbFirstSector: resw 1 +dpbMaxCluster: resw 1 +dpbFATSize: resw 1 +dpbDirSector: resw 1 +dpbDriverAddr: resd 1 +dpbMedia: resb 1 +dpbFirstAccess: resb 1 +dpbNextDPB: resd 1 +dpbNextFree: resw 1 +dpbFreeCnt: resw 1 + endstruc + + section .bss + alignb 2 +SectorSize resw 1 + + section .text +got_cmdline: + xor al,al ; Zero-terminate filename + stosb + + mov dl,[DriveNo] + inc dl ; 1-based + mov ah,32h + int 21h ; Get Drive Parameter Block + + and al,al + jnz filesystem_error + + mov ax,[bx+dpbSectorSize] +; +; Read the boot sector. +; + section .data + align 4, db 0 +DISKIO equ $ +diStartSector: dd 0 ; Absolute sector 0 +diSectors: dw 1 ; One sector +diBuffer: dw SectorBuffer ; Buffer offset + dw 0 ; Buffer segment + + section .text +read_bootsect: + mov ax,cs ; Set DS <- CS + mov ds,ax + + cmp word [DOSVersion],0400h ; DOS 4.00 has a new interface + jae .new +.old: + mov bx,SectorBuffer + mov cx,1 ; One sector + jmp short .common +.new: + mov [diBuffer+2],ax ; == DS + mov bx,DISKIO + mov cx,-1 +.common: + xor dx,dx ; Absolute sector 0 + mov al,[DriveNo] + int 25h ; DOS absolute disk read + pop ax ; Remove flags from stack + jc disk_read_error + +; +; Open the file and write the boot sector to the file. +; + mov dx,FileName + mov cx,0020h ; Attribute = ARCHIVE + mov ah,3Ch ; Create file + int 21h + jc file_write_error + + mov bx,ax + push ax ; Handle + + mov cx,[SectorSize] + mov dx,SectorBuffer + mov ah,40h ; Write file + int 21h + jc file_write_error + cmp ax,[SectorSize] + jne file_write_error + + pop bx ; Handle + mov ah,3Eh ; Close file + int 21h + jc file_write_error +; +; We're done! +; + mov ax,4C00h ; exit(0) + int 21h + +; +; Error routine jump +; +filesystem_error: + mov dx,msg_filesystem_err + jmp short die +disk_read_error: + mov dx,msg_read_err + jmp short die +file_write_error: + mov dx,msg_write_err +die: + push cs + pop ds + push dx + mov dx,msg_error + mov ah,09h + int 21h + pop dx + + mov ah,09h ; Write string + int 21h + + mov ax,4C01h ; Exit error status + int 21h + + section .data +msg_error: db 'ERROR: $' +msg_ancient_err: db 'DOS version 2.00 or later required', 0Dh, 0Ah, '$' +msg_filesystem_err: db 'Filesystem not found on disk', 0Dh, 0Ah, '$' +msg_read_err: db 'Boot sector read failed', 0Dh, 0Ah, '$' +msg_write_err: db 'File write failed', 0Dh, 0Ah, '$' + + section .bss + alignb 4 +SectorBuffer: resb 4096 |