?? ldlinux.asm
字號:
; -*- fundamental -*- (asm-mode sucks); $Id: ldlinux.asm,v 1.13 1998/02/06 00:19:21 hpa Exp $; ****************************************************************************;; ldlinux.asm;; A program to boot Linux kernels off an MS-DOS formatted floppy disk. This; functionality is good to have for installation floppies, where it may; be hard to find a functional Linux system to run LILO off.;; This program allows manipulation of the disk to take place entirely; from MS-LOSS, and can be especially useful in conjunction with the; umsdos filesystem.;; This file is loaded in stages; first the boot sector at offset 7C00h,; then the first sector (cluster, really, but we can only assume 1 sector); of LDLINUX.SYS at 7E00h and finally the remainder of LDLINUX.SYS at 8000h.;; Copyright (C) 1994-1998 H. Peter Anvin;; 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.; ; ****************************************************************************;; Some semi-configurable constants... change on your own risk;max_cmd_len equ 2047 ; Must be odd; 2047 is the kernel limitretry_count equ 6 ; How patient are we with the disk?;; Should be updated with every release to avoid bootsector/SYS file mismatch;%define version_str VERSION ; Must be 4 characters long!%define date DATE_STR ; Defined from the Makefile%define year '1998';; Debgging stuff;; %define debug 1 ; Uncomment to enable debugging;; ID for SYSLINUX (reported to kernel);syslinux_id equ 031h ; SYSLINUX (3) version 1.x (1);; Segments used by Linux;real_mode_seg equ 9000h struc real_mode_seg_t resb 20h-($-$$) ; org 20hkern_cmd_magic resw 1 ; Magic # for command linekern_cmd_offset resw 1 ; Offset for kernel command line resb 497-($-$$) ; org 497dbs_setupsecs resb 1 ; Sectors for setup code (0 -> 4)bs_rootflags resw 1 ; Root readonly flagbs_syssize resw 1bs_swapdev resw 1 ; Swap device (obsolete)bs_ramsize resw 1 ; Ramdisk flags, formerly ramdisk sizebs_vidmode resw 1 ; Video modebs_rootdev resw 1 ; Root devicebs_bootsign resw 1 ; Boot sector signature (0AA55h)su_jump resb 1 ; 0EBhsu_jump2 resb 1su_header resd 1 ; New setup code: headersu_version resw 1 ; See linux/arch/i386/boot/setup.Ssu_switch resw 1su_setupseg resw 1su_startsys resw 1su_kver resw 1 ; Kernel version pointersu_loader resb 1 ; Loader IDsu_loadflags resb 1 ; Load high flagsu_movesize resw 1su_code32start resd 1 ; Start of code loaded highsu_ramdiskat resd 1 ; Start of initial ramdisksu_ramdisklen equ $ ; Length of initial ramdisksu_ramdisklen1 resw 1su_ramdisklen2 resw 1su_bsklugeoffs resw 1su_bsklugeseg resw 1su_heapend resw 1 resb (8000h-12)-($-$$) ; Were bootsect.S puts it...linux_stack equ $linux_fdctab equ $ resb 8000h-($-$$)cmd_line_here equ $ ; Should be out of the way endstrucsetup_seg equ 9020h struc setup_seg_t org 0h ; as 9020:0000, not 9000:0200setup_entry equ $ endstruc;; Magic number of su_header field;HEADER_ID equ 'HdrS' ; HdrS (in littleendian hex);; Flags for the su_loadflags field;LOAD_HIGH equ 01h ; Large kernel, load highCAN_USE_HEAP equ 80h ; Boot loader reports heap size;; The following structure is used for "virtual kernels"; i.e. LILO-style; option labels. The options we permit here are `kernel' and `append; Since there is no room in the bottom 64K for up to 16 of these, we; stick them at 8000:0000 and copy them down before we need them.;; Note: this structure can be added to, but must be less than 4K in size.; struc vkernelvk_vname: resb 11 ; Virtual name **MUST BE FIRST!** resb 3 ; Alignment fillervk_rname: resb 11 ; Real name resb 1 ; Fillervk_appendlen: resw 1vk_append: resb max_cmd_len+1 ; Command linevk_size: equ $ endstruc;; Segment assignments in the bottom 640K; 0000h - main code/data segment (and BIOS segment); 9000h - real_mode_seg;vk_seg equ 8000h ; This is where we stick'emxfer_buf_seg equ 7000h ; Bounce buffer for I/O to high memfat_seg equ 1000h ; 128K area for FAT (2x64K);; For our convenience: define macros for jump-over-unconditinal jumps;%macro jmpz 1 jnz %%skip jmp %1%%skip:%endmacro%macro jmpnz 1 jz %%skip jmp %1%%skip:%endmacro%macro jmpe 1 jne %%skip jmp %1%%skip:%endmacro%macro jmpne 1 je %%skip jmp %1%%skip:%endmacro%macro jmpc 1 jnc %%skip jmp %1%%skip:%endmacro%macro jmpnc 1 jc %%skip jmp %1%%skip:%endmacro%macro jmpb 1 jnb %%skip jmp %1%%skip:%endmacro%macro jmpnb 1 jb %%skip jmp %1%%skip:%endmacro;; Macros similar to res[bwd], but which works in the code segment (after; section .text);%macro zb 1 times %1 db 0%endmacro%macro zw 1 times %1 dw 0%endmacro%macro zd 1 times %1 dd 0%endmacro; ---------------------------------------------------------------------------; BEGIN THE BIOS/CODE/DATA SEGMENT; --------------------------------------------------------------------------- absolute 4*1Eh ; In the interrupt tablefdctab equ $fdctab1 resw 1fdctab2 resw 1%ifdef debug org 0100h..start: ;; Hook for debugger stuff. This gets automatically removed when; generating the real thing.;; Initialize the registers for debugger operation; cli mov ax,cs mov ds,ax mov es,ax mov ss,ax mov sp,StackBuf sti cld;; Load the actual boot sector so we can copy the data block; xor ax,ax ; Reset floppy xor dx,dx int 13h mov cx,6 ; Retry count...debug_tryloop: push cx mov bx,trackbuf mov cx,0001h xor dx,dx mov ax,0201h int 13h pop cx jnc debug_okay loop debug_tryloop int 3 ; Halt! (Breakpoint)debug_okay: mov si,trackbuf+0bh mov di,bsBytesPerSec mov cx,33h rep movsb;; Save bogus "BIOS floppy block" info to the stack in case we hit kaboom; push si push si push si ; Writing to the trackbuf is harmless;; Copy the BIOS data area; push ds xor ax,ax mov ds,ax mov si,0400h mov di,si mov cx,0100h rep movsw pop ds;;; A NOP where we can breakpoint, then jump into the code *after*; the segment register initialization section; nop jmp debugentrypt%endif absolute 0484hBIOS_vidrows resb 1 ; Number of screen rows absolute 0600htrackbuf equ $ ; Track buffer goes heretrackbufsize equ 16384 ; Safe size of track buffer; trackbuf ends at 4600h absolute 6000h ; Here we keep our BSS stuffStackBuf equ $ ; Start the stack here (grow down)VKernelBuf: resb vk_size ; "Current" vkernel alignb 4AppendBuf resb max_cmd_len+1 ; append=FKeyName resb 10*16 ; File names for F-key helpNumBuf resb 16 ; Buffer to load numberNumBufEnd equ NumBuf+15 ; Pointer to last byte in NumBufRootDir equ $ ; Location of root directoryRootDir1 resw 1RootDir2 resw 1DataArea equ $ ; Location of data areaDataArea1 resw 1DataArea2 resw 1FBytes equ $ ; Used by open/getcFBytes1 resw 1FBytes2 resw 1RootDirSize resw 1 ; Root dir size in sectorsDirScanCtr resw 1 ; Used while searching directoryDirBlocksLeft resw 1 ; DittoEndofDirSec resw 1 ; = trackbuf+bsBytesPerSec-31RunLinClust resw 1 ; Cluster # for LDLINUX.SYSClustSize resw 1 ; Bytes/clusterSecPerClust resw 1 ; Same as bsSecPerClust, but a wordBufSafe resw 1 ; Clusters we can load into trackbufBufSafeSec resw 1 ; = how many sectors?BufSafeBytes resw 1 ; = how many bytes?EndOfGetCBuf resw 1 ; = getcbuf+BufSafeBytesHighMemSize resw 1 ; High memory (K)KernelClust resw 1 ; Kernel size in clustersKernelK resw 1 ; Kernel size in kilobytesInitRDClust resw 1 ; Ramdisk size in clustersInitRDat resw 1 ; Load address (x256)ClustPerMoby resw 1 ; Clusters per 64KFClust resw 1 ; Number of clusters in open/getc fileFNextClust resw 1 ; Pointer to next cluster in d:oFPtr resw 1 ; Pointer to next char in bufferCmdOptPtr resw 1 ; Pointer to first option on cmd lineKernelCNameLen resw 1 ; Length of unmangled kernel nameInitRDCNameLen resw 1 ; Length of unmangled initrd nameNextCharJump resw 1 ; Routine to interpret next print charHiLoadAddr resw 1 ; Address pointer for high load loopSetupSecs resw 1 ; Number of setup sectorsTextAttrBX equ $TextAttribute resb 1 ; Text attribute for message fileTextPage resb 1 ; Active display pageCursorDX equ $CursorCol resb 1 ; Cursor column for message fileCursorRow resb 1 ; Cursor row for message fileScreenSize equ $VidCols resb 1 ; Columns on screen-1VidRows resb 1 ; Rows on screen-1RetryCount resb 1 ; Used for disk access retriesKbdFlags resb 1 ; Check for keyboard escapesMNameBuf resb 11 ; Generic mangled file name bufferKernelName resb 11 ; Mangled name for kernelInitRD resb 11 ; initrd= mangled nameKernelCName resb 13 ; Unmangled kernel nameInitRDCName resb 13 ; Unmangled initrd name section .text org 7C00hbootsec equ $ jmp short start ; 2 bytes nop ; 1 byte;; "Superblock" follows -- it's in the boot sector, so it's already; loaded and ready for us;bsOemName db 'SYSLINUX' ; The SYS command sets this, so...bsBytesPerSec zw 1bsSecPerClust zb 1bsResSectors zw 1bsFATs zb 1bsRootDirEnts zw 1bsSectors zw 1bsMedia zb 1bsFATsecs zw 1bsSecPerTrack zw 1bsHeads zw 1bsHiddenSecs equ $bsHidden1 zw 1bsHidden2 zw 1bsHugeSectors equ $bsHugeSec1 zw 1bsHugeSec2 zw 1bsDriveNumber zb 1bsReserved1 zb 1bsBootSignature zb 1 ; 29h if the following fields existbsVolumeID zd 1bsVolumeLabel zb 11bsFileSysType zb 8 ; Must be FAT12 for this version;; Note we don't check the constraints above now; we did that at install; time (we hope!);floppy_table equ $ ; No sense in wasting memory, overwrite startstart: cli ; No interrupts yet, please xor ax,ax mov es,ax mov ss,ax mov sp,StackBuf ; Just below BSS;; Now sautee the BIOS floppy info block to that it will support decent-; size transfers; the floppy block is 11 bytes and is stored in the; INT 1Eh vector (brilliant waste of resources, eh?);; Of course, if BIOSes had been properly programmed, we wouldn't have; had to waste precious boot sector space with this code.; mov bx,fdctab lds si,[ss:bx] ; DS:SI -> original push ds ; Save on stack in case push si ; we have to bail push bx mov cx,6 ; 12 bytes mov di,floppy_table push di cld rep movsw ; Faster to move words pop di mov ds,ax ; Now we can point DS to here, too mov cl,[bsSecPerTrack] ; Patch the sector count mov [di+4],cl; mov byte ptr [di+9],0Fh ; I have no clue what this does??? mov [bx+2],ax ; Segment 0 mov [bx],di ; offset floppy_block;; Ready to enable interrupts, captain; sti;; Reset floppy system to load new parameter block; xor dx,dx int 13h ; AH = 00h already;; Now we have to do some arithmetric to figure out where things are located.; If Microsoft had had brains they would already have done this for us,; and stored it in the superblock at format time, but here we go,; wasting precious boot sector space again...;debugentrypt: mov al,[bsFATs] ; Number of FATs jmpc kaboom ; If the floppy init failed ; (too far to be above the mov) 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?) adc dx,byte 0 mov [RootDir1],ax ; Location of root directory mov [RootDir2],dx mov [DataArea1],ax mov [DataArea2],dx push ax push dx mov ax,32 ; Size of a directory entry mul word [bsRootDirEnts] mov bx,[bsBytesPerSec] add ax,bx ; Round up, not down dec ax
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -