aboutsummaryrefslogtreecommitdiffstats
path: root/copybs.asm
diff options
context:
space:
mode:
authorhpa <hpa>1998-05-07 06:11:10 +0000
committerhpa <hpa>1998-05-07 06:11:10 +0000
commit29456d6e5107613d3c8ab88f05c7f3909712db0d (patch)
tree86a5bc23563a46aa89286c19393ef0c14b7b139e /copybs.asm
parent6f5359aa7065210af374bf0d3576f04b1967aacd (diff)
downloadsyslinux-elf-29456d6e5107613d3c8ab88f05c7f3909712db0d.tar.gz
syslinux-elf-29456d6e5107613d3c8ab88f05c7f3909712db0d.tar.xz
syslinux-elf-29456d6e5107613d3c8ab88f05c7f3909712db0d.zip
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.asm269
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