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

📄 prom_init.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	s = os = (char *)RELOC(dt_string_start);	s += 4;	while (s <  (char *)RELOC(dt_string_end)) {		if (strcmp(s, str) == 0)			return s - os;		s += strlen(s) + 1;	}	return 0;}/* * The Open Firmware 1275 specification states properties must be 31 bytes or * less, however not all firmwares obey this. Make it 64 bytes to be safe. */#define MAX_PROPERTY_NAME 64static void __init scan_dt_build_strings(phandle node,					 unsigned long *mem_start,					 unsigned long *mem_end){	char *prev_name, *namep, *sstart;	unsigned long soff;	phandle child;	sstart =  (char *)RELOC(dt_string_start);	/* get and store all property names */	prev_name = RELOC("");	for (;;) {		/* 64 is max len of name including nul. */		namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);		if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {			/* No more nodes: unwind alloc */			*mem_start = (unsigned long)namep;			break;		} 		/* skip "name" */ 		if (strcmp(namep, RELOC("name")) == 0) { 			*mem_start = (unsigned long)namep; 			prev_name = RELOC("name"); 			continue; 		}		/* get/create string entry */		soff = dt_find_string(namep);		if (soff != 0) {			*mem_start = (unsigned long)namep;			namep = sstart + soff;		} else {			/* Trim off some if we can */			*mem_start = (unsigned long)namep + strlen(namep) + 1;			RELOC(dt_string_end) = *mem_start;		}		prev_name = namep;	}	/* do all our children */	child = call_prom("child", 1, 1, node);	while (child != 0) {		scan_dt_build_strings(child, mem_start, mem_end);		child = call_prom("peer", 1, 1, child);	}}static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,					unsigned long *mem_end){	phandle child;	char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;	unsigned long soff;	unsigned char *valp;	static char pname[MAX_PROPERTY_NAME];	int l, room;	dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);	/* get the node's full name */	namep = (char *)*mem_start;	room = *mem_end - *mem_start;	if (room > 255)		room = 255;	l = call_prom("package-to-path", 3, 1, node, namep, room);	if (l >= 0) {		/* Didn't fit?  Get more room. */		if (l >= room) {			if (l >= *mem_end - *mem_start)				namep = make_room(mem_start, mem_end, l+1, 1);			call_prom("package-to-path", 3, 1, node, namep, l);		}		namep[l] = '\0';		/* Fixup an Apple bug where they have bogus \0 chars in the		 * middle of the path in some properties, and extract		 * the unit name (everything after the last '/').		 */		for (lp = p = namep, ep = namep + l; p < ep; p++) {			if (*p == '/')				lp = namep;			else if (*p != 0)				*lp++ = *p;		}		*lp = 0;		*mem_start = _ALIGN((unsigned long)lp + 1, 4);	}	/* get it again for debugging */	path = RELOC(prom_scratch);	memset(path, 0, PROM_SCRATCH_SIZE);	call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);	/* get and store all properties */	prev_name = RELOC("");	sstart = (char *)RELOC(dt_string_start);	for (;;) {		if (call_prom("nextprop", 3, 1, node, prev_name,			      RELOC(pname)) != 1)			break; 		/* skip "name" */ 		if (strcmp(RELOC(pname), RELOC("name")) == 0) { 			prev_name = RELOC("name"); 			continue; 		}		/* find string offset */		soff = dt_find_string(RELOC(pname));		if (soff == 0) {			prom_printf("WARNING: Can't find string index for"				    " <%s>, node %s\n", RELOC(pname), path);			break;		}		prev_name = sstart + soff;		/* get length */		l = call_prom("getproplen", 2, 1, node, RELOC(pname));		/* sanity checks */		if (l == PROM_ERROR)			continue;		if (l > MAX_PROPERTY_LENGTH) {			prom_printf("WARNING: ignoring large property ");			/* It seems OF doesn't null-terminate the path :-( */			prom_printf("[%s] ", path);			prom_printf("%s length 0x%x\n", RELOC(pname), l);			continue;		}		/* push property head */		dt_push_token(OF_DT_PROP, mem_start, mem_end);		dt_push_token(l, mem_start, mem_end);		dt_push_token(soff, mem_start, mem_end);		/* push property content */		valp = make_room(mem_start, mem_end, l, 4);		call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);		*mem_start = _ALIGN(*mem_start, 4);	}	/* Add a "linux,phandle" property. */	soff = dt_find_string(RELOC("linux,phandle"));	if (soff == 0)		prom_printf("WARNING: Can't find string index for"			    " <linux-phandle> node %s\n", path);	else {		dt_push_token(OF_DT_PROP, mem_start, mem_end);		dt_push_token(4, mem_start, mem_end);		dt_push_token(soff, mem_start, mem_end);		valp = make_room(mem_start, mem_end, 4, 4);		*(u32 *)valp = node;	}	/* do all our children */	child = call_prom("child", 1, 1, node);	while (child != 0) {		scan_dt_build_struct(child, mem_start, mem_end);		child = call_prom("peer", 1, 1, child);	}	dt_push_token(OF_DT_END_NODE, mem_start, mem_end);}static void __init flatten_device_tree(void){	phandle root;	unsigned long mem_start, mem_end, room;	struct boot_param_header *hdr;	struct prom_t *_prom = &RELOC(prom);	char *namep;	u64 *rsvmap;	/*	 * Check how much room we have between alloc top & bottom (+/- a	 * few pages), crop to 4Mb, as this is our "chuck" size	 */	room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000;	if (room > DEVTREE_CHUNK_SIZE)		room = DEVTREE_CHUNK_SIZE;	prom_debug("starting device tree allocs at %x\n", RELOC(alloc_bottom));	/* Now try to claim that */	mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);	if (mem_start == 0)		prom_panic("Can't allocate initial device-tree chunk\n");	mem_end = RELOC(alloc_top);	/* Get root of tree */	root = call_prom("peer", 1, 1, (phandle)0);	if (root == (phandle)0)		prom_panic ("couldn't get device tree root\n");	/* Build header and make room for mem rsv map */ 	mem_start = _ALIGN(mem_start, 4);	hdr = make_room(&mem_start, &mem_end,			sizeof(struct boot_param_header), 4);	RELOC(dt_header_start) = (unsigned long)hdr;	rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);	/* Start of strings */	mem_start = PAGE_ALIGN(mem_start);	RELOC(dt_string_start) = mem_start;	mem_start += 4; /* hole */	/* Add "linux,phandle" in there, we'll need it */	namep = make_room(&mem_start, &mem_end, 16, 1);	strcpy(namep, RELOC("linux,phandle"));	mem_start = (unsigned long)namep + strlen(namep) + 1;	/* Build string array */	prom_printf("Building dt strings...\n"); 	scan_dt_build_strings(root, &mem_start, &mem_end);	RELOC(dt_string_end) = mem_start;	/* Build structure */	mem_start = PAGE_ALIGN(mem_start);	RELOC(dt_struct_start) = mem_start;	prom_printf("Building dt structure...\n"); 	scan_dt_build_struct(root, &mem_start, &mem_end);	dt_push_token(OF_DT_END, &mem_start, &mem_end);	RELOC(dt_struct_end) = PAGE_ALIGN(mem_start);	/* Finish header */	hdr->boot_cpuid_phys = _prom->cpu;	hdr->magic = OF_DT_HEADER;	hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);	hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);	hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);	hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);	hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);	hdr->version = OF_DT_VERSION;	/* Version 16 is not backward compatible */	hdr->last_comp_version = 0x10;	/* Reserve the whole thing and copy the reserve map in, we	 * also bump mem_reserve_cnt to cause further reservations to	 * fail since it's too late.	 */	reserve_mem(RELOC(dt_header_start), hdr->totalsize);	memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map));#ifdef DEBUG_PROM	{		int i;		prom_printf("reserved memory map:\n");		for (i = 0; i < RELOC(mem_reserve_cnt); i++)			prom_printf("  %x - %x\n",				    RELOC(mem_reserve_map)[i].base,				    RELOC(mem_reserve_map)[i].size);	}#endif	RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE;	prom_printf("Device tree strings 0x%x -> 0x%x\n",		    RELOC(dt_string_start), RELOC(dt_string_end)); 	prom_printf("Device tree struct  0x%x -> 0x%x\n",		    RELOC(dt_struct_start), RELOC(dt_struct_end));}static void __init fixup_device_tree(void){#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)	phandle u3, i2c, mpic;	u32 u3_rev;	u32 interrupts[2];	u32 parent;	/* Some G5s have a missing interrupt definition, fix it up here */	u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));	if (!PHANDLE_VALID(u3))		return;	i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));	if (!PHANDLE_VALID(i2c))		return;	mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));	if (!PHANDLE_VALID(mpic))		return;	/* check if proper rev of u3 */	if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))	    == PROM_ERROR)		return;	if (u3_rev < 0x35 || u3_rev > 0x39)		return;	/* does it need fixup ? */	if (prom_getproplen(i2c, "interrupts") > 0)		return;	prom_printf("fixing up bogus interrupts for u3 i2c...\n");	/* interrupt on this revision of u3 is number 0 and level */	interrupts[0] = 0;	interrupts[1] = 1;	prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",		     &interrupts, sizeof(interrupts));	parent = (u32)mpic;	prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",		     &parent, sizeof(parent));#endif}static void __init prom_find_boot_cpu(void){       	struct prom_t *_prom = &RELOC(prom);	u32 getprop_rval;	ihandle prom_cpu;	phandle cpu_pkg;	_prom->cpu = 0;	if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)		return;	cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);	prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));	_prom->cpu = getprop_rval;	prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);}static void __init prom_check_initrd(unsigned long r3, unsigned long r4){#ifdef CONFIG_BLK_DEV_INITRD       	struct prom_t *_prom = &RELOC(prom);	if (r3 && r4 && r4 != 0xdeadbeef) {		unsigned long val;		RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;		RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;		val = RELOC(prom_initrd_start);		prom_setprop(_prom->chosen, "/chosen", "linux,initrd-start",			     &val, sizeof(val));		val = RELOC(prom_initrd_end);		prom_setprop(_prom->chosen, "/chosen", "linux,initrd-end",			     &val, sizeof(val));		reserve_mem(RELOC(prom_initrd_start),			    RELOC(prom_initrd_end) - RELOC(prom_initrd_start));		prom_debug("initrd_start=0x%x\n", RELOC(prom_initrd_start));		prom_debug("initrd_end=0x%x\n", RELOC(prom_initrd_end));	}#endif /* CONFIG_BLK_DEV_INITRD */}/* * We enter here early on, when the Open Firmware prom is still * handling exceptions and the MMU hash table for us. */unsigned long __init prom_init(unsigned long r3, unsigned long r4,			       unsigned long pp,			       unsigned long r6, unsigned long r7){	       	struct prom_t *_prom;	unsigned long hdr;	u32 getprop_rval;	unsigned long offset = reloc_offset();#ifdef CONFIG_PPC32	reloc_got2(offset);#endif	_prom = &RELOC(prom);	/*	 * First zero the BSS	 */	memset(&RELOC(__bss_start), 0, __bss_stop - __bss_start);	/*	 * Init interface to Open Firmware, get some node references,	 * like /chosen	 */	prom_init_client_services(pp);	/*	 * See if this OF is old enough that we need to do explicit maps	 * and other workarounds	 */	prom_find_mmu();	/*	 * Init prom stdout device	 */	prom_init_stdout();	/*	 * Check for an initrd	 */	prom_check_initrd(r3, r4);	/*	 * Get default machine type. At this point, we do not differentiate	 * between pSeries SMP and pSeries LPAR	 */	RELOC(of_platform) = prom_find_machine_type();	getprop_rval = RELOC(of_platform);	prom_setprop(_prom->chosen, "/chosen", "linux,platform",		     &getprop_rval, sizeof(getprop_rval));#ifdef CONFIG_PPC_PSERIES	/*	 * On pSeries, inform the firmware about our capabilities	 */	if (RELOC(of_platform) == PLATFORM_PSERIES ||	    RELOC(of_platform) == PLATFORM_PSERIES_LPAR)		prom_send_capabilities();#endif	/*	 * Copy the CPU hold code	 */       	if (RELOC(of_platform) != PLATFORM_POWERMAC)       		copy_and_flush(0, KERNELBASE + offset, 0x100, 0);	/*	 * Do early parsing of command line	 */	early_cmdline_parse();	/*	 * Initialize memory management within prom_init	 */	prom_init_mem();	/*	 * Determine which cpu is actually running right _now_	 */	prom_find_boot_cpu();	/* 	 * Initialize display devices	 */	prom_check_displays();#ifdef CONFIG_PPC64	/*	 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else	 * that uses the allocator, we need to make sure we get the top of memory	 * available for us here...	 */	if (RELOC(of_platform) == PLATFORM_PSERIES)		prom_initialize_tce_table();#endif	/*	 * On non-powermacs, try to instantiate RTAS and puts all CPUs	 * in spin-loops. PowerMacs don't have a working RTAS and use	 * a different way to spin CPUs	 */	if (RELOC(of_platform) != PLATFORM_POWERMAC) {		prom_instantiate_rtas();		prom_hold_cpus();	}	/*	 * Fill in some infos for use by the kernel later on	 */	if (RELOC(prom_memory_limit))		prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",			     &RELOC(prom_memory_limit),			     sizeof(prom_memory_limit));#ifdef CONFIG_PPC64	if (RELOC(ppc64_iommu_off))		prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",			     NULL, 0);	if (RELOC(iommu_force_on))		prom_setprop(_prom->chosen, "/chosen", "linux,iommu-force-on",			     NULL, 0);	if (RELOC(prom_tce_alloc_start)) {		prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-start",			     &RELOC(prom_tce_alloc_start),			     sizeof(prom_tce_alloc_start));		prom_setprop(_prom->chosen, "/chosen", "linux,tce-alloc-end",			     &RELOC(prom_tce_alloc_end),			     sizeof(prom_tce_alloc_end));	}#endif	/*	 * Fixup any known bugs in the device-tree	 */	fixup_device_tree();	/*	 * Now finally create the flattened device-tree	 */	prom_printf("copying OF device tree ...\n");	flatten_device_tree();	/*	 * in case stdin is USB and still active on IBM machines...	 * Unfortunately quiesce crashes on some powermacs if we have	 * closed stdin already (in particular the powerbook 101).	 */	if (RELOC(of_platform) != PLATFORM_POWERMAC)		prom_close_stdin();	/*	 * Call OF "quiesce" method to shut down pending DMA's from	 * devices etc...	 */	prom_printf("Calling quiesce ...\n");	call_prom("quiesce", 0, 0);	/*	 * And finally, call the kernel passing it the flattened device	 * tree and NULL as r5, thus triggering the new entry point which	 * is common to us and kexec	 */	hdr = RELOC(dt_header_start);	prom_printf("returning from prom_init\n");	prom_debug("->dt_header_start=0x%x\n", hdr);#ifdef CONFIG_PPC32	reloc_got2(-offset);#endif	__start(hdr, KERNELBASE + offset, 0);	return 0;}

⌨️ 快捷键说明

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