⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldlinux.asm

📁 Windows上的精简Linux系统
💻 ASM
📖 第 1 页 / 共 3 页
字号:
; -*- fundamental -*- (asm-mode sucks); $Id: ldlinux.asm,v 1.147 2004/06/13 20:50:44 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-2004  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.; ; ****************************************************************************%ifndef IS_MDSLINUX%define IS_SYSLINUX 1%endif%include "macros.inc"%include "config.inc"%include "kernel.inc"%include "bios.inc"%include "tracers.inc";; Some semi-configurable constants... change on your own risk.;my_id		equ syslinux_idFILENAME_MAX_LG2 equ 4			; log2(Max filename size Including final null)FILENAME_MAX	equ 11			; Max mangled filename sizeNULLFILE	equ ' '			; First char space == null filenameretry_count	equ 6			; How patient are we with the disk?%assign HIGHMEM_SLOP 0			; Avoid this much memory near the top;; This is what we need to do when idle;%macro	RESET_IDLE 0	; Nothing%endmacro%macro	DO_IDLE 0	; Nothing%endmacro;; 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 all of these, we; stick them at vk_seg:0000 and copy them down before we need them.;; Note: this structure can be added to, but it must ;%define vk_power	7		; log2(max number of vkernels)%define	max_vk		(1 << vk_power)	; Maximum number of vkernels%define vk_shift	(16-vk_power)	; Number of bits to shift%define vk_size		(1 << vk_shift)	; Size of a vkernel buffer		struc vkernelvk_vname:	resb FILENAME_MAX	; Virtual name **MUST BE FIRST!**vk_rname:	resb FILENAME_MAX	; Real namevk_appendlen:	resw 1		alignb 4vk_append:	resb max_cmd_len+1	; Command line		alignb 4vk_end:		equ $			; Should be <= vk_size		endstruc%ifndef DEPEND%if (vk_end > vk_size) || (vk_size*max_vk > 65536)%error "Too many vkernels defined, reduce vk_power"%endif%endif;; Segment assignments in the bottom 640K; Stick to the low 512K in case we're using something like M-systems flash; which load a driver into low RAM (evil!!);; 0000h - main code/data segment (and BIOS segment);real_mode_seg	equ 5000hfat_seg		equ 3000h		; 128K area for FAT (2x64K)vk_seg          equ 2000h		; Virtual kernelsxfer_buf_seg	equ 1000h		; Bounce buffer for I/O to high memcomboot_seg	equ real_mode_seg	; COMBOOT image loading zone; ---------------------------------------------------------------------------;   BEGIN CODE; ---------------------------------------------------------------------------;; Memory below this point is reserved for the BIOS and the MBR; 		absolute 1000htrackbuf	equ $			; Track buffer goes heretrackbufsize	equ 16384		; Safe size of track buffer;		trackbuf ends at 5000h;; Constants for the xfer_buf_seg;; The xfer_buf_seg is also used to store message file buffers.  We; need two trackbuffers (text and graphics), plus a work buffer; for the graphics decompressor.;xbs_textbuf	equ 0			; Also hard-coded, do not changexbs_vgabuf	equ trackbufsizexbs_vgatmpbuf	equ 2*trackbufsize                absolute 5000h          ; Here we keep our BSS stuffVKernelBuf:	resb vk_size		; "Current" vkernel		alignb 4AppendBuf       resb max_cmd_len+1	; append=Ontimeout	resb max_cmd_len+1	; ontimeoutOnerror		resb max_cmd_len+1	; onerrorKbdMap		resb 256		; Keyboard mapFKeyName	resb 10*16		; File names for F-key helpNumBuf		resb 15			; Buffer to load numberNumBufEnd	resb 1			; Last byte in NumBuf		alignb 8		; Expanded superblockSuperInfo	equ $		resq 16			; The first 16 bytes expanded 8 times		;		; These need to follow SuperInfo		;RootDir		resd 1			; Location of root directoryDataArea	resd 1			; Location of data areaRootDirSize	resw 1			; Root dir size in sectorsDirScanCtr	resw 1			; Used while searching directoryEndofDirSec	resw 1			; = trackbuf+bsBytesPerSec-31		alignb 4E820Buf		resd 5			; INT 15:E820 data bufferE820Mem		resd 1			; Memory detected by E820E820Max		resd 1			; Is E820 memory capped?HiLoadAddr      resd 1			; Address pointer for high load loopHighMemSize	resd 1			; End of memory pointer (bytes)RamdiskMax	resd 1			; Highest address for a ramdiskKernelSize	resd 1			; Size of kernel (bytes)SavedSSSP	resd 1			; Our SS:SP while running a COMBOOT imagePMESP		resd 1			; Protected-mode ESPClustPerMoby	resd 1			; Clusters per 64KClustSize	resd 1			; Bytes/clusterKernelName      resb 12		        ; Mangled name for kernel					; (note the spare byte after!)OrigKernelExt	resd 1			; Original kernel extensionFBytes		equ $			; Used by open/getcFBytes1		resw 1FBytes2		resw 1DirBlocksLeft	resw 1			; DittoRunLinClust	resw 1			; Cluster # for LDLINUX.SYSBufSafe		resw 1			; Clusters we can load into trackbufBufSafeSec	resw 1			; = how many sectors?BufSafeBytes	resw 1			; = how many bytes?EndOfGetCBuf	resw 1			; = getcbuf+BufSafeBytesKernelClust	resw 1			; Kernel size in clustersFClust		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 charSetupSecs	resw 1			; Number of setup sectorsA20Test		resw 1			; Counter for testing status of A20A20Type		resw 1			; A20 typeCmdLineLen	resw 1			; Length of command line including nullGraphXSize	resw 1			; Width of splash screen fileVGAPos		resw 1			; Pointer into VGA memoryVGACluster	resw 1			; Cluster pointer for VGA image fileVGAFilePtr	resw 1			; Pointer into VGAFileBufCom32SysSP	resw 1			; SP saved during COM32 syscallCursorDX        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-1BaudDivisor	resw 1			; Baud rate divisorFlowControl	equ $FlowOutput	resb 1			; Outputs to assert for serial flowFlowInput	resb 1			; Input bits for serial flowFlowIgnore	resb 1			; Ignore input unless these bits setTextAttribute   resb 1			; Text attribute for message fileRetryCount      resb 1			; Used for disk access retriesKbdFlags	resb 1			; Check for keyboard escapesLoadFlags	resb 1			; Loadflags from kernelA20Tries	resb 1			; Times until giving up on A20FuncFlag	resb 1			; Escape sequences received from keyboardDisplayMask	resb 1			; Display modes maskCopySuper	resb 1			; Distinguish .bs versus .bssMNameBuf        resb 11            	; Generic mangled file name bufferInitRD          resb 11                 ; initrd= mangled nameKernelCName     resb 13                 ; Unmangled kernel nameInitRDCName     resb 13            	; Unmangled initrd nameTextColorReg	resb 17			; VGA color registers for text modeVGAFileBuf	resb 13			; Unmangled VGA image nameVGAFileBufEnd	equ $VGAFileMBuf	resb 11			; Mangled VGA image name                alignb 4		; For the good of REP MOVSDcommand_line	resb max_cmd_len+2	; Command line bufferdefault_cmd	resb max_cmd_len+1	; "default" command linekern_cmd_len	equ $-command_line		section .text                org 7C00h;; Some of the things that have to be saved very early are saved; "close" to the initial stack pointer offset, in order to; reduce the code size...;StackBuf	equ $-44-32		; Start the stack here (grow down - 4K)PartInfo	equ StackBuf		; Saved partition table entryFloppyTable	equ PartInfo+16		; Floppy info table (must follow PartInfo)OrigFDCTabPtr	equ StackBuf-4		; The high dword on the stack;; Primary entry point.  Tempting as though it may be, we can't put the; initial "cli" here; the jmp opcode in the first byte is part of the; "magic number" (using the term very loosely) for the DOS superblock.;bootsec		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...;; These are the fields we actually care about.  We end up expanding them; all to dword size early in the code, so generate labels for both; the expanded and unexpanded versions.;;%macro		superb 1bx %+ %1	equ SuperInfo+($-superblock)*8+4bs %+ %1	equ $		zb 1%endmacro%macro		superw 1bx %+ %1	equ SuperInfo+($-superblock)*8bs %+ %1	equ $		zw 1%endmacro%macro		superd 1bx %+ %1	equ $			; no expansion for dwordsbs %+ %1	equ $		zd 1%endmacrosuperblock	equ $		superw BytesPerSec		superb SecPerClust		superw ResSectors		superb FATs		superw RootDirEnts		superw Sectors		superb Media		superw FATsecs		superw SecPerTrack		superw Headssuperinfo_size	equ ($-superblock)-1	; How much to expand		superd Hidden		superd HugeSectors		superb DriveNumber		superb Reserved1		superb BootSignature	; 29h if the following fields exist		superd VolumeIDbsVolumeLabel	zb 11bsFileSysType	zb 8			; Must be FAT12 or FAT16 for this versionsuperblock_len	equ $-superblockSecPerClust	equ bxSecPerClust;; 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		cld			; Copy upwards;; Set up the stack;		xor ax,ax		mov ss,ax		mov sp,StackBuf		; Just below BSS		mov es,ax;; DS:SI may contain a partition table entry.  Preserve it for us.;		mov cx,8		; Save partition info		mov di,sp		rep movsw		mov ds,ax		; Now we can initialize DS...		mov [di+bsDriveNumber-FloppyTable],dl;; 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 space with this code.;		mov bx,fdctab		lfs si,[bx]		; FS:SI -> original fdctab		push fs			; Save on stack in case we need to bail		push si		; Save the old fdctab even if hard disk so the stack layout		; is the same.  The instructions above do not change the flags		and dl,dl		; If floppy disk (00-7F), assume no					; partition table		js harddiskfloppy:		mov cl,6		; 12 bytes (CX == 0)		; es:di -> FloppyTable already		; This should be safe to do now, interrupts are off...		mov [bx],di		; FloppyTable		mov [bx+2],ax		; Segment 0		fs rep movsw		; Faster to move words		mov cl,[bsSecPerTrack]  ; Patch the sector count		mov [di-8],cl		; AX == 0 here		int 13h			; Some BIOSes need this		jmp short not_harddisk;; The drive number and possibly partition information was passed to us; by the BIOS or previous boot loader (MBR).  Current "best practice" is to; trust that rather than what the superblock contains.;; Would it be better to zero out bsHidden if we don't have a partition table?;; Note: di points to beyond the end of PartInfo;harddisk:		test byte [di-16],7Fh	; Sanity check: "active flag" should		jnz no_partition	; be 00 or 80		mov eax,[di-8]		; Partition offset (dword)		mov [bsHidden],eaxno_partition:;; Get disk drive parameters (don't trust the superblock.)  Don't do this for; floppy drives -- INT 13:08 on floppy drives will (may?) return info about; what the *drive* supports, not about the *media*.  Fortunately floppy disks; tend to have a fixed, well-defined geometry which is stored in the superblock.;		; DL == drive # still		mov ah,08h		int 13h		jc no_driveparm		and ah,ah		jnz no_driveparm		shr dx,8		inc dx			; Contains # of heads - 1		mov [bsHeads],dx		and cx,3fh		mov [bsSecPerTrack],cxno_driveparm:not_harddisk:;; Ready to enable interrupts, captain;		sti;; Insane hack to expand the superblock to dwords;expand_super:		xor eax,eax		mov es,ax			; INT 13:08 destroys ES		mov si,superblock		mov di,SuperInfo		mov cl,superinfo_size		; CH == 0.loop:		lodsw		dec si		stosd				; Store expanded word		xor ah,ah		stosd				; Store expanded byte		loop .loop;; Now we have to do some arithmetric to figure out where things are located.; If Micro$oft 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...;%define		Z di-superinfo_size*8-SuperInfodebugentrypt:		mov ax,[bxFATs]		; Number of FATs (eax<31:16> == 0)		mov edx,[Z+bxFATsecs]	; Sectors/FAT		mul edx			; Get the size of the FAT area		; edx <- 0		add eax,[bxHidden]		; Add hidden sectors		add eax,[Z+bxResSectors]	; And reserved sectors		mov [RootDir],eax	; Location of root directory		mov [DataArea],eax	; First data sector		push eax		mov eax,[Z+bxRootDirEnts]		shl ax,5		; Size of a directory entry		mov bx,[Z+bxBytesPerSec]		add ax,bx		; Round up, not down		dec ax		div bx			; Now we have the size of the root dir		mov [RootDirSize],ax		mov [DirScanCtr],ax		add bx,trackbuf-31		mov [Z+EndofDirSec],bx	; End of a single directory sector		add [Z+DataArea],eax		pop eax			; Reload root directory starting point;; 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:	push eax		mov bx,trackbuf		push bx		call getonesec		pop sisd_nextentry:	mov cx,11		cmp [si],ch		; Directory high water mark		je kaboom; This no longer fits... since we'd be dead anyway if there; was a nonfile named LDLINUX.SYS on the disk, it shouldn't; matter...;		test byte [si+11],18h	; Must be a file;		jnz sd_not_file		mov di,ldlinux_name		push si		repe cmpsb		pop si		je found_itsd_not_file:	add si,byte 32		; Distance to next		cmp si,[EndofDirSec]		jb sd_nextentry		pop eax		inc eax		dec word [DirScanCtr]		jnz sd_nextsec;; kaboom: write a message and bail out.;kaboom:		xor si,si		mov ss,si				mov sp,StackBuf-4 	; Reset stack		mov ds,si		; Reset data segment		pop dword [fdctab]	; Restore FDC table.patch:		mov si,bailmsg		call writestr		; Returns with AL = 0		cbw			; AH <- 0		int 16h			; Wait for keypress		int 19h			; And try once more to boot....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:	; Note: we actually leave two words on the stack here		; (who cares?)		mov eax,[bxSecPerClust]		mov bp,ax		; Load an entire cluster		movzx ebx,word [si+26]	; First cluster		mov [RunLinClust],bx	; Save for later use		dec bx			; First cluster is "cluster 2"		dec bx		mul ebx		add eax,[DataArea]		mov bx,ldlinux_sys

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -