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

📄 memdisk16.asm

📁 linux内核
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;; -*- fundamental -*-;; $Id$;; -----------------------------------------------------------------------;;   ;;   Copyright 1994-2004 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., 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.;;;; -----------------------------------------------------------------------;;;; init16.asm;;;; Routine to initialize and to trampoline into 32-bit;; protected memory.  This code is derived from bcopy32.inc and;; com32.inc in the main SYSLINUX distribution.;;MY_CS		equ 0x0800		; Segment address to useCS_BASE		equ (MY_CS << 4)	; Corresponding address; Low memory bounce bufferBOUNCE_SEG	equ (MY_CS+0x1000)%define DO_WBINVD 0%define STACK_HEAP_SIZE	(128*1024)		section .rodata align=16		section .data   align=16		section .bss    align=16;; -----------------------------------------------------------------------;;  Kernel image header;; -----------------------------------------------------------------------		section .text		; Must be first in image		bits 16cmdline		times 497 db 0		; We put the command line heresetup_sects	db 0root_flags	dw 0syssize		dw 0swap_dev	dw 0ram_size	dw 0vid_mode	dw 0root_dev	dw 0boot_flag	dw 0xAA55_start:		jmp short start		db "HdrS"		; Header signature		dw 0x0203		; Header version numberrealmode_swtch	dw 0, 0			; default_switch, SETUPSEGstart_sys_seg	dw 0x1000		; obsoleteversion_ptr	dw memdisk_version-0x200	; version string ptrtype_of_loader	db 0			; Filled in by boot loaderloadflags	db 1			; Please load highsetup_move_size	dw 0			; Unusedcode32_start	dd 0x100000		; 32-bit start addressramdisk_image	dd 0			; Loaded ramdisk image addressramdisk_size	dd 0			; Size of loaded ramdiskbootsect_kludge	dw 0, 0heap_end_ptr	dw 0pad1		dw 0cmd_line_ptr	dd 0			; Command lineramdisk_max	dd 0xffffffff		; Highest allowed ramdisk address		section .rodatamemdisk_version:		db "MEMDISK ", VERSION, " ", DATE, 0;; -----------------------------------------------------------------------;;  End kernel image header;; -----------------------------------------------------------------------;; Move ourselves down into memory to reduce the risk of conflicts;; then canonicalize CS to match the other segments.;		section .text		bits 16start:		mov ax,MY_CS		mov es,ax		movzx cx,byte [setup_sects]		inc cx			; Add one for the boot sector		shl cx,7		; Convert to dwords		xor si,si		xor di,di		mov fs,si		; fs <- 0		cld		rep movsd		mov ds,ax		mov ss,ax		xor esp,esp		; Stack at top of 64K segment		jmp MY_CS:.next.next:;; Copy the command line, if there is one;copy_cmdline:		xor di,di		; Bottom of our own segment (= "boot sector")		mov eax,[cmd_line_ptr]		and eax,eax		jz .endcmd		; No command line		mov si,ax		shr eax,4		; Convert to segment		and si,0x000F		; Starting offset only		mov gs,ax		mov cx,496		; Max number of bytes.copycmd:		gs lodsb		and al,al		jz .endcmd		stosb		loop .copycmd.endcmd:		xor al,al		stosb;; Now jump to 32-bit code;		sti		call init32;; When init32 returns, we have been set up, the new boot sector loaded,; and we should go and and run the newly loaded boot sector;; The setup function returns (in AL) the drive number which should be; put into DL;		mov dx,ax		cli		xor esi,esi		; No partition table involved		mov ds,si		; Make all the segments consistent		mov es,si		mov fs,si		mov gs,si		mov ss,si		mov esp,0x7C00		; Good place for SP to start out		jmp 0:0x7C00;; We enter protected mode, set up a flat 32-bit environment, run rep movsd; and then exit.  IMPORTANT: This code assumes cs == MY_CS.;; This code is probably excessively anal-retentive in its handling of; segments, but this stuff is painful enough as it is without having to rely; on everything happening "as it ought to.";		section .rodata	; desc base, limit, flags%macro	desc 3	dd (%2 & 0xffff) | ((%1 & 0xffff) << 16)	dd (%1 & 0xff000000) | (%2 & 0xf0000) | ((%3 & 0xf0ff) << 8) | ((%1 & 0x00ff0000) >> 16)%endmacro			align 8, db 0call32_gdt:	dw call32_gdt_size-1	; Null descriptor - contains GDT.adj1:		dd call32_gdt+CS_BASE	; pointer for LGDT instruction		dw 0				; 0008: Code segment, use16, readable, dpl 0, base CS_BASE, 64K		desc CS_BASE, 0xffff, 0x009b		; 0010: Data segment, use16, read/write, dpl 0, base CS_BASE, 64K		desc CS_BASE, 0xffff, 0x0093		; 0018: Data segment, use16, read/write, dpl 0, base 0, 4G		desc 0, 0xfffff, 0x809b		; 0020: Code segment, use32, read/write, dpl 0, base 0, 4G		desc 0, 0xfffff, 0xc09b		; 0028: Data segment, use32, read/write, dpl 0, base 0, 4G		desc 0, 0xfffff, 0xc093	call32_gdt_size:	equ $-call32_gdterr_a20:	db 'ERROR: A20 gate not responding!',13,10,0			section .bss		alignb 4SavedSSSP	resd 1			; Place to save SS:SPReturn		resd 1			; Return valueA20Test		resw 1			; Space to test A20A20Tries	resb 1				section .data		alignb 4Target		dd 0			; Target addressTarget_Seg	dw 20h			; Target CSA20Type		dw 0			; Default = unknown				section .text		bits 16;; Routines to enable and disable (yuck) A20.  These routines are gathered; from tips from a couple of sources, including the Linux kernel and; http://www.x86.org/.  The need for the delay to be as large as given here; is indicated by Donnie Barnes of RedHat, the problematic system being an; IBM ThinkPad 760EL.;; We typically toggle A20 twice for every 64K transferred.; %define	io_delay	call _io_delay%define IO_DELAY_PORT	80h		; Invalid port (we hope!)%define disable_wait 	32		; How long to wait for a disable%define A20_DUNNO	0		; A20 type unknown%define A20_NONE	1		; A20 always on?%define A20_BIOS	2		; A20 BIOS enable%define A20_KBC		3		; A20 through KBC%define A20_FAST	4		; A20 through port 92h		align 2, db 0A20List		dw a20_dunno, a20_none, a20_bios, a20_kbc, a20_fastA20DList	dw a20d_dunno, a20d_none, a20d_bios, a20d_kbc, a20d_fasta20_adjust_cnt	equ ($-A20List)/2slow_out:	out dx, al		; Fall through_io_delay:	out IO_DELAY_PORT,al		out IO_DELAY_PORT,al		retenable_a20:		pushad		mov byte [A20Tries],255 ; Times to try to make this worktry_enable_a20:;; Flush the caches;%if DO_WBINVD		call try_wbinvd%endif;; If the A20 type is known, jump straight to type;		mov bp,[A20Type]		add bp,bp			; Convert to word offset.adj4:		jmp word [bp+A20List];; First, see if we are on a system with no A20 gate;a20_dunno:a20_none:		mov byte [A20Type], A20_NONE		call a20_test		jnz a20_done;; Next, try the BIOS (INT 15h AX=2401h);a20_bios:		mov byte [A20Type], A20_BIOS		mov ax,2401h		pushf				; Some BIOSes muck with IF		int 15h		popf		call a20_test		jnz a20_done;; Enable the keyboard controller A20 gate;a20_kbc:		mov dl, 1			; Allow early exit		call empty_8042		jnz a20_done			; A20 live, no need to use KBC		mov byte [A20Type], A20_KBC	; Starting KBC command sequence		mov al,0D1h			; Command write		out 064h, al		call empty_8042_uncond		mov al,0DFh			; A20 on		out 060h, al		call empty_8042_uncond		; Verify that A20 actually is enabled.  Do that by		; observing a word in low memory and the same word in		; the HMA until they are no longer coherent.  Note that		; we don't do the same check in the disable case, because		; we don't want to *require* A20 masking (SYSLINUX should		; work fine without it, if the BIOS does.).kbc_wait:	push cx		xor cx,cx.kbc_wait_loop:		call a20_test		jnz a20_done_pop		loop .kbc_wait_loop		pop cx;; Running out of options here.  Final attempt: enable the "fast A20 gate";a20_fast:		mov byte [A20Type], A20_FAST	; Haven't used the KBC yet		in al, 092h		or al,02h		and al,~01h			; Don't accidentally reset the machine!		out 092h, al.fast_wait:	push cx		xor cx,cx.fast_wait_loop:		call a20_test		jnz a20_done_pop		loop .fast_wait_loop		pop cx;; Oh bugger.  A20 is not responding.  Try frobbing it again; eventually give up; and report failure to the user.;		dec byte [A20Tries]		jnz try_enable_a20		; Error message time		mov si,err_a20print_err:		lodsb		and al,al		jz die		mov bx,7		mov ah,0xe		int 10h		jmp print_errdie:		sti.hlt:		hlt		jmp short .hlt;; A20 unmasked, proceed...;a20_done_pop:	pop cxa20_done:	popad		ret;; This routine tests if A20 is enabled (ZF = 0).  This routine; must not destroy any register contents.;a20_test:		push es		push cx		push ax		mov cx,0FFFFh		; HMA = segment 0FFFFh		mov es,cx		mov cx,32		; Loop count		mov ax,[A20Test].a20_wait:	inc ax		mov [A20Test],ax		io_delay		; Serialize, and fix delay		cmp ax,[es:A20Test+CS_BASE+10h]		loopz .a20_wait.a20_done:	pop ax		pop cx		pop es		ret

⌨️ 快捷键说明

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