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

📄 asm.s

📁 i386的bootloader源码grub
💻 S
📖 第 1 页 / 共 3 页
字号:
/* *  GRUB  --  GRand Unified Bootloader *  Copyright (C) 1999,2000,2001,2002,2004 Free Software Foundation, Inc. * *  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; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* * Note: These functions defined in this file may be called from C. *       Be careful of that you must not modify some registers. Quote *       from gcc-2.95.2/gcc/config/i386/i386.h:	   1 for registers not available across function calls.   These must include the FIXED_REGISTERS and also any   registers that can be used without being saved.   The latter must include the registers where values are returned   and the register where structure-value addresses are passed.   Aside from that, you can include as many other registers as you like.  ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg{  1, 1, 1, 0, 0, 0, 0, 1, 1,  1,  1,  1,  1,  1,  1,  1,  1 } */#define ASM_FILE#include "shared.h"#ifdef STAGE1_5# define	ABS(x)	((x) - EXT_C(main) + 0x2200)#else# define	ABS(x)	((x) - EXT_C(main) + 0x8200)#endif		.file	"asm.S"	.text	/* Tell GAS to generate 16-bit instructions so that this code works	   in real mode. */	.code16#ifndef STAGE1_5	/* 	 * In stage2, do not link start.S with the rest of the source	 * files directly, so define the start symbols here just to	 * force ld quiet. These are not referred anyway.	 */	.globl	start, _startstart:_start:#endif /* ! STAGE1_5 */	ENTRY(main)	/*	 *  Guarantee that "main" is loaded at 0x0:0x8200 in stage2 and	 *  at 0x0:0x2200 in stage1.5.	 */	ljmp $0, $ABS(codestart)	/*	 *  Compatibility version number	 *	 *  These MUST be at byte offset 6 and 7 of the executable	 *  DO NOT MOVE !!!	 */	. = EXT_C(main) + 0x6	.byte	COMPAT_VERSION_MAJOR, COMPAT_VERSION_MINOR	/*	 *  This is a special data area 8 bytes from the beginning.	 */	. = EXT_C(main) + 0x8VARIABLE(install_partition)	.long	0xFFFFFFVARIABLE(saved_entryno)	.long	0VARIABLE(stage2_id)	.byte	STAGE2_IDVARIABLE(force_lba)	.byte	0VARIABLE(version_string)	.string VERSIONVARIABLE(config_file)#ifndef STAGE1_5	.string "/boot/grub/menu.lst"#else   /* STAGE1_5 */	.long	0xffffffff	.string "/boot/grub/stage2"#endif  /* STAGE1_5 */	/*	 *  Leave some breathing room for the config file name.	 */	. = EXT_C(main) + 0x70/* the real mode code continues... */codestart:	cli		/* we're not safe here! */	/* set up %ds, %ss, and %es */	xorw	%ax, %ax	movw	%ax, %ds	movw	%ax, %ss	movw	%ax, %es#ifndef SUPPORT_DISKLESS	/*	 * Save the sector number of the second sector (i.e. this sector)	 * in INSTALL_SECOND_SECTOR. See also "stage2/start.S".	 */	ADDR32	movl	%ebp, EXT_C(install_second_sector)#endif		/* set up the real mode/BIOS stack */	movl	$STACKOFF, %ebp	movl	%ebp, %esp	sti		/* we're safe again */#ifndef SUPPORT_DISKLESS	/* save boot drive reference */	ADDR32	movb	%dl, EXT_C(boot_drive)	/* reset disk system (%ah = 0) */	int	$0x13#endif	/* transition to protected mode */	DATA32	call EXT_C(real_to_prot)	/* The ".code32" directive takes GAS out of 16-bit mode. */	.code32	/* clean out the bss */	/* set %edi to the bss starting address */#if defined(HAVE_USCORE_USCORE_BSS_START_SYMBOL)	movl	$__bss_start, %edi#elif defined(HAVE_USCORE_EDATA_SYMBOL)	movl	$_edata, %edi#elif defined(HAVE_EDATA_SYMBOL)	movl	$edata, %edi#endif	/* set %ecx to the bss end */	#if defined(HAVE_END_SYMBOL)	movl	$end, %ecx#elif defined(HAVE_USCORE_END_SYMBOL)	movl	$_end, %ecx#endif	/* compute the bss length */	subl	%edi, %ecx		/* zero %al */	xorb	%al, %al	/* set the direction */	cld		/* clean out */	rep	stosb		/*	 *  Call the start of main body of C code, which does some	 *  of it's own initialization before transferring to "cmain".	 */	call EXT_C(init_bios_info)/* *  This call is special...  it never returns...  in fact it should simply *  hang at this point! */ENTRY(stop)	call	EXT_C(prot_to_real)	/*	 * This next part is sort of evil.  It takes advantage of the	 * byte ordering on the x86 to work in either 16-bit or 32-bit	 * mode, so think about it before changing it.	 */ENTRY(hard_stop)	hlt	jmp EXT_C(hard_stop)#ifndef STAGE1_5/* * stop_floppy() * * Stops the floppy drive from spinning, so that other software is * jumped to with a known state. */ENTRY(stop_floppy)	pusha	call	EXT_C(prot_to_real)	.code16	xorb	%dl, %dl	int	$0x13	DATA32  call EXT_C(real_to_prot)	.code32	popa	ret/* * grub_reboot() * * Reboot the system. At the moment, rely on BIOS. */ENTRY(grub_reboot)	call	EXT_C(prot_to_real)	.code16	/* cold boot */	movw	$0x0472, %di	movw	%ax, (%di)	ljmp	$0xFFFF, $0x0000	.code32	/* * grub_halt(int no_apm) * * Halt the system, using APM if possible. If NO_APM is true, don't use * APM even if it is available. */ENTRY(grub_halt)	/* get the argument */	movl	4(%esp), %eax		/* see if zero */	testl	%eax, %eax	jnz	EXT_C(stop)	call	EXT_C(prot_to_real)	.code16		/* detect APM */	movw	$0x5300, %ax	xorw	%bx, %bx	int	$0x15	jc	EXT_C(hard_stop)	/* don't check %bx for buggy BIOSes... */	/* disconnect APM first */	movw	$0x5304, %ax	xorw	%bx, %bx	int	$0x15	/* connect APM */	movw	$0x5301, %ax	xorw	%bx, %bx	int	$0x15	jc	EXT_C(hard_stop)	/* set APM protocol level - 1.1 or bust. (this covers APM 1.2 also) */	movw	$0x530E, %ax	xorw	%bx, %bx	movw	$0x0101, %cx	int	$0x15	jc	EXT_C(hard_stop)		/* set the power state to off */	movw	$0x5307, %ax	movw	$1, %bx	movw	$3, %cx	int	$0x15	/* shouldn't reach here */	jmp	EXT_C(hard_stop)	.code32	/* * track_int13(int drive) * * Track the int13 handler to probe I/O address space. */ENTRY(track_int13)	pushl	%ebp	movl	%esp, %ebp	pushl	%ebx	pushl	%edi	/* copy the original int13 handler segment:offset */	movl	$0x4c, %edi	movl	(%edi), %eax	movl	%eax, track_int13_addr			/* replace the int1 handler */	movl	$0x4, %edi	pushl	(%edi)	movl	$ABS(int1_handler), %eax	movl	%eax, (%edi)	/* read the MBR to call int13 successfully */	movb	8(%ebp), %dl		call	EXT_C(prot_to_real)	.code16	movw	$SCRATCHSEG, %ax	movw	%ax, %es	xorw	%bx, %bx	movw	$1, %cx	xorb	%dh, %dh	/* save FLAGS on the stack to emulate int13 */	pushfw		/* set the TF flag */	/* FIXME: this can be simplified not to use AX */	pushfw	popw	%ax	orw	$0x100, %ax	pushw	%ax	popfw	movw	$0x0201, %ax	.byte	0x9a		/* lcall */track_int13_addr:	.word	0		/* offset */	.word	0		/* segment */	/* TF is cleared here automatically */		DATA32	call	EXT_C(real_to_prot)	.code32	/* restore the int1 handler */	movl	$0x4, %edi	popl	(%edi)	popl	%edi	popl	%ebx	popl	%ebp		ret/* * Check if the next instruction is I/O, and if this is true, add the * port into the io map. * * Note: Probably this will make the execution of int13 very slow. * * Note2: In this implementation, all we can know is I/O-mapped I/O. It * is impossible to detect memory-mapped I/O. */int1_handler:	.code16		pushw	%bp	movw	%sp, %bp	pushw	%ds	pushw	%ax	pushw	%si	pushw	%dx		/* IP */	movw	2(%bp), %si	/* CS */	movw	4(%bp), %ax	movw	%ax, %ds	/* examine the next instruction */1:	lodsb	(%si), %al	/* skip this code if it is a prefix */	cmpb	$0x2E, %al	je	1b	cmpb	$0x36, %al	je	1b	cmpb	$0x3E, %al	je	1b	cmpb	$0x26, %al	je	1b	cmpb	$0x64, %al	jl	2f	cmpb	$0x67, %al	jle	1b2:	cmpb	$0xF0, %al	jl	3f	cmpb	$0xF3, %al	jle	1b	3:	/* check if this code is out* or in* */	/* ins? or outs? */	cmpb	$0x6C, %al	jl	4f	cmpb	$0x6F, %al	jle	5f4:	/* in? or out? (register operand version) */	cmpb	$0xEC, %al	jl	6f	cmpb	$0xEF, %al	jle	5f	6:	/* in? or out? (immediate operand version) */	cmpb	$0xE4, %al	jl	8f	cmpb	$0xE7, %al	jg	8f7:	/* immediate has a port */	lodsb	(%si), %al	movzbw	%al, %dx	5:	/* %dx has a port */	/* set %ds to zero */	xorw	%ax, %ax	movw	%ax, %ds			/* set %si to the io map */	movw	$ABS(EXT_C(io_map)), %si		9:	/* check if the io map already has the port */	lodsw	(%si), %ax	/* check if this is the end */	testw	%ax, %ax	jz	1f	/* check if this matches the port */	cmpw	%ax, %dx	jne	9b	/* if so, leave from this handler */	jmp	8f	1:	/* check for the buffer overrun */	cmpw	$(ABS(EXT_C(io_map)) + (IO_MAP_SIZE + 1) * 2), %si	je	8f	/* add the port into the io map */	movw	%dx, -2(%si)8:	/* restore registers */		popw	%dx	popw	%si	popw	%ax	popw	%ds	popw	%bp	iret		.code32ENTRY(io_map)	.space	(IO_MAP_SIZE + 1) * 2		/* * set_int15_handler(void) * * Set up int15_handler. */ENTRY(set_int15_handler)	pushl	%edi		/* save the original int15 handler */	movl	$0x54, %edi	movw	(%edi), %ax	movw	%ax, ABS(int15_offset)	movw	2(%edi), %ax	movw	%ax, ABS(int15_segment)	/* save the new int15 handler */	movw	$ABS(int15_handler), %ax	movw	%ax, (%edi)	xorw	%ax, %ax	movw	%ax, 2(%edi)	popl	%edi	ret/* * unset_int15_handler(void) * * Restore the original int15 handler */ENTRY(unset_int15_handler)	pushl	%edi		/* check if int15_handler is set */	movl	$0x54, %edi	movw	$ABS(int15_handler), %ax	cmpw	%ax, (%edi)	jne	1f	xorw	%ax, %ax	cmpw	%ax, 2(%edi)	jne	1f	/* restore the original */	movw	ABS(int15_offset), %ax	movw	%ax, (%edi)	movw	ABS(int15_segment), %ax	movw	%ax, 2(%edi)1:	popl	%edi	ret/* * Translate a key code to another. * * Note: This implementation cannot handle more than one length * scancodes (such as Right Ctrl). */	.code16int15_handler:	/* if non-carrier, ignore it */	jnc	1f	/* check if AH=4F */	cmpb	$0x4F, %ah	jne	1f	/* E0 and E1 are special */	cmpb	$0xE1, %al	je	4f	cmpb	$0xE0, %al	/* this flag is actually the machine code (je or jmp) */int15_skip_flag:		je	4f		pushw	%bp	movw	%sp, %bp		pushw	%bx	pushw	%dx	pushw	%ds	pushw	%si	/* save bits 0-6 of %al in %dl */	movw	%ax, %dx	andb	$0x7f, %dl	/* save the highest bit in %bl */	movb	%al, %bl	xorb	%dl, %bl	/* set %ds to 0 */	xorw	%ax, %ax	movw	%ax, %ds	/* set %si to the key map */	movw	$ABS(EXT_C(bios_key_map)), %si	/* find the key code from the key map */2:	lodsw	/* check if this is the end */	testw	%ax, %ax	jz	3f	/* check if this matches the key code */	cmpb	%al, %dl	jne	2b	/* if so, perform the mapping */	movb	%ah, %dl3:	/* restore %ax */	movw	%dx, %ax	orb	%bl, %al	/* make sure that CF is set */	orw	$1, 6(%bp)	/* restore other registers */	popw	%si	popw	%ds	popw	%dx	popw	%bx	popw	%bp	iret	4:	/* tricky: jmp (0x74) <-> je (0xeb) */	xorb	$(0x74 ^ 0xeb), ABS(int15_skip_flag)1:	/* just cascade to the original */	/* ljmp */	.byte	0xeaint15_offset:	.word	0int15_segment:	.word	0	.code32	.align	4	ENTRY(bios_key_map)	.space	(KEY_MAP_SIZE + 1) * 2		/* * set_int13_handler(map) * * Copy MAP to the drive map and set up int13_handler. */ENTRY(set_int13_handler)	pushl	%ebp	movl	%esp, %ebp	pushl	%edi	pushl	%esi	/* copy MAP to the drive map */	movl	$(DRIVE_MAP_SIZE * 2), %ecx	movl	$ABS(drive_map), %edi	movl	8(%ebp), %esi	cld	rep	movsb	/* save the original int13 handler */	movl	$0x4c, %edi	movw	(%edi), %ax	movw	%ax, ABS(int13_offset)	movw	2(%edi), %ax	movw	%ax, ABS(int13_segment)		/* decrease the lower memory size and set it to the BIOS memory */	movl	$0x413, %edi	decw	(%edi)	xorl	%eax, %eax	movw	(%edi), %ax		/* compute the segment */	shll	$6, %eax	/* save the new int13 handler */	movl	$0x4c, %edi	movw	%ax, 2(%edi)	xorw	%cx, %cx	movw	%cx, (%edi)	/* copy int13_handler to the reserved area */	shll	$4, %eax	movl	%eax, %edi	movl	$ABS(int13_handler), %esi	movl	$(int13_handler_end - int13_handler), %ecx	rep	movsb	popl	%esi	popl	%edi	popl	%ebp	ret	/*  * Map a drive to another drive. */		.code16	int13_handler:	pushw	%ax	pushw	%bp	movw	%sp, %bp		pushw	%si	/* set %si to the drive map */	movw	$(drive_map - int13_handler), %si	/* find the drive number from the drive map */	cld1:		lodsw	%cs:(%si), %ax	/* check if this is the end */	testw	%ax, %ax	jz	2f	/* check if this matches the drive number */	cmpb	%al, %dl	jne	1b	/* if so, perform the mapping */	movb	%ah, %dl2:	/* restore %si */	popw	%si	/* save %ax in the stack */	pushw	%ax	/* simulate the interrupt call */	pushw	8(%bp)	/* set %ax and %bp to the original values */	movw	2(%bp), %ax	movw	(%bp), %bp	/* lcall */	.byte	0x9aint13_offset:	.word	0int13_segment:	.word	0	/* save flags */	pushf	/* restore %bp */	movw	%sp, %bp	/* save %ax */	pushw	%ax	/* set the flags in the stack to the value returned by int13 */	movw	(%bp), %ax	movw	%ax, 0xc(%bp)	/* check if should map the drive number */	movw	6(%bp), %ax	cmpw	$0x8, %ax	jne	3f	cmpw	$0x15, %ax	jne	3f	/* check if the mapping was performed */	movw	2(%bp), %ax	testw	%ax, %ax	jz	3f	/* perform the mapping */	movb	%al, %dl3:	popw	%ax	movw	4(%bp), %bp	addw	$8, %sp	iret	.align	4drive_map:	.space	(DRIVE_MAP_SIZE + 1) * 2int13_handler_end:		.code32		/* * chain_stage1(segment, offset, part_table_addr) * *  This starts another stage1 loader, at segment:offset. */ENTRY(chain_stage1)	/* no need to save anything, just use %esp */	/* store %ESI, presuming %ES is 0 */	movl	0xc(%esp), %esi	/* store new offset */	movl	0x8(%esp), %eax	movl	%eax, offset	/* store new segment */	movw	0x4(%esp), %ax	movw	%ax, segment	/* set up to pass boot drive */	movb	EXT_C(boot_drive), %dl	call	EXT_C(prot_to_real)	.code16#ifdef ABSOLUTE_WITHOUT_ASTERISK	DATA32	ADDR32	ljmp	(offset)#else	DATA32	ADDR32	ljmp	*(offset)#endif	.code32#endif /* STAGE1_5 */#ifdef STAGE1_5/* * chain_stage2(segment, offset, second_sector) * *  This starts another stage2 loader, at segment:offset.  It presumes *  that the other one starts with this same "asm.S" file, and passes *  parameters by writing the embedded install variables. */ENTRY(chain_stage2)	/* no need to save anything, just use %esp */	/* store new offset */	movl	0x8(%esp), %eax	movl	%eax, offset	movl	%eax, %ebx

⌨️ 快捷键说明

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