mov al,[bsFATs] ; Number of FATs
jmpc kaboom ; If the floppy init failed
; (too far to be above the mov)
- cbw ; Clear AH
- mul byte [bsFATsecs] ; Get the size of the FAT area
+ cbw ; Clear AH (we WILL have < 128 FATs)
+ mul word [bsFATsecs] ; Get the size of the FAT area
add ax,[bsHidden1] ; Add hidden sectors
adc dx,[bsHidden2]
add ax,[bsResSectors] ; And reserved sectors (why two?)
add bx,trackbuf-31
mov [EndofDirSec],bx ; End of a single directory sector
- add [DataArea1],ax ; Now we have the location of the
- adc word [DataArea2],byte 0 ; first data cluster
+ add [DataArea1],ax
+ adc word [DataArea2],byte 0
+
+ pop dx ; Reload root directory starting point
+ pop ax
;
; Now the fun begins. We have to search the root directory for
; LDLINUX.SYS and load the first sector, so we have a little more
; space to have fun with. Then we can go chasing through the FAT.
; Joy!!
;
-sd_nextsec: pop dx
- pop ax
- push ax
+sd_nextsec: push ax
push dx
mov bx,trackbuf
+ push bx
call getonesec
- mov si,trackbuf
+ pop si
sd_nextentry: cmp byte [si],0 ; Directory high water mark
-jz_kaboom: jz kaboom
+ je kaboom
mov di,ldlinux_sys
mov cx,11
push si
add si,byte 32 ; Distance to next
cmp si,[EndofDirSec]
jb sd_nextentry
+ pop dx
+ pop ax
add ax,byte 1
adc dx,byte 0
dec word [DirScanCtr]
pop word [si+2]
sti
int 19h ; And try once more to boot...
-norge: jmp short norge ; If int 19h returned... oh boy...
+norge: jmp short norge ; If int 19h returned; this is the end
;
; found_it: now we compute the location of the first sector, then
; load it and JUMP (since we're almost out of space)
;
-found_it: pop ax
- pop ax
+found_it: ; Note: we actually leave two words on the stack here
+ ; (who cares?)
mov al,[bsSecPerClust]
- cbw ; We won't have 128 sec/cluster
+ xor ah,ah
mov bp,ax ; Load an entire cluster
mov bx,[si+26] ; First cluster
push bx ; Remember which cluster it was
add ax,[DataArea1]
adc dx,[DataArea2]
mov bx,ldlinux_magic
+ push bx
call getlinsec
mov si,bs_magic
- mov di,ldlinux_magic
- mov cx,[magic_len]
+ pop di
+ mov cx,magic_len
repe cmpsb ; Make sure that the bootsector
- jne kaboom
- jmp ldlinux_ent ; matches LDLINUX.SYS
+ jne kaboom ; matches LDLINUX.SYS
+ jmp ldlinux_ent
;
; writestr: write a null-terminated string to the console
;
push cx
mov cl,6 ; Because IBM was STOOPID
- shl ah,cl ; and thought 8 bits was enough
- ; then thought 10 bits was enough...
+ shl ah,cl ; and thought 8 bits were enough
+ ; then thought 10 bits were enough...
pop cx ; Sector #
inc cx ; Sector numbers are 1-based
or cl,ah
; Sets CF on return if end of file.
;
nextcluster:
- push bx
- mov bx,si ; Multiply by 3/2
- shr bx,1
+nextcluster_fat12:
+ push ax
+ mov ax,si ; Multiply by 3/2
+ shr ax,1
pushf ; CF now set if odd
- add si,bx
+ add si,ax
mov si,[FAT+si]
popf
jnc nc_even
and si,0FFFh
cmp si,0FF0h ; Clears CF if at end of file
cmc ; But we want it SET...
- pop bx
+ pop ax
nc_return: ret
+nextcluster_fat16:
+ push ax
+ push es
+ mov ax,(fat_seg >> 12)
+ shl si,1
+ adc ax,byte 0
+ mov es,ax
+ mov si,[es:si]
+ cmp si,0FFF0h
+ cmc
+ pop es
+ pop ax
+ ret
+
;
; Debug routine
;
mov si,trackbuf
dir_test_name: cmp byte [si],0 ; Directory high water mark
je dir_return ; Failed
- test byte [si+11],010h ; Check it really is a file
+ test byte [si+11],018h ; Check it really is a file
jnz dir_not_this
push di
push si
;
absolute 0080h
-psp_cmdlen resb 1
-psp_cmdline resb 127
+psp_cmdlen: resb 1
+psp_cmdline: resb 127
section .text
org 0100h
mov [DriveNo],al ; Save away drive index
section .bss
-DriveNo resb 1
+DriveNo: resb 1
section .text
;
int 21h
section .data
-msg_unfair db 'Usage: syslinux <drive>:', 0Dh, 0Ah, '$'
+msg_unfair: db 'Usage: syslinux <drive>:', 0Dh, 0Ah, '$'
section .text
;
; Parsed the command line OK, now get to work
;
got_cmdline: ; BUG: check sector size == 512
+ ; Use INT 21h:32h
mov bx,SectorBuffer
mov al,[DriveNo]
mov di,BootSector+11
mov cx,51 ; Superblock = 51 bytes
rep movsb ; Copy the superblock
+;
+; Writing LDLINUX.SYS
+;
+ ; 1. If the file exists, strip its attributes and delete
+
+ xor cx,cx ; Clear attributes
+ mov dx,ldlinux_sys_str
+ mov ax,4301h ; Set file attributes
+ int 21h
+
+ mov dx,ldlinux_sys_str
+ mov ah,41h ; Delete file
+ int 21h
+
+ section .data
+ldlinux_sys_str: db '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
+ mov [FileHandle],ax
+
+ mov bx,ax
+ mov cx,ldlinux_size
+ mov dx,LDLinuxSYS
+ mov ah,40h ; Write data
+ int 21h
+ jc file_write_error
+ cmp ax,ldlinux_size
+ jne file_write_error
+
+ mov bx,[FileHandle]
+ mov ah,3Eh ; Close file
+ int 21h
+
+ section .bss
+FileHandle: resw 1
+
+ section .text
- ; Write LDLINUX.SYS here (*before* writing boot sector)
+ ; 3. Set the readonly flag on LDLINUX.SYS
+ mov dx,ldlinux_sys_str
+ mov cx,1 ; Read only
+ mov ax,4301h ; Set attributes
+ int 21h
+;
+; Writing boot sector
+;
mov bx,BootSector
mov cx,1 ; One sector
xor dx,dx ; Absolute sector 0
disk_read_error:
disk_write_error:
- mov ax,4C01h
+file_write_error:
+ mov dx,msg_bummer
+ mov ah,09h ; Write string
int 21h
+ mov ax,4C01h ; Exit error status
+ int 21h
+
+ section .data
+msg_bummer: db 'Disk write error', 0Dh, 0Ah, '$'
+
section .data
align 4, db 0
BootSector: incbin "bootsect.bin"
LDLinuxSYS: incbin "ldlinux.sys"
+ldlinux_size: equ $-LDLinuxSYS
section .bss
alignb 4