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

📄 prom.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
/* - undefined for user space *  * * 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. */#if 0#define DEBUG_YABOOT#endif#if 0#define DEBUG_PROM#endif#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/blk.h>#ifdef DEBUG_YABOOT#define call_yaboot(FUNC,...) \	do { \		if (FUNC) {					\			struct prom_t *_prom = PTRRELOC(&prom);	\			unsigned long prom_entry = _prom->entry;\			_prom->entry = (unsigned long)(FUNC);	\			enter_prom(__VA_ARGS__); 		\			_prom->entry = prom_entry;		\		}						\	} while (0)#else#define call_yaboot(FUNC,...) do { ; } while (0)#endif#include <asm/init.h>#include <linux/types.h>#include <linux/pci.h>#include <asm/prom.h>#include <asm/rtas.h>#include <asm/lmb.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 "open_pic.h"#include <asm/bootinfo.h>#include <asm/ppcdebug.h>#ifdef CONFIG_FB#include <asm/linux_logo.h>#endifextern char _end[];/* * 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_print(RELOC("kernel BUG at ")); \        prom_print(RELOC(__FILE__)); \        prom_print(RELOC(":")); \        prom_print_hex(__LINE__); \        prom_print(RELOC("!\n")); \        __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \} while (0)struct pci_reg_property {	struct pci_address addr;	u32 size_hi;	u32 size_lo;};struct isa_reg_property {	u32 space;	u32 address;	u32 size;};struct pci_intr_map {	struct pci_address addr;	u32 dunno;	phandle int_ctrler;	u32 intr;};typedef unsigned long interpret_func(struct device_node *, unsigned long,				     int, int);#if 0static interpret_func interpret_pci_props;#endifstatic unsigned long interpret_pci_props(struct device_node *, unsigned long,					 int, int);static interpret_func interpret_isa_props;static interpret_func interpret_root_props;#ifndef FB_MAX			/* avoid pulling in all of the fb stuff */#define FB_MAX	8#endifstruct prom_t prom = {	0,			/* entry */	0,			/* chosen */	0,			/* cpu */	0,			/* stdout */	0,			/* disp_node */	{0,0,0,{0},NULL},	/* args */	0,			/* version */	32,			/* encode_phys_size */	0			/* bi_rec pointer */#ifdef DEBUG_YABOOT	,NULL			/* yaboot */#endif};char *prom_display_paths[FB_MAX] __initdata = { 0, };unsigned int prom_num_displays = 0;char *of_stdout_device = 0;extern struct rtas_t rtas;extern unsigned long klimit;extern unsigned long embedded_sysmap_end;extern struct lmb lmb;#ifdef CONFIG_MSCHUNKSextern struct msChunks msChunks;#endif /* CONFIG_MSCHUNKS */#define MAX_PHB 16 * 3  // 16 Towers * 3 PHBs/towerstruct _of_tce_table of_tce_table[MAX_PHB + 1] = {{0, 0, 0}};char *bootpath = 0;char *bootdevice = 0;struct device_node *allnodes = 0;#define UNDEFINED_IRQ 0xffffunsigned short real_irq_to_virt_map[NR_HW_IRQS];unsigned short virt_irq_to_real_map[NR_IRQS];int last_virt_irq = 2;	/* index of last virt_irq.  Skip through IPI */static unsigned long call_prom(const char *service, int nargs, int nret, ...);static void prom_exit(void);static unsigned long copy_device_tree(unsigned long);static unsigned long inspect_node(phandle, struct device_node *, unsigned long,				  unsigned long, struct device_node ***);static unsigned long finish_node(struct device_node *, unsigned long,				 interpret_func *, int, int);static unsigned long finish_node_interrupts(struct device_node *, unsigned long);static unsigned long check_display(unsigned long);static int prom_next_node(phandle *);static struct bi_record * prom_bi_rec_verify(struct bi_record *);static unsigned long prom_bi_rec_reserve(unsigned long);static struct device_node *find_phandle(phandle);#ifdef CONFIG_MSCHUNKSstatic unsigned long prom_initialize_mschunks(unsigned long);#ifdef DEBUG_PROMvoid prom_dump_mschunks_mapping(void);#endif /* DEBUG_PROM */#endif /* CONFIG_MSCHUNKS */#ifdef DEBUG_PROMvoid prom_dump_lmb(void);#endifextern unsigned long reloc_offset(void);extern void enter_prom(void *dummy,...);void cacheable_memzero(void *, unsigned int);#ifndef CONFIG_CMDLINE#define CONFIG_CMDLINE ""#endifchar cmd_line[512] = CONFIG_CMDLINE;unsigned long dev_tree_size;#ifdef CONFIG_HMTstruct {	unsigned int pir;	unsigned int threadid;} hmt_thread_data[NR_CPUS] = {0};#endif /* CONFIG_HMT */char testString[] = "LINUX\n"; /* 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. */static unsigned long __initcall_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 = (u32)LONG_LSW(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] = (prom_arg_t)LONG_LSW(va_arg(list, unsigned long));        va_end(list);	for (i=0; i < nret ;i++)		_prom->args.rets[i] = 0;	enter_prom(&_prom->args);	return (unsigned long)((nret > 0) ? _prom->args.rets[0] : 0);}static void __initprom_exit(){	unsigned long offset = reloc_offset();	call_prom(RELOC("exit"), 0, 0);	for (;;)			/* should never get here */		;}void __initprom_enter(void){	unsigned long offset = reloc_offset();	call_prom(RELOC("enter"), 0, 0);}void __initprom_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(RELOC("write"), 3, 1, _prom->stdout,				  p, q - p);		if (*q != 0) {			++q;			call_prom(RELOC("write"), 3, 1, _prom->stdout,				  RELOC("\r\n"), 2);		}	}}voidprom_print_hex(unsigned long val){        int i, nibbles = sizeof(val)*2;        char buf[sizeof(val)*2+1];        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';	prom_print(buf);}voidprom_print_nl(void){	unsigned long offset = reloc_offset();	prom_print(RELOC("\n"));}static unsigned longprom_initialize_naca(unsigned long mem){	phandle node;	char type[64];        unsigned long num_cpus = 0;        unsigned long offset = reloc_offset();	struct prom_t *_prom = PTRRELOC(&prom);        struct naca_struct *_naca = RELOC(naca);	/* NOTE: _naca->debug_switch is already initialized. */#ifdef DEBUG_PROM	prom_print(RELOC("prom_initialize_naca: start...\n"));#endif	_naca->pftSize = 0;	/* ilog2 of htab size.  computed below. */        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("cpu"))) {			num_cpus += 1;			/* We're assuming *all* of the CPUs have the same			 * d-cache and i-cache sizes... -Peter			 */			if ( num_cpus == 1 ) {				u32 size, lsize, sets;				call_prom(RELOC("getprop"), 4, 1, node,					  RELOC("d-cache-size"),					  &size, sizeof(size));				call_prom(RELOC("getprop"), 4, 1, node,					  RELOC("d-cache-line-size"),					  &lsize, sizeof(lsize));				call_prom(RELOC("getprop"), 4, 1, node,					  RELOC("d-cache-sets"),					  &sets, sizeof(sets));				_naca->dCacheL1Size         = size;				_naca->dCacheL1LineSize     = lsize;				_naca->dCacheL1LogLineSize  = __ilog2(lsize);				_naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize;				_naca->dCacheL1Assoc = size / lsize / sets;				call_prom(RELOC("getprop"), 4, 1, node,					  RELOC("i-cache-line-size"),					  &size, sizeof(size));				call_prom(RELOC("getprop"), 4, 1, node,					  RELOC("i-cache-line-size"),					  &lsize, sizeof(lsize));				call_prom(RELOC("getprop"), 4, 1, node,					  RELOC("i-cache-sets"),					  &sets, sizeof(sets));				_naca->iCacheL1Size         = size;				_naca->iCacheL1LineSize     = lsize;				_naca->iCacheL1LogLineSize  = __ilog2(lsize);				_naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize;				_naca->iCacheL1Assoc = size / lsize / sets;				if (_naca->platform == PLATFORM_PSERIES_LPAR) {					u32 pft_size[2];					call_prom(RELOC("getprop"), 4, 1, node, 						  RELOC("ibm,pft-size"),						  &pft_size, sizeof(pft_size));				/* pft_size[0] is the NUMA CEC cookie */					_naca->pftSize = pft_size[1];				}			}                } else if (!strcmp(type, RELOC("serial"))) {			phandle isa, pci;			struct isa_reg_property reg;			union pci_range ranges;			type[0] = 0;			call_prom(RELOC("getprop"), 4, 1, node,				  RELOC("ibm,aix-loc"), type, sizeof(type));			if (strcmp(type, RELOC("S1")))				continue;			call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),				  &reg, sizeof(reg));			isa = call_prom(RELOC("parent"), 1, 1, node);			if (!isa)				PROM_BUG();			pci = call_prom(RELOC("parent"), 1, 1, isa);			if (!pci)				PROM_BUG();			call_prom(RELOC("getprop"), 4, 1, pci, RELOC("ranges"),				  &ranges, sizeof(ranges));			if ( _prom->encode_phys_size == 32 )				_naca->serialPortAddr = ranges.pci32.phys+reg.address;			else {				_naca->serialPortAddr = 					((((unsigned long)ranges.pci64.phys_hi) << 32) |					 (ranges.pci64.phys_lo)) + reg.address;			}                }	}	_naca->interrupt_controller = IC_INVALID;        for (node = 0; prom_next_node(&node); ) {                type[0] = 0;                call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"),                          type, sizeof(type));                if (strcmp(type, RELOC("interrupt-controller"))) {			continue;		}                call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"),                          type, sizeof(type));                if (strstr(type, RELOC("open-pic"))) {			_naca->interrupt_controller = IC_OPEN_PIC;		} else if (strstr(type, RELOC("ppc-xicp"))) {			_naca->interrupt_controller = IC_PPC_XIC;		} else {			prom_print(RELOC("prom: failed to recognize interrupt-controller\n"));		}		break;	}	if (_naca->interrupt_controller == IC_INVALID) {		prom_print(RELOC("prom: failed to find interrupt-controller\n"));		PROM_BUG();	}	/* We gotta have at least 1 cpu... */        if ( (_naca->processorCount = num_cpus) < 1 )                PROM_BUG();	_naca->physicalMemorySize = lmb_phys_mem_size();

⌨️ 快捷键说明

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