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

📄 startmenu.s

📁 linux下从网卡远程启动
💻 S
📖 第 1 页 / 共 2 页
字号:
/* * Converted to use Eric Biederman's _real_call routine which frees * the 16 bit code from running in the same 64kB segment as the * 32 bit code's stack. *//* #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	CR0_PE,1#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#define	DO_REAL_CALL	pushl $10f; pushl $20f-10f; call _real_call; .section ".text16"; 10: .code16#define	DO_REAL_RETURN	ret; 20: .code32; .previous	.section	".text"	.section	".text16","ax",@progbits	.previous	.code32	.arch	i386/* * 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. *//**************************************************************************START - Where all the fun begins....**************************************************************************//* this must be the first thing in the file because we enter from the top */	.global	_start_start:/* We have to use our own GDT when running in our segment because the old   GDT will have the wrong descriptors for the real code segments */	sgdt	gdtsave		/* save old GDT */	lgdt	gdtarg		/* load ours */	/* reload the segment registers */	movl	$KERN_DATA_SEG,%eax	movl	%eax,%ds	movl	%eax,%es	movl	%eax,%ss	movl	%eax,%fs	movl	%eax,%gs	/* flush prefetch queue, and reload %cs:%eip */	ljmp	$KERN_CODE_SEG,$1f1:	/* save the stack pointer and call the routine */	movl	%esp,%eax	movl	%eax,initsp	movl	$RELOC+0x20000,%esp	/* change stack */	pushl	12(%eax)	/* replicate args on new stack */	pushl	8(%eax)	pushl	4(%eax)	call	menu_exit:/*	we reset sp to the location just before entering first	instead of relying on the return from menu because exit	could have been called from anywhere */	movl	initsp,%ebx	movl	%ebx,%esp	lgdt	gdtsave		/* restore old GDT */	ret	.globl	exitexit:	movl	4(%esp),%eax	jmp	_exit/**************************************************************************SET_SEG_BASE - Set the base address of a segment registerStolen from Etherboot 5.1. With thanks to Eric Biederman**************************************************************************/	/* .globl set_seg_base */set_seg_base:	/* Low half of the gdt base */	movl	4(%esp), %eax	shll	$16, %eax	/* High half of the gdt base */		movl	4(%esp), %ecx	shrl	$16, %ecx	andl	$0xff, %ecx	movl	4(%esp), %edx	andl	$0xff000000, %edx	orl	%edx, %ecx	movl	8(%esp), %edx	/* Fixup the code segment */	andl	$0x0000ffff,  0(%edx)	orl	%eax       ,  0(%edx)	andl	$0x00ffff00,  4(%edx)	orl	%ecx       ,  4(%edx)	/* Fixup the data segment */	andl	$0x0000ffff,  8(%edx)	orl	%eax       ,  8(%edx)	andl	$0x00ffff00, 12(%edx)	orl	%ecx       , 12(%edx)	ret/**************************************************************************_REAL_CALL - Run some code in real mode.Stolen from Etherboot 5.1. With thanks to Eric Biederman**************************************************************************/	/* MAX_REAL_MODE_STACK is carefully tuned to work	 * with the stack bottom at 0x7c00 while not chancing	 * overwriting data below 0x500.	 */#define MAX_REAL_MODE_STACK 29696#define RADDR(sym)	(((sym) - _end16) + MAX_REAL_MODE_STACK)	.balign 4	/* .globl real_mode_stack */real_mode_stack:	.long 0x7c00  /* Put the stack just below the dos load address */real_stack_top:	.long 0_save_esp:	.long 0	/* .globl _real_call */_real_call:	/* Save the original %esp value */	movl	%esp, _save_esp	/* Save the temporary registers I use */	pushl	$0	pushl	%ebx	pushl	%ecx	pushl	%edx	pushl	%esi	pushl	%edi	pushl	%ebp	/* Load up the registers */	movl	32(%esp), %ecx		/* The 16bit code len */	movl	36(%esp), %esi		/* The 16bit code start */	movl	virt_offset, %ebp	/* The virtual offset */	/* stack top = phys_to_virt(real_mode_stack - MAX_REAL_MODE_STACK) */	movl	real_mode_stack, %ebx	/* The stack top */	subl	$MAX_REAL_MODE_STACK, %ebx	movl	%ebx, real_stack_top	subl	%ebp, %ebx	/* Save the real mode stack top */	movl	%ebx, 24(%esp)	/* Compute where the copied code goes */	leal	RADDR(__real_call)(%ebx), %edi	subl	%ecx, %edi	andl	$0xfffffffc, %edi	/* 4 byte aligned */	/* Remember where the code is executed */	movl	%edi, %eax	subl	%ebx, %eax	movw	%ax, real_ip	/* Copy the user code onto the real mode stack */	rep	movsb	/* Copy the trampoline onto the stack */	movl	$__real_call, %esi	movl	$_end16 - __real_call, %ecx	leal	RADDR(__real_call)(%ebx), %edi	rep	movsb	/* Fixup real_gdtarg */	leal	_gdt(%ebp), %eax	movl	%eax, RADDR(real_gdtarg +2)(%ebx)	/* Fixup the gdt */	pushl	$_rmcs	leal	0(%ebx, %ebp), %eax	pushl	%eax	call	set_seg_base	addl	$8, %esp	/* Restore the saved registers */	popl	%ebp	popl	%edi	popl	%esi	popl	%edx	popl	%ecx	popl	%ebx	/* And switch stacks */	popl	%esp	movzwl	RADDR(real_ip)(%esp), %eax	addl	%eax, %esp	/* Setup for jump to real mode */	movl	real_stack_top, %eax	shrl	$4, %eax	pushw	%ax	pushw	$RADDR(real16)	/* Switch stack from %esp 32bit virtual to %sp 16bit physical */	addl	virt_offset, %esp	subl	real_stack_top, %esp	/* Jump to 16bit code */	ljmp	$REAL_CODE_SEG, $RADDR(code16) 	/* jump to a 16 bit segment */_real_call_ret:	/* reload  segment registers */	movl	$KERN_DATA_SEG,%eax	movl	%eax,%ds	movl	%eax,%es	movl	%eax,%ss	movl	%eax,%fs	movl	%eax,%gs	/* Restore the stack */	movl	_save_esp, %esp	/* Restore the direction flag */	cld	/* Get the real mode stack pointer */	movl	real_stack_top, %eax	subl	virt_offset, %eax	pushl	%eax	movzwl	RADDR(real_sp)(%eax), %eax	addl	0(%esp), %eax	addl	$4, %esp	/* Return to my caller */	ret	$8	.balign 16__real_call:real_sp:	.word 0real_ip:	.word 0real_gdtarg:	.word	_gdt_end - _gdt - 1	/* limit */	.long	_gdt			/* addr */	.code16code16:	/* Load 16bit segment descriptors to force 16bit segment limit */	movw	$REAL_DATA_SEG, %ax	movw	%ax,%ds	movw	%ax,%ss	movw	%ax,%es	movw	%ax,%fs	movw	%ax,%gs	/* clear the PE bit of CR0 */	movl	%cr0,%eax	andb	$0!CR0_PE,%al	movl	%eax,%cr0	/* make intersegment jmp to flush the processor pipeline	 * and reload %cs:%eip (to clear upper 16 bits of %eip).	 */	lretreal16:		/* we are in real mode now	 * set up the real mode segment registers : %ds, $ss, %es	 */	movw	%cs, %ax	movw	%ax, %ss	movw	%ax, %ds	movw	%ax, %fs	movw	%ax, %gs	/* Enable interrupts */	sti	/* Call the user supplied code */	call	*RADDR(real_ip)	/* Save the stack pointer */	/* Reload %ds */	movw	%cs, %ax	movw	%ax, %ds	movw	%sp, RADDR(real_sp)	/* Disable interrupts */	cli	/* Switch back to protected mode */	cs	DATA32 lgdt RADDR(real_gdtarg)	movl	%cr0, %eax	orb	$CR0_PE, %al	movl	%eax, %cr0	/* turn on protected mode */	/* flush prefetch queue, and reload %cs:%eip */	DATA32 ljmp	$KERN_CODE_SEG, $_real_call_ret	.code32__end16:	.balign 16_end16:	.code32/**************************************************************************CURRTICKS - Get TimeUse direct memory access to BIOS variables, longword 0040:006C (tickstoday) and byte 0040:0070 (midnight crossover flag) instead of callingtimeofday BIOS interrupt.**************************************************************************/	.globl	currtickscurrticks:	pushl	%ebp	pushl	%ebx	pushl	%esi	pushl	%edi	DO_REAL_CALL	DO_REAL_RETURN	movl	virt_offset,%ebp	negl	%ebp	movl	0x46C(%ebp), %eax	movb	0x470(%ebp), %bl	cmpb	$0, %bl	je	notmidnite	movb	$0, 0x470(%ebp)		/* clear the flag */	addl	$0x1800b0,days		/* 0x1800b0 ticks per day */notmidnite:	addl	days,%eax	popl	%edi	popl	%esi	popl	%ebx	popl	%ebp	ret/**************************************************************************console_cls()BIOS call "INT 10H Function 0Fh" to get current video mode	Call with	%ah = 0x0f        Returns         %al = (video mode)                        %bh = (page number)BIOS call "INT 10H Function 00h" to set the video mode (clears screen)	Call with	%ah = 0x00                        %al = (video mode)**************************************************************************/	.globl	console_clsconsole_cls:	pushl	%ebx	pushl	%esi	pushl	%edi	DO_REAL_CALL	movb	$0xf, %ah	int	$0x10			/* Get Current Video mode */        xorb	%ah, %ah        int	$0x10                   /* Set Video mode (clears screen) */	DO_REAL_RETURN	popl	%edi	popl	%esi	popl	%ebx	ret/**************************************************************************console_nocursor()BIOS call "INT 10H Function 01h" to set cursor type        Call with       %ah = 0x01                        %ch = cursor starting scanline                        %cl = cursor ending scanline**************************************************************************/	.globl	console_nocursorconsole_nocursor:	pushl	%ebx	pushl	%esi	pushl	%edi	DO_REAL_CALL	movw    $0x2000, %cx	movb    $0x1, %ah	int     $0x10 	DO_REAL_RETURN	popl	%edi	popl	%esi	popl	%ebx	ret/**************************************************************************console_getxy()

⌨️ 快捷键说明

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