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

📄 prom.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * 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 l;	char *p, *d; 	unsigned long phys; 	/* Default */ 	phys = offset + KERNELBASE;	/* First get a handle for the stdout device */	RELOC(prom) = pp;	RELOC(prom_chosen) = call_prom(RELOC("finddevice"), 1, 1,				       RELOC("/chosen"));	if (RELOC(prom_chosen) == (void *)-1)		prom_exit();	if ((int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),			    RELOC("stdout"), &RELOC(prom_stdout),			    sizeof(prom_stdout)) <= 0)		prom_exit();	/* Get the full OF pathname of the stdout device */	mem = (unsigned long) RELOC(klimit) + offset;	p = (char *) mem;	memset(p, 0, 256);	call_prom(RELOC("instance-to-path"), 3, 1, RELOC(prom_stdout), p, 255);	RELOC(of_stdout_device) = PTRUNRELOC(p);	mem += strlen(p) + 1;	/* Get the boot device and translate it to a full OF pathname. */	p = (char *) mem;	l = (int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),			    RELOC("bootpath"), p, 1<<20);	if (l > 0) {		p[l] = 0;	/* should already be null-terminated */		RELOC(bootpath) = PTRUNRELOC(p);		mem += l + 1;		d = (char *) mem;		*d = 0;		call_prom(RELOC("canon"), 3, 1, p, d, 1<<20);		RELOC(bootdevice) = PTRUNRELOC(d);		mem = ALIGN(mem + strlen(d) + 1);	}	prom_instantiate_rtas();#ifdef CONFIG_PPC64BRIDGE	/*	 * Find out how much memory we have and allocate a	 * suitably-sized hash table.	 */	prom_alloc_htab();#endif	mem = check_display(mem);	prom_print(RELOC("copying OF device tree..."));	mem = copy_device_tree(mem, mem + (1<<20));	prom_print(RELOC("done\n"));#ifdef CONFIG_SMP	prom_hold_cpus(mem);#endif	RELOC(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)		phys = 0;	else { 	    if ((int) call_prom(RELOC("getprop"), 4, 1, RELOC(prom_chosen),			    RELOC("mmu"), &prom_mmu, sizeof(prom_mmu)) <= 0) {		prom_print(RELOC(" no MMU found\n"));	    } else {		int nargs;		struct prom_args prom_args;		nargs = 4;		prom_args.service = RELOC("call-method");		prom_args.nargs = nargs;		prom_args.nret = 4;		prom_args.args[0] = RELOC("translate");		prom_args.args[1] = prom_mmu;		prom_args.args[2] = (void *)(offset + KERNELBASE);		prom_args.args[3] = (void *)1;		RELOC(prom)(&prom_args);		/* We assume the phys. address size is 3 cells */		if (prom_args.args[nargs] != 0)			prom_print(RELOC(" (translate failed)\n"));		else			phys = (unsigned long)prom_args.args[nargs+3];	    }	}#ifdef CONFIG_BOOTX_TEXT	if (RELOC(prom_disp_node) != 0)		setup_disp_fake_bi(RELOC(prom_disp_node));#endif	/* Use quiesce call to get OF to shut down any devices it's using */	prom_print(RELOC("Calling quiesce ...\n"));	call_prom(RELOC("quiesce"), 0, 0);#ifdef CONFIG_BOOTX_TEXT	if (RELOC(prom_disp_node) != 0)		btext_prepare_BAT();#endif	prom_print(RELOC("returning "));	prom_print_hex(phys);	prom_print(RELOC(" from prom_init\n"));	RELOC(prom_stdout) = 0;	return phys;}void phys_call_rtas(int service, int nargs, int nret, ...){	va_list list;	union {		unsigned long words[16];		double align;	} u;	unsigned long offset = reloc_offset();	void (*rtas)(void *, unsigned long);	int i;	u.words[0] = service;	u.words[1] = nargs;	u.words[2] = nret;	va_start(list, nret);	for (i = 0; i < nargs; ++i)		u.words[i+3] = va_arg(list, unsigned long);	va_end(list);	rtas = (void (*)(void *, unsigned long)) RELOC(rtas_entry);	rtas(&u, RELOC(rtas_data));}static int __initprom_set_color(ihandle ih, int i, int r, int g, int b){	struct prom_args prom_args;	unsigned long offset = reloc_offset();	prom_args.service = RELOC("call-method");	prom_args.nargs = 6;	prom_args.nret = 1;	prom_args.args[0] = RELOC("color!");	prom_args.args[1] = ih;	prom_args.args[2] = (void *) i;	prom_args.args[3] = (void *) b;	prom_args.args[4] = (void *) g;	prom_args.args[5] = (void *) r;	RELOC(prom)(&prom_args);	return (int) prom_args.args[6];}/* * If we have a display that we don't know how to drive, * we will want to try to execute OF's open method for it * later.  However, OF will probably fall over if we do that * we've taken over the MMU. * So we check whether we will need to open the display, * and if so, open it now. */static unsigned long __initcheck_display(unsigned long mem){	phandle node;	ihandle ih;	int i;	unsigned long offset = reloc_offset();	char type[16], *path;	static unsigned char default_colors[] = {		0x00, 0x00, 0x00,		0x00, 0x00, 0xaa,		0x00, 0xaa, 0x00,		0x00, 0xaa, 0xaa,		0xaa, 0x00, 0x00,		0xaa, 0x00, 0xaa,		0xaa, 0xaa, 0x00,		0xaa, 0xaa, 0xaa,		0x55, 0x55, 0x55,		0x55, 0x55, 0xff,		0x55, 0xff, 0x55,		0x55, 0xff, 0xff,		0xff, 0x55, 0x55,		0xff, 0x55, 0xff,		0xff, 0xff, 0x55,		0xff, 0xff, 0xff	};	RELOC(prom_disp_node) = 0;	for (node = 0; prom_next_node(&node); ) {		type[0] = 0;		call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),			  type, sizeof(type));		if (strcmp(type, RELOC("display")) != 0)			continue;		/* It seems OF doesn't null-terminate the path :-( */		path = (char *) mem;		memset(path, 0, 256);		if ((int) call_prom(RELOC("package-to-path"), 3, 1,				    node, path, 255) < 0)			continue;		/*		 * If this display is the device that OF is using for stdout,		 * move it to the front of the list.		 */		mem += strlen(path) + 1;		i = RELOC(prom_num_displays)++;		if (RELOC(of_stdout_device) != 0 && i > 0		    && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {			for (; i > 0; --i) {				RELOC(prom_display_paths[i])					= RELOC(prom_display_paths[i-1]);				RELOC(prom_display_nodes[i])					= RELOC(prom_display_nodes[i-1]);			}		}		RELOC(prom_display_paths[i]) = PTRUNRELOC(path);		RELOC(prom_display_nodes[i]) = node;		if (i == 0)			RELOC(prom_disp_node) = node;		if (RELOC(prom_num_displays) >= FB_MAX)			break;	}try_again:	/*	 * Open the first display and set its colormap.	 */	if (RELOC(prom_num_displays) > 0) {		path = PTRRELOC(RELOC(prom_display_paths[0]));		prom_print(RELOC("opening display "));		prom_print(path);		ih = call_prom(RELOC("open"), 1, 1, path);		if (ih == 0 || ih == (ihandle) -1) {			prom_print(RELOC("... failed\n"));			for (i=1; i<RELOC(prom_num_displays); i++) {				RELOC(prom_display_paths[i-1]) = RELOC(prom_display_paths[i]);				RELOC(prom_display_nodes[i-1]) = RELOC(prom_display_nodes[i]);			}			if (--RELOC(prom_num_displays) > 0)				RELOC(prom_disp_node) = RELOC(prom_display_nodes[0]);			else				RELOC(prom_disp_node) = NULL;			goto try_again;		} else {			prom_print(RELOC("... ok\n"));			/*			 * Setup a usable color table when the appropriate			 * method is available.			 * Should update this to use set-colors.			 */			for (i = 0; i < 32; i++)				if (prom_set_color(ih, i, RELOC(default_colors)[i*3],						   RELOC(default_colors)[i*3+1],						   RELOC(default_colors)[i*3+2]) != 0)					break;#ifdef CONFIG_FB			for (i = 0; i < LINUX_LOGO_COLORS; i++)				if (prom_set_color(ih, i + 32,						   RELOC(linux_logo_red)[i],						   RELOC(linux_logo_green)[i],						   RELOC(linux_logo_blue)[i]) != 0)					break;#endif /* CONFIG_FB */		}	}	return ALIGN(mem);}/* This function will enable the early boot text when doing OF booting. This * way, xmon output should work too */#ifdef CONFIG_BOOTX_TEXTstatic void __initsetup_disp_fake_bi(ihandle dp){	int width = 640, height = 480, depth = 8, pitch;	unsigned address;	unsigned long offset = reloc_offset();	struct pci_reg_property addrs[8];	int i, naddrs;	char name[32];	char *getprop = RELOC("getprop");	prom_print(RELOC("Initializing fake screen: "));	memset(name, 0, sizeof(name));	call_prom(getprop, 4, 1, dp, RELOC("name"), name, sizeof(name));	name[sizeof(name)-1] = 0;	prom_print(name);	prom_print(RELOC("\n"));	call_prom(getprop, 4, 1, dp, RELOC("width"), &width, sizeof(width));	call_prom(getprop, 4, 1, dp, RELOC("height"), &height, sizeof(height));	call_prom(getprop, 4, 1, dp, RELOC("depth"), &depth, sizeof(depth));	pitch = width * ((depth + 7) / 8);	call_prom(getprop, 4, 1, dp, RELOC("linebytes"),		  &pitch, sizeof(pitch));	if (pitch == 1)		pitch = 0x1000;		/* for strange IBM display */	address = 0;	call_prom(getprop, 4, 1, dp, RELOC("address"),		  &address, sizeof(address));	if (address == 0) {		/* look for an assigned address with a size of >= 1MB */		naddrs = (int) call_prom(getprop, 4, 1, dp,				RELOC("assigned-addresses"),				addrs, sizeof(addrs));		naddrs /= sizeof(struct pci_reg_property);		for (i = 0; i < naddrs; ++i) {			if (addrs[i].size_lo >= (1 << 20)) {				address = addrs[i].addr.a_lo;				/* use the BE aperture if possible */				if (addrs[i].size_lo >= (16 << 20))					address += (8 << 20);				break;			}		}		if (address == 0) {			prom_print(RELOC("Failed to get address\n"));			return;		}	}	/* kludge for valkyrie */	if (strcmp(name, RELOC("valkyrie")) == 0)		address += 0x1000;	btext_setup_display(width, height, depth, pitch, address);}#endifstatic int __initprom_next_node(phandle *nodep){	phandle node;	unsigned long offset = reloc_offset();	if ((node = *nodep) != 0	    && (*nodep = call_prom(RELOC("child"), 1, 1, node)) != 0)		return 1;	if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)		return 1;	for (;;) {		if ((node = call_prom(RELOC("parent"), 1, 1, node)) == 0)			return 0;		if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)			return 1;	}}/* * 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;	unsigned long offset = reloc_offset();	root = call_prom(RELOC("peer"), 1, 1, (phandle)0);	if (root == (phandle)0) {		prom_print(RELOC("couldn't get device tree root\n"));		prom_exit();	}	allnextp = &RELOC(allnodes);	mem_start = ALIGN(mem_start);	new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp);	*allnextp = 0;	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;	unsigned long offset = reloc_offset();	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 = RELOC("");	for (;;) {		pp = (struct property *) mem_start;		namep = (char *) (pp + 1);		pp->name = PTRUNRELOC(namep);		if ((int) call_prom(RELOC("nextprop"), 3, 1, node, prev_name,				    namep) <= 0)			break;		mem_start = ALIGN((unsigned long)namep + strlen(namep) + 1);		prev_name = namep;		valp = (unsigned char *) mem_start;		pp->value = PTRUNRELOC(valp);		pp->length = (int)			call_prom(RELOC("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 = ALIGN(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, RELOC("linux,phandle"));		mem_start = ALIGN((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(RELOC("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 = ALIGN(mem_start + l + 1);	}	/* do all our children */	child = call_prom(RELOC("child"), 1, 1, node);	while (child != (void *)0) {		mem_start = inspect_node(child, np, mem_start, mem_end,					 allnextpp);		child = call_prom(RELOC("peer"), 1, 1, child);	}	return mem_start;}/* * finish_device_tree is called once things are running normally * (i.e. with text and data mapped to the address they were linked at). * It traverses the device tree and fills in the name, type, * {n_}addrs and {n_}intrs fields of each node. */void __initfinish_device_tree(void){	unsigned long mem = (unsigned long) klimit;	struct device_node *np;	/* All newworld pmac machines and CHRPs now use the interrupt tree */	for (np = allnodes; np != NULL; np = np->allnext) {		if (get_property(np, "interrupt-parent", 0)) {			use_of_interrupt_tree = 1;			break;		}	}	if (_machine == _MACH_Pmac && use_of_interrupt_tree)		pmac_newworld = 1;#ifdef CONFIG_BOOTX_TEXT	if (boot_infos && pmac_newworld) {		prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n");		prom_print("          You should use an Open Firmware bootloader\n");	}#endif /* CONFIG_BOOTX_TEXT */	if (use_of_interrupt_tree) {		/*		 * We want to find out here how many interrupt-controller		 * nodes there are, and if we are booted from BootX,		 * we need a pointer to the first (and hopefully only)		 * such node.  But we can't use find_devices here since		 * np->name has not been set yet.  -- paulus		 */		int n = 0;		char *name, *ic;		int iclen;		for (np = allnodes; np != NULL; np = np->allnext) {			ic = get_property(np, "interrupt-controller", &iclen);			name = get_property(np, "name", NULL);			/* checking iclen makes sure we don't get a false			   match on /chosen.interrupt_controller */			if ((name != NULL			     && strcmp(name, "interrupt-controller") == 0)			    || (ic != NULL && iclen == 0)) {				if (n == 0)					dflt_interrupt_controller = np;				++n;			}		}		num_interrupt_controllers = n;	}	mem = finish_node(allnodes, mem, NULL, 1, 1);	dev_tree_size = mem - (unsigned long) allnodes;	klimit = (char *) mem;}

⌨️ 快捷键说明

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