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

📄 head.s

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 S
字号:
/* *  head.S -- Bootloader Entry point * *  Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es * *  Modified to compile in RTEMS development environment *  by Eric Valette * *  Copyright (C) 1999 Eric Valette. valette@crf.canon.fr * *  The license and distribution terms for this file may be *  found in found in the file LICENSE in this distribution or at *  http://www.rtems.com/license/LICENSE. * * $Id: head.S,v 1.3.2.3 2003/09/29 21:43:26 joel Exp $ */#include <asm.h>#include <rtems/score/cpu.h>#include "bootldr.h"#define TEST_PPCBUG_CALLS		#undef TEST_PPCBUG_CALLS	#define FRAME_SIZE 32#define LOCK_CACHES (HID0_DLOCK | HID0_ILOCK)#define INVL_CACHES (HID0_DCI | HID0_ICFI)#define ENBL_CACHES (HID0_DCE | HID0_ICE)#define USE_PPCBUG	#define PRINT_CHAR(c)		\	addi	r20,r3,0	; \	li	r3,c		; \	li	r10,0x20	; \	sc			; \	addi	r3,r20,0	; \	li	r10,0x26	; \	sc				#define MONITOR_ENTER			\	mfmsr	r10		;	\	ori	r10,r10,MSR_IP	;	\	mtmsr	r10		;	\	li	r10,0x63	;	\	sc				START_GOT	GOT_ENTRY(_GOT2_TABLE_)	GOT_ENTRY(_FIXUP_TABLE_)	GOT_ENTRY(.bss)	GOT_ENTRY(codemove)	GOT_ENTRY(0)	GOT_ENTRY(__bd)	GOT_ENTRY(moved)	GOT_ENTRY(_binary_rtems_gz_start) 	GOT_ENTRY(_binary_initrd_gz_start) 	GOT_ENTRY(_binary_initrd_gz_end)#ifdef TEST_PPCBUG_CALLS		GOT_ENTRY(banner_start)	GOT_ENTRY(banner_end)#endif	#ifdef USE_PPCBUG	GOT_ENTRY(nioc_reset_packet)#endif	END_GOT	.globl	start	.type	start,@function	/* Point the stack into the PreP partition header in the x86 reserved * code area, so that simple C routines can be called.  */start:	#if defined(USE_PPCBUG) && defined(DEBUG) && defined(REENTER_MONITOR)	MONITOR_ENTER#endif	bl	1f1:	mflr	r1	li	r0,0	stwu	r0,start-1b-0x400+0x1b0-FRAME_SIZE(r1)	stmw	r26,FRAME_SIZE-24(r1)	GET_GOT	mfmsr	r28			/* Turn off interrupts */	ori	r0,r28,MSR_EE	xori	r0,r0,MSR_EE	mtmsr	r0	/* Enable the caches, from now on cr2.eq set means processor is 601 */		mfpvr	r0	mfspr	r29,HID0	srwi	r0,r0,16	cmplwi	cr2,r0,1	beq	2,2f/* * commented out, 11/7/2002, gregm.  This instruction sequence seems to * be pathological on the 603e. *	#ifndef USE_PPCBUG	ori	r0,r29,ENBL_CACHES|INVL_CACHES|LOCK_CACHES	xori	r0,r0,INVL_CACHES|LOCK_CACHES	sync	isync	mtspr	HID0,r0#endif*/				2:	bl	reloc	/* save all the parameters and the orginal msr/hid0/r31 */	lwz	bd,GOT(__bd)	stw	r3,0(bd)	stw	r4,4(bd)	stw	r5,8(bd)	stw	r6,12(bd)	stw	r7,16(bd)	stw	r8,20(bd)	stw	r9,24(bd)	stw	r10,28(bd)	stw	r28,o_msr(bd)	stw	r29,o_hid0(bd)	stw	r31,o_r31(bd)#ifdef USE_PPCBUG/* Stop the network interface - otherwise, memory can get * corrupted by the IF DMAing data into its old buffers or * by writing descriptors... */	lwz r3,GOT(nioc_reset_packet) 	li  r10, 0x1d /* .NETCTRL */	sc#endif/* Call the routine to fill boot_data structure from residual data.  * And to find where the code has to be moved.  */	lis	r3,__size@sectoff@ha	addi	r3,r3,__size@sectoff@l	bl	early_setup/* Now we need to relocate ourselves, where we are told to. First put a  * copy of the codemove routine to some place in memory. * (which may be where the 0x41 partition was loaded, so size is critical).  */	lwz	r4,GOT(codemove)	li	r5,_size_codemove	lwz	r3,mover(bd)	lwz	r6,cache_lsize(bd)	bl	codemove	mtctr	r3		# Where the temporary codemove is.	lwz	r3,image(bd)	lis	r5,_edata@sectoff@ha	lwz	r4,GOT(0)	# Our own address	addi	r5,r5,_edata@sectoff@l	lwz	r6,cache_lsize(bd)	lwz	r8,GOT(moved)	sub	r7,r3,r4	# Difference to adjust pointers.	add	r8,r8,r7	add	r30,r30,r7	add	bd,bd,r7/* Call the copy routine but return to the new area. */	mtlr	r8		# for the return address	bctr			# returns to the moved instruction	/* Establish the new top stack frame. */moved:	lwz	r1,stack(bd)	li	r0,0	stwu	r0,-16(r1)/* relocate again */	bl	reloc	/* Clear all of BSS */	lwz	r10,GOT(.bss)	li	r0,__bss_words@sectoff@l	subi	r10,r10,4	cmpwi	r0,0	mtctr	r0	li	r0,0	beq	4f3:	stwu	r0,4(r10)	bdnz	3b/* Final memory initialization. First switch to unmapped mode * in case the FW had set the MMU on, and flush the TLB to avoid * stale entries from interfering. No I/O access is allowed * during this time! */4:#if defined(USE_PPCBUG) && defined(DEBUG)	PRINT_CHAR('M')#endif	bl	MMUoff#if defined(USE_PPCBUG) && defined(DEBUG)	PRINT_CHAR('B')#endif	bl	flush_tlb/* Some firmware versions leave stale values in the BATs, it's time * to invalidate them to avoid interferences with our own mappings. * But the 601 valid bit is in the BATL (IBAT only) and others are in * the [ID]BATU. Bloat, bloat.. fortunately thrown away later.  */#if defined(USE_PPCBUG) && defined(DEBUG)	PRINT_CHAR('T')#endif	li	r3,0	beq	cr2,5f	mtdbatu 0,r3	mtdbatu 1,r3	mtdbatu 2,r3	mtdbatu 3,r35:	mtibatu 0,r3	mtibatl	0,r3	mtibatu 1,r3	mtibatl 1,r3	mtibatu 2,r3	mtibatl 2,r3	mtibatu 3,r3	mtibatl 3,r3	lis	r3,__size@sectoff@ha	addi	r3,r3,__size@sectoff@l	sync				# We are going to touch SDR1 !#if defined(USE_PPCBUG) && defined(DEBUG)	PRINT_CHAR('i')#endif	bl	mm_init	#if defined(USE_PPCBUG) && defined(DEBUG)	PRINT_CHAR('M')#endif	bl	MMUon	/* Now we are mapped and can perform I/O if we want */#ifdef TEST_PPCBUG_CALLS	/* Experience seems to show that PPCBug can only be called with the * data cache disabled and with MMU disabled. Bummer. */		li	r10,0x22		# .OUTLN	lwz	r3,GOT(banner_start)	lwz	r4,GOT(banner_end)	sc#endif	#if defined(USE_PPCBUG) && defined(DEBUG)	PRINT_CHAR('H')#endif	bl	setup_hw	lwz	r4,GOT(_binary_rtems_gz_start)	lis	r5,_rtems_gz_size@sectoff@ha	lwz	r6,GOT(_binary_initrd_gz_start)	lis	r3,_rtems_size@sectoff@ha	lwz	r7,GOT(_binary_initrd_gz_end)	addi	r5,r5,_rtems_gz_size@sectoff@l	addi	r3,r3,_rtems_size@sectoff@l	sub	r7,r7,r6	bl	decompress_kernel/* Back here we are unmapped and we start the kernel, passing up to eight * parameters just in case, only r3 to r7 used for now. Flush the tlb so * that the loaded image starts in a clean state. */	bl	flush_tlb	lwz	r3,0(bd)	lwz	r4,4(bd)	lwz	r5,8(bd)	lwz	r6,12(bd)	lwz	r7,16(bd)	lwz	r8,20(bd)	lwz	r9,24(bd)	lwz	r10,28(bd)	lwz	r30,0(0)	mtctr	r30/* *	Linux code again *	lis	r30,0xdeadc0de@ha	addi	r30,r30,0xdeadc0de@l	stw	r30,0(0)	li	r30,0*/	dcbst	0,r30	/* Make sure it's in memory ! */	/* We just flash invalidate and disable the dcache, unless it's a 601,  * critical areas have been flushed and we don't care about the stack  * and other scratch areas. */	beq	cr2,1f	mfspr	r0,HID0	ori	r0,r0,HID0_DCI|HID0_DCE	sync	mtspr	HID0,r0	xori	r0,r0,HID0_DCI|HID0_DCE	mtspr	HID0,r0	/* Provisional return to FW, works for PPCBug */#if 0 && defined(REENTER_MONITOR)	MONITOR_ENTER#else1:	bctr#endif			/* relocation function, r30 must point to got2+0x8000 */reloc:	/* Adjust got2 pointers, no need to check for 0, this code already puts * a few entries in the table.  */	li	r0,__got2_entries@sectoff@l	la	r12,GOT(_GOT2_TABLE_)	lwz	r11,GOT(_GOT2_TABLE_)	mtctr	r0	sub	r11,r12,r11	addi	r12,r12,-41:	lwzu	r0,4(r12)	add	r0,r0,r11	stw	r0,0(r12)	bdnz	1b	/* Now adjust the fixups and the pointers to the fixups in case we need * to move ourselves again.  */	2:	li	r0,__fixup_entries@sectoff@l	lwz	r12,GOT(_FIXUP_TABLE_)	cmpwi	r0,0	mtctr	r0	addi	r12,r12,-4	beqlr3:	lwzu	r10,4(r12)	lwzux	r0,r10,r11	add	r0,r0,r11	stw	r10,0(r12)	stw	r0,0(r10)	bdnz	3b	blr		/* Set the MMU on and off: code is always mapped 1:1 and does not need MMU, * but it does not cost so much to map it also and it catches calls through * NULL function pointers.  */	.globl  MMUon	.type	MMUon,@functionMMUon:	blr	nop/*		mfmsr	r0	ori	r0,r0,MSR_IR|MSR_DR|MSR_IP	mflr	r11	xori	r0,r0,MSR_IP	mtsrr0	r11	mtsrr1	r0	rfi*/	.globl  MMUoff	.type	MMUoff,@functionMMUoff:	blr	nop	/*	mfmsr	r0	ori	r0,r0,MSR_IR|MSR_DR|MSR_IP	mflr	r11	xori	r0,r0,MSR_IR|MSR_DR	mtsrr0	r11	mtsrr1	r0	rfi*//* Due to the PPC architecture (and according to the specifications), a * series of tlbie which goes through a whole 256 MB segment always flushes  * the whole TLB. This is obviously overkill and slow, but who cares ?  * It takes about 1 ms on a 200 MHz 603e and works even if residual data  * get the number of TLB entries wrong. */flush_tlb:	lis	r11,0x10001:	addic.  r11,r11,-0x1000	tlbie	r11	bnl	1b/* tlbsync is not implemented on 601, so use sync which seems to be a superset * of tlbsync in all cases and do not bother with CPU dependant code */	sync		blr						.globl  codemovecodemove:	.type	codemove,@function/* r3 dest, r4 src, r5 length in bytes, r6 cachelinesize */	cmplw	cr1,r3,r4	addi	r0,r5,3	srwi.	r0,r0,2	beq	cr1,4f	/* In place copy is not necessary */	beq	7f	/* Protect against 0 count */	mtctr	r0	bge	cr1,2f		la	r8,-4(r4)	la	r7,-4(r3)1:	lwzu	r0,4(r8)	stwu	r0,4(r7)		bdnz	1b	b	4f2:	slwi	r0,r0,2	add	r8,r4,r0	add	r7,r3,r03:	lwzu	r0,-4(r8)	stwu	r0,-4(r7)	bdnz	3b	/* Now flush the cache:	note that we must start from a cache aligned * address. Otherwise we might miss one cache line.  */4:	cmpwi	r6,0	add	r5,r3,r5	beq	7f	/* Always flush prefetch queue in any case */ 	subi	r0,r6,1	andc	r3,r3,r0	mr	r4,r35:	cmplw	r4,r5		dcbst	0,r4	add	r4,r4,r6	blt	5b	sync		/* Wait for all dcbst to complete on bus */	mr	r4,r36:	cmplw	r4,r5		icbi	0,r4	add	r4,r4,r6	blt	6b7:	sync		/* Wait for all icbi to complete on bus */	isync	blr	.size	codemove,.-codemove_size_codemove=.-codemove	.section        ".data" # .rodata	.align 4#ifdef USE_PPCBUG/* A control 'packet' for the .NETCTRL PPCBug syscall to * reset a network interface. Let's hope they used the * first one for booting!! (CLUN/DLUN == 0/0) * Must be 4-byte aligned... */nioc_reset_packet:	.byte	0	/* Contoller LUN                                   */	.byte	0	/* Device LUN                                      */	.word   0   /* status return                                   */	.long	5	/* Command (5=RESET)                               */	.long   0   /* Mem. Addr. for real data (unused for reset)     */	.long   0   /* Number of bytes                                 */	.long   0   /* Status/Control Flags (unused for reset)         */#endif#ifdef TEST_PPCBUG_CALLS	banner_start:		.ascii "This message was printed by PPCBug with MMU enabled"banner_end:	#endif

⌨️ 快捷键说明

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