home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 1999 May / pcp151c.iso / misc / src / trees / syslinux-1.40 / syslinux.asm < prev    next >
Encoding:
Assembly Source File  |  1998-05-07  |  7.0 KB  |  344 lines

  1. ; -*- fundamental -*- (asm-mode sucks)
  2. ; $Id: syslinux.asm,v 1.10 1998/05/07 07:03:17 hpa Exp $
  3. ; -----------------------------------------------------------------------
  4. ;   
  5. ;   Copyright 1998 H. Peter Anvin - All Rights Reserved
  6. ;
  7. ;   This program is free software; you can redistribute it and/or modify
  8. ;   it under the terms of the GNU General Public License as published by
  9. ;   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
  10. ;   USA; either version 2 of the License, or (at your option) any later
  11. ;   version; incorporated herein by reference.
  12. ;
  13. ; -----------------------------------------------------------------------
  14.  
  15. ;
  16. ; syslinux.asm
  17. ;
  18. ;    DOS installer for SYSLINUX
  19. ;
  20.  
  21.         absolute 0
  22. pspInt20:        resw 1
  23. pspNextParagraph:    resw 1
  24.             resb 1        ; reserved
  25. pspDispatcher:        resb 5
  26. pspTerminateVector:    resd 1
  27. pspControlCVector:    resd 1
  28. pspCritErrorVector:    resd 1
  29.             resw 11        ; reserved
  30. pspEnvironment:        resw 1
  31.             resw 23        ; reserved
  32. pspFCB_1:        resb 16
  33. pspFCB_2:        resb 16
  34.             resd 1        ; reserved
  35. pspCommandLen:        resb 1
  36. pspCommandArg:        resb 127
  37.  
  38.         section .text
  39.         org 0100h
  40. _start:        
  41.         mov ax,3000h            ; Get DOS version
  42.         int 21h
  43.         xchg al,ah
  44.         mov [DOSVersion],ax
  45.         cmp ax,0314h            ; DOS 3.20 minimum
  46.         jae dosver_ok
  47.         mov dx,msg_ancient_err
  48.         jmp die
  49.  
  50.         section .bss
  51.         alignb 2
  52. DOSVersion:    resw 1
  53.  
  54.         section .text
  55. ;
  56. ; Scan command line for a drive letter followed by a colon
  57. ;
  58. dosver_ok:
  59.         xor cx,cx
  60.         mov si,pspCommandArg
  61.         mov cl,[pspCommandLen]
  62.         
  63. cmdscan1:    jcxz bad_usage            ; End of command line?
  64.         lodsb                ; Load character
  65.         dec cx
  66.         cmp al,' '            ; White space
  67.         jbe cmdscan1
  68.         cmp al,'-'
  69.         je scan_option
  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
  79. DriveNo:    resb 1
  80.  
  81.         section .text
  82. ;
  83. ; Got the leading letter, now the next character must be a colon
  84. ;
  85. got_letter:    jcxz bad_usage
  86.         lodsb
  87.         dec cx
  88.         cmp al,':'
  89.         jne bad_usage
  90. ;
  91. ; Got the colon; the rest better be whitespace
  92. ;
  93. got_colon:    jcxz got_cmdline
  94.         lodsb
  95.         dec cx
  96.         cmp al,' '
  97.         jbe got_colon
  98. ;
  99. ; We end up here if the command line doesn't parse
  100. ;
  101. bad_usage:    mov dx,msg_unfair
  102.         jmp die
  103.  
  104.         section .data
  105. msg_unfair:    db 'Usage: syslinux [-s] <drive>:', 0Dh, 0Ah, '$'
  106.  
  107.         section .text
  108. ;
  109. ; Scan for options after a - sign.  The only recognized option right now
  110. ; is -s.
  111. ;
  112. scan_option:    jcxz bad_usage
  113.         lodsb
  114.         dec cx
  115.         cmp al,' '
  116.         jbe cmdscan1
  117.         or al,20h
  118.         cmp al,'s'
  119.         jne bad_usage
  120.         push si            ; make_stupid doesn't save these
  121.         push cx
  122.         call make_stupid    ; Enable stupid boot sector
  123.         pop cx
  124.         pop si
  125.         jmp short scan_option
  126.  
  127. ;
  128. ; Parsed the command line OK.  Check that the drive parameters are acceptable
  129. ;
  130.         struc DPB
  131. dpbDrive:    resb 1
  132. dpbUnit:    resb 1
  133. dpbSectorSize:    resw 1
  134. dpbClusterMask:    resb 1
  135. dpbClusterShift: resb 1
  136. dpbFirstFAT:    resw 1
  137. dpbFATCount:    resb 1
  138. dpbRootEntries:    resw 1
  139. dpbFirstSector:    resw 1
  140. dpbMaxCluster:    resw 1
  141. dpbFATSize:    resw 1
  142. dpbDirSector:    resw 1
  143. dpbDriverAddr:    resd 1
  144. dpbMedia:    resb 1
  145. dpbFirstAccess:    resb 1
  146. dpbNextDPB:    resd 1
  147. dpbNextFree:    resw 1
  148. dpbFreeCnt:    resw 1
  149.         endstruc
  150.  
  151. got_cmdline:
  152.         mov dl,[DriveNo]
  153.         inc dl                ; 1-based
  154.         mov bx,DPB
  155.         mov ah,32h
  156.         int 21h                ; Get Drive Parameter Block
  157.         
  158.         and al,al
  159.         jnz filesystem_error
  160.  
  161.         cmp word [bx+dpbSectorSize],512    ; Sector size = 512 required
  162.         jne sectorsize_error
  163.  
  164.         cmp byte [bx+dpbClusterShift],5    ; Max size = 16K = 2^5 sectors
  165.         jna read_bootsect
  166.  
  167. hugeclust_error:
  168.         mov dx,msg_hugeclust_err
  169.         jmp die
  170. filesystem_error:
  171.         mov dx,msg_filesystem_err
  172.         jmp die
  173. sectorsize_error:
  174.         mov dx,msg_sectorsize_err
  175.         jmp die
  176.  
  177. ;
  178. ; Good enough.  Now read the old boot sector and copy the superblock.
  179. ;
  180.         section .data
  181.         align 4, db 0
  182. DISKIO        equ $
  183. diStartSector:    dd 0                ; Absolute sector 0
  184. diSectors:    dw 1                ; One sector
  185. diBuffer:    dw SectorBuffer            ; Buffer offset
  186.         dw 0                ; Buffer segment
  187.  
  188.         section .text
  189. read_bootsect:
  190.         mov ax,cs            ; Set DS <- CS
  191.         mov ds,ax
  192.  
  193.         cmp word [DOSVersion],0400h    ; DOS 4.00 has a new interface
  194.         jae .new
  195. .old:
  196.         mov bx,SectorBuffer
  197.         mov cx,1            ; One sector
  198.         jmp short .common
  199. .new:
  200.         mov bx,DISKIO
  201.         mov [bx+8],ax            ; Buffer segment
  202.         mov cx,-1
  203. .common:
  204.         xor dx,dx            ; Absolute sector 0
  205.         mov al,[DriveNo]
  206.         int 25h                ; DOS absolute disk read
  207.         pop ax                ; Remove flags from stack
  208.         jc disk_read_error
  209.  
  210.         mov si,SectorBuffer+11        ; Offset of superblock
  211.         mov di,BootSector+11
  212.         mov cx,51            ; Superblock = 51 bytes
  213.         rep movsb            ; Copy the superblock
  214.         jmp short write_file
  215. disk_read_error:
  216.         mov dx,msg_read_err
  217.         jmp die
  218. ;
  219. ; Writing LDLINUX.SYS
  220. ;
  221. write_file:
  222.         ; 0. Set the correct filename
  223.  
  224.         mov al,[DriveNo]
  225.         add [ldlinux_sys_str],al
  226.  
  227.         ; 1. If the file exists, strip its attributes and delete
  228.  
  229.         xor cx,cx            ; Clear attributes
  230.         mov dx,ldlinux_sys_str
  231.         mov ax,4301h            ; Set file attributes
  232.         int 21h
  233.  
  234.         mov dx,ldlinux_sys_str
  235.         mov ah,41h            ; Delete file
  236.         int 21h
  237.  
  238.         section .data
  239. ldlinux_sys_str: db 'A:\LDLINUX.SYS', 0
  240.  
  241.         section .text
  242.  
  243.         ; 2. Create LDLINUX.SYS and write data to it
  244.  
  245.         mov dx,ldlinux_sys_str
  246.         xor cx,cx            ; Normal file
  247.         mov ah,3Ch            ; Create file
  248.         int 21h
  249.         jc file_write_error
  250.         mov [FileHandle],ax
  251.  
  252.         mov bx,ax
  253.         mov cx,ldlinux_size
  254.         mov dx,LDLinuxSYS
  255.         mov ah,40h            ; Write data
  256.         int 21h
  257.         jc file_write_error
  258.         cmp ax,ldlinux_size
  259.         jne file_write_error
  260.  
  261.         mov bx,[FileHandle]
  262.         mov ah,3Eh            ; Close file
  263.         int 21h
  264.  
  265.         section .bss
  266. FileHandle:    resw 1
  267.  
  268.         section .text
  269.  
  270.         ; 3. Set the readonly flag on LDLINUX.SYS
  271.  
  272.         mov dx,ldlinux_sys_str
  273.         mov cx,1            ; Read only
  274.         mov ax,4301h            ; Set attributes
  275.         int 21h
  276. ;
  277. ; Writing boot sector
  278. ;
  279. write_bootsect:
  280.         cmp word [DOSVersion],0400h    ; DOS 4.00 has a new interface
  281.         jae .new
  282. .old:
  283.         mov bx,BootSector
  284.         mov cx,1            ; One sector
  285.         jmp short .common
  286. .new:
  287.         mov bx,DISKIO
  288.         mov word [bx+6],BootSector
  289.         mov cx,-1
  290. .common:
  291.         xor dx,dx            ; Absolute sector 0
  292.         mov al,[DriveNo]
  293.         int 26h                ; DOS absolute disk write
  294.         pop ax                ; Remove flags from stack
  295.         jc disk_write_error
  296.  
  297. all_done:    mov ax,4C00h            ; Exit good status
  298.         int 21h
  299. ;
  300. ; Error routine jump
  301. ;
  302. disk_write_error:
  303. file_write_error:
  304.         mov dx,msg_write_err
  305. die:
  306.         push cs
  307.         pop ds
  308.         push dx
  309.         mov dx,msg_error
  310.         mov ah,09h
  311.         int 21h
  312.         pop dx
  313.  
  314.         mov ah,09h            ; Write string
  315.         int 21h
  316.  
  317.         mov ax,4C01h            ; Exit error status
  318.         int 21h
  319.  
  320. ;
  321. ; This includes a small subroutine make_stupid to patch up the boot sector
  322. ; in case we give the -s (stupid) option
  323. ;
  324.         %include "stupid.inc"
  325.  
  326.         section .data
  327. msg_error:        db 'ERROR: $'
  328. msg_ancient_err:    db 'DOS version 3.20 or later required', 0Dh, 0Ah, '$'
  329. msg_filesystem_err:    db 'Filesystem not found on disk', 0Dh, 0Ah, '$'
  330. msg_sectorsize_err:    db 'Sector sizes other than 512 bytes not supported', 0Dh, 0Ah, '$'
  331. msg_hugeclust_err:    db 'Clusters larger than 16K not supported', 0Dh, 0Ah, '$'
  332. msg_read_err:        db 'Boot sector read failed', 0Dh, 0Ah, '$'
  333. msg_write_err:        db 'Disk write failed', 0Dh, 0Ah, '$'
  334.  
  335.         section .data
  336.         align 4, db 0
  337. BootSector:    incbin "bootsect.bin"
  338. LDLinuxSYS:    incbin "ldlinux.sys"
  339. ldlinux_size:    equ $-LDLinuxSYS
  340.  
  341.         section .bss
  342.         alignb 4
  343. SectorBuffer:    resb 512
  344.