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

📄 extlinux.asm

📁 linux内核
💻 ASM
📖 第 1 页 / 共 3 页
字号:
; -*- fundamental -*- (asm-mode sucks); $Id$; ****************************************************************************;;  extlinux.asm;;  A program to boot Linux kernels off an ext2/ext3 filesystem.;;   Copyright (C) 1994-2005  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., 53 Temple Place Ste 330,;  Boston MA 02111-1307, USA; either version 2 of the License, or;  (at your option) any later version; incorporated herein by reference.; ; ****************************************************************************%define IS_EXTLINUX 1%include "macros.inc"%include "config.inc"%include "kernel.inc"%include "bios.inc"%include "tracers.inc"%include "layout.inc"%include "ext2_fs.inc";; Some semi-configurable constants... change on your own risk.;my_id		equ extlinux_id; NASM 0.98.38 croaks if these are equ's rather than macros...FILENAME_MAX_LG2 equ 8			; log2(Max filename size Including final null)FILENAME_MAX	equ (1 << FILENAME_MAX_LG2)	; Max mangled filename sizeNULLFILE	equ 0			; Null character == empty filenameNULLOFFSET	equ 0			; Position in which to lookretry_count	equ 16			; How patient are we with the disk?%assign HIGHMEM_SLOP 0			; Avoid this much memory near the topLDLINUX_MAGIC	equ 0x3eb202fe		; A random number to identify ourselves withMAX_OPEN_LG2	equ 6			; log2(Max number of open files)MAX_OPEN	equ (1 << MAX_OPEN_LG2)SECTOR_SHIFT	equ 9SECTOR_SIZE	equ (1 << SECTOR_SHIFT)MAX_SYMLINKS	equ 64			; Maximum number of symlinks per lookupSYMLINK_SECTORS	equ 2			; Max number of sectors in a symlink					; (should be >= FILENAME_MAX);; 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.;		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;; 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 4000hcache_seg	equ 3000h		; 64K area for metadata cachevk_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;; File structure.  This holds the information for each currently open file.;		struc open_file_tfile_left	resd 1			; Number of sectors left (0 = free)file_sector	resd 1			; Next linear sector to readfile_in_sec	resd 1			; Sector where inode livesfile_in_off	resw 1file_mode	resw 1		endstruc%ifndef DEPEND%if (open_file_t_size & (open_file_t_size-1))%error "open_file_t is not a power of 2"%endif%endif; ---------------------------------------------------------------------------;   BEGIN CODE; ---------------------------------------------------------------------------;; Memory below this point is reserved for the BIOS and the MBR;		section .earlybsstrackbufsize	equ 8192trackbuf	resb trackbufsize	; Track buffer goes heregetcbuf		resb trackbufsize		; ends at 4800h		section .latebssSuperBlock	resb 1024		; ext2 superblockSuperInfo	resq 16			; DOS superblock expandedClustSize	resd 1			; Bytes/cluster ("block")SecPerClust	resd 1			; Sectors/clusterClustMask	resd 1			; Sectors/cluster - 1PtrsPerBlock1	resd 1			; Pointers/clusterPtrsPerBlock2	resd 1			; (Pointers/cluster)^2DriveNumber	resb 1			; BIOS drive numberClustShift	resb 1			; Shift count for sectors/clusterClustByteShift	resb 1			; Shift count for bytes/cluster		alignb open_file_t_sizeFiles		resb MAX_OPEN*open_file_t_size;; 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		section .text;; 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 'EXTLINUX'		; 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		;		; This is as far as FAT12/16 and FAT32 are consistent		;		zb 54			; FAT12/16 need 26 more bytes,					; FAT32 need 54 more bytessuperblock_len	equ $-superblock;; Note we don't check the constraints above now; we did that at install; time (we hope!);start:		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...;; 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		mov [DriveNumber],dl	; Save drive number in DL		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;; Do we have EBIOS (EDD)?;eddcheck:		mov bx,55AAh		mov ah,41h		; EDD existence query		mov dl,[DriveNumber]		int 13h		jc .noedd		cmp bx,0AA55h		jne .noedd		test cl,1		; Extended disk access functionality set		jz .noedd		;		; We have EDD support...		;		mov byte [getlinsec.jmp+1],(getlinsec_ebios-(getlinsec.jmp+2)).noedd:;; Load the first sector of LDLINUX.SYS; this used to be all proper; with parsing the superblock and root directory; it doesn't fit; together with EBIOS support, unfortunately.;		mov eax,[FirstSector]	; Sector start		mov bx,ldlinux_sys	; Where to load it		call getonesec				; Some modicum of integrity checking		cmp dword [ldlinux_magic+4],LDLINUX_MAGIC^HEXDATE		jne kaboom		; Go for it...		jmp ldlinux_ent;; getonesec: get one disk sector;getonesec:		mov bp,1		; One sector		; Fall through;; getlinsec: load a sequence of BP floppy sector given by the linear sector;	     number in EAX into the buffer at ES:BX.  We try to optimize;	     by loading up to a whole track at a time, but the user;	     is responsible for not crossing a 64K boundary.;	     (Yes, BP is weird for a count, but it was available...);;	     On return, BX points to the first byte after the transferred;	     block.;;            This routine assumes CS == DS, and trashes most registers.;; Stylistic note: use "xchg" instead of "mov" when the source is a register; that is dead from that point; this saves space.  However, please keep; the order to dst,src to keep things sane.;getlinsec:		add eax,[bsHidden]		; Add partition offset		xor edx,edx			; Zero-extend LBA (eventually allow 64 bits).jmp:		jmp strict short getlinsec_cbios;; getlinsec_ebios:;; getlinsec implementation for EBIOS (EDD);getlinsec_ebios:.loop:                push bp                         ; Sectors left.retry2:		call maxtrans			; Enforce maximum transfer size		movzx edi,bp			; Sectors we are about to read		mov cx,retry_count.retry:		; Form DAPA on stack		push edx		push eax		push es		push bx		push di		push word 16		mov si,sp		pushad                mov dl,[DriveNumber]		push ds		push ss		pop ds				; DS <- SS                mov ah,42h                      ; Extended Read		int 13h		pop ds		popad		lea sp,[si+16]			; Remove DAPA		jc .error        	pop bp		add eax,edi			; Advance sector pointer		sub bp,di			; Sectors left                shl di,SECTOR_SHIFT		; 512-byte sectors                add bx,di                   	; Advance buffer pointer                and bp,bp                jnz .loop                ret.error:		; Some systems seem to get "stuck" in an error state when		; using EBIOS.  Doesn't happen when using CBIOS, which is		; good, since some other systems get timeout failures		; waiting for the floppy disk to spin up.		pushad				; Try resetting the device		xor ax,ax		mov dl,[DriveNumber]		int 13h		popad		loop .retry			; CX-- and jump if not zero		;shr word [MaxTransfer],1	; Reduce the transfer size		;jnz .retry2		; Total failure.  Try falling back to CBIOS.		mov byte [getlinsec.jmp+1],(getlinsec_cbios-(getlinsec.jmp+2))		;mov byte [MaxTransfer],63	; Max possibe CBIOS transfer		pop bp		; ... fall through ...;; getlinsec_cbios:;; getlinsec implementation for legacy CBIOS;getlinsec_cbios:.loop:		push edx		push eax		push bp		push bx		movzx esi,word [bsSecPerTrack]		movzx edi,word [bsHeads]		;		; Dividing by sectors to get (track,sector): we may have		; up to 2^18 tracks, so we need to use 32-bit arithmetric.		;		div esi		xor cx,cx		xchg cx,dx		; CX <- sector index (0-based)					; EDX <- 0		; eax = track #		div edi			; Convert track to head/cyl		; We should test this, but it doesn't fit...		; cmp eax,1023		; ja .error		;		; Now we have AX = cyl, DX = head, CX = sector (0-based),		; BP = sectors to transfer, SI = bsSecPerTrack,		; ES:BX = data target		;		call maxtrans			; Enforce maximum transfer size		; Must not cross track boundaries, so BP <= SI-CX		sub si,cx		cmp bp,si		jna .bp_ok		mov bp,si.bp_ok:			shl ah,6		; Because IBM was STOOPID					; and thought 8 bits were enough					; then thought 10 bits were enough...		inc cx			; Sector numbers are 1-based, sigh		or cl,ah		mov ch,al		mov dh,dl		mov dl,[DriveNumber]		xchg ax,bp		; Sector to transfer count		mov ah,02h		; Read sectors		mov bp,retry_count.retry:		pushad		int 13h		popad		jc .error.resume:		movzx ecx,al		; ECX <- sectors transferred		shl ax,SECTOR_SHIFT	; Convert sectors in AL to bytes in AX		pop bx		add bx,ax		pop bp		pop eax		pop edx		add eax,ecx		sub bp,cx		jnz .loop		ret.error:		dec bp		jnz .retry		xchg ax,bp		; Sectors transferred <- 0		shr word [MaxTransfer],1		jnz .resume		; Fall through to disk_error	;; kaboom: write a message and bail out.;disk_error: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:					; When we have full code, intercept here		mov si,bailmsg		; Write error message, this assumes screen page 0.loop:		lodsb		and al,al                jz .done		mov ah,0Eh		; Write to screen as TTY		mov bx,0007h		; Attribute		int 10h		jmp short .loop.done:		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;

⌨️ 快捷键说明

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