#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/ioport.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/bitops.h>
#include <asm/sections.h>
#include <asm/prom.h>
#include <asm/system.h>
#include <asm/mmu.h>
#include <asm/pgtable.h>
-#include <asm/bitops.h>
#include <asm/bootinfo.h>
#include <asm/btext.h>
#include <asm/pci-bridge.h>
#define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
+typedef u32 prom_arg_t;
+
struct prom_args {
const char *service;
int nargs;
int nret;
- void *args[10];
+ prom_arg_t args[10];
};
struct pci_address {
};
static void prom_exit(void);
-static void *call_prom(const char *service, int nargs, int nret, ...);
-static void *call_prom_ret(const char *service, int nargs, int nret,
- void **rets, ...);
+static int call_prom(const char *service, int nargs, int nret, ...);
+static int call_prom_ret(const char *service, int nargs, int nret,
+ prom_arg_t *rets, ...);
static void prom_print_hex(unsigned int v);
static int prom_set_color(ihandle ih, int i, int r, int g, int b);
static int prom_next_node(phandle *nodep);
static void * early_get_property(unsigned long base, unsigned long node,
char *prop);
-prom_entry prom __initdata = 0;
-ihandle prom_chosen __initdata = 0;
-ihandle prom_stdout __initdata = 0;
+prom_entry prom __initdata;
+ihandle prom_chosen __initdata;
+ihandle prom_stdout __initdata;
-char *prom_display_paths[FB_MAX] __initdata = { 0, };
-phandle prom_display_nodes[FB_MAX] __initdata;
-unsigned int prom_num_displays __initdata = 0;
-static char *of_stdout_device __initdata = 0;
-static ihandle prom_disp_node __initdata = 0;
+static char *prom_display_paths[FB_MAX] __initdata;
+static phandle prom_display_nodes[FB_MAX] __initdata;
+static unsigned int prom_num_displays __initdata;
+static ihandle prom_disp_node __initdata;
+char *of_stdout_device __initdata;
unsigned int rtas_data; /* physical pointer */
unsigned int rtas_entry; /* physical pointer */
;
}
-static void * __init
+static int __init
call_prom(const char *service, int nargs, int nret, ...)
{
va_list list;
prom_args.nret = nret;
va_start(list, nret);
for (i = 0; i < nargs; ++i)
- prom_args.args[i] = va_arg(list, void *);
+ prom_args.args[i] = va_arg(list, prom_arg_t);
va_end(list);
for (i = 0; i < nret; ++i)
prom_args.args[i + nargs] = 0;
return prom_args.args[nargs];
}
-static void * __init
-call_prom_ret(const char *service, int nargs, int nret, void **rets, ...)
+static int __init
+call_prom_ret(const char *service, int nargs, int nret, prom_arg_t *rets, ...)
{
va_list list;
int i;
prom_args.nret = nret;
va_start(list, rets);
for (i = 0; i < nargs; ++i)
- prom_args.args[i] = va_arg(list, void *);
+ prom_args.args[i] = va_arg(list, int);
va_end(list);
for (i = 0; i < nret; ++i)
prom_args.args[i + nargs] = 0;
static int __init
prom_set_color(ihandle ih, int i, int r, int g, int b)
{
- struct prom_args prom_args;
-
- prom_args.service = "call-method";
- prom_args.nargs = 6;
- prom_args.nret = 1;
- prom_args.args[0] = "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;
- prom(&prom_args);
- return (int) prom_args.args[6];
+ return call_prom("call-method", 6, 1, "color!", ih, i, b, g, r);
}
static int __init
/* It seems OF doesn't null-terminate the path :-( */
path = (char *) mem;
memset(path, 0, 256);
- if ((int) call_prom("package-to-path", 3, 1,
- node, path, 255) < 0)
+ if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
continue;
/*
for (j=0; j<prom_num_displays; j++) {
path = prom_display_paths[j];
+ node = prom_display_nodes[j];
prom_print("opening display ");
prom_print(path);
ih = call_prom("open", 1, 1, path);
prom_disp_node = prom_display_nodes[j];
j--;
} else
- prom_disp_node = NULL;
+ prom_disp_node = 0;
continue;
} else {
prom_print("... ok\n");
+ call_prom("setprop", 4, 1, node, "linux,opened", 0, 0);
+
/*
* Setup a usable color table when the appropriate
* method is available.
#endif /* CONFIG_LOGO_LINUX_CLUT224 */
}
}
+
+ if (prom_stdout) {
+ phandle p;
+ p = call_prom("instance-to-package", 1, 1, prom_stdout);
+ if (p && p != -1) {
+ type[0] = 0;
+ call_prom("getprop", 4, 1, p, "device_type",
+ type, sizeof(type));
+ if (strcmp(type, "display") == 0)
+ call_prom("setprop", 4, 1, p, "linux,boot-display",
+ 0, 0);
+ }
+ }
return ALIGNUL(mem);
}
&address, sizeof(address));
if (address == 0) {
/* look for an assigned address with a size of >= 1MB */
- naddrs = (int) call_prom(getprop, 4, 1, dp,
- "assigned-addresses",
- addrs, sizeof(addrs));
+ naddrs = call_prom(getprop, 4, 1, dp, "assigned-addresses",
+ addrs, sizeof(addrs));
naddrs /= sizeof(struct pci_reg_property);
for (i = 0; i < naddrs; ++i) {
if (addrs[i].size_lo >= (1 << 20)) {
}
allnextp = &allnodes;
mem_start = ALIGNUL(mem_start);
- new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp);
- *allnextp = 0;
+ new_start = inspect_node(root, NULL, mem_start, mem_end, &allnextp);
+ *allnextp = NULL;
return new_start;
}
pp = (struct property *) mem_start;
namep = (char *) (pp + 1);
pp->name = PTRUNRELOC(namep);
- if ((int) call_prom("nextprop", 3, 1, node, prev_name,
- namep) <= 0)
+ if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0)
break;
mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
prev_name = namep;
valp = (unsigned char *) mem_start;
pp->value = PTRUNRELOC(valp);
- pp->length = (int)
- call_prom("getprop", 4, 1, node, namep,
- valp, mem_end - mem_start);
+ pp->length = call_prom("getprop", 4, 1, node, namep,
+ valp, mem_end - mem_start);
if (pp->length < 0)
continue;
#ifdef MAX_PROPERTY_LENGTH
*prev_propp = PTRUNRELOC(pp);
prev_propp = &pp->next;
}
- if (np->node != NULL) {
+ if (np->node != 0) {
/* Add a "linux,phandle" property" */
pp = (struct property *) mem_start;
*prev_propp = PTRUNRELOC(pp);
*prev_propp = NULL;
/* get the node's full name */
- l = (int) call_prom("package-to-path", 3, 1, node,
- (char *) mem_start, mem_end - mem_start);
+ l = call_prom("package-to-path", 3, 1, node,
+ mem_start, mem_end - mem_start);
if (l >= 0) {
+ char *p, *ep;
+
np->full_name = PTRUNRELOC((char *) mem_start);
*(char *)(mem_start + l) = 0;
+ /* Fixup an Apple bug where they have bogus \0 chars in the
+ * middle of the path in some properties
+ */
+ for (p = (char *)mem_start, ep = p + l; p < ep; p++)
+ if ((*p) == '\0') {
+ memmove(p, p+1, ep - p);
+ ep--;
+ }
mem_start = ALIGNUL(mem_start + l + 1);
}
/* do all our children */
child = call_prom("child", 1, 1, node);
- while (child != (void *)0) {
+ while (child != 0) {
mem_start = inspect_node(child, np, mem_start, mem_end,
allnextpp);
child = call_prom("peer", 1, 1, child);
* chrp we have a device_type property -- Cort
*/
node = call_prom("finddevice", 1, 1, "/");
- if ((int)call_prom("getprop", 4, 1, node,
- "device_type",type, sizeof(type)) <= 0)
+ if (call_prom("getprop", 4, 1, node,
+ "device_type", type, sizeof(type)) <= 0)
return;
/* copy the holding pattern code to someplace safe (0) */
continue;
path = (char *) mem;
memset(path, 0, 256);
- if ((int) call_prom("package-to-path", 3, 1,
- node, path, 255) < 0)
+ if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
continue;
reg = -1;
call_prom("getprop", 4, 1, node, "reg", ®, sizeof(reg));
prom_instantiate_rtas(void)
{
ihandle prom_rtas;
- unsigned int i;
- struct prom_args prom_args;
+ prom_arg_t result;
prom_rtas = call_prom("finddevice", 1, 1, "/rtas");
- if (prom_rtas == (void *) -1)
+ if (prom_rtas == -1)
return;
rtas_size = 0;
prom_rtas = call_prom("open", 1, 1, "/rtas");
prom_print("...");
- prom_args.service = "call-method";
- prom_args.nargs = 3;
- prom_args.nret = 2;
- prom_args.args[0] = "instantiate-rtas";
- prom_args.args[1] = prom_rtas;
- prom_args.args[2] = (void *) rtas_data;
- prom(&prom_args);
- i = 0;
- if (prom_args.args[3] == 0)
- i = (unsigned int)prom_args.args[4];
- rtas_entry = i;
+ rtas_entry = 0;
+ if (call_prom_ret("call-method", 3, 2, &result,
+ "instantiate-rtas", prom_rtas, rtas_data) == 0)
+ rtas_entry = result;
if ((rtas_entry == -1) || (rtas_entry == 0))
prom_print(" failed\n");
else
int i, l;
char *p, *d;
unsigned long phys;
- void *result[3];
+ prom_arg_t result[3];
+ char model[32];
+ phandle node;
+ int rc;
/* Default */
phys = (unsigned long) &_stext;
/* First get a handle for the stdout device */
prom = pp;
prom_chosen = call_prom("finddevice", 1, 1, "/chosen");
- if (prom_chosen == (void *)-1)
+ if (prom_chosen == -1)
prom_exit();
- if ((int) call_prom("getprop", 4, 1, prom_chosen,
- "stdout", &prom_stdout,
- sizeof(prom_stdout)) <= 0)
+ if (call_prom("getprop", 4, 1, prom_chosen, "stdout",
+ &prom_stdout, sizeof(prom_stdout)) <= 0)
prom_exit();
/* Get the full OF pathname of the stdout device */
/* Get the boot device and translate it to a full OF pathname. */
p = (char *) mem;
- l = (int) call_prom("getprop", 4, 1, prom_chosen,
- "bootpath", p, 1<<20);
+ l = call_prom("getprop", 4, 1, prom_chosen, "bootpath", p, 1<<20);
if (l > 0) {
p[l] = 0; /* should already be null-terminated */
bootpath = PTRUNRELOC(p);
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) {
+ node = call_prom("finddevice", 1, 1, "/");
+ rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model));
+ if (rc > 0 && !strncmp (model, "Pegasos", 7)
+ && strncmp (model, "Pegasos2", 8)) {
+ /* Pegasos 1 has a broken translate method in the OF,
+ * and furthermore the BATs are mapped 1:1 so the phys
+ * address calculated above is correct, so let's use
+ * it directly.
+ */
+ } else if (offset == 0) {
+ /* 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.
+ */
prom_print("(already at 0xc0000000) phys=0\n");
phys = 0;
- } else if ((int) call_prom("getprop", 4, 1, prom_chosen, "mmu",
- &prom_mmu, sizeof(prom_mmu)) <= 0) {
+ } else if (call_prom("getprop", 4, 1, prom_chosen, "mmu",
+ &prom_mmu, sizeof(prom_mmu)) <= 0) {
prom_print(" no MMU found\n");
- } else if ((int)call_prom_ret("call-method", 4, 4, result, "translate",
- prom_mmu, &_stext, 1) != 0) {
+ } else if (call_prom_ret("call-method", 4, 4, result, "translate",
+ prom_mmu, &_stext, 1) != 0) {
prom_print(" (translate failed)\n");
} else {
/* We assume the phys. address size is 3 cells */
- phys = (unsigned long)result[2];
+ phys = result[2];
}
if (prom_disp_node != 0)
for (i = 0; i < prom_num_displays; ++i)
prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]);
+#ifdef CONFIG_SERIAL_CORE_CONSOLE
+ /* Relocate the of stdout for console autodetection */
+ of_stdout_device = PTRUNRELOC(of_stdout_device);
+#endif
+
prom_print("returning 0x");
prom_print_hex(phys);
prom_print("from prom_init\n");
return (void *)((unsigned long)pp->value + base);
}
}
- return 0;
+ return NULL;
}
/* Is boot-info compatible ? */
boot_infos = PTRUNRELOC(bi);
if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
- bi->logicalDisplayBase = 0;
+ bi->logicalDisplayBase = NULL;
#ifdef CONFIG_BOOTX_TEXT
btext_init(bi);