📄 boot_of.c
字号:
/* * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright IBM Corp. 2005, 2006, 2007 * * Authors: Jimi Xenidis <jimix@watson.ibm.com> * Hollis Blanchard <hollisb@us.ibm.com> */#include <xen/config.h>#include <xen/init.h>#include <xen/lib.h>#include <xen/version.h>#include <xen/spinlock.h>#include <xen/serial.h>#include <xen/time.h>#include <xen/sched.h>#include <asm/page.h>#include <asm/io.h>#include <asm/boot.h>#include "exceptions.h"#include "of-devtree.h"#include "oftree.h"#include "rtas.h"/* Secondary processors use this for handshaking with main processor. */volatile unsigned int __spin_ack;static ulong of_vec;static ulong of_msr;static int of_out;static ulong eomem;/* Track memory during early boot with a limited per-page bitmap. We need an * allocator to tell us where we can place RTAS, our copy of the device tree. * We could examine the "available" properties in memory nodes, but we * apparently can't depend on firmware to update those when we call "claim". So * we need to track it ourselves. * We can't dynamically allocate the bitmap, because we would need something * to tell us where it's safe to allocate... */#define MEM_AVAILABLE_PAGES ((32 << 20) >> PAGE_SHIFT)static DECLARE_BITMAP(mem_available_pages, MEM_AVAILABLE_PAGES);extern struct ns16550_defaults ns16550;#undef OF_DEBUG#undef OF_DEBUG_LOW#ifdef OF_DEBUG#define DBG(args...) of_printf(args)#else#define DBG(args...)#endif#ifdef OF_DEBUG_LOW#define DBG_LOW(args...) of_printf(args)#else#define DBG_LOW(args...)#endif#define of_panic(MSG...) \ do { of_printf(MSG); of_printf("\nHANG\n"); for (;;); } while (0)struct of_service { u32 ofs_service; u32 ofs_nargs; u32 ofs_nrets; u32 ofs_args[10];};static int bof_chosen;static struct of_service s;static int __init of_call( const char *service, u32 nargs, u32 nrets, s32 rets[], ...){ int rc; if (of_vec != 0) { va_list args; int i; memset(&s, 0, sizeof (s)); s.ofs_service = (ulong)service; s.ofs_nargs = nargs; s.ofs_nrets = nrets; s.ofs_nargs = nargs; /* copy all the params into the args array */ va_start(args, rets); for (i = 0; i < nargs; i++) { s.ofs_args[i] = va_arg(args, u32); } va_end(args); rc = prom_call(&s, 0, of_vec, of_msr); /* yes always to the copy, just in case */ for (i = 0; i < nrets; i++) { rets[i] = s.ofs_args[i + nargs]; } } else { rc = OF_FAILURE; } return rc;}/* popular OF methods */static int __init _of_write(int ih, const char *addr, u32 len){ int rets[1] = { OF_FAILURE }; if (of_call("write", 3, 1, rets, ih, addr, len) == OF_FAILURE) { return OF_FAILURE; } return rets[0];}/* popular OF methods */static int __init of_write(int ih, const char *addr, u32 len){ int rc; int i = 0; int sum = 0; while (i < len) { if (addr[i] == '\n') { if (i > 0) { rc = _of_write(ih, addr, i); if (rc == OF_FAILURE) return rc; sum += rc; } rc = _of_write(ih, "\r\n", 2); if (rc == OF_FAILURE) return rc; sum += rc; i++; addr += i; len -= i; i = 0; continue; } i++; } if (len > 0) { rc = _of_write(ih, addr, len); if (rc == OF_FAILURE) return rc; sum += rc; } return sum;}static int of_printf(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));static int __init of_printf(const char *fmt, ...){ static char buf[1024]; va_list args; int sz; if (of_out == 0) { return OF_FAILURE; } va_start(args, fmt); sz = vsnprintf(buf, sizeof (buf), fmt, args); if (sz <= sizeof (buf)) { of_write(of_out, buf, sz); } else { static const char trunc[] = "\n(TRUNCATED)\n"; sz = sizeof (buf); of_write(of_out, buf, sz); of_write(of_out, trunc, sizeof (trunc)); } return sz;}static int __init of_finddevice(const char *devspec){ int rets[1] = { OF_FAILURE }; of_call("finddevice", 1, 1, rets, devspec); if (rets[0] == OF_FAILURE) { DBG("finddevice %s -> FAILURE %d\n",devspec,rets[0]); return OF_FAILURE; } DBG_LOW("finddevice %s -> %d\n",devspec, rets[0]); return rets[0];}static int __init of_getprop(int ph, const char *name, void *buf, u32 buflen){ int rets[1] = { OF_FAILURE }; of_call("getprop", 4, 1, rets, ph, name, buf, buflen); if (rets[0] == OF_FAILURE) { DBG_LOW("getprop 0x%x %s -> FAILURE\n", ph, name); return OF_FAILURE; } DBG_LOW("getprop 0x%x %s -> 0x%x (%s)\n", ph, name, rets[0], (char *)buf); return rets[0];}static int __init of_setprop( int ph, const char *name, const void *buf, u32 buflen){ int rets[1] = { OF_FAILURE }; of_call("setprop", 4, 1, rets, ph, name, buf, buflen); if (rets[0] == OF_FAILURE) { DBG("setprop 0x%x %s -> FAILURE\n", ph, name); return OF_FAILURE; } DBG_LOW("setprop 0x%x %s -> %s\n", ph, name, (char *)buf); return rets[0];}/* * returns 0 if there are no children (of spec) */static int __init of_getchild(int ph){ int rets[1] = { OF_FAILURE }; of_call("child", 1, 1, rets, ph); DBG_LOW("getchild 0x%x -> 0x%x\n", ph, rets[0]); return rets[0];}/* * returns 0 is there are no peers */static int __init of_getpeer(int ph){ int rets[1] = { OF_FAILURE }; of_call("peer", 1, 1, rets, ph); DBG_LOW("getpeer 0x%x -> 0x%x\n", ph, rets[0]); return rets[0];}static int __init of_getproplen(int ph, const char *name){ int rets[1] = { OF_FAILURE }; of_call("getproplen", 2, 1, rets, ph, name); if (rets[0] == OF_FAILURE) { DBG("getproplen 0x%x %s -> FAILURE\n", ph, name); return OF_FAILURE; } DBG_LOW("getproplen 0x%x %s -> 0x%x\n", ph, name, rets[0]); return rets[0];}static int __init of_package_to_path(int ph, char *buffer, u32 buflen){ int rets[1] = { OF_FAILURE }; of_call("package-to-path", 3, 1, rets, ph, buffer, buflen); if (rets[0] == OF_FAILURE) { DBG("%s 0x%x -> FAILURE\n", __func__, ph); return OF_FAILURE; } DBG_LOW("%s 0x%x %s -> 0x%x\n", __func__, ph, buffer, rets[0]); if (rets[0] <= buflen) buffer[rets[0]] = '\0'; return rets[0];}static int __init of_nextprop(int ph, const char *name, void *buf){ int rets[1] = { OF_FAILURE }; of_call("nextprop", 3, 1, rets, ph, name, buf); if (rets[0] == OF_FAILURE) { DBG("nextprop 0x%x %s -> FAILURE\n", ph, name); return OF_FAILURE; } DBG_LOW("nextprop 0x%x %s -> %s\n", ph, name, (char *)buf); return rets[0];}static int __init of_instance_to_path(int ih, char *buffer, u32 buflen){ int rets[1] = { OF_FAILURE }; if (of_call("instance-to-path", 3, 1, rets, ih, buffer, buflen) == OF_FAILURE) return OF_FAILURE; if (rets[0] <= buflen) buffer[rets[0]] = '\0'; return rets[0];}static int __init of_start_cpu(int cpu, u32 pc, u32 reg){ int ret; ret = of_call("start-cpu", 3, 0, NULL, cpu, pc, reg); return ret;}static void __init of_test(const char *of_method_name){ int rets[1] = { OF_FAILURE }; of_call("test", 1, 1, rets, of_method_name); if (rets[0] == OF_FAILURE ) { of_printf("Warning: possibly no OF method %s.\n" "(Ignore this warning on PIBS.)\n", of_method_name); }}static int __init of_claim(u32 virt, u32 size, u32 align){ int rets[1] = { OF_FAILURE }; of_call("claim", 3, 1, rets, virt, size, align); if (rets[0] == OF_FAILURE) { DBG("%s 0x%08x 0x%08x 0x%08x -> FAIL\n", __func__, virt, size, align); return OF_FAILURE; } DBG_LOW("%s 0x%08x 0x%08x 0x%08x -> 0x%08x\n", __func__, virt, size, align, rets[0]); return rets[0];}static int __init of_instance_to_package(int ih){ int rets[1] = { OF_FAILURE }; of_call("instance-to-package", 1, 1, rets, ih); if (rets[0] == OF_FAILURE) return OF_FAILURE; return rets[0];}static int __init of_getparent(int ph){ int rets[1] = { OF_FAILURE }; of_call("parent", 1, 1, rets, ph); DBG_LOW("getparent 0x%x -> 0x%x\n", ph, rets[0]); return rets[0];}static int __init of_open(const char *devspec){ int rets[1] = { OF_FAILURE }; of_call("open", 1, 1, rets, devspec); return rets[0];}static void boot_of_alloc_init(int m, uint addr_cells, uint size_cells){ int rc; uint pg; uint a[64]; int tst; u64 start; u64 size; rc = of_getprop(m, "available", a, sizeof (a)); if (rc > 0) { int l = rc / sizeof(a[0]); int r = 0;#ifdef OF_DEBUG { int i; of_printf("avail:\n"); for (i = 0; i < l; i += 4) of_printf(" 0x%x%x, 0x%x%x\n", a[i], a[i + 1], a[i + 2] ,a[i + 3]); }#endif pg = 0; while (pg < MEM_AVAILABLE_PAGES && r < l) { ulong end; start = a[r++]; if (addr_cells == 2 && (r < l) ) start = (start << 32) | a[r++]; size = a[r++];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -