summaryrefslogtreecommitdiff
path: root/syslinux.asm
diff options
context:
space:
mode:
authorhpa <hpa>2001-09-07 05:33:12 +0000
committerhpa <hpa>2001-09-07 05:33:12 +0000
commit4dcdfa8284bf999c6d1ef9e2bc95e8d6454fc225 (patch)
tree18a1138f3d5e1cf5385b27d3e92dec99951c5673 /syslinux.asm
parentf60b806fa5de0de039569f0cd2486ff0f26b200f (diff)
downloadsyslinux-4dcdfa8284bf999c6d1ef9e2bc95e8d6454fc225.tar.gz
Try to placate recent versions of Windows when using the DOS installer.
Diffstat (limited to 'syslinux.asm')
-rw-r--r--syslinux.asm185
1 files changed, 133 insertions, 52 deletions
diff --git a/syslinux.asm b/syslinux.asm
index ebc8ba43..e7930299 100644
--- a/syslinux.asm
+++ b/syslinux.asm
@@ -162,7 +162,7 @@ got_cmdline:
jne sectorsize_error
cmp byte [bx+dpbClusterShift],5 ; Max size = 16K = 2^5 sectors
- jna read_bootsect
+ jna drive_ok
hugeclust_error:
mov dx,msg_hugeclust_err
@@ -174,50 +174,16 @@ sectorsize_error:
mov dx,msg_sectorsize_err
jmp die
+drive_ok:
+
;
-; Good enough. Now read the old boot sector and copy the superblock.
+; Writing LDLINUX.SYS
;
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
-
+ldlinux_sys_str:
+ db 'A:\LDLINUX.SYS', 0
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 bx,DISKIO
- mov [bx+8],ax ; Buffer segment
- 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
- mov si,SectorBuffer+11 ; Offset of superblock
- mov di,BootSector+11
- mov cx,51 ; Superblock = 51 bytes
- rep movsb ; Copy the superblock
- jmp short write_file
-disk_read_error:
- mov dx,msg_read_err
- jmp die
-;
-; Writing LDLINUX.SYS
-;
write_file:
; 0. Set the correct filename
@@ -235,18 +201,13 @@ write_file:
mov ah,41h ; Delete file
int 21h
- section .data
-ldlinux_sys_str: db 'A:\LDLINUX.SYS', 0
-
- section .text
-
; 2. Create LDLINUX.SYS and write data to it
mov dx,ldlinux_sys_str
xor cx,cx ; Normal file
mov ah,3Ch ; Create file
int 21h
- jc file_write_error
+ jc .file_write_error
mov [FileHandle],ax
mov bx,ax
@@ -254,9 +215,12 @@ ldlinux_sys_str: db 'A:\LDLINUX.SYS', 0
mov dx,LDLinuxSYS
mov ah,40h ; Write data
int 21h
- jc file_write_error
+ jc .file_write_error
cmp ax,ldlinux_size
- jne file_write_error
+ je .no_file_write_error
+.file_write_error:
+ jmp file_write_error
+.no_file_write_error:
mov bx,[FileHandle]
mov ah,3Eh ; Close file
@@ -273,6 +237,102 @@ FileHandle: resw 1
mov cx,1 ; Read only
mov ax,4301h ; Set attributes
int 21h
+
+;
+; Now, if we're on a recent Windows system we need to lock the device.
+; This call should have no effect on plain DOS.
+;
+lock_drive:
+ cmp word [DOSVersion], 0700h ; Win9x/NT?
+ jb .plain_dos ; Plain DOS -> no locking
+
+ mov ax,440Dh ; Generic IOCTL
+ mov bl,[DriveNo]
+ inc bl ; 1-based
+ mov bh,1 ; Lock level 1
+ mov cx,084Ah ; Lock logical volume
+ mov dx,01h ; Allow write mappings/allow new mappings
+ pusha
+ int 21h
+ popa
+ jc .disk_lock_error_nocleanup
+
+ xor dx,dx
+ inc bh ; Lock level 2
+ pusha
+ int 21h
+ popa
+ jc .disk_lock_error
+
+ inc bh ; Lock level 3
+ pusha
+ int 21h
+ popa
+ jnc .done
+
+.disk_lock_error:
+ xor cx,cx
+ mov cl,bh
+ dec cx
+.lock_cleanup:
+ push cx
+ mov ax, 440Dh
+ mov bl,[DriveNo]
+ inc bl
+ mov cx,086Ah
+ int 21h
+ pop cx
+ loop .lock_cleanup
+
+.disk_lock_error_nocleanup:
+ mov dx, msg_lock_err
+ jmp die
+
+.done:
+.plain_dos: ; Plain DOS -> no locking
+
+;
+; Now read the old boot sector and copy the superblock.
+;
+ 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 bx,DISKIO
+ mov [bx+8],ax ; Buffer segment
+ 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
+
+ mov si,SectorBuffer+11 ; Offset of superblock
+ mov di,BootSector+11
+ mov cx,51 ; Superblock = 51 bytes
+ rep movsb ; Copy the superblock
+ jmp short write_bootsect
+disk_read_error:
+ mov dx,msg_read_err
+ jmp die
+
;
; Writing boot sector
;
@@ -294,19 +354,39 @@ write_bootsect:
pop ax ; Remove flags from stack
jc disk_write_error
+;
+; Unlock the disk if we had to lock it
+;
+unlock_disk:
+ cmp word [DOSVersion], 0700h
+ jb .plain_dos
+
+ mov cx, 3 ; Need to release lock 3 times
+.loop:
+ push cx
+ mov ax,440Dh ; Generic IOCTL
+ mov bl,[DriveNo]
+ inc bl ; 1-based drive number
+ mov cx,086Ah ; Unlock logical drive
+ int 21h
+ pop cx
+ loop .loop
+
+.plain_dos: ; Plain DOS -> no locking
+
all_done: mov ax,4C00h ; Exit good status
int 21h
;
; Error routine jump
;
-disk_write_error:
file_write_error:
+disk_write_error:
mov dx,msg_write_err
die:
push cs
pop ds
push dx
- mov dx,msg_error
+ mov dx, msg_error
mov ah,09h
int 21h
pop dx
@@ -331,13 +411,14 @@ msg_sectorsize_err: db 'Sector sizes other than 512 bytes not supported', 0Dh, 0
msg_hugeclust_err: db 'Clusters larger than 16K not supported', 0Dh, 0Ah, '$'
msg_read_err: db 'Boot sector read failed', 0Dh, 0Ah, '$'
msg_write_err: db 'Disk write failed', 0Dh, 0Ah, '$'
+msg_lock_err: db 'Unable to lock drive for exclusive access', 0Dh, 0Ah, '$'
section .data
- align 4, db 0
+ align 16, db 0
BootSector: incbin "bootsect.bin"
LDLinuxSYS: incbin "ldlinux.sys"
ldlinux_size: equ $-LDLinuxSYS
section .bss
- alignb 4
+ alignb 16
SectorBuffer: resb 512