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

📄 start32.s

📁 linux下从网卡远程启动
💻 S
📖 第 1 页 / 共 2 页
字号:
/* #defines because ljmp wants a number, probably gas bug *//*	.equ	KERN_CODE_SEG,_pmcs-_gdt	*/#define	KERN_CODE_SEG	0x08	.equ	KERN_DATA_SEG,_pmds-_gdt/*	.equ	REAL_CODE_SEG,_rmcs-_gdt	*/#define	REAL_CODE_SEG	0x18	.equ	REAL_DATA_SEG,_rmds-_gdt	.equ	FLAT_CODE_SEG,_pmcs2-_gdt	.equ	FLAT_DATA_SEG,_pmds2-_gdt	.equ	CR0_PE,1#ifdef CONFIG_X86_64	.equ	LM_CODE_SEG,  _lmcs-_gdt	.equ	LM_DATA_SEG,  _lmds-_gdt#endif	.equ	MSR_K6_EFER,   0xC0000080	.equ	EFER_LME,      0x00000100	.equ	X86_CR4_PAE,   0x00000020	.equ	CR0_PG,        0x80000000#undef CODE16#if defined(PCBIOS) || defined(TAGGED_IMAGE)#define	CODE16#endif	#ifdef	GAS291#define DATA32 data32;#define ADDR32 addr32;#define	LJMPI(x)	ljmp	x#else#define DATA32 data32#define ADDR32 addr32/* newer GAS295 require #define	LJMPI(x)	ljmp	*x */#define	LJMPI(x)	ljmp	x#endif/* * NOTE: if you write a subroutine that is called from C code (gcc/egcs), * then you only have to take care of %ebx, %esi, %edi and %ebp.  These * registers must not be altered under any circumstance.  All other registers * may be clobbered without any negative side effects.  If you don't follow * this rule then you'll run into strange effects that only occur on some * gcc versions (because the register allocator may use different registers). * * All the data32 prefixes for the ljmp instructions are necessary, because * the assembler emits code with a relocation address of 0.  This means that * all destinations are initially negative, which the assembler doesn't grok, * because for some reason negative numbers don't fit into 16 bits. The addr32 * prefixes are there for the same reasons, because otherwise the memory * references are only 16 bit wide.  Theoretically they are all superfluous. * One last note about prefixes: the data32 prefixes on all call _real_to_prot * instructions could be removed if the _real_to_prot function is changed to * deal correctly with 16 bit return addresses.  I tried it, but failed. *//**************************************************************************START - Where all the fun begins....**************************************************************************//* this must be the first thing in the file because we enter from the top */	.text	.arch i386	.global	_start_start:	.code32	cli	/* Save the initial ebp value */	pushl	%ebp	/*	 * See where I am running, and compute virt_offset	 */	call	1f1:	popl	%ebp	subl	$1b, %ebp	movl	%ebp, virt_offset(%ebp)	/*	 * Save the initial register contents	 */	movl	%edi,  0 + initial_regs(%ebp)	movl	%esi,  4 + initial_regs(%ebp)	popl	%edi /* original %ebp */	movl	%edi,  8 + initial_regs(%ebp)	movl	%esp, 12 + initial_regs(%ebp)	movl	%ebx, 16 + initial_regs(%ebp)	movl	%edx, 20 + initial_regs(%ebp)	movl	%ecx, 24 + initial_regs(%ebp)	movl	%eax, 28 + initial_regs(%ebp)	/*	 * Setup the stack	 */	leal	_estack(%ebp), %esp	/* Fixup the gdt */	leal	_pmcs(%ebp), %eax	pushl	%eax	pushl	%ebp	call	set_seg_base	addl	$8, %esp	/* Fixup gdtarg */	leal	_gdt(%ebp), %eax	movl	%eax, gdtarg +2(%ebp)	/* Load the global descriptor table */	cs	lgdt	gdtarg(%ebp)	/* reload cs */	ljmp	$KERN_CODE_SEG, $1f1:	/* reload other segment registers */	movl	$KERN_DATA_SEG, %eax	movl	%eax,%ds	movl	%eax,%es	movl	%eax,%ss	movl	%eax,%fs	movl	%eax,%gs	/* Fixup the stack pointer */	subl	%ebp, %esp	call	main	/* fall through */	/* exit */	/* Switch back to the original stack */	movl	12 + initial_regs, %esp	subl	virt_offset, %esp#ifdef CODE16	/* Make certain we don't have a null return address.	 */	cmpl	$0, 0(%esp)	je	exit16#endif	/* Revert to flat physical addresses and return */	call	_virt_to_phys	xorl	%eax, %eax	ret#ifdef CODE16exit16:	/* We have a null return address so assume a 16bit far return	 * address is burried deeper on the stack.	 */	movzwl	4(%esp), %ebx	movzwl  6(%esp), %ecx	pushl	$ 10f	pushl	$ 20f - 10f	call	_real_call	.section ".text16"10:	.code16	cli	/* Switch back to the callers stack, and return */	movw	%bx, %sp	movw	%cx, %ss	popf	lret20:	.code32	.previous#endif /* CODE16 */	.code32#if defined(TAGGED_IMAGE)/**************************************************************************XSTART16 - Transfer control to the kernel just loaded**************************************************************************/	.globl	xstart16xstart16:	pushl	%ebp	movl	%esp,%ebp	pushl	%ebx	pushl	%esi	pushl	%edi	movl	8(%ebp),%edx	movl	12(%ebp),%ebx	/* FIXME handle the bootp record */	movl	16(%ebp),%ecx	/* bootp record (32bit pointer) */	shll	$12,%ecx	/* convert to segment:offset form */	shrw	$12,%cx	pushl	$ 10f	pushl	$ 20f - 10f	call	_real_call	.section ".text16"10:	.code16	popw	%ax		/* get the return ip addr */	pushl	%ecx		/* bootp record */	pushl	%ebx		/* file header */	pushw	%cs		/* Setup the far return address */	pushw	%ax			pushl	%edx		/* Setup the far address to call */	lret			/* Back into the routine I'm calling */20:	.code32	.previous		popl	%edi	popl	%esi	popl	%ebx	popl	%ebp	ret#endif /* TAGGED_IMAGE */#if defined(RELOCATE)/**************************************************************************RELOCATE_TO - relocate etherboot to the specified address**************************************************************************/	.globl relocate_torelocate_to:	/* Save the callee save registers */	pushl	%ebp	pushl	%esi	pushl	%edi	/* Compute the virtual destination address */	movl	16(%esp), %edi	# dest	subl	virt_offset, %edi		/* Compute the new value of virt_offset */	movl	16(%esp), %ebp	# virt_offset	subl	$_text, %ebp	/* Fixup the gdt */	pushl	$_pmcs	pushl	%ebp		# virt_offset	call	set_seg_base	addl	$8, %esp	/* Fixup gdtarg */	leal	_gdt(%ebp), %eax	movl	%eax, gdtarg +2	/* Fixup virt_offset */	movl	%ebp, virt_offset	/* Load the move parameters */	movl	$_text, %esi	movl	$_end, %ecx	subl	%esi, %ecx	/* Move etherboot uses %esi, %edi, %ecx */	rep 	movsb	/* Reload the gdt */	cs	lgdt	gdtarg	/* Reload %cs */	ljmp	$KERN_CODE_SEG, $1f1:	/* reload other segment registers */	movl	$KERN_DATA_SEG, %eax	movl	%eax,%ds	movl	%eax,%es	movl	%eax,%ss	movl	%eax,%fs	movl	%eax,%gs	/* Restore the callee save registers */	popl	%edi	popl	%esi	popl	%ebp	/* return */	ret#endif /* RELOCATE */	/**************************************************************************XSTART32 - Transfer control to the kernel just loaded**************************************************************************/	.globl xstart32xstart32:	/* Save the callee save registers */	movl	%ebp, os_regs + 32	movl	%esi, os_regs + 36	movl	%edi, os_regs + 40	movl	%ebx, os_regs + 44	/* save the return address */	popl	%eax	movl	%eax, os_regs + 48	/* save the stack pointer */	movl	%esp, os_regs + 52	/* Get the new destination address */	popl	%ecx	/* Store the physical address of xend on the stack */	movl	$xend32, %ebx	addl	virt_offset, %ebx	pushl	%ebx	/* Store the destination address on the stack */	pushl	$FLAT_CODE_SEG	pushl	%ecx	/* Switch to using physical addresses */	call	_virt_to_phys	/* Save the target stack pointer */	movl	%esp, os_regs + 12(%ebp)	leal	os_regs(%ebp), %esp	/* Store the pointer to os_regs */	movl	%esp, os_regs_ptr(%ebp)	/* Load my new registers */	popal	movl	(-32 + 12)(%esp), %esp	/* Jump to the new kernel	 * The lret switches to a flat code segment	 */	lret	.balign 4	.globl xend32xend32:	/* Fixup %eflags */	nop	cli	cld		/* Load %esp with &os_regs + virt_offset */	.byte	0xbc /* movl $0, %esp */os_regs_ptr:	.long	0	/* Save the result registers */	addl	$32, %esp	pushal	/* Compute virt_offset */	movl	%esp, %ebp	subl	$os_regs, %ebp		/* Load the stack pointer */	movl	52(%esp), %esp	/* Enable the virtual addresses */	leal	_phys_to_virt(%ebp), %eax	call	*%eax	/* Restore the callee save registers */	movl	os_regs + 32, %ebp	movl	os_regs + 36, %esi	movl	os_regs + 40, %edi	movl	os_regs + 44, %ebx	movl	os_regs + 48, %edx	movl	os_regs + 52, %esp	/* Get the C return value */	movl	os_regs + 28, %eax	jmpl	*%edx#ifdef CONFIG_X86_64	.arch	sledgehammer/**************************************************************************XSTART_lm - Transfer control to the kernel just loaded in long mode**************************************************************************/	.globl xstart_lmxstart_lm:	/* Save the callee save registers */	pushl	%ebp	pushl	%esi	pushl	%edi	pushl	%ebx	/* Switch to using physical addresses */	call	_virt_to_phys	/* Cache virt_offset & 0xfffff000 */	mov	%ebp, %ebx	andl	$0xfffff000, %ebx	/* Initialize the page tables */	/* Level 4 */	leal	0x23 + pgt_level3(%ebx), %eax	leal	pgt_level4(%ebx), %edi	movl	%eax, (%edi)	/* Level 3 */	leal	0x23 + pgt_level2(%ebx), %eax	leal	pgt_level3(%ebx), %edi	movl	%eax, 0x00(%edi)	addl	$4096, %eax	movl	%eax, 0x08(%edi)	addl	$4096, %eax	movl	%eax, 0x10(%edi)	addl	$4096, %eax	movl	%eax, 0x18(%edi)	/* Level 2 */	movl	$0xe3, %eax	leal	pgt_level2(%ebx), %edi	leal	16384(%edi), %esipgt_level2_loop:	movl	%eax, (%edi)	addl	$8, %edi	addl	$0x200000, %eax	cmp	%esi, %edi	jne	pgt_level2_loop	/* Point at the x86_64 page tables */	leal	pgt_level4(%ebx), %edi	movl	%edi, %cr3	/* Setup for the return from 64bit mode */	/* 64bit align the stack */	movl	%esp, %ebx		/* original stack pointer + 16 */	andl	$0xfffffff8, %esp	/* Save original stack pointer + 16 */	pushl	%ebx	/* Save virt_offset */	pushl	%ebp		/* Setup for the jmp to 64bit long mode */	leal	start_lm(%ebp), %eax	movl	%eax, 0x00 + start_lm_addr(%ebp)	movl	$LM_CODE_SEG, %eax	movl	%eax, 0x04 + start_lm_addr(%ebp)	/* Setup for the jump out of 64bit long mode */	leal	end_lm(%ebp), %eax	movl	%eax, 0x00 + end_lm_addr(%ebp)	movl	$FLAT_CODE_SEG, %eax	movl	%eax, 0x04 + end_lm_addr(%ebp)		/* Enable PAE mode */	movl	%cr4, %eax	orl	$X86_CR4_PAE, %eax	movl	%eax, %cr4	/* Enable long mode */	movl	$MSR_K6_EFER, %ecx	rdmsr	orl	$EFER_LME, %eax	wrmsr	/* Start paging, entering 32bit compatiblity mode */	movl	%cr0, %eax	orl	$CR0_PG, %eax	movl	%eax, %cr0	/* Enter 64bit long mode */	ljmp	*start_lm_addr(%ebp)	.code64start_lm:	/* Load 64bit data segments */	movl	$LM_DATA_SEG, %eax	movl	%eax, %ds	movl	%eax, %es	movl	%eax, %ss	andq	$0xffffffff, %rbx	/* Get the address to jump to */	movl	20(%rbx), %edx

⌨️ 快捷键说明

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