欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

prom_init.c

Linux Kernel 2.6.9 for OMAP1710
C
第 1 页 / 共 4 页
字号:
/* *  * * Procedures for interfacing to Open Firmware. * * Paul Mackerras	August 1996. * Copyright (C) 1996 Paul Mackerras. *  *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. *    {engebret|bergner}@us.ibm.com  * *      This program is free software; you can redistribute it and/or *      modify it under the terms of the GNU General Public License *      as published by the Free Software Foundation; either version *      2 of the License, or (at your option) any later version. */#undef DEBUG_PROM#include <stdarg.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/init.h>#include <linux/version.h>#include <linux/threads.h>#include <linux/spinlock.h>#include <linux/types.h>#include <linux/pci.h>#include <linux/proc_fs.h>#include <linux/stringify.h>#include <linux/delay.h>#include <linux/initrd.h>#include <asm/prom.h>#include <asm/rtas.h>#include <asm/abs_addr.h>#include <asm/page.h>#include <asm/processor.h>#include <asm/irq.h>#include <asm/io.h>#include <asm/smp.h>#include <asm/system.h>#include <asm/mmu.h>#include <asm/pgtable.h>#include <asm/bitops.h>#include <asm/naca.h>#include <asm/pci.h>#include <asm/iommu.h>#include <asm/bootinfo.h>#include <asm/ppcdebug.h>#include <asm/btext.h>#include <asm/sections.h>#include <asm/machdep.h>#include "open_pic.h"#ifdef CONFIG_LOGO_LINUX_CLUT224#include <linux/linux_logo.h>extern const struct linux_logo logo_linux_clut224;#endif/* * Properties whose value is longer than this get excluded from our * copy of the device tree. This value does need to be big enough to * ensure that we don't lose things like the interrupt-map property * on a PCI-PCI bridge. */#define MAX_PROPERTY_LENGTH	(1UL * 1024 * 1024)/* * Eventually bump that one up */#define DEVTREE_CHUNK_SIZE	0x100000/* * This is the size of the local memory reserve map that gets copied * into the boot params passed to the kernel. That size is totally * flexible as the kernel just reads the list until it encounters an * entry with size 0, so it can be changed without breaking binary * compatibility */#define MEM_RESERVE_MAP_SIZE	8/* * prom_init() is called very early on, before the kernel text * and data have been mapped to KERNELBASE.  At this point the code * is running at whatever address it has been loaded at, so * references to extern and static variables must be relocated * explicitly.  The procedure reloc_offset() returns the address * we're currently running at minus the address we were linked at. * (Note that strings count as static variables.) * * Because OF may have mapped I/O devices into the area starting at * KERNELBASE, particularly on CHRP machines, we can't safely call * OF once the kernel has been mapped to KERNELBASE.  Therefore all * OF calls should be done within prom_init(), and prom_init() * and all routines called within it must be careful to relocate * references as necessary. * * Note that the bss is cleared *after* prom_init runs, so we have * to make sure that any static or extern variables it accesses * are put in the data segment. */#define PROM_BUG() do {						\        prom_printf("kernel BUG at %s line 0x%x!\n",		\		    RELOC(__FILE__), __LINE__);			\        __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR);	\} while (0)#ifdef DEBUG_PROM#define prom_debug(x...)	prom_printf(x)#else#define prom_debug(x...)#endiftypedef u32 prom_arg_t;struct prom_args {        u32 service;        u32 nargs;        u32 nret;        prom_arg_t args[10];        prom_arg_t *rets;     /* Pointer to return values in args[16]. */};struct prom_t {	unsigned long entry;	ihandle root;	ihandle chosen;	int cpu;	ihandle stdout;	ihandle disp_node;	struct prom_args args;	unsigned long version;	unsigned long root_size_cells;	unsigned long root_addr_cells;};struct pci_reg_property {	struct pci_address addr;	u32 size_hi;	u32 size_lo;};struct mem_map_entry {	u64	base;	u64	size;};typedef u32 cell_t;extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);extern unsigned long reloc_offset(void);extern void enter_prom(struct prom_args *args, unsigned long entry);extern void copy_and_flush(unsigned long dest, unsigned long src,			   unsigned long size, unsigned long offset);extern unsigned long klimit;//int global_width = 640, global_height = 480, global_depth = 8, global_pitch;//unsigned global_address;/* prom structure */static struct prom_t __initdata prom;#define PROM_SCRATCH_SIZE 256static char __initdata of_stdout_device[256];static char __initdata prom_scratch[PROM_SCRATCH_SIZE];static unsigned long __initdata dt_header_start;static unsigned long __initdata dt_struct_start, dt_struct_end;static unsigned long __initdata dt_string_start, dt_string_end;static unsigned long __initdata prom_initrd_start, prom_initrd_end;static int __initdata iommu_force_on;static int __initdata ppc64_iommu_off;static int __initdata of_platform;static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];static unsigned long __initdata alloc_top;static unsigned long __initdata alloc_top_high;static unsigned long __initdata alloc_bottom;static unsigned long __initdata rmo_top;static unsigned long __initdata ram_top;static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];static int __initdata mem_reserve_cnt;static cell_t __initdata regbuf[1024];#define MAX_CPU_THREADS 2/* TO GO */#ifdef CONFIG_HMTstruct {	unsigned int pir;	unsigned int threadid;} hmt_thread_data[NR_CPUS];#endif /* CONFIG_HMT *//* * This are used in calls to call_prom.  The 4th and following * arguments to call_prom should be 32-bit values.  64 bit values * are truncated to 32 bits (and fortunately don't get interpreted * as two arguments). */#define ADDR(x)		(u32) ((unsigned long)(x) - offset)/* This is the one and *ONLY* place where we actually call open * firmware from, since we need to make sure we're running in 32b * mode when we do.  We switch back to 64b mode upon return. */#define PROM_ERROR	(-1)static int __init call_prom(const char *service, int nargs, int nret, ...){	int i;	unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	va_list list;	_prom->args.service = ADDR(service);	_prom->args.nargs = nargs;	_prom->args.nret = nret;	_prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]);	va_start(list, nret);	for (i=0; i < nargs; i++)		_prom->args.args[i] = va_arg(list, prom_arg_t);	va_end(list);	for (i=0; i < nret ;i++)		_prom->args.rets[i] = 0;	enter_prom(&_prom->args, _prom->entry);	return (nret > 0) ? _prom->args.rets[0] : 0;}static unsigned int __init prom_claim(unsigned long virt, unsigned long size,				unsigned long align){	return (unsigned int)call_prom("claim", 3, 1,				       (prom_arg_t)virt, (prom_arg_t)size,				       (prom_arg_t)align);}static void __init prom_print(const char *msg){	const char *p, *q;	unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	if (_prom->stdout == 0)		return;	for (p = msg; *p != 0; p = q) {		for (q = p; *q != 0 && *q != '\n'; ++q)			;		if (q > p)			call_prom("write", 3, 1, _prom->stdout, p, q - p);		if (*q == 0)			break;		++q;		call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2);	}}static void __init prom_print_hex(unsigned long val){	unsigned long offset = reloc_offset();	int i, nibbles = sizeof(val)*2;	char buf[sizeof(val)*2+1];	struct prom_t *_prom = PTRRELOC(&prom);	for (i = nibbles-1;  i >= 0;  i--) {		buf[i] = (val & 0xf) + '0';		if (buf[i] > '9')			buf[i] += ('a'-'0'-10);		val >>= 4;	}	buf[nibbles] = '\0';	call_prom("write", 3, 1, _prom->stdout, buf, nibbles);}static void __init prom_printf(const char *format, ...){	unsigned long offset = reloc_offset();	const char *p, *q, *s;	va_list args;	unsigned long v;	struct prom_t *_prom = PTRRELOC(&prom);	va_start(args, format);	for (p = PTRRELOC(format); *p != 0; p = q) {		for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)			;		if (q > p)			call_prom("write", 3, 1, _prom->stdout, p, q - p);		if (*q == 0)			break;		if (*q == '\n') {			++q;			call_prom("write", 3, 1, _prom->stdout,				  ADDR("\r\n"), 2);			continue;		}		++q;		if (*q == 0)			break;		switch (*q) {		case 's':			++q;			s = va_arg(args, const char *);			prom_print(s);			break;		case 'x':			++q;			v = va_arg(args, unsigned long);			prom_print_hex(v);			break;		}	}}static void __init __attribute__((noreturn)) prom_panic(const char *reason){	unsigned long offset = reloc_offset();	prom_print(PTRRELOC(reason));	/* ToDo: should put up an SRC here */	call_prom("exit", 0, 0);	for (;;)			/* should never get here */		;}static int __init prom_next_node(phandle *nodep){	phandle node;	if ((node = *nodep) != 0	    && (*nodep = call_prom("child", 1, 1, node)) != 0)		return 1;	if ((*nodep = call_prom("peer", 1, 1, node)) != 0)		return 1;	for (;;) {		if ((node = call_prom("parent", 1, 1, node)) == 0)			return 0;		if ((*nodep = call_prom("peer", 1, 1, node)) != 0)			return 1;	}}static int __init prom_getprop(phandle node, const char *pname,			       void *value, size_t valuelen){	unsigned long offset = reloc_offset();	return call_prom("getprop", 4, 1, node, ADDR(pname),			 (u32)(unsigned long) value, (u32) valuelen);}static int __init prom_getproplen(phandle node, const char *pname){	unsigned long offset = reloc_offset();	return call_prom("getproplen", 2, 1, node, ADDR(pname));}static int __init prom_setprop(phandle node, const char *pname,			       void *value, size_t valuelen){	unsigned long offset = reloc_offset();	return call_prom("setprop", 4, 1, node, ADDR(pname),			 (u32)(unsigned long) value, (u32) valuelen);}/* * Early parsing of the command line passed to the kernel, used for * the options that affect the iommu */static void __init early_cmdline_parse(void){	unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);	char *opt, *p;	int l = 0;	RELOC(prom_cmd_line[0]) = 0;	p = RELOC(prom_cmd_line);	if ((long)_prom->chosen > 0)		l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1);#ifdef CONFIG_CMDLINE	if (l == 0) /* dbl check */		strlcpy(RELOC(prom_cmd_line),			RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line));#endif /* CONFIG_CMDLINE */	prom_printf("command line: %s\n", RELOC(prom_cmd_line));	opt = strstr(RELOC(prom_cmd_line), RELOC("iommu="));	if (opt) {		prom_printf("iommu opt is: %s\n", opt);		opt += 6;		while (*opt && *opt == ' ')			opt++;		if (!strncmp(opt, RELOC("off"), 3))			RELOC(ppc64_iommu_off) = 1;		else if (!strncmp(opt, RELOC("force"), 5))			RELOC(iommu_force_on) = 1;	}}/* * Memory allocation strategy... our layout is normally:

⌨️ 快捷键说明

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