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

📄 prom_init.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (strcmp(name, "valkyrie") == 0)		address += 0x1000;#ifdef CONFIG_POWER4#if CONFIG_TASK_SIZE > 0x80000000#error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5#endif	{		extern boot_infos_t disp_bi;		unsigned long va, pa, i, offset;       		va = 0x90000000;		pa = address & 0xfffff000ul;		offset = address & 0x00000fff;		for (i=0; i<0x4000; i++) {  			make_pte((unsigned long)Hash - KERNELBASE, Hash_size, va, pa, 				 _PAGE_ACCESSED | _PAGE_NO_CACHE |				 _PAGE_GUARDED | PP_RWXX);			va += 0x1000;			pa += 0x1000;		}		btext_setup_display(width, height, depth, pitch, 0x90000000 | offset);		disp_bi.dispDeviceBase = (u8 *)address;	}#else /* CONFIG_POWER4 */	btext_setup_display(width, height, depth, pitch, address);	btext_prepare_BAT();#endif /* CONFIG_POWER4 */#endif /* CONFIG_BOOTX_TEXT */}/* * Make a copy of the device tree from the PROM. */static unsigned long __initcopy_device_tree(unsigned long mem_start, unsigned long mem_end){	phandle root;	unsigned long new_start;	struct device_node **allnextp;	root = call_prom("peer", 1, 1, (phandle)0);	if (root == (phandle)0) {		prom_print("couldn't get device tree root\n");		prom_exit();	}	allnextp = &allnodes;	mem_start = ALIGNUL(mem_start);	new_start = inspect_node(root, NULL, mem_start, mem_end, &allnextp);	*allnextp = NULL;	return new_start;}static unsigned long __initinspect_node(phandle node, struct device_node *dad,	     unsigned long mem_start, unsigned long mem_end,	     struct device_node ***allnextpp){	int l;	phandle child;	struct device_node *np;	struct property *pp, **prev_propp;	char *prev_name, *namep;	unsigned char *valp;	np = (struct device_node *) mem_start;	mem_start += sizeof(struct device_node);	memset(np, 0, sizeof(*np));	np->node = node;	**allnextpp = PTRUNRELOC(np);	*allnextpp = &np->allnext;	if (dad != 0) {		np->parent = PTRUNRELOC(dad);		/* we temporarily use the `next' field as `last_child'. */		if (dad->next == 0)			dad->child = PTRUNRELOC(np);		else			dad->next->sibling = PTRUNRELOC(np);		dad->next = np;	}	/* get and store all properties */	prev_propp = &np->properties;	prev_name = "";	for (;;) {		pp = (struct property *) mem_start;		namep = (char *) (pp + 1);		pp->name = PTRUNRELOC(namep);		if ((int) call_prom("nextprop", 3, 1, node, prev_name,				    namep) <= 0)			break;		mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);		prev_name = namep;		valp = (unsigned char *) mem_start;		pp->value = PTRUNRELOC(valp);		pp->length = (int)			call_prom("getprop", 4, 1, node, namep,				  valp, mem_end - mem_start);		if (pp->length < 0)			continue;#ifdef MAX_PROPERTY_LENGTH		if (pp->length > MAX_PROPERTY_LENGTH)			continue; /* ignore this property */#endif		mem_start = ALIGNUL(mem_start + pp->length);		*prev_propp = PTRUNRELOC(pp);		prev_propp = &pp->next;	}	if (np->node != NULL) {		/* Add a "linux,phandle" property" */		pp = (struct property *) mem_start;		*prev_propp = PTRUNRELOC(pp);		prev_propp = &pp->next;		namep = (char *) (pp + 1);		pp->name = PTRUNRELOC(namep);		strcpy(namep, "linux,phandle");		mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);		pp->value = (unsigned char *) PTRUNRELOC(&np->node);		pp->length = sizeof(np->node);	}	*prev_propp = NULL;	/* get the node's full name */	l = (int) call_prom("package-to-path", 3, 1, node,			    (char *) mem_start, mem_end - mem_start);	if (l >= 0) {		np->full_name = PTRUNRELOC((char *) mem_start);		*(char *)(mem_start + l) = 0;		mem_start = ALIGNUL(mem_start + l + 1);	}	/* do all our children */	child = call_prom("child", 1, 1, node);	while (child != (void *)0) {		mem_start = inspect_node(child, np, mem_start, mem_end,					 allnextpp);		child = call_prom("peer", 1, 1, child);	}	return mem_start;}unsigned long smp_chrp_cpu_nr __initdata = 0;/* * With CHRP SMP we need to use the OF to start the other * processors so we can't wait until smp_boot_cpus (the OF is * trashed by then) so we have to put the processors into * a holding pattern controlled by the kernel (not OF) before * we destroy the OF. * * This uses a chunk of high memory, puts some holding pattern * code there and sends the other processors off to there until * smp_boot_cpus tells them to do something.  We do that by using * physical address 0x0.  The holding pattern checks that address * until its cpu # is there, when it is that cpu jumps to * __secondary_start().  smp_boot_cpus() takes care of setting those * values. * * We also use physical address 0x4 here to tell when a cpu * is in its holding pattern code. * * -- Cort * * Note that we have to do this if we have more than one CPU, * even if this is a UP kernel.  Otherwise when we trash OF * the other CPUs will start executing some random instructions * and crash the system.  -- paulus */static void __initprom_hold_cpus(unsigned long mem){	extern void __secondary_hold(void);	unsigned long i;	int cpu;	phandle node;	char type[16], *path;	unsigned int reg;	/*	 * XXX: hack to make sure we're chrp, assume that if we're	 *      chrp we have a device_type property -- Cort	 */	node = call_prom("finddevice", 1, 1, "/");	if ((int)call_prom("getprop", 4, 1, node,			   "device_type",type, sizeof(type)) <= 0)		return;	/* copy the holding pattern code to someplace safe (0) */	/* the holding pattern is now within the first 0x100	   bytes of the kernel image -- paulus */	memcpy((void *)0, _stext, 0x100);	flush_icache_range(0, 0x100);	/* look for cpus */	*(unsigned long *)(0x0) = 0;	asm volatile("dcbf 0,%0": : "r" (0) : "memory");	for (node = NULL; prom_next_node(&node); ) {		type[0] = 0;		call_prom("getprop", 4, 1, node, "device_type",			  type, sizeof(type));		if (strcmp(type, "cpu") != 0)			continue;		path = (char *) mem;		memset(path, 0, 256);		if ((int) call_prom("package-to-path", 3, 1,				    node, path, 255) < 0)			continue;		reg = -1;		call_prom("getprop", 4, 1, node, "reg", &reg, sizeof(reg));		cpu = smp_chrp_cpu_nr++;#ifdef CONFIG_SMP		smp_hw_index[cpu] = reg;#endif /* CONFIG_SMP */		/* XXX: hack - don't start cpu 0, this cpu -- Cort */		if (cpu == 0)			continue;		prom_print("starting cpu ");		prom_print(path);		*(ulong *)(0x4) = 0;		call_prom("start-cpu", 3, 0, node,			  (char *)__secondary_hold - _stext, cpu);		prom_print("...");		for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )			;		if (*(ulong *)(0x4) == cpu)			prom_print("ok\n");		else {			prom_print("failed: ");			prom_print_hex(*(ulong *)0x4);			prom_print("\n");		}	}}static void __initprom_instantiate_rtas(void){	ihandle prom_rtas;	unsigned int i;	struct prom_args prom_args;	prom_rtas = call_prom("finddevice", 1, 1, "/rtas");	if (prom_rtas == (void *) -1)		return;	rtas_size = 0;	call_prom("getprop", 4, 1, prom_rtas,		  "rtas-size", &rtas_size, sizeof(rtas_size));	prom_print("instantiating rtas");	if (rtas_size == 0) {		rtas_data = 0;	} else {		/*		 * Ask OF for some space for RTAS.		 * Actually OF has bugs so we just arbitrarily		 * use memory at the 6MB point.		 */		rtas_data = 6 << 20;		prom_print(" at ");		prom_print_hex(rtas_data);	}	prom_rtas = call_prom("open", 1, 1, "/rtas");	prom_print("...");	prom_args.service = "call-method";	prom_args.nargs = 3;	prom_args.nret = 2;	prom_args.args[0] = "instantiate-rtas";	prom_args.args[1] = prom_rtas;	prom_args.args[2] = (void *) rtas_data;	prom(&prom_args);	i = 0;	if (prom_args.args[3] == 0)		i = (unsigned int)prom_args.args[4];	rtas_entry = i;	if ((rtas_entry == -1) || (rtas_entry == 0))		prom_print(" failed\n");	else		prom_print(" done\n");}/* * We enter here early on, when the Open Firmware prom is still * handling exceptions and the MMU hash table for us. */unsigned long __initprom_init(int r3, int r4, prom_entry pp){	unsigned long mem;	ihandle prom_mmu;	unsigned long offset = reloc_offset();	int i, l;	char *p, *d; 	unsigned long phys;	void *result[3]; 	/* Default */ 	phys = (unsigned long) &_stext;	/* First get a handle for the stdout device */	prom = pp;	prom_chosen = call_prom("finddevice", 1, 1, "/chosen");	if (prom_chosen == (void *)-1)		prom_exit();	if ((int) call_prom("getprop", 4, 1, prom_chosen,			    "stdout", &prom_stdout,			    sizeof(prom_stdout)) <= 0)		prom_exit();	/* Get the full OF pathname of the stdout device */	mem = (unsigned long) klimit + offset;	p = (char *) mem;	memset(p, 0, 256);	call_prom("instance-to-path", 3, 1, prom_stdout, p, 255);	of_stdout_device = p;	mem += strlen(p) + 1;	/* Get the boot device and translate it to a full OF pathname. */	p = (char *) mem;	l = (int) call_prom("getprop", 4, 1, prom_chosen,			    "bootpath", p, 1<<20);	if (l > 0) {		p[l] = 0;	/* should already be null-terminated */		bootpath = PTRUNRELOC(p);		mem += l + 1;		d = (char *) mem;		*d = 0;		call_prom("canon", 3, 1, p, d, 1<<20);		bootdevice = PTRUNRELOC(d);		mem = ALIGNUL(mem + strlen(d) + 1);	}	prom_instantiate_rtas();#ifdef CONFIG_POWER4	/*	 * Find out how much memory we have and allocate a	 * suitably-sized hash table.	 */	prom_alloc_htab();#endif	mem = check_display(mem);	prom_print("copying OF device tree...");	mem = copy_device_tree(mem, mem + (1<<20));	prom_print("done\n");	prom_hold_cpus(mem);	klimit = (char *) (mem - offset);	/* If we are already running at 0xc0000000, we assume we were	 * loaded by an OF bootloader which did set a BAT for us.	 * This breaks OF translate so we force phys to be 0.	 */	if (offset == 0) {		prom_print("(already at 0xc0000000) phys=0\n");		phys = 0;	} else if ((int) call_prom("getprop", 4, 1, prom_chosen, "mmu",				 &prom_mmu, sizeof(prom_mmu)) <= 0) {		prom_print(" no MMU found\n");	} else if ((int)call_prom_ret("call-method", 4, 4, result, "translate",				      prom_mmu, &_stext, 1) != 0) {		prom_print(" (translate failed)\n");	} else {		/* We assume the phys. address size is 3 cells */		phys = (unsigned long)result[2];	}	if (prom_disp_node != 0)		setup_disp_fake_bi(prom_disp_node);	/* Use quiesce call to get OF to shut down any devices it's using */	prom_print("Calling quiesce ...\n");	call_prom("quiesce", 0, 0);	/* Relocate various pointers which will be used once the	   kernel is running at the address it was linked at. */	for (i = 0; i < prom_num_displays; ++i)		prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]);#ifdef CONFIG_SERIAL_CORE_CONSOLE	/* Relocate the of stdout for console autodetection */	of_stdout_device = PTRUNRELOC(of_stdout_device);#endif	prom_print("returning 0x");	prom_print_hex(phys);	prom_print("from prom_init\n");	prom_stdout = NULL;	return phys;}/* * early_get_property is used to access the device tree image prepared * by BootX very early on, before the pointers in it have been relocated. */static void * __initearly_get_property(unsigned long base, unsigned long node, char *prop){	struct device_node *np = (struct device_node *)(base + node);	struct property *pp;	for (pp = np->properties; pp != 0; pp = pp->next) {		pp = (struct property *) (base + (unsigned long)pp);		if (strcmp((char *)((unsigned long)pp->name + base),			   prop) == 0) {			return (void *)((unsigned long)pp->value + base);		}	}	return NULL;}/* Is boot-info compatible ? */#define BOOT_INFO_IS_COMPATIBLE(bi)		((bi)->compatible_version <= BOOT_INFO_VERSION)#define BOOT_INFO_IS_V2_COMPATIBLE(bi)	((bi)->version >= 2)#define BOOT_INFO_IS_V4_COMPATIBLE(bi)	((bi)->version >= 4)void __initbootx_init(unsigned long r4, unsigned long phys){	boot_infos_t *bi = (boot_infos_t *) r4;	unsigned long space;	unsigned long ptr, x;	char *model;	boot_infos = PTRUNRELOC(bi);	if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))		bi->logicalDisplayBase = NULL;#ifdef CONFIG_BOOTX_TEXT	btext_init(bi);	/*	 * Test if boot-info is compatible.  Done only in config	 * CONFIG_BOOTX_TEXT since there is nothing much we can do	 * with an incompatible version, except display a message	 * and eventually hang the processor...	 *	 * I'll try to keep enough of boot-info compatible in the	 * future to always allow display of this message;	 */	if (!BOOT_INFO_IS_COMPATIBLE(bi)) {		btext_drawstring(" !!! WARNING - Incompatible version of BootX !!!\n\n\n");		btext_flushscreen();	}#endif	/* CONFIG_BOOTX_TEXT */	/* New BootX enters kernel with MMU off, i/os are not allowed	   here. This hack will have been done by the boostrap anyway.	*/	if (bi->version < 4) {		/*		 * XXX If this is an iMac, turn off the USB controller.		 */		model = (char *) early_get_property			(r4 + bi->deviceTreeOffset, 4, "model");		if (model		    && (strcmp(model, "iMac,1") == 0			|| strcmp(model, "PowerMac1,1") == 0)) {			out_le32((unsigned *)0x80880008, 1);	/* XXX */		}	}	/* Move klimit to enclose device tree, args, ramdisk, etc... */	if (bi->version < 5) {		space = bi->deviceTreeOffset + bi->deviceTreeSize;		if (bi->ramDisk)			space = bi->ramDisk + bi->ramDiskSize;	} else		space = bi->totalParamsSize;	klimit = PTRUNRELOC((char *) bi + space);	/* New BootX will have flushed all TLBs and enters kernel with	   MMU switched OFF, so this should not be useful anymore.	*/	if (bi->version < 4) {		/*		 * Touch each page to make sure the PTEs for them		 * are in the hash table - the aim is to try to avoid		 * getting DSI exceptions while copying the kernel image.		 */		for (ptr = ((unsigned long) &_stext) & PAGE_MASK;		     ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)			x = *(volatile unsigned long *)ptr;	}#ifdef CONFIG_BOOTX_TEXT	/*	 * Note that after we call btext_prepare_BAT, we can't do	 * prom_draw*, flushscreen or clearscreen until we turn the MMU	 * on, since btext_prepare_BAT sets disp_bi.logicalDisplayBase	 * to a virtual address.	 */	btext_prepare_BAT();#endif}

⌨️ 快捷键说明

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