📄 syslinux.asm
字号:
; -*- fundamental -*- (asm-mode sucks); $Id: syslinux.asm,v 1.16 2002/06/02 05:12:25 hpa Exp $; -----------------------------------------------------------------------; ; Copyright 1998-2001 H. Peter Anvin - All Rights Reserved;; This program is free software; you can redistribute it and/or modify; it under the terms of the GNU General Public License as published by; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,; USA; either version 2 of the License, or (at your option) any later; version; incorporated herein by reference.;; -----------------------------------------------------------------------;; syslinux.asm;; DOS installer for SYSLINUX; absolute 0pspInt20: resw 1pspNextParagraph: resw 1 resb 1 ; reservedpspDispatcher: resb 5pspTerminateVector: resd 1pspControlCVector: resd 1pspCritErrorVector: resd 1 resw 11 ; reservedpspEnvironment: resw 1 resw 23 ; reservedpspFCB_1: resb 16pspFCB_2: resb 16 resd 1 ; reservedpspCommandLen: resb 1pspCommandArg: resb 127 section .text org 0100h_start: mov ax,3000h ; Get DOS version int 21h xchg al,ah mov [DOSVersion],ax cmp ax,0314h ; DOS 3.20 minimum jae dosver_ok mov dx,msg_ancient_err jmp die section .bss alignb 2DOSVersion: 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 cmp al,'-' je scan_option 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 .bssDriveNo: 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; the rest better be whitespace;got_colon: jcxz got_cmdline lodsb dec cx cmp al,' ' jbe got_colon;; We end up here if the command line doesn't parse;bad_usage: mov dx,msg_unfair jmp die section .datamsg_unfair: db 'Usage: syslinux [-s] <drive>:', 0Dh, 0Ah, '$' section .text;; Scan for options after a - sign. The only recognized option right now; is -s.;scan_option: jcxz bad_usage lodsb dec cx cmp al,' ' jbe cmdscan1 or al,20h cmp al,'s' jne bad_usage push si ; make_stupid doesn't save these push cx call make_stupid ; Enable stupid boot sector pop cx pop si jmp short scan_option;; Parsed the command line OK. Check that the drive parameters are acceptable; struc DPBdpbDrive: resb 1dpbUnit: resb 1dpbSectorSize: resw 1dpbClusterMask: resb 1dpbClusterShift: resb 1dpbFirstFAT: resw 1dpbFATCount: resb 1dpbRootEntries: resw 1dpbFirstSector: resw 1dpbMaxCluster: resw 1dpbFATSize: resw 1dpbDirSector: resw 1dpbDriverAddr: resd 1dpbMedia: resb 1dpbFirstAccess: resb 1dpbNextDPB: resd 1dpbNextFree: resw 1dpbFreeCnt: resw 1 endstrucgot_cmdline: mov dl,[DriveNo] inc dl ; 1-based mov ah,32h int 21h ; Get Drive Parameter Block and al,al jnz filesystem_error cmp word [bx+dpbSectorSize],512 ; Sector size = 512 required jne sectorsize_error cmp byte [bx+dpbClusterShift],5 ; Max size = 16K = 2^5 sectors jna drive_okhugeclust_error: mov dx,msg_hugeclust_err jmp diefilesystem_error: mov dx,msg_filesystem_err jmp doserrsectorsize_error: mov dx,msg_sectorsize_err jmp diedrive_ok: push cs pop ds;; Writing LDLINUX.SYS; section .dataldlinux_sys_str: db 'A:\LDLINUX.SYS', 0 section .textwrite_file: ; 0. Set the correct filename mov al,[DriveNo] add byte [ldlinux_sys_str],al ; 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 ; 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 je .no_file_write_error.file_write_error: mov dx, msg_fwrite_err jmp doserr.no_file_write_error: mov bx,[FileHandle] mov ah,3Eh ; Close file int 21h section .bssFileHandle: resw 1 section .text ; 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;; 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 jc .disk_lock_error_nocleanup popa xor dx,dx inc bh ; Lock level 2 pusha int 21h jc .disk_lock_error popa inc bh ; Lock level 3 pusha int 21h 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: popa mov dx, msg_lock_err jmp doserr.done: popa.plain_dos: ; Plain DOS -> no locking;; Now read the old boot sector and copy the superblock.; section .data align 4, db 0DISKIO equ $diStartSector: dd 0 ; Absolute sector 0diSectors: dw 1 ; One sectordiBuffer: dw SectorBuffer ; Buffer offset dw 0 ; Buffer segment section .textread_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_bootsectdisk_read_error: mov dx,msg_read_err jmp doserr;; Writing boot sector;write_bootsect: cmp word [DOSVersion],0400h ; DOS 4.00 has a new interface jae .new.old: mov bx,BootSector mov cx,1 ; One sector jmp short .common.new: mov bx,DISKIO mov word [bx+6],BootSector mov cx,-1.common: xor dx,dx ; Absolute sector 0 mov al,[DriveNo] int 26h ; DOS absolute disk write 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 lockingall_done: mov ax,4C00h ; Exit good status int 21h;; Error routine jump;disk_write_error: mov dx,msg_write_errdoserr: push cs pop ds push dx ; Error message push ax ; Error code mov dx, msg_error_sp mov ah,09h int 21h pop ax mov cx,4 mov bx,hexdigits mov si,ax.digit: rol si,1 rol si,1 rol si,1 rol si,1 mov ax,si and al,0Fh xlatb mov ah,02h ; Display character mov dl,al int 21h loop .digit mov dx,msg_colon mov ah,09h int 21h jmp short die_common section .datahexdigits: db '0123456789ABCDEF' section .textdie: push cs pop ds push dx mov dx, msg_error mov ah,09h int 21hdie_common: pop dx ; Error message mov ah,09h ; Write string int 21h mov ax,4C01h ; Exit error status int 21h;; Patch the code to make it "stupid";make_stupid: ; Only access one sector at a time mov word [LDLinuxSYS+PATCH_OFFSET],1 ret section .datamsg_error_sp: db 'ERROR $'msg_colon: db ': $'msg_error: db 'ERROR: $'msg_ancient_err: db 'DOS version 3.20 or later required', 0Dh, 0Ah, '$'msg_filesystem_err: db 'Filesystem not found on disk', 0Dh, 0Ah, '$'msg_sectorsize_err: db 'Sector sizes other than 512 bytes not supported', 0Dh, 0Ah, '$'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 'Boot sector write failed', 0Dh, 0Ah, '$'msg_fwrite_err: db 'LDLINUX.SYS write failed', 0Dh, 0Ah, '$'msg_lock_err: db 'Unable to lock drive for exclusive access', 0Dh, 0Ah, '$' section .data align 16, db 0BootSector: incbin "ldlinux.bss"LDLinuxSYS: incbin "ldlinux.sys"ldlinux_size: equ $-LDLinuxSYS section .bss alignb 16SectorBuffer: resb 512
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -