Commit c4988820 authored by Paul Mackerras's avatar Paul Mackerras

powerpc: Fixes to get the Longtrail CHRP a bit further

Talk about buggy firmware...  the OF on the Longtrail returns 0
from the claim client service rather than -1 when the claim fails.
It also has no device_type on the /memory node and blows up if
the output buffer for package-to-path is too big.

This also fixes a bug with calling alloc_up with align == 0, where
we did _ALIGN_UP(alloc_bottom, 0) which will end up as 0.

Lastly, we now check the return value (in r3) from calling the
prom, and return -1 from call_prom if we get a negative value back.
That is supposed to indicate that the requested client service
doesn't exist.
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent bbd0abda
...@@ -145,11 +145,11 @@ typedef u32 cell_t; ...@@ -145,11 +145,11 @@ typedef u32 cell_t;
extern void __start(unsigned long r3, unsigned long r4, unsigned long r5); extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
extern void enter_prom(struct prom_args *args, unsigned long entry); extern int enter_prom(struct prom_args *args, unsigned long entry);
#else #else
static inline void enter_prom(struct prom_args *args, unsigned long entry) static inline int enter_prom(struct prom_args *args, unsigned long entry)
{ {
((void (*)(struct prom_args *))entry)(args); return ((int (*)(struct prom_args *))entry)(args);
} }
#endif #endif
...@@ -241,7 +241,8 @@ static int __init call_prom(const char *service, int nargs, int nret, ...) ...@@ -241,7 +241,8 @@ static int __init call_prom(const char *service, int nargs, int nret, ...)
for (i = 0; i < nret; i++) for (i = 0; i < nret; i++)
args.args[nargs+i] = 0; args.args[nargs+i] = 0;
enter_prom(&args, RELOC(prom_entry)); if (enter_prom(&args, RELOC(prom_entry)) < 0)
return PROM_ERROR;
return (nret > 0) ? args.args[nargs] : 0; return (nret > 0) ? args.args[nargs] : 0;
} }
...@@ -265,7 +266,8 @@ static int __init call_prom_ret(const char *service, int nargs, int nret, ...@@ -265,7 +266,8 @@ static int __init call_prom_ret(const char *service, int nargs, int nret,
for (i = 0; i < nret; i++) for (i = 0; i < nret; i++)
rets[nargs+i] = 0; rets[nargs+i] = 0;
enter_prom(&args, RELOC(prom_entry)); if (enter_prom(&args, RELOC(prom_entry)) < 0)
return PROM_ERROR;
if (rets != NULL) if (rets != NULL)
for (i = 1; i < nret; ++i) for (i = 1; i < nret; ++i)
...@@ -670,9 +672,11 @@ static void __init prom_send_capabilities(void) ...@@ -670,9 +672,11 @@ static void __init prom_send_capabilities(void)
*/ */
static unsigned long __init alloc_up(unsigned long size, unsigned long align) static unsigned long __init alloc_up(unsigned long size, unsigned long align)
{ {
unsigned long base = _ALIGN_UP(RELOC(alloc_bottom), align); unsigned long base = RELOC(alloc_bottom);
unsigned long addr = 0; unsigned long addr = 0;
if (align)
base = _ALIGN_UP(base, align);
prom_debug("alloc_up(%x, %x)\n", size, align); prom_debug("alloc_up(%x, %x)\n", size, align);
if (RELOC(ram_top) == 0) if (RELOC(ram_top) == 0)
prom_panic("alloc_up() called with mem not initialized\n"); prom_panic("alloc_up() called with mem not initialized\n");
...@@ -686,7 +690,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align) ...@@ -686,7 +690,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align)
base = _ALIGN_UP(base + 0x100000, align)) { base = _ALIGN_UP(base + 0x100000, align)) {
prom_debug(" trying: 0x%x\n\r", base); prom_debug(" trying: 0x%x\n\r", base);
addr = (unsigned long)prom_claim(base, size, 0); addr = (unsigned long)prom_claim(base, size, 0);
if (addr != PROM_ERROR) if (addr != PROM_ERROR && addr != 0)
break; break;
addr = 0; addr = 0;
if (align == 0) if (align == 0)
...@@ -746,7 +750,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align, ...@@ -746,7 +750,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align,
base = _ALIGN_DOWN(base - 0x100000, align)) { base = _ALIGN_DOWN(base - 0x100000, align)) {
prom_debug(" trying: 0x%x\n\r", base); prom_debug(" trying: 0x%x\n\r", base);
addr = (unsigned long)prom_claim(base, size, 0); addr = (unsigned long)prom_claim(base, size, 0);
if (addr != PROM_ERROR) if (addr != PROM_ERROR && addr != 0)
break; break;
addr = 0; addr = 0;
} }
...@@ -852,9 +856,16 @@ static void __init prom_init_mem(void) ...@@ -852,9 +856,16 @@ static void __init prom_init_mem(void)
type[0] = 0; type[0] = 0;
prom_getprop(node, "device_type", type, sizeof(type)); prom_getprop(node, "device_type", type, sizeof(type));
if (type[0] == 0) {
/*
* CHRP Longtrail machines have no device_type
* on the memory node, so check the name instead...
*/
prom_getprop(node, "name", type, sizeof(type));
}
if (strcmp(type, RELOC("memory"))) if (strcmp(type, RELOC("memory")))
continue; continue;
plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf)); plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf));
if (plen > sizeof(regbuf)) { if (plen > sizeof(regbuf)) {
prom_printf("memory node too large for buffer !\n"); prom_printf("memory node too large for buffer !\n");
...@@ -1632,18 +1643,21 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, ...@@ -1632,18 +1643,21 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
unsigned long soff; unsigned long soff;
unsigned char *valp; unsigned char *valp;
static char pname[MAX_PROPERTY_NAME]; static char pname[MAX_PROPERTY_NAME];
int l; int l, room;
dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
/* get the node's full name */ /* get the node's full name */
namep = (char *)*mem_start; namep = (char *)*mem_start;
l = call_prom("package-to-path", 3, 1, node, room = *mem_end - *mem_start;
namep, *mem_end - *mem_start); if (room > 255)
room = 255;
l = call_prom("package-to-path", 3, 1, node, namep, room);
if (l >= 0) { if (l >= 0) {
/* Didn't fit? Get more room. */ /* Didn't fit? Get more room. */
if ((l+1) > (*mem_end - *mem_start)) { if (l >= room) {
namep = make_room(mem_start, mem_end, l+1, 1); if (l >= *mem_end - *mem_start)
namep = make_room(mem_start, mem_end, l+1, 1);
call_prom("package-to-path", 3, 1, node, namep, l); call_prom("package-to-path", 3, 1, node, namep, l);
} }
namep[l] = '\0'; namep[l] = '\0';
......
...@@ -29,6 +29,7 @@ claim(unsigned int virt, unsigned int size, unsigned int align) ...@@ -29,6 +29,7 @@ claim(unsigned int virt, unsigned int size, unsigned int align)
args.virt = virt; args.virt = virt;
args.size = size; args.size = size;
args.align = align; args.align = align;
args.ret = (void *) 0;
(*of_prom_entry)(&args); (*of_prom_entry)(&args);
return args.ret; return args.ret;
} }
...@@ -78,7 +78,7 @@ boot(int a1, int a2, void *prom) ...@@ -78,7 +78,7 @@ boot(int a1, int a2, void *prom)
begin_avail = avail_high = avail_ram; begin_avail = avail_high = avail_ram;
end_avail = scratch + sizeof(scratch); end_avail = scratch + sizeof(scratch);
printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len); printf("gunzipping (0x%p <- 0x%p:0x%p)...", dst, im, im+len);
gunzip(dst, 0x400000, im, &len); gunzip(dst, PROG_SIZE - PROG_START, im, &len);
printf("done %u bytes\n\r", len); printf("done %u bytes\n\r", len);
printf("%u bytes of heap consumed, max in use %u\n\r", printf("%u bytes of heap consumed, max in use %u\n\r",
avail_high - begin_avail, heap_max); avail_high - begin_avail, heap_max);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment