From 154337688bfa970453836e65a27de011aba55331 Mon Sep 17 00:00:00 2001 From: Julian Calaby Date: Fri, 3 Dec 2010 17:56:45 +0000 Subject: sparc: prom: Sanitize return value from prom_nbputchar() Signed-off-by: Julian Calaby Signed-off-by: David S. Miller --- arch/sparc/prom/console_32.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/sparc/prom/console_32.c b/arch/sparc/prom/console_32.c index 48863108a44c..b05e3db5fa63 100644 --- a/arch/sparc/prom/console_32.c +++ b/arch/sparc/prom/console_32.c @@ -27,13 +27,14 @@ static int prom_nbputchar(const char *buf) spin_lock_irqsave(&prom_lock, flags); switch(prom_vers) { case PROM_V0: - i = (*(romvec->pv_nbputchar))(*buf); + if ((*(romvec->pv_nbputchar))(*buf)) + i = 1; break; case PROM_V2: case PROM_V3: if ((*(romvec->pv_v2devops).v2_dev_write)(*romvec->pv_v2bootargs.fd_stdout, buf, 0x1) == 1) - i = 0; + i = 1; break; default: break; @@ -47,7 +48,7 @@ void prom_console_write_buf(const char *buf, int len) { while (len) { int n = prom_nbputchar(buf); - if (n) + if (n < 0) continue; len--; buf++; -- cgit v1.2.3 From bce5feeab418fb1df9ce1c3fcc14f0aacf740208 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 12 Dec 2010 14:57:53 -0800 Subject: sparc: Eliminate prom_stdin. Completely unused. Based upon a patch by Julian Calaby. Signed-off-by: David S. Miller --- arch/sparc/include/asm/oplib_64.h | 4 ++-- arch/sparc/prom/console_64.c | 2 -- arch/sparc/prom/init_64.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/sparc/include/asm/oplib_64.h b/arch/sparc/include/asm/oplib_64.h index 8cd0df34e82b..97a90475c314 100644 --- a/arch/sparc/include/asm/oplib_64.h +++ b/arch/sparc/include/asm/oplib_64.h @@ -18,8 +18,8 @@ extern char prom_version[]; */ extern phandle prom_root_node; -/* PROM stdin and stdout */ -extern int prom_stdin, prom_stdout; +/* PROM stdout */ +extern int prom_stdout; /* /chosen node of the prom device tree, this stays constant after * initialization is complete. diff --git a/arch/sparc/prom/console_64.c b/arch/sparc/prom/console_64.c index ed39e75828bd..9de6c8cfe04a 100644 --- a/arch/sparc/prom/console_64.c +++ b/arch/sparc/prom/console_64.c @@ -13,8 +13,6 @@ #include #include -extern int prom_stdin, prom_stdout; - static int __prom_console_write_buf(const char *buf, int len) { unsigned long args[7]; diff --git a/arch/sparc/prom/init_64.c b/arch/sparc/prom/init_64.c index 3ff911e7d25b..9c6ac4b81ded 100644 --- a/arch/sparc/prom/init_64.c +++ b/arch/sparc/prom/init_64.c @@ -18,7 +18,7 @@ char prom_version[80]; /* The root node of the prom device tree. */ -int prom_stdin, prom_stdout; +int prom_stdout; phandle prom_chosen_node; /* You must call prom_init() before you attempt to use any of the @@ -38,7 +38,6 @@ void __init prom_init(void *cif_handler, void *cif_stack) if (!prom_chosen_node || prom_chosen_node == -1) prom_halt(); - prom_stdin = prom_getint(prom_chosen_node, "stdin"); prom_stdout = prom_getint(prom_chosen_node, "stdout"); node = prom_finddevice("/openprom"); -- cgit v1.2.3 From 743ceeed277c77a7e6751649ad0c4fa42af8063b Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 1 Jan 2011 12:53:08 +0000 Subject: sparc: drop prom/devmap.c None of the functions was used. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/include/asm/oplib_32.h | 12 --------- arch/sparc/prom/Makefile | 1 - arch/sparc/prom/devmap.c | 53 --------------------------------------- 3 files changed, 66 deletions(-) delete mode 100644 arch/sparc/prom/devmap.c diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 9e5c64084b86..31d2249d326b 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -48,18 +48,6 @@ extern void prom_init(struct linux_romvec *rom_ptr); /* Boot argument acquisition, returns the boot command line string. */ extern char *prom_getbootargs(void); -/* Device utilities. */ - -/* Map and unmap devices in IO space at virtual addresses. Note that the - * virtual address you pass is a request and the prom may put your mappings - * somewhere else, so check your return value as that is where your new - * mappings really are! - * - * Another note, these are only available on V2 or higher proms! - */ -extern char *prom_mapio(char *virt_hint, int io_space, unsigned int phys_addr, unsigned int num_bytes); -extern void prom_unmapio(char *virt_addr, unsigned int num_bytes); - /* Miscellaneous routines, don't really fit in any category per se. */ /* Reboot the machine with the command line passed. */ diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile index 816c0fa12dc0..113e6302a6ec 100644 --- a/arch/sparc/prom/Makefile +++ b/arch/sparc/prom/Makefile @@ -5,7 +5,6 @@ asflags := -ansi ccflags := -Werror lib-y := bootstr_$(BITS).o -lib-$(CONFIG_SPARC32) += devmap.o lib-y += init_$(BITS).o lib-$(CONFIG_SPARC32) += memory.o lib-y += misc_$(BITS).o diff --git a/arch/sparc/prom/devmap.c b/arch/sparc/prom/devmap.c deleted file mode 100644 index 46157d2aba0d..000000000000 --- a/arch/sparc/prom/devmap.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * promdevmap.c: Map device/IO areas to virtual addresses. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ - -#include -#include -#include - -#include -#include - -extern void restore_current(void); - -/* Just like the routines in palloc.c, these should not be used - * by the kernel at all. Bootloader facility mainly. And again, - * this is only available on V2 proms and above. - */ - -/* Map physical device address 'paddr' in IO space 'ios' of size - * 'num_bytes' to a virtual address, with 'vhint' being a hint to - * the prom as to where you would prefer the mapping. We return - * where the prom actually mapped it. - */ -char * -prom_mapio(char *vhint, int ios, unsigned int paddr, unsigned int num_bytes) -{ - unsigned long flags; - char *ret; - - spin_lock_irqsave(&prom_lock, flags); - if((num_bytes == 0) || (paddr == 0)) ret = (char *) 0x0; - else - ret = (*(romvec->pv_v2devops.v2_dumb_mmap))(vhint, ios, paddr, - num_bytes); - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); - return ret; -} - -/* Unmap an IO/device area that was mapped using the above routine. */ -void -prom_unmapio(char *vaddr, unsigned int num_bytes) -{ - unsigned long flags; - - if(num_bytes == 0x0) return; - spin_lock_irqsave(&prom_lock, flags); - (*(romvec->pv_v2devops.v2_dumb_munmap))(vaddr, num_bytes); - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); -} -- cgit v1.2.3 From efef2e497717958d9c8bde24998c5a915dd04cd5 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 1 Jan 2011 12:53:09 +0000 Subject: sparc: drop prom/palloc.c None of the functions was used. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/include/asm/oplib_32.h | 10 --------- arch/sparc/prom/Makefile | 1 - arch/sparc/prom/palloc.c | 43 --------------------------------------- 3 files changed, 54 deletions(-) delete mode 100644 arch/sparc/prom/palloc.c diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 31d2249d326b..91411bc2d4c0 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -114,16 +114,6 @@ extern int prom_idlecpu(int cpunode); /* Re-Start the CPU with the passed device tree node. */ extern int prom_restartcpu(int cpunode); -/* PROM memory allocation facilities... */ - -/* Allocated at possibly the given virtual address a chunk of the - * indicated size. - */ -extern char *prom_alloc(char *virt_hint, unsigned int size); - -/* Free a previously allocated chunk. */ -extern void prom_free(char *virt_addr, unsigned int size); - /* Sun4/sun4c specific memory-management startup hook. */ /* Map the passed segment in the given context at the passed diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile index 113e6302a6ec..8287bbe88768 100644 --- a/arch/sparc/prom/Makefile +++ b/arch/sparc/prom/Makefile @@ -9,7 +9,6 @@ lib-y += init_$(BITS).o lib-$(CONFIG_SPARC32) += memory.o lib-y += misc_$(BITS).o lib-$(CONFIG_SPARC32) += mp.o -lib-$(CONFIG_SPARC32) += palloc.o lib-$(CONFIG_SPARC32) += ranges.o lib-$(CONFIG_SPARC32) += segment.o lib-y += console_$(BITS).o diff --git a/arch/sparc/prom/palloc.c b/arch/sparc/prom/palloc.c deleted file mode 100644 index 2e2a88b211fb..000000000000 --- a/arch/sparc/prom/palloc.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * palloc.c: Memory allocation from the Sun PROM. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ - -#include -#include - -/* You should not call these routines after memory management - * has been initialized in the kernel, if fact you should not - * use these if at all possible in the kernel. They are mainly - * to be used for a bootloader for temporary allocations which - * it will free before jumping into the kernel it has loaded. - * - * Also, these routines don't work on V0 proms, only V2 and later. - */ - -/* Allocate a chunk of memory of size 'num_bytes' giving a suggestion - * of virtual_hint as the preferred virtual base address of this chunk. - * There are no guarantees that you will get the allocation, or that - * the prom will abide by your "hint". So check your return value. - */ -char * -prom_alloc(char *virtual_hint, unsigned int num_bytes) -{ - if(prom_vers == PROM_V0) return (char *) 0x0; - if(num_bytes == 0x0) return (char *) 0x0; - return (*(romvec->pv_v2devops.v2_dumb_mem_alloc))(virtual_hint, num_bytes); -} - -/* Free a previously allocated chunk back to the prom at virtual address - * 'vaddr' of size 'num_bytes'. NOTE: This vaddr is not the hint you - * used for the allocation, but the virtual address the prom actually - * returned to you. They may be have been the same, they may have not, - * doesn't matter. - */ -void -prom_free(char *vaddr, unsigned int num_bytes) -{ - if((prom_vers == PROM_V0) || (num_bytes == 0x0)) return; - (*(romvec->pv_v2devops.v2_dumb_mem_free))(vaddr, num_bytes); -} -- cgit v1.2.3 From a7e4236511c678bf012901faf3c285d199a1adc8 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 1 Jan 2011 12:53:10 +0000 Subject: sparc: remove unused prom cpu functions Remove the following unused funtions: prom_stopcpu() prom_idlecpu() prom_restartcpu() Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/include/asm/oplib_32.h | 9 ----- arch/sparc/prom/mp.c | 78 --------------------------------------- 2 files changed, 87 deletions(-) diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 91411bc2d4c0..640558801b8e 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -105,15 +105,6 @@ extern void prom_write(const char *buf, unsigned int len); extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table, int context, char *program_counter); -/* Stop the CPU with the passed device tree node. */ -extern int prom_stopcpu(int cpunode); - -/* Idle the CPU with the passed device tree node. */ -extern int prom_idlecpu(int cpunode); - -/* Re-Start the CPU with the passed device tree node. */ -extern int prom_restartcpu(int cpunode); - /* Sun4/sun4c specific memory-management startup hook. */ /* Map the passed segment in the given context at the passed diff --git a/arch/sparc/prom/mp.c b/arch/sparc/prom/mp.c index 4c4dc79f65af..97c44c9ddbc8 100644 --- a/arch/sparc/prom/mp.c +++ b/arch/sparc/prom/mp.c @@ -41,81 +41,3 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha return ret; } - -/* Stop CPU with device prom-tree node 'cpunode'. - * XXX Again, what does the return value really mean? XXX - */ -int -prom_stopcpu(int cpunode) -{ - int ret; - unsigned long flags; - - spin_lock_irqsave(&prom_lock, flags); - switch(prom_vers) { - case PROM_V0: - case PROM_V2: - default: - ret = -1; - break; - case PROM_V3: - ret = (*(romvec->v3_cpustop))(cpunode); - break; - }; - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); - - return ret; -} - -/* Make CPU with device prom-tree node 'cpunode' idle. - * XXX Return value, anyone? XXX - */ -int -prom_idlecpu(int cpunode) -{ - int ret; - unsigned long flags; - - spin_lock_irqsave(&prom_lock, flags); - switch(prom_vers) { - case PROM_V0: - case PROM_V2: - default: - ret = -1; - break; - case PROM_V3: - ret = (*(romvec->v3_cpuidle))(cpunode); - break; - }; - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); - - return ret; -} - -/* Resume the execution of CPU with nodeid 'cpunode'. - * XXX Come on, somebody has to know... XXX - */ -int -prom_restartcpu(int cpunode) -{ - int ret; - unsigned long flags; - - spin_lock_irqsave(&prom_lock, flags); - switch(prom_vers) { - case PROM_V0: - case PROM_V2: - default: - ret = -1; - break; - case PROM_V3: - ret = (*(romvec->v3_cpuresume))(cpunode); - break; - }; - restore_current(); - spin_unlock_irqrestore(&prom_lock, flags); - - return ret; -} -- cgit v1.2.3 From 1f42be484ffc5559a29466c82adac7dd472d4439 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sat, 1 Jan 2011 12:53:11 +0000 Subject: sparc: remove unused prom tree functions Remove the following unused funtions: prom_nodematch() prom_firstprop() prom_node_has_property() Also declare a few local functions static. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/include/asm/oplib_32.h | 11 ---------- arch/sparc/prom/tree_32.c | 44 +++------------------------------------ 2 files changed, 3 insertions(+), 52 deletions(-) diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 640558801b8e..98f70822fa05 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -147,19 +147,11 @@ extern int prom_getbool(phandle node, char *prop); /* Acquire a string property, null string on error. */ extern void prom_getstring(phandle node, char *prop, char *buf, int bufsize); -/* Does the passed node have the given "name"? YES=1 NO=0 */ -extern int prom_nodematch(phandle thisnode, char *name); - /* Search all siblings starting at the passed node for "name" matching * the given string. Returns the node on success, zero on failure. */ extern phandle prom_searchsiblings(phandle node_start, char *name); -/* Return the first property type, as a string, for the given node. - * Returns a null string on error. - */ -extern char *prom_firstprop(phandle node, char *buffer); - /* Returns the next property after the passed property for the given * node. Returns null string on failure. */ @@ -168,9 +160,6 @@ extern char *prom_nextprop(phandle node, char *prev_property, char *buffer); /* Returns phandle of the path specified */ extern phandle prom_finddevice(char *name); -/* Returns 1 if the specified node has given property. */ -extern int prom_node_has_property(phandle node, char *property); - /* Set the indicated property at the given node with the passed value. * Returns the number of bytes of your value that the prom took. */ diff --git a/arch/sparc/prom/tree_32.c b/arch/sparc/prom/tree_32.c index 535e2e69ac1d..f8860eba32c2 100644 --- a/arch/sparc/prom/tree_32.c +++ b/arch/sparc/prom/tree_32.c @@ -20,7 +20,7 @@ extern void restore_current(void); static char promlib_buf[128]; /* Internal version of prom_getchild that does not alter return values. */ -phandle __prom_getchild(phandle node) +static phandle __prom_getchild(phandle node) { unsigned long flags; phandle cnode; @@ -52,7 +52,7 @@ phandle prom_getchild(phandle node) EXPORT_SYMBOL(prom_getchild); /* Internal version of prom_getsibling that does not alter return values. */ -phandle __prom_getsibling(phandle node) +static phandle __prom_getsibling(phandle node) { unsigned long flags; phandle cnode; @@ -177,20 +177,6 @@ void prom_getstring(phandle node, char *prop, char *user_buf, int ubuf_size) EXPORT_SYMBOL(prom_getstring); -/* Does the device at node 'node' have name 'name'? - * YES = 1 NO = 0 - */ -int prom_nodematch(phandle node, char *name) -{ - int error; - - static char namebuf[128]; - error = prom_getproperty(node, "name", namebuf, sizeof(namebuf)); - if (error == -1) return 0; - if(strcmp(namebuf, name) == 0) return 1; - return 0; -} - /* Search siblings at 'node_start' for a node with name * 'nodename'. Return node if successful, zero if not. */ @@ -214,7 +200,7 @@ phandle prom_searchsiblings(phandle node_start, char *nodename) EXPORT_SYMBOL(prom_searchsiblings); /* Interal version of nextprop that does not alter return values. */ -char *__prom_nextprop(phandle node, char * oprop) +static char *__prom_nextprop(phandle node, char * oprop) { unsigned long flags; char *prop; @@ -227,17 +213,6 @@ char *__prom_nextprop(phandle node, char * oprop) return prop; } -/* Return the first property name for node 'node'. */ -/* buffer is unused argument, but as v9 uses it, we need to have the same interface */ -char *prom_firstprop(phandle node, char *bufer) -{ - if (node == 0 || node == -1) - return ""; - - return __prom_nextprop(node, ""); -} -EXPORT_SYMBOL(prom_firstprop); - /* Return the property type string after property type 'oprop' * at node 'node' . Returns empty string if no more * property types for this node. @@ -299,19 +274,6 @@ phandle prom_finddevice(char *name) } EXPORT_SYMBOL(prom_finddevice); -int prom_node_has_property(phandle node, char *prop) -{ - char *current_property = ""; - - do { - current_property = prom_nextprop(node, current_property, NULL); - if(!strcmp(current_property, prop)) - return 1; - } while (*current_property); - return 0; -} -EXPORT_SYMBOL(prom_node_has_property); - /* Set property 'pname' at node 'node' to value 'value' which has a length * of 'size' bytes. Return the number of bytes the prom accepted. */ -- cgit v1.2.3 From 5f66dd35b49ea81a03e71bfd74c28364f4e32d21 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 3 Jan 2011 08:27:55 +0000 Subject: sparc: fix sparse warnings in arch/sparc/prom for 32 bit build Fix following sparse warnings: arch/sparc/prom/bootstr_32.c:32:35: warning: Using plain integer as NULL pointer arch/sparc/prom/memory.c:61:13: warning: symbol 'prom_meminit' was not declared. Should it be static? arch/sparc/prom/misc_32.c:74:1: error: symbol 'prom_halt' redeclared with different type (originally declared at arch/sparc/include/asm/oplib_32.h:67) - different modifiers arch/sparc/prom/ranges.c:16:26: warning: symbol 'promlib_obio_ranges' was not declared. Should it be static? arch/sparc/prom/ranges.c:17:5: warning: symbol 'num_obio_ranges' was not declared. Should it be static? arch/sparc/prom/ranges.c:39:1: warning: symbol 'prom_adjust_ranges' was not declared. Should it be static? arch/sparc/prom/ranges.c:69:13: warning: symbol 'prom_ranges_init' was not declared. Should it be static? arch/sparc/prom/tree_32.c:286:22: warning: Using plain integer as NULL pointer arch/sparc/prom/tree_32.c:286:38: warning: Using plain integer as NULL pointer None of the warnings indicated any serious issues. We are now sparse clean for 32 bit build in arch/sparc/prom. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/include/asm/oplib_32.h | 6 +++++- arch/sparc/prom/bootstr_32.c | 3 ++- arch/sparc/prom/misc_32.c | 2 +- arch/sparc/prom/ranges.c | 6 +++--- arch/sparc/prom/tree_32.c | 6 ++++-- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index 98f70822fa05..71e5e9aeb67e 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h @@ -64,7 +64,7 @@ extern void prom_cmdline(void); /* Enter the prom, with no chance of continuation for the stand-alone * which calls this. */ -extern void prom_halt(void) __attribute__ ((noreturn)); +extern void __noreturn prom_halt(void); /* Set the PROM 'sync' callback function to the passed function pointer. * When the user gives the 'sync' command at the prom prompt while the @@ -113,6 +113,8 @@ extern int prom_startcpu(int cpunode, struct linux_prom_registers *context_table extern void prom_putsegment(int context, unsigned long virt_addr, int physical_segment); +/* Initialize the memory lists based upon the prom version. */ +void prom_meminit(void); /* PROM device tree traversal functions... */ @@ -177,6 +179,8 @@ extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nr extern void prom_apply_generic_ranges(phandle node, phandle parent, struct linux_prom_registers *sbusregs, int nregs); +void prom_ranges_init(void); + /* CPU probing helpers. */ int cpu_find_by_instance(int instance, phandle *prom_node, int *mid); int cpu_find_by_mid(int mid, phandle *prom_node); diff --git a/arch/sparc/prom/bootstr_32.c b/arch/sparc/prom/bootstr_32.c index 916831da7e67..f5ec32e0d419 100644 --- a/arch/sparc/prom/bootstr_32.c +++ b/arch/sparc/prom/bootstr_32.c @@ -29,7 +29,8 @@ prom_getbootargs(void) /* Start from 1 and go over fd(0,0,0)kernel */ for(iter = 1; iter < 8; iter++) { arg = (*(romvec->pv_v0bootargs))->argv[iter]; - if(arg == 0) break; + if (arg == NULL) + break; while(*arg != 0) { /* Leave place for space and null. */ if(cp >= barg_buf + BARG_LEN-2){ diff --git a/arch/sparc/prom/misc_32.c b/arch/sparc/prom/misc_32.c index 4d61c540bb3d..8c278c311ba4 100644 --- a/arch/sparc/prom/misc_32.c +++ b/arch/sparc/prom/misc_32.c @@ -70,7 +70,7 @@ prom_cmdline(void) /* Drop into the prom, but completely terminate the program. * No chance of continuing. */ -void +void __noreturn prom_halt(void) { unsigned long flags; diff --git a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c index 541fc829c207..0857aa9e839d 100644 --- a/arch/sparc/prom/ranges.c +++ b/arch/sparc/prom/ranges.c @@ -13,8 +13,8 @@ #include #include -struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; -int num_obio_ranges; +static struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; +static int num_obio_ranges; /* Adjust register values based upon the ranges parameters. */ static void @@ -35,7 +35,7 @@ prom_adjust_regs(struct linux_prom_registers *regp, int nregs, } } -void +static void prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1, struct linux_prom_ranges *ranges2, int nranges2) { diff --git a/arch/sparc/prom/tree_32.c b/arch/sparc/prom/tree_32.c index f8860eba32c2..bc8e4cb87a68 100644 --- a/arch/sparc/prom/tree_32.c +++ b/arch/sparc/prom/tree_32.c @@ -282,8 +282,10 @@ int prom_setprop(phandle node, const char *pname, char *value, int size) unsigned long flags; int ret; - if(size == 0) return 0; - if((pname == 0) || (value == 0)) return 0; + if (size == 0) + return 0; + if ((pname == NULL) || (value == NULL)) + return 0; spin_lock_irqsave(&prom_lock, flags); ret = prom_nodeops->no_setprop(node, pname, value, size); restore_current(); -- cgit v1.2.3 From 53aea7caf2e27108912b9b9dbc5bfe18dbbaec9d Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Tue, 4 Jan 2011 01:41:29 +0000 Subject: SPARC/LEON: find IRQCTRL and Timer via OF-Tree, instead of hardcoded. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- arch/sparc/kernel/leon_kernel.c | 44 +++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index f01c42661ee5..80ba8f517318 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -23,15 +23,15 @@ #include "prom.h" #include "irq.h" -struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */ -struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */ +struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */ +struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */ struct amba_apb_device leon_percpu_timer_dev[16]; int leondebug_irq_disable; int leon_debug_irqout; static int dummy_master_l10_counter; -unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */ +unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ unsigned int sparc_leon_eirq; #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) @@ -105,13 +105,41 @@ static void leon_disable_irq(unsigned int irq_nr) void __init leon_init_timers(irq_handler_t counter_fn) { int irq; + struct device_node *rootnp, *np; + struct property *pp; + int len; leondebug_irq_disable = 0; leon_debug_irqout = 0; master_l10_counter = (unsigned int *)&dummy_master_l10_counter; dummy_master_l10_counter = 0; - if (leon3_gptimer_regs && leon3_irqctrl_regs) { + /*Find IRQMP IRQ Controller Registers base address otherwise bail out.*/ + rootnp = of_find_node_by_path("/ambapp0"); + if (!rootnp) + goto bad; + np = of_find_node_by_name(rootnp, "GAISLER_IRQMP"); + if (!np) + goto bad; + pp = of_find_property(np, "reg", &len); + if (!pp) + goto bad; + leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value; + + /* Find GPTIMER Timer Registers base address otherwise bail out. */ + np = of_find_node_by_name(rootnp, "GAISLER_GPTIMER"); + if (!np) + goto bad; + pp = of_find_property(np, "reg", &len); + if (!pp) + goto bad; + leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)pp->value; + pp = of_find_property(np, "interrupts", &len); + if (!pp) + goto bad; + leon3_gptimer_irq = *(unsigned int *)pp->value; + + if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, (((1000000 / HZ) - 1))); @@ -133,8 +161,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) # endif } else { - printk(KERN_ERR "No Timer/irqctrl found\n"); - BUG(); + goto bad; } irq = request_irq(leon3_gptimer_irq, @@ -183,6 +210,11 @@ void __init leon_init_timers(irq_handler_t counter_fn) #endif } + return; +bad: + printk(KERN_ERR "No Timer/irqctrl found\n"); + BUG(); + return; } void leon_clear_clock_irq(void) -- cgit v1.2.3 From e2305e37d4c82ef55be54e9edc8a7e2250739b4f Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Tue, 4 Jan 2011 01:41:30 +0000 Subject: SPARC/LEON: added support for IRQAMP IRQ Controller Needed for LEON AMP systems where different CPUs are routed to different IRQ controllers. This patch selects the IRQ Controller which has been routed to the boot CPU, it is up to the boot loader to configure the IRQ controller. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- arch/sparc/include/asm/leon.h | 12 ++++++++++++ arch/sparc/include/asm/leon_amba.h | 6 +++--- arch/sparc/kernel/leon_kernel.c | 14 ++++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h index 3ea5964c43b4..8580d1764f90 100644 --- a/arch/sparc/include/asm/leon.h +++ b/arch/sparc/include/asm/leon.h @@ -224,6 +224,18 @@ static inline void sparc_leon3_disable_cache(void) "sta %%l2, [%%g0] 2\n\t" : : : "l1", "l2"); }; +static inline unsigned long sparc_leon3_asr17(void) +{ + u32 asr17; + __asm__ __volatile__ ("rd %%asr17, %0\n\t" : "=r"(asr17)); + return asr17; +}; + +static inline int sparc_leon3_cpuid(void) +{ + return sparc_leon3_asr17() >> 28; +} + #endif /*!__ASSEMBLY__*/ #ifdef CONFIG_SMP diff --git a/arch/sparc/include/asm/leon_amba.h b/arch/sparc/include/asm/leon_amba.h index 618e88821795..263c719e96f5 100644 --- a/arch/sparc/include/asm/leon_amba.h +++ b/arch/sparc/include/asm/leon_amba.h @@ -100,9 +100,8 @@ struct leon3_irqctrl_regs_map { u32 mpbroadcast; u32 notused02; u32 notused03; - u32 notused10; - u32 notused11; - u32 notused12; + u32 ampctrl; + u32 icsel[2]; u32 notused13; u32 notused20; u32 notused21; @@ -112,6 +111,7 @@ struct leon3_irqctrl_regs_map { u32 force[16]; /* Extended IRQ registers */ u32 intid[16]; /* 0xc0 */ + u32 unused[(0x1000-0x100)/4]; }; struct leon3_apbuart_regs_map { diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 80ba8f517318..91a978f4d83b 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -108,6 +108,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) struct device_node *rootnp, *np; struct property *pp; int len; + int cpu, icsel; leondebug_irq_disable = 0; leon_debug_irqout = 0; @@ -160,6 +161,19 @@ void __init leon_init_timers(irq_handler_t counter_fn) LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); # endif + /* + * The IRQ controller may (if implemented) consist of multiple + * IRQ controllers, each mapped on a 4Kb boundary. + * Each CPU may be routed to different IRQCTRLs, however + * we assume that all CPUs (in SMP system) is routed to the + * same IRQ Controller, and for non-SMP only one IRQCTRL is + * accessed anyway. + * In AMP systems, Linux must run on CPU0 for the time being. + */ + cpu = sparc_leon3_cpuid(); + icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]); + icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf; + leon3_irqctrl_regs += icsel; } else { goto bad; } -- cgit v1.2.3 From 9742e72cd1e24ede007daa8f3eb1cece66f0fd0f Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Tue, 4 Jan 2011 01:41:31 +0000 Subject: LEON: added raw AMBA vendor/device number to find TIMER, IRQCTRL Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- arch/sparc/kernel/leon_kernel.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 91a978f4d83b..88ade07f976c 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -120,8 +120,11 @@ void __init leon_init_timers(irq_handler_t counter_fn) if (!rootnp) goto bad; np = of_find_node_by_name(rootnp, "GAISLER_IRQMP"); - if (!np) - goto bad; + if (!np) { + np = of_find_node_by_name(rootnp, "01_00d"); + if (!np) + goto bad; + } pp = of_find_property(np, "reg", &len); if (!pp) goto bad; @@ -129,8 +132,11 @@ void __init leon_init_timers(irq_handler_t counter_fn) /* Find GPTIMER Timer Registers base address otherwise bail out. */ np = of_find_node_by_name(rootnp, "GAISLER_GPTIMER"); - if (!np) - goto bad; + if (!np) { + np = of_find_node_by_name(np, "01_011"); + if (!np) + goto bad; + } pp = of_find_property(np, "reg", &len); if (!pp) goto bad; -- cgit v1.2.3 From 2791c1a4390085789e37347fc49f7d189fedae88 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Tue, 4 Jan 2011 01:41:32 +0000 Subject: SPARC/LEON: added support for selecting Timer Core and Timer within core The ability to select Timer Core and Timer instance for system clock makes it possible for multiple AMP systems to coexist. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- arch/sparc/kernel/leon_kernel.c | 80 +++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 26 deletions(-) diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c index 88ade07f976c..fdab7f854f80 100644 --- a/arch/sparc/kernel/leon_kernel.c +++ b/arch/sparc/kernel/leon_kernel.c @@ -32,6 +32,7 @@ int leon_debug_irqout; static int dummy_master_l10_counter; unsigned long leon3_gptimer_irq; /* interrupt controller irq number */ +unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ unsigned int sparc_leon_eirq; #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) @@ -105,10 +106,11 @@ static void leon_disable_irq(unsigned int irq_nr) void __init leon_init_timers(irq_handler_t counter_fn) { int irq; - struct device_node *rootnp, *np; + struct device_node *rootnp, *np, *nnp; struct property *pp; int len; int cpu, icsel; + int ampopts; leondebug_irq_disable = 0; leon_debug_irqout = 0; @@ -131,30 +133,52 @@ void __init leon_init_timers(irq_handler_t counter_fn) leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value; /* Find GPTIMER Timer Registers base address otherwise bail out. */ - np = of_find_node_by_name(rootnp, "GAISLER_GPTIMER"); - if (!np) { - np = of_find_node_by_name(np, "01_011"); - if (!np) - goto bad; - } - pp = of_find_property(np, "reg", &len); - if (!pp) - goto bad; - leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)pp->value; - pp = of_find_property(np, "interrupts", &len); - if (!pp) - goto bad; - leon3_gptimer_irq = *(unsigned int *)pp->value; + nnp = rootnp; + do { + np = of_find_node_by_name(nnp, "GAISLER_GPTIMER"); + if (!np) { + np = of_find_node_by_name(nnp, "01_011"); + if (!np) + goto bad; + } + + ampopts = 0; + pp = of_find_property(np, "ampopts", &len); + if (pp) { + ampopts = *(int *)pp->value; + if (ampopts == 0) { + /* Skip this instance, resource already + * allocated by other OS */ + nnp = np; + continue; + } + } + + /* Select Timer-Instance on Timer Core. Default is zero */ + leon3_gptimer_idx = ampopts & 0x7; + + pp = of_find_property(np, "reg", &len); + if (pp) + leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **) + pp->value; + pp = of_find_property(np, "interrupts", &len); + if (pp) + leon3_gptimer_irq = *(unsigned int *)pp->value; + } while (0); if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, - (((1000000 / HZ) - 1))); - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); + LEON3_BYPASS_STORE_PA( + &leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0); + LEON3_BYPASS_STORE_PA( + &leon3_gptimer_regs->e[leon3_gptimer_idx].rld, + (((1000000 / HZ) - 1))); + LEON3_BYPASS_STORE_PA( + &leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); #ifdef CONFIG_SMP leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; - leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1; + leon_percpu_timer_dev[0].irq = leon3_gptimer_irq + 1 + + leon3_gptimer_idx; if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & (1<e[1].val, 0); - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1))); - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); + LEON3_BYPASS_STORE_PA( + &leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0); + LEON3_BYPASS_STORE_PA( + &leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, + (((1000000/HZ) - 1))); + LEON3_BYPASS_STORE_PA( + &leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0); # endif /* @@ -184,7 +212,7 @@ void __init leon_init_timers(irq_handler_t counter_fn) goto bad; } - irq = request_irq(leon3_gptimer_irq, + irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); @@ -216,13 +244,13 @@ void __init leon_init_timers(irq_handler_t counter_fn) # endif if (leon3_gptimer_regs) { - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, LEON3_GPTIMER_EN | LEON3_GPTIMER_RL | LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); #ifdef CONFIG_SMP - LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, + LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, LEON3_GPTIMER_EN | LEON3_GPTIMER_RL | LEON3_GPTIMER_LD | -- cgit v1.2.3 From 9663eb21fcfeb1ed9afd73d14bbc4198796cfc7b Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Tue, 4 Jan 2011 01:41:33 +0000 Subject: SPARC/LEON: avoid AMBAPP name duplicates in openprom fs when REG is missing When the REG property is not available the NODE-ID is used as an unique identifier in order to avoid filesystem name duplicates in /proc/openprom filesystem Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- arch/sparc/kernel/prom_32.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c index 0a37e8cfd160..05fb25330583 100644 --- a/arch/sparc/kernel/prom_32.c +++ b/arch/sparc/kernel/prom_32.c @@ -136,18 +136,29 @@ static void __init ebus_path_component(struct device_node *dp, char *tmp_buf) /* "name:vendor:device@irq,addrlo" */ static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf) { - struct amba_prom_registers *regs; unsigned int *intr; - unsigned int *device, *vendor; + struct amba_prom_registers *regs; + unsigned int *intr, *device, *vendor, reg0; struct property *prop; + int interrupt = 0; + /* In order to get a unique ID in the device tree (multiple AMBA devices + * may have the same name) the node number is printed + */ prop = of_find_property(dp, "reg", NULL); - if (!prop) - return; - regs = prop->value; + if (!prop) { + reg0 = (unsigned int)dp->phandle; + } else { + regs = prop->value; + reg0 = regs->phys_addr; + } + + /* Not all cores have Interrupt */ prop = of_find_property(dp, "interrupts", NULL); if (!prop) - return; - intr = prop->value; + intr = &interrupt; /* IRQ0 does not exist */ + else + intr = prop->value; + prop = of_find_property(dp, "vendor", NULL); if (!prop) return; @@ -159,7 +170,7 @@ static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf) sprintf(tmp_buf, "%s:%d:%d@%x,%x", dp->name, *vendor, *device, - *intr, regs->phys_addr); + *intr, reg0); } static void __init __build_path_component(struct device_node *dp, char *tmp_buf) -- cgit v1.2.3 From d89ddf0da8f0a140d4dc2e2dbc594fb278e33db5 Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Tue, 4 Jan 2011 01:41:34 +0000 Subject: APBUART: added raw AMBA vendor/device number to match against. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/serial/apbuart.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/serial/apbuart.c b/drivers/serial/apbuart.c index cc01c650a144..7160345a184e 100644 --- a/drivers/serial/apbuart.c +++ b/drivers/serial/apbuart.c @@ -580,6 +580,9 @@ static struct of_device_id __initdata apbuart_match[] = { { .name = "GAISLER_APBUART", }, + { + .name = "01_00c", + }, {}, }; -- cgit v1.2.3 From f28f3313aa97dcb46954f90f596d75f8faf4626e Mon Sep 17 00:00:00 2001 From: Daniel Hellstrom Date: Tue, 4 Jan 2011 01:41:35 +0000 Subject: Added support for ampopts in APBUART driver. Used in AMP systems. Signed-off-by: Daniel Hellstrom Signed-off-by: David S. Miller --- drivers/serial/apbuart.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/serial/apbuart.c b/drivers/serial/apbuart.c index 7160345a184e..767ce9e396c5 100644 --- a/drivers/serial/apbuart.c +++ b/drivers/serial/apbuart.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -573,7 +574,6 @@ static int __devinit apbuart_probe(struct platform_device *op, printk(KERN_INFO "grlib-apbuart at 0x%llx, irq %d\n", (unsigned long long) port->mapbase, port->irq); return 0; - } static struct of_device_id __initdata apbuart_match[] = { @@ -623,9 +623,12 @@ static void grlib_apbuart_configure(void) int *vendor = (int *) of_get_property(np, "vendor", NULL); int *device = (int *) of_get_property(np, "device", NULL); int *irqs = (int *) of_get_property(np, "interrupts", NULL); + int *ampopts = (int *) of_get_property(np, "ampopts", NULL); regs = (struct amba_prom_registers *) of_get_property(np, "reg", NULL); + if (ampopts && (*ampopts == 0)) + continue; /* Ignore if used by another OS instance */ if (vendor) v = *vendor; if (device) -- cgit v1.2.3 From 2fe74fa9662f8df51e6ef18227089f54cc07e16a Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 4 Jan 2011 11:39:10 +0000 Subject: sparc: refactor piggy_32.c Refactoring to increase readability (a little). - sort includes - spaces around operators - small helpers introduced - added a few comments Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/boot/piggyback_32.c | 142 +++++++++++++++++++++++++++++------------ 1 file changed, 102 insertions(+), 40 deletions(-) diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index ac944aec7301..cfd95ec01f18 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c @@ -9,7 +9,7 @@ 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 @@ -18,15 +18,16 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include + +#include +#include #include +#include #include #include #include -#include -#include -#include +#include + #include #include @@ -35,16 +36,19 @@ * as PROM looks for a.out image only. */ +/* read two bytes as big endian */ static unsigned short ld2(char *p) { return (p[0] << 8) | p[1]; } +/* read 4 bytes as big endian */ static unsigned int ld4(char *p) { return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; } +/* save 4 bytes as big endian */ static void st4(char *p, unsigned int x) { p[0] = x >> 24; @@ -53,6 +57,12 @@ static void st4(char *p, unsigned int x) p[3] = x; } +static void die(const char *str) +{ + perror(str); + exit(1); +} + static void usage(void) { /* fs_img.gz is an image of initial ramdisk. */ @@ -61,10 +71,57 @@ static void usage(void) exit(1); } -static void die(char *str) +static int start_line(const char *line) { - perror (str); - exit(1); + if (strcmp(line + 8, " T start\n") == 0) + return 1; + else if (strcmp(line + 16, " T start\n") == 0) + return 1; + return 0; +} + +static int end_line(const char *line) +{ + if (strcmp(line + 8, " A _end\n") == 0) + return 1; + else if (strcmp (line + 16, " A _end\n") == 0) + return 1; + return 0; +} + +/* + * Find address for start and end in System.map. + * The file looks like this: + * f0004000 T start + * f0379f79 A _end + * 1234567890123456 + * ^coloumn 1 + * There is support for 64 bit addresses too. + * + * Return 0 if either start or end is not found + */ +static int get_start_end(const char *filename, unsigned int *start, unsigned int *end) +{ + FILE *map; + char buffer[1024]; + + *start = 0; + *end = 0; + map = fopen(filename, "r"); + if (!map) + die(filename); + while (fgets(buffer, 1024, map)) { + if (start_line(buffer)) + *start = strtoul(buffer, NULL, 16); + else if (end_line(buffer)) + *end = strtoul(buffer, NULL, 16); + } + fclose (map); + + if (*start == 0 || *end == 0) + return 0; + + return 1; } int main(int argc,char **argv) @@ -72,33 +129,29 @@ int main(int argc,char **argv) static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; char buffer[1024], *q, *r; unsigned int i, j, k, start, end, offset; - FILE *map; struct stat s; int image, tail; - if (argc != 4) usage(); - start = end = 0; - if (stat (argv[3], &s) < 0) die (argv[3]); - map = fopen (argv[2], "r"); - if (!map) die(argv[2]); - while (fgets (buffer, 1024, map)) { - if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n")) - start = strtoul (buffer, NULL, 16); - else if (!strcmp (buffer + 8, " A _end\n") || !strcmp (buffer + 16, " A _end\n")) - end = strtoul (buffer, NULL, 16); - } - fclose (map); - if (!start || !end) { - fprintf (stderr, "Could not determine start and end from System.map\n"); + if (argc != 4) + usage(); + if (stat (argv[3], &s) < 0) + die(argv[3]); + + if (!get_start_end(argv[2], &start, &end)) { + fprintf (stderr, "Could not determine start and end from %s\n", argv[2]); exit(1); } - if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]); - if (read(image,buffer,512) != 512) die(argv[1]); + if ((image = open(argv[1], O_RDWR)) < 0) + die(argv[1]); + if (read(image, buffer, 512) != 512) + die(argv[1]); if (memcmp (buffer, "\177ELF", 4) == 0) { q = buffer + ld4(buffer + 28); i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8); - if (lseek(image,i,0) < 0) die("lseek"); - if (read(image,buffer,512) != 512) die(argv[1]); + if (lseek(image, i, 0) < 0) + die("lseek"); + if (read(image, buffer, 512) != 512) + die(argv[1]); j = 0; } else if (memcmp(buffer, aout_magic, 4) == 0) { i = j = 32; @@ -107,9 +160,11 @@ int main(int argc,char **argv) exit(1); } k = i; - i += (ld2(buffer + j + 2)<<2) - 512; - if (lseek(image,i,0) < 0) die("lseek"); - if (read(image,buffer,1024) != 1024) die(argv[1]); + i += (ld2(buffer + j + 2) << 2) - 512; + if (lseek(image, i, 0) < 0) + die("lseek"); + if (read(image, buffer, 1024) != 1024) + die(argv[1]); for (q = buffer, r = q + 512; q < r; q += 4) { if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S') break; @@ -119,19 +174,26 @@ int main(int argc,char **argv) exit(1); } offset = i + (q - buffer) + 10; - if (lseek(image, offset, 0) < 0) die ("lseek"); + if (lseek(image, offset, 0) < 0) + die("lseek"); st4(buffer, 0); st4(buffer + 4, 0x01000000); st4(buffer + 8, (end + 32 + 4095) & ~4095); st4(buffer + 12, s.st_size); - if (write(image,buffer+2,14) != 14) die (argv[1]); - if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) die ("lseek"); - if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]); - while ((i = read (tail,buffer,1024)) > 0) - if (write(image,buffer,i) != i) die (argv[1]); - if (close(image) < 0) die("close"); - if (close(tail) < 0) die("close"); - return 0; + if (write(image, buffer + 2, 14) != 14) + die(argv[1]); + if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) + die("lseek"); + if ((tail = open(argv[3],O_RDONLY)) < 0) + die(argv[3]); + while ((i = read (tail, buffer, 1024)) > 0) + if (write(image, buffer, i) != i) + die(argv[1]); + if (close(image) < 0) + die("close"); + if (close(tail) < 0) + die("close"); + return 0; } -- cgit v1.2.3 From e405ae76af19cd2c85335b842f880a2bc98ba785 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 4 Jan 2011 11:39:11 +0000 Subject: sparc: use trapbase in setup_arch start and trapbase point to the same address. But using start to assing to sparc_ttable looked confusing. Replace this with the use of trapbase. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/kernel/setup_32.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/sparc/kernel/setup_32.c b/arch/sparc/kernel/setup_32.c index b22ce6100403..648f2161b851 100644 --- a/arch/sparc/kernel/setup_32.c +++ b/arch/sparc/kernel/setup_32.c @@ -185,7 +185,6 @@ static void __init boot_flags_init(char *commands) extern void sun4c_probe_vac(void); extern char cputypval; -extern unsigned long start, end; extern unsigned short root_flags; extern unsigned short root_dev; @@ -210,7 +209,7 @@ void __init setup_arch(char **cmdline_p) int i; unsigned long highest_paddr; - sparc_ttable = (struct tt_entry *) &start; + sparc_ttable = (struct tt_entry *) &trapbase; /* Initialize PROM console and command line. */ *cmdline_p = prom_getbootargs(); -- cgit v1.2.3 From b2a39b0d8ec2ce2bdcff4e01572b4e885220254d Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 4 Jan 2011 11:39:12 +0000 Subject: sparc: use _start for the start entry (like 64 bit does) We use "_start" in 64 bit - do the same in 32 bit. It is always good to be consistent. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/boot/piggyback_32.c | 6 +++--- arch/sparc/kernel/head_32.S | 3 +-- arch/sparc/mm/sun4c.c | 8 +++----- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index cfd95ec01f18..5c86a7d03b6f 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c @@ -73,9 +73,9 @@ static void usage(void) static int start_line(const char *line) { - if (strcmp(line + 8, " T start\n") == 0) + if (strcmp(line + 8, " T _start\n") == 0) return 1; - else if (strcmp(line + 16, " T start\n") == 0) + else if (strcmp(line + 16, " T _start\n") == 0) return 1; return 0; } @@ -92,7 +92,7 @@ static int end_line(const char *line) /* * Find address for start and end in System.map. * The file looks like this: - * f0004000 T start + * f0004000 T _start * f0379f79 A _end * 1234567890123456 * ^coloumn 1 diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S index 21bb2590d4ae..59423491cef8 100644 --- a/arch/sparc/kernel/head_32.S +++ b/arch/sparc/kernel/head_32.S @@ -73,12 +73,11 @@ sun4e_notsup: /* The Sparc trap table, bootloader gives us control at _start. */ __HEAD - .globl start, _stext, _start, __stext + .globl _stext, _start, __stext .globl trapbase _start: /* danger danger */ __stext: _stext: -start: trapbase: #ifdef CONFIG_SMP trapbase_cpu0: diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index ddd0d86e508e..b5137cc2aba3 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c @@ -435,16 +435,14 @@ void __init sun4c_probe_memerr_reg(void) static inline void sun4c_init_ss2_cache_bug(void) { - extern unsigned long start; - if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) || (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) || (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) { /* Whee.. */ printk("SS2 cache bug detected, uncaching trap table page\n"); - sun4c_flush_page((unsigned int) &start); - sun4c_put_pte(((unsigned long) &start), - (sun4c_get_pte((unsigned long) &start) | _SUN4C_PAGE_NOCACHE)); + sun4c_flush_page((unsigned int) &_start); + sun4c_put_pte(((unsigned long) &_start), + (sun4c_get_pte((unsigned long) &_start) | _SUN4C_PAGE_NOCACHE)); } } -- cgit v1.2.3 From 9c239053045568abf960b01e4eb2c7205e3cd7d6 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 4 Jan 2011 11:39:13 +0000 Subject: sparc: additional comments to piggyback_32.c While reverse engineering the functionality of piggyback I missed that the code was actually commented. So I added a few comments. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/boot/piggyback_32.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index 5c86a7d03b6f..5e856f2e9e0f 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c @@ -36,6 +36,8 @@ * as PROM looks for a.out image only. */ +#define AOUT_TEXT_OFFSET 32 + /* read two bytes as big endian */ static unsigned short ld2(char *p) { @@ -154,12 +156,20 @@ int main(int argc,char **argv) die(argv[1]); j = 0; } else if (memcmp(buffer, aout_magic, 4) == 0) { - i = j = 32; + i = j = AOUT_TEXT_OFFSET; } else { fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n"); exit(1); } k = i; + /* + * We need to fill in values for sparc_ramdisk_image + sparc_ramdisk_size + * To locate these symbols search for the "HdrS" text which appear + * in the image a little before the gokernel symbol. + * See definition of these in init_32.S + */ + + /* Find the gokernel label */ i += (ld2(buffer + j + 2) << 2) - 512; if (lseek(image, i, 0) < 0) die("lseek"); @@ -177,6 +187,13 @@ int main(int argc,char **argv) if (lseek(image, offset, 0) < 0) die("lseek"); + /* + * root_flags = 0 + * root_dev = 1 (RAMDISK_MAJOR) + * ram_flags = 0 + * sparc_ramdisk_image = "PAGE aligned address after _end") + * sparc_ramdisk_size = size of image + */ st4(buffer, 0); st4(buffer + 4, 0x01000000); st4(buffer + 8, (end + 32 + 4095) & ~4095); @@ -184,11 +201,13 @@ int main(int argc,char **argv) if (write(image, buffer + 2, 14) != 14) die(argv[1]); + + /* seek page aligned boundary in the image file and add boot image */ if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) die("lseek"); if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]); - while ((i = read (tail, buffer, 1024)) > 0) + while ((i = read(tail, buffer, 1024)) > 0) if (write(image, buffer, i) != i) die(argv[1]); if (close(image) < 0) -- cgit v1.2.3 From 571e08f6e2ddd6ec5d547358f55342726c063072 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 4 Jan 2011 11:39:14 +0000 Subject: sparc: remove obsolete ELF support in piggyback_32.c As we always convert to a.out there is no need to support ELF. Removing ELF support because: - it is not used - it simplifies code to support a.out only Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/boot/piggyback_32.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index 5e856f2e9e0f..369634d8271e 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c @@ -44,12 +44,6 @@ static unsigned short ld2(char *p) return (p[0] << 8) | p[1]; } -/* read 4 bytes as big endian */ -static unsigned int ld4(char *p) -{ - return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; -} - /* save 4 bytes as big endian */ static void st4(char *p, unsigned int x) { @@ -130,7 +124,7 @@ int main(int argc,char **argv) { static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; char buffer[1024], *q, *r; - unsigned int i, j, k, start, end, offset; + unsigned int i, start, end, offset; struct stat s; int image, tail; @@ -147,21 +141,10 @@ int main(int argc,char **argv) die(argv[1]); if (read(image, buffer, 512) != 512) die(argv[1]); - if (memcmp (buffer, "\177ELF", 4) == 0) { - q = buffer + ld4(buffer + 28); - i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8); - if (lseek(image, i, 0) < 0) - die("lseek"); - if (read(image, buffer, 512) != 512) - die(argv[1]); - j = 0; - } else if (memcmp(buffer, aout_magic, 4) == 0) { - i = j = AOUT_TEXT_OFFSET; - } else { - fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n"); + if (memcmp(buffer, aout_magic, 4) != 0) { + fprintf (stderr, "Not a.out. Don't blame me.\n"); exit(1); } - k = i; /* * We need to fill in values for sparc_ramdisk_image + sparc_ramdisk_size * To locate these symbols search for the "HdrS" text which appear @@ -170,7 +153,7 @@ int main(int argc,char **argv) */ /* Find the gokernel label */ - i += (ld2(buffer + j + 2) << 2) - 512; + i = AOUT_TEXT_OFFSET + (ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2) - 512; if (lseek(image, i, 0) < 0) die("lseek"); if (read(image, buffer, 1024) != 1024) @@ -203,7 +186,7 @@ int main(int argc,char **argv) die(argv[1]); /* seek page aligned boundary in the image file and add boot image */ - if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) + if (lseek(image, AOUT_TEXT_OFFSET - start + ((end + 32 + 4095) & ~4095), 0) < 0) die("lseek"); if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]); -- cgit v1.2.3 From a020bb17b7046cd97ea6924ca99325b6e516bc2d Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 4 Jan 2011 11:39:15 +0000 Subject: sparc: add $BITS to piggyback arguments Add new option to piggyback that identify if this is for 32 or 64 bit. Use this information to determine the alignment used. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/boot/Makefile | 2 +- arch/sparc/boot/piggyback_32.c | 45 +++++++++++++++++++++++++++--------------- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index 97e3feb9ff1b..4c81fe59ab58 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile @@ -15,7 +15,7 @@ quiet_cmd_elftoaout = ELFTOAOUT $@ ifeq ($(CONFIG_SPARC32),y) quiet_cmd_piggy = PIGGY $@ - cmd_piggy = $(obj)/piggyback_32 $@ System.map $(ROOT_IMG) + cmd_piggy = $(obj)/piggyback_32 $(BITS) $@ System.map $(ROOT_IMG) quiet_cmd_btfix = BTFIX $@ cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@ quiet_cmd_sysmap = SYSMAP $(obj)/System.map diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index 369634d8271e..c4b0843f56ad 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c @@ -38,6 +38,17 @@ #define AOUT_TEXT_OFFSET 32 +static int is64bit = 0; + +/* align to power-of-two size */ +static int align(int n) +{ + if (is64bit) + return (n + 0x1fff) & ~0x1fff; + else + return (n + 0xfff) & ~0xfff; +} + /* read two bytes as big endian */ static unsigned short ld2(char *p) { @@ -62,7 +73,7 @@ static void die(const char *str) static void usage(void) { /* fs_img.gz is an image of initial ramdisk. */ - fprintf(stderr, "Usage: piggyback vmlinux.aout System.map fs_img.gz\n"); + fprintf(stderr, "Usage: piggyback bits vmlinux.aout System.map fs_img.gz\n"); fprintf(stderr, "\tKernel image will be modified in place.\n"); exit(1); } @@ -128,19 +139,21 @@ int main(int argc,char **argv) struct stat s; int image, tail; - if (argc != 4) + if (argc != 5) usage(); - if (stat (argv[3], &s) < 0) - die(argv[3]); + if (strcmp(argv[1], "64") == 0) + is64bit = 1; + if (stat (argv[4], &s) < 0) + die(argv[4]); - if (!get_start_end(argv[2], &start, &end)) { - fprintf (stderr, "Could not determine start and end from %s\n", argv[2]); + if (!get_start_end(argv[3], &start, &end)) { + fprintf (stderr, "Could not determine start and end from %s\n", argv[3]); exit(1); } - if ((image = open(argv[1], O_RDWR)) < 0) - die(argv[1]); + if ((image = open(argv[2], O_RDWR)) < 0) + die(argv[2]); if (read(image, buffer, 512) != 512) - die(argv[1]); + die(argv[2]); if (memcmp(buffer, aout_magic, 4) != 0) { fprintf (stderr, "Not a.out. Don't blame me.\n"); exit(1); @@ -157,7 +170,7 @@ int main(int argc,char **argv) if (lseek(image, i, 0) < 0) die("lseek"); if (read(image, buffer, 1024) != 1024) - die(argv[1]); + die(argv[2]); for (q = buffer, r = q + 512; q < r; q += 4) { if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S') break; @@ -179,20 +192,20 @@ int main(int argc,char **argv) */ st4(buffer, 0); st4(buffer + 4, 0x01000000); - st4(buffer + 8, (end + 32 + 4095) & ~4095); + st4(buffer + 8, align(end + 32)); st4(buffer + 12, s.st_size); if (write(image, buffer + 2, 14) != 14) - die(argv[1]); + die(argv[2]); /* seek page aligned boundary in the image file and add boot image */ - if (lseek(image, AOUT_TEXT_OFFSET - start + ((end + 32 + 4095) & ~4095), 0) < 0) + if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0) die("lseek"); - if ((tail = open(argv[3],O_RDONLY)) < 0) - die(argv[3]); + if ((tail = open(argv[4], O_RDONLY)) < 0) + die(argv[4]); while ((i = read(tail, buffer, 1024)) > 0) if (write(image, buffer, i) != i) - die(argv[1]); + die(argv[2]); if (close(image) < 0) die("close"); if (close(tail) < 0) -- cgit v1.2.3 From 1075c4ef707ca83afbeb0950094436eb0245ec86 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 4 Jan 2011 11:39:16 +0000 Subject: sparc: fix tftpboot.img for sparc64 on little-endian host piggyback_32 adapted to support sparc64: - locating "HdrS" differs for sparc and sparc64 - sparc64 updates a_text, a_data + a_bss in the final a.out header Updated Makefile to use piggyback_32 for sparc64. Deleted the now unused piggyback_64.c piggyback_32.c is host endian neutral and works on both little-endian and big-endian hosts. This fixes a long standing bug where sparc64 could not generate tftpboot.img on a x86 host. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/boot/Makefile | 6 +-- arch/sparc/boot/piggyback_32.c | 97 ++++++++++++++++++++++++++++-------- arch/sparc/boot/piggyback_64.c | 110 ----------------------------------------- 3 files changed, 80 insertions(+), 133 deletions(-) delete mode 100644 arch/sparc/boot/piggyback_64.c diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index 4c81fe59ab58..06a79a2018de 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile @@ -6,7 +6,7 @@ ROOT_IMG := /usr/src/root.img ELFTOAOUT := elftoaout -hostprogs-y := piggyback_32 piggyback_64 btfixupprep +hostprogs-y := piggyback_32 btfixupprep targets := tftpboot.img btfix.o btfix.S image zImage vmlinux.aout clean-files := System.map @@ -69,7 +69,7 @@ endif ifeq ($(CONFIG_SPARC64),y) quiet_cmd_piggy = PIGGY $@ - cmd_piggy = $(obj)/piggyback_64 $@ System.map $(ROOT_IMG) + cmd_piggy = $(obj)/piggyback_32 $(BITS) $@ System.map $(ROOT_IMG) quiet_cmd_strip = STRIP $@ cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@ @@ -82,7 +82,7 @@ $(obj)/image: vmlinux FORCE $(obj)/zImage: $(obj)/image $(call if_changed,gzip) -$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE +$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE $(call if_changed,elftoaout) $(call if_changed,piggy) @echo ' kernel: $@ is ready' diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index c4b0843f56ad..d56e9de85d27 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c @@ -107,7 +107,8 @@ static int end_line(const char *line) * * Return 0 if either start or end is not found */ -static int get_start_end(const char *filename, unsigned int *start, unsigned int *end) +static int get_start_end(const char *filename, unsigned int *start, + unsigned int *end) { FILE *map; char buffer[1024]; @@ -131,11 +132,60 @@ static int get_start_end(const char *filename, unsigned int *start, unsigned int return 1; } +#define LOOKBACK (128 * 4) +#define BUFSIZE 1024 +/* + * Find the HdrS entry from head_32/head_64. + * We check if it is at the beginning of the file (sparc64 case) + * and if not we search for it. + * When we search do so in steps of 4 as HdrS is on a 4-byte aligned + * address (it is on same alignment as sparc instructions) + * Return the offset to the HdrS entry (as off_t) + */ +static off_t get_hdrs_offset(int kernelfd, const char *filename) +{ + char buffer[BUFSIZE]; + off_t offset; + int i; + + if (lseek(kernelfd, 0, SEEK_SET) < 0) + die("lseek"); + if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) + die(filename); + + if (buffer[40] == 'H' && buffer[41] == 'd' && + buffer[42] == 'r' && buffer[43] == 'S') { + return 40; + } else { + /* Find the gokernel label */ + /* Decode offset from branch instruction */ + offset = ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2; + /* Go back 512 bytes so we do not miss HdrS */ + offset -= LOOKBACK; + /* skip a.out header */ + offset += AOUT_TEXT_OFFSET; + if (lseek(kernelfd, offset, SEEK_SET) < 0) + die("lseek"); + if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) + die(filename); + + for (i = 0; i < LOOKBACK; i += 4) { + if (buffer[i + 0] == 'H' && buffer[i + 1] == 'd' && + buffer[i + 2] == 'r' && buffer[i + 3] == 'S') { + return offset + i; + } + } + } + fprintf (stderr, "Couldn't find headers signature in %s\n", filename); + exit(1); +} + int main(int argc,char **argv) { static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; - char buffer[1024], *q, *r; - unsigned int i, start, end, offset; + char buffer[1024]; + unsigned int i, start, end; + off_t offset; struct stat s; int image, tail; @@ -147,7 +197,8 @@ int main(int argc,char **argv) die(argv[4]); if (!get_start_end(argv[3], &start, &end)) { - fprintf (stderr, "Could not determine start and end from %s\n", argv[3]); + fprintf(stderr, "Could not determine start and end from %s\n", + argv[3]); exit(1); } if ((image = open(argv[2], O_RDWR)) < 0) @@ -159,27 +210,17 @@ int main(int argc,char **argv) exit(1); } /* - * We need to fill in values for sparc_ramdisk_image + sparc_ramdisk_size + * We need to fill in values for + * sparc_ramdisk_image + sparc_ramdisk_size * To locate these symbols search for the "HdrS" text which appear * in the image a little before the gokernel symbol. * See definition of these in init_32.S */ - /* Find the gokernel label */ - i = AOUT_TEXT_OFFSET + (ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2) - 512; - if (lseek(image, i, 0) < 0) - die("lseek"); - if (read(image, buffer, 1024) != 1024) - die(argv[2]); - for (q = buffer, r = q + 512; q < r; q += 4) { - if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S') - break; - } - if (q == r) { - fprintf (stderr, "Couldn't find headers signature in the kernel.\n"); - exit(1); - } - offset = i + (q - buffer) + 10; + offset = get_hdrs_offset(image, argv[2]); + /* skip HdrS + LINUX_VERSION_CODE + HdrS version */ + offset += 10; + if (lseek(image, offset, 0) < 0) die("lseek"); @@ -198,6 +239,22 @@ int main(int argc,char **argv) if (write(image, buffer + 2, 14) != 14) die(argv[2]); + /* For sparc64 update a_text and clear a_data + a_bss */ + if (is64bit) + { + if (lseek(image, 4, 0) < 0) + die("lseek"); + /* a_text */ + st4(buffer, align(end + 32 + 8191) - (start & ~0x3fffffUL) + + s.st_size); + /* a_data */ + st4(buffer + 4, 0); + /* a_bss */ + st4(buffer + 8, 0); + if (write(image, buffer, 12) != 12) + die(argv[2]); + } + /* seek page aligned boundary in the image file and add boot image */ if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0) die("lseek"); diff --git a/arch/sparc/boot/piggyback_64.c b/arch/sparc/boot/piggyback_64.c deleted file mode 100644 index a26a686cb5aa..000000000000 --- a/arch/sparc/boot/piggyback_64.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - Simple utility to make a single-image install kernel with initial ramdisk - for Sparc64 tftpbooting without need to set up nfs. - - Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - - 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Note: run this on an a.out kernel (use elftoaout for it), as PROM looks for a.out image onlly - usage: piggyback vmlinux System.map tail, where tail is gzipped fs of the initial ramdisk */ - -static void die(char *str) -{ - perror (str); - exit(1); -} - -int main(int argc,char **argv) -{ - char buffer [1024], *q, *r; - unsigned int i, j, k, start, end, offset; - FILE *map; - struct stat s; - int image, tail; - - start = end = 0; - if (stat (argv[3], &s) < 0) die (argv[3]); - map = fopen (argv[2], "r"); - if (!map) die(argv[2]); - while (fgets (buffer, 1024, map)) { - if (!strcmp (buffer + 19, "_start\n")) - start = strtoul (buffer + 8, NULL, 16); - else if (!strcmp (buffer + 19, "_end\n")) - end = strtoul (buffer + 8, NULL, 16); - } - fclose (map); - if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]); - if (read(image,buffer,512) != 512) die(argv[1]); - if (!memcmp (buffer, "\177ELF", 4)) { - unsigned int *p = (unsigned int *)(buffer + *(unsigned int *)(buffer + 28)); - - i = p[1] + *(unsigned int *)(buffer + 24) - p[2]; - if (lseek(image,i,0) < 0) die("lseek"); - if (read(image,buffer,512) != 512) die(argv[1]); - j = 0; - } else if (*(unsigned int *)buffer == 0x01030107) { - i = j = 32; - } else { - fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n"); - exit(1); - } - k = i; - if (j == 32 && buffer[40] == 'H' && buffer[41] == 'd' && buffer[42] == 'r' && buffer[43] == 'S') { - offset = 40 + 10; - } else { - i += ((*(unsigned short *)(buffer + j + 2))<<2) - 512; - if (lseek(image,i,0) < 0) die("lseek"); - if (read(image,buffer,1024) != 1024) die(argv[1]); - for (q = buffer, r = q + 512; q < r; q += 4) { - if (*q == 'H' && q[1] == 'd' && q[2] == 'r' && q[3] == 'S') - break; - } - if (q == r) { - fprintf (stderr, "Couldn't find headers signature in the kernel.\n"); - exit(1); - } - offset = i + (q - buffer) + 10; - } - if (lseek(image, offset, 0) < 0) die ("lseek"); - *(unsigned *)buffer = 0; - *(unsigned *)(buffer + 4) = 0x01000000; - *(unsigned *)(buffer + 8) = ((end + 32 + 8191) & ~8191); - *(unsigned *)(buffer + 12) = s.st_size; - if (write(image,buffer+2,14) != 14) die (argv[1]); - if (lseek(image, 4, 0) < 0) die ("lseek"); - *(unsigned *)buffer = ((end + 32 + 8191) & ~8191) - (start & ~0x3fffffUL) + s.st_size; - *(unsigned *)(buffer + 4) = 0; - *(unsigned *)(buffer + 8) = 0; - if (write(image,buffer,12) != 12) die (argv[1]); - if (lseek(image, k - start + ((end + 32 + 8191) & ~8191), 0) < 0) die ("lseek"); - if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]); - while ((i = read (tail,buffer,1024)) > 0) - if (write(image,buffer,i) != i) die (argv[1]); - if (close(image) < 0) die("close"); - if (close(tail) < 0) die("close"); - return 0; -} -- cgit v1.2.3 From 56818a6f9105ac016ecf5907f7cb63bcdab639fe Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 4 Jan 2011 11:39:17 +0000 Subject: sparc: rename piggyback_32 to piggyback Now that we use the same piggyback for 32 and 64 bit we can drop the _32 suffix. Include some trivial unification in the Makefile now that 32 and 64 bit can share the same piggyback command. Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/boot/Makefile | 20 +-- arch/sparc/boot/piggyback.c | 271 +++++++++++++++++++++++++++++++++++++++++ arch/sparc/boot/piggyback_32.c | 271 ----------------------------------------- 3 files changed, 277 insertions(+), 285 deletions(-) create mode 100644 arch/sparc/boot/piggyback.c delete mode 100644 arch/sparc/boot/piggyback_32.c diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index 06a79a2018de..f9d3bf96806e 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile @@ -6,16 +6,16 @@ ROOT_IMG := /usr/src/root.img ELFTOAOUT := elftoaout -hostprogs-y := piggyback_32 btfixupprep +hostprogs-y := piggyback btfixupprep targets := tftpboot.img btfix.o btfix.S image zImage vmlinux.aout clean-files := System.map quiet_cmd_elftoaout = ELFTOAOUT $@ cmd_elftoaout = $(ELFTOAOUT) $(obj)/image -o $@ +quiet_cmd_piggy = PIGGY $@ + cmd_piggy = $(obj)/piggyback $(BITS) $@ System.map $(ROOT_IMG) ifeq ($(CONFIG_SPARC32),y) -quiet_cmd_piggy = PIGGY $@ - cmd_piggy = $(obj)/piggyback_32 $(BITS) $@ System.map $(ROOT_IMG) quiet_cmd_btfix = BTFIX $@ cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@ quiet_cmd_sysmap = SYSMAP $(obj)/System.map @@ -58,18 +58,12 @@ $(obj)/image: $(obj)/btfix.o FORCE $(obj)/zImage: $(obj)/image $(call if_changed,strip) -$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE - $(call if_changed,elftoaout) - $(call if_changed,piggy) - $(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE $(call if_changed,btfix) endif ifeq ($(CONFIG_SPARC64),y) -quiet_cmd_piggy = PIGGY $@ - cmd_piggy = $(obj)/piggyback_32 $(BITS) $@ System.map $(ROOT_IMG) quiet_cmd_strip = STRIP $@ cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@ @@ -82,13 +76,11 @@ $(obj)/image: vmlinux FORCE $(obj)/zImage: $(obj)/image $(call if_changed,gzip) -$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE - $(call if_changed,elftoaout) - $(call if_changed,piggy) - @echo ' kernel: $@ is ready' - $(obj)/vmlinux.aout: vmlinux FORCE $(call if_changed,elftoaout) @echo ' kernel: $@ is ready' endif +$(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE + $(call if_changed,elftoaout) + $(call if_changed,piggy) diff --git a/arch/sparc/boot/piggyback.c b/arch/sparc/boot/piggyback.c new file mode 100644 index 000000000000..d56e9de85d27 --- /dev/null +++ b/arch/sparc/boot/piggyback.c @@ -0,0 +1,271 @@ +/* + Simple utility to make a single-image install kernel with initial ramdisk + for Sparc tftpbooting without need to set up nfs. + + Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + Pete Zaitcev endian fixes for cross-compiles, 2000. + + 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * Note: run this on an a.out kernel (use elftoaout for it), + * as PROM looks for a.out image only. + */ + +#define AOUT_TEXT_OFFSET 32 + +static int is64bit = 0; + +/* align to power-of-two size */ +static int align(int n) +{ + if (is64bit) + return (n + 0x1fff) & ~0x1fff; + else + return (n + 0xfff) & ~0xfff; +} + +/* read two bytes as big endian */ +static unsigned short ld2(char *p) +{ + return (p[0] << 8) | p[1]; +} + +/* save 4 bytes as big endian */ +static void st4(char *p, unsigned int x) +{ + p[0] = x >> 24; + p[1] = x >> 16; + p[2] = x >> 8; + p[3] = x; +} + +static void die(const char *str) +{ + perror(str); + exit(1); +} + +static void usage(void) +{ + /* fs_img.gz is an image of initial ramdisk. */ + fprintf(stderr, "Usage: piggyback bits vmlinux.aout System.map fs_img.gz\n"); + fprintf(stderr, "\tKernel image will be modified in place.\n"); + exit(1); +} + +static int start_line(const char *line) +{ + if (strcmp(line + 8, " T _start\n") == 0) + return 1; + else if (strcmp(line + 16, " T _start\n") == 0) + return 1; + return 0; +} + +static int end_line(const char *line) +{ + if (strcmp(line + 8, " A _end\n") == 0) + return 1; + else if (strcmp (line + 16, " A _end\n") == 0) + return 1; + return 0; +} + +/* + * Find address for start and end in System.map. + * The file looks like this: + * f0004000 T _start + * f0379f79 A _end + * 1234567890123456 + * ^coloumn 1 + * There is support for 64 bit addresses too. + * + * Return 0 if either start or end is not found + */ +static int get_start_end(const char *filename, unsigned int *start, + unsigned int *end) +{ + FILE *map; + char buffer[1024]; + + *start = 0; + *end = 0; + map = fopen(filename, "r"); + if (!map) + die(filename); + while (fgets(buffer, 1024, map)) { + if (start_line(buffer)) + *start = strtoul(buffer, NULL, 16); + else if (end_line(buffer)) + *end = strtoul(buffer, NULL, 16); + } + fclose (map); + + if (*start == 0 || *end == 0) + return 0; + + return 1; +} + +#define LOOKBACK (128 * 4) +#define BUFSIZE 1024 +/* + * Find the HdrS entry from head_32/head_64. + * We check if it is at the beginning of the file (sparc64 case) + * and if not we search for it. + * When we search do so in steps of 4 as HdrS is on a 4-byte aligned + * address (it is on same alignment as sparc instructions) + * Return the offset to the HdrS entry (as off_t) + */ +static off_t get_hdrs_offset(int kernelfd, const char *filename) +{ + char buffer[BUFSIZE]; + off_t offset; + int i; + + if (lseek(kernelfd, 0, SEEK_SET) < 0) + die("lseek"); + if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) + die(filename); + + if (buffer[40] == 'H' && buffer[41] == 'd' && + buffer[42] == 'r' && buffer[43] == 'S') { + return 40; + } else { + /* Find the gokernel label */ + /* Decode offset from branch instruction */ + offset = ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2; + /* Go back 512 bytes so we do not miss HdrS */ + offset -= LOOKBACK; + /* skip a.out header */ + offset += AOUT_TEXT_OFFSET; + if (lseek(kernelfd, offset, SEEK_SET) < 0) + die("lseek"); + if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) + die(filename); + + for (i = 0; i < LOOKBACK; i += 4) { + if (buffer[i + 0] == 'H' && buffer[i + 1] == 'd' && + buffer[i + 2] == 'r' && buffer[i + 3] == 'S') { + return offset + i; + } + } + } + fprintf (stderr, "Couldn't find headers signature in %s\n", filename); + exit(1); +} + +int main(int argc,char **argv) +{ + static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; + char buffer[1024]; + unsigned int i, start, end; + off_t offset; + struct stat s; + int image, tail; + + if (argc != 5) + usage(); + if (strcmp(argv[1], "64") == 0) + is64bit = 1; + if (stat (argv[4], &s) < 0) + die(argv[4]); + + if (!get_start_end(argv[3], &start, &end)) { + fprintf(stderr, "Could not determine start and end from %s\n", + argv[3]); + exit(1); + } + if ((image = open(argv[2], O_RDWR)) < 0) + die(argv[2]); + if (read(image, buffer, 512) != 512) + die(argv[2]); + if (memcmp(buffer, aout_magic, 4) != 0) { + fprintf (stderr, "Not a.out. Don't blame me.\n"); + exit(1); + } + /* + * We need to fill in values for + * sparc_ramdisk_image + sparc_ramdisk_size + * To locate these symbols search for the "HdrS" text which appear + * in the image a little before the gokernel symbol. + * See definition of these in init_32.S + */ + + offset = get_hdrs_offset(image, argv[2]); + /* skip HdrS + LINUX_VERSION_CODE + HdrS version */ + offset += 10; + + if (lseek(image, offset, 0) < 0) + die("lseek"); + + /* + * root_flags = 0 + * root_dev = 1 (RAMDISK_MAJOR) + * ram_flags = 0 + * sparc_ramdisk_image = "PAGE aligned address after _end") + * sparc_ramdisk_size = size of image + */ + st4(buffer, 0); + st4(buffer + 4, 0x01000000); + st4(buffer + 8, align(end + 32)); + st4(buffer + 12, s.st_size); + + if (write(image, buffer + 2, 14) != 14) + die(argv[2]); + + /* For sparc64 update a_text and clear a_data + a_bss */ + if (is64bit) + { + if (lseek(image, 4, 0) < 0) + die("lseek"); + /* a_text */ + st4(buffer, align(end + 32 + 8191) - (start & ~0x3fffffUL) + + s.st_size); + /* a_data */ + st4(buffer + 4, 0); + /* a_bss */ + st4(buffer + 8, 0); + if (write(image, buffer, 12) != 12) + die(argv[2]); + } + + /* seek page aligned boundary in the image file and add boot image */ + if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0) + die("lseek"); + if ((tail = open(argv[4], O_RDONLY)) < 0) + die(argv[4]); + while ((i = read(tail, buffer, 1024)) > 0) + if (write(image, buffer, i) != i) + die(argv[2]); + if (close(image) < 0) + die("close"); + if (close(tail) < 0) + die("close"); + return 0; +} diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c deleted file mode 100644 index d56e9de85d27..000000000000 --- a/arch/sparc/boot/piggyback_32.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - Simple utility to make a single-image install kernel with initial ramdisk - for Sparc tftpbooting without need to set up nfs. - - Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - Pete Zaitcev endian fixes for cross-compiles, 2000. - - 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, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/* - * Note: run this on an a.out kernel (use elftoaout for it), - * as PROM looks for a.out image only. - */ - -#define AOUT_TEXT_OFFSET 32 - -static int is64bit = 0; - -/* align to power-of-two size */ -static int align(int n) -{ - if (is64bit) - return (n + 0x1fff) & ~0x1fff; - else - return (n + 0xfff) & ~0xfff; -} - -/* read two bytes as big endian */ -static unsigned short ld2(char *p) -{ - return (p[0] << 8) | p[1]; -} - -/* save 4 bytes as big endian */ -static void st4(char *p, unsigned int x) -{ - p[0] = x >> 24; - p[1] = x >> 16; - p[2] = x >> 8; - p[3] = x; -} - -static void die(const char *str) -{ - perror(str); - exit(1); -} - -static void usage(void) -{ - /* fs_img.gz is an image of initial ramdisk. */ - fprintf(stderr, "Usage: piggyback bits vmlinux.aout System.map fs_img.gz\n"); - fprintf(stderr, "\tKernel image will be modified in place.\n"); - exit(1); -} - -static int start_line(const char *line) -{ - if (strcmp(line + 8, " T _start\n") == 0) - return 1; - else if (strcmp(line + 16, " T _start\n") == 0) - return 1; - return 0; -} - -static int end_line(const char *line) -{ - if (strcmp(line + 8, " A _end\n") == 0) - return 1; - else if (strcmp (line + 16, " A _end\n") == 0) - return 1; - return 0; -} - -/* - * Find address for start and end in System.map. - * The file looks like this: - * f0004000 T _start - * f0379f79 A _end - * 1234567890123456 - * ^coloumn 1 - * There is support for 64 bit addresses too. - * - * Return 0 if either start or end is not found - */ -static int get_start_end(const char *filename, unsigned int *start, - unsigned int *end) -{ - FILE *map; - char buffer[1024]; - - *start = 0; - *end = 0; - map = fopen(filename, "r"); - if (!map) - die(filename); - while (fgets(buffer, 1024, map)) { - if (start_line(buffer)) - *start = strtoul(buffer, NULL, 16); - else if (end_line(buffer)) - *end = strtoul(buffer, NULL, 16); - } - fclose (map); - - if (*start == 0 || *end == 0) - return 0; - - return 1; -} - -#define LOOKBACK (128 * 4) -#define BUFSIZE 1024 -/* - * Find the HdrS entry from head_32/head_64. - * We check if it is at the beginning of the file (sparc64 case) - * and if not we search for it. - * When we search do so in steps of 4 as HdrS is on a 4-byte aligned - * address (it is on same alignment as sparc instructions) - * Return the offset to the HdrS entry (as off_t) - */ -static off_t get_hdrs_offset(int kernelfd, const char *filename) -{ - char buffer[BUFSIZE]; - off_t offset; - int i; - - if (lseek(kernelfd, 0, SEEK_SET) < 0) - die("lseek"); - if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) - die(filename); - - if (buffer[40] == 'H' && buffer[41] == 'd' && - buffer[42] == 'r' && buffer[43] == 'S') { - return 40; - } else { - /* Find the gokernel label */ - /* Decode offset from branch instruction */ - offset = ld2(buffer + AOUT_TEXT_OFFSET + 2) << 2; - /* Go back 512 bytes so we do not miss HdrS */ - offset -= LOOKBACK; - /* skip a.out header */ - offset += AOUT_TEXT_OFFSET; - if (lseek(kernelfd, offset, SEEK_SET) < 0) - die("lseek"); - if (read(kernelfd, buffer, BUFSIZE) != BUFSIZE) - die(filename); - - for (i = 0; i < LOOKBACK; i += 4) { - if (buffer[i + 0] == 'H' && buffer[i + 1] == 'd' && - buffer[i + 2] == 'r' && buffer[i + 3] == 'S') { - return offset + i; - } - } - } - fprintf (stderr, "Couldn't find headers signature in %s\n", filename); - exit(1); -} - -int main(int argc,char **argv) -{ - static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; - char buffer[1024]; - unsigned int i, start, end; - off_t offset; - struct stat s; - int image, tail; - - if (argc != 5) - usage(); - if (strcmp(argv[1], "64") == 0) - is64bit = 1; - if (stat (argv[4], &s) < 0) - die(argv[4]); - - if (!get_start_end(argv[3], &start, &end)) { - fprintf(stderr, "Could not determine start and end from %s\n", - argv[3]); - exit(1); - } - if ((image = open(argv[2], O_RDWR)) < 0) - die(argv[2]); - if (read(image, buffer, 512) != 512) - die(argv[2]); - if (memcmp(buffer, aout_magic, 4) != 0) { - fprintf (stderr, "Not a.out. Don't blame me.\n"); - exit(1); - } - /* - * We need to fill in values for - * sparc_ramdisk_image + sparc_ramdisk_size - * To locate these symbols search for the "HdrS" text which appear - * in the image a little before the gokernel symbol. - * See definition of these in init_32.S - */ - - offset = get_hdrs_offset(image, argv[2]); - /* skip HdrS + LINUX_VERSION_CODE + HdrS version */ - offset += 10; - - if (lseek(image, offset, 0) < 0) - die("lseek"); - - /* - * root_flags = 0 - * root_dev = 1 (RAMDISK_MAJOR) - * ram_flags = 0 - * sparc_ramdisk_image = "PAGE aligned address after _end") - * sparc_ramdisk_size = size of image - */ - st4(buffer, 0); - st4(buffer + 4, 0x01000000); - st4(buffer + 8, align(end + 32)); - st4(buffer + 12, s.st_size); - - if (write(image, buffer + 2, 14) != 14) - die(argv[2]); - - /* For sparc64 update a_text and clear a_data + a_bss */ - if (is64bit) - { - if (lseek(image, 4, 0) < 0) - die("lseek"); - /* a_text */ - st4(buffer, align(end + 32 + 8191) - (start & ~0x3fffffUL) + - s.st_size); - /* a_data */ - st4(buffer + 4, 0); - /* a_bss */ - st4(buffer + 8, 0); - if (write(image, buffer, 12) != 12) - die(argv[2]); - } - - /* seek page aligned boundary in the image file and add boot image */ - if (lseek(image, AOUT_TEXT_OFFSET - start + align(end + 32), 0) < 0) - die("lseek"); - if ((tail = open(argv[4], O_RDONLY)) < 0) - die(argv[4]); - while ((i = read(tail, buffer, 1024)) > 0) - if (write(image, buffer, i) != i) - die(argv[2]); - if (close(image) < 0) - die("close"); - if (close(tail) < 0) - die("close"); - return 0; -} -- cgit v1.2.3 From 9202db2202288f0013c3285b291d8281a8190962 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 4 Jan 2011 11:39:18 +0000 Subject: sparc: unify strip command in boot/Makefile Include an additional "Kernel is ready" print for zImage Signed-off-by: Sam Ravnborg Signed-off-by: David S. Miller --- arch/sparc/boot/Makefile | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index f9d3bf96806e..a2c5898c1ab1 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile @@ -14,6 +14,8 @@ quiet_cmd_elftoaout = ELFTOAOUT $@ cmd_elftoaout = $(ELFTOAOUT) $(obj)/image -o $@ quiet_cmd_piggy = PIGGY $@ cmd_piggy = $(obj)/piggyback $(BITS) $@ System.map $(ROOT_IMG) +quiet_cmd_strip = STRIP $@ + cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $< -o $@ ifeq ($(CONFIG_SPARC32),y) quiet_cmd_btfix = BTFIX $@ @@ -22,9 +24,6 @@ quiet_cmd_sysmap = SYSMAP $(obj)/System.map cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap quiet_cmd_image = LD $@ cmd_image = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_$(@F)) -o $@ -quiet_cmd_strip = STRIP $@ - cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start $(obj)/image -o $@ - define rule_image $(if $($(quiet)cmd_image), \ @@ -57,6 +56,7 @@ $(obj)/image: $(obj)/btfix.o FORCE $(obj)/zImage: $(obj)/image $(call if_changed,strip) + @echo ' kernel: $@ is ready' $(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE $(call if_changed,btfix) @@ -64,9 +64,6 @@ $(obj)/btfix.S: $(obj)/btfixupprep vmlinux FORCE endif ifeq ($(CONFIG_SPARC64),y) -quiet_cmd_strip = STRIP $@ - cmd_strip = $(STRIP) -R .comment -R .note -K sun4u_init -K _end -K _start vmlinux -o $@ - # Actual linking $(obj)/image: vmlinux FORCE @@ -75,6 +72,7 @@ $(obj)/image: vmlinux FORCE $(obj)/zImage: $(obj)/image $(call if_changed,gzip) + @echo ' kernel: $@ is ready' $(obj)/vmlinux.aout: vmlinux FORCE $(call if_changed,elftoaout) -- cgit v1.2.3 From 050855887236701c5e7ff803b42265824ce99885 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Tue, 4 Jan 2011 11:39:19 +0000 Subject: sparc: update copyright in piggyback.c Update copyright info in piggyback.c to include info from piggyback_64.c. Include my own copyright too. Signed-off-by: Sam Ravnborg Cc: Josip Rodin Cc: Jakub Jelinek Signed-off-by: David S. Miller --- arch/sparc/boot/piggyback.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sparc/boot/piggyback.c b/arch/sparc/boot/piggyback.c index d56e9de85d27..c0a798fcf030 100644 --- a/arch/sparc/boot/piggyback.c +++ b/arch/sparc/boot/piggyback.c @@ -2,8 +2,9 @@ Simple utility to make a single-image install kernel with initial ramdisk for Sparc tftpbooting without need to set up nfs. - Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) + Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) Pete Zaitcev endian fixes for cross-compiles, 2000. + Copyright (C) 2011 Sam Ravnborg 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 -- cgit v1.2.3 From 09798eb9479da3413bdf96e7d22a84d8b21e05e1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 5 Jan 2011 13:08:06 -0800 Subject: atyfb: Fix bootup hangs on sparc64. After commit 25edd6946a1d74e5e77813c2324a0908c68bcf9e ("sparc64: Get rid of indirect p1275 PROM call buffer.") we can't pass virtual addresses >4GB to PROM calls. Largely this is never necessary in drivers because we have a copy of the entire PROM device tree in the kernel and a set of of_*() interfaces to access it. Unfortunately there were some lingering prom calls in the atyfb driver, in particular prom_finddevice() was being called with an on-stack address which could be anywhere. This code is actually probing for information we already have, the PROM choosen console output device is stored in of_console_device so all of this nasty code consolidates into a one-line comparison. Next we have some prom_getintdefault() calls which are trivially transformed into the equivalent of_getintprop_default(). Special thanks to Fabio, who figured out exactly where the bootup was hanging. That made this bug trivial to fix. Reported-by: Fabio M. Di NItto Reported-by: Sam Ravnborg Reported-by: Frans van Berckel Signed-off-by: David S. Miller Signed-off-by: Fabio M. Di NItto --- drivers/video/aty/atyfb_base.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 5bf91236c701..5a3ce3ad1ec8 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -2969,10 +2969,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, { struct atyfb_par *par = info->par; struct device_node *dp; - char prop[128]; - phandle node; - int len, i, j, ret; u32 mem, chip_id; + int i, j, ret; /* * Map memory-mapped registers. @@ -3088,23 +3086,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, aty_st_le32(MEM_CNTL, mem, par); } - /* - * If this is the console device, we will set default video - * settings to what the PROM left us with. - */ - node = prom_getchild(prom_root_node); - node = prom_searchsiblings(node, "aliases"); - if (node) { - len = prom_getproperty(node, "screen", prop, sizeof(prop)); - if (len > 0) { - prop[len] = '\0'; - node = prom_finddevice(prop); - } else - node = 0; - } - dp = pci_device_to_OF_node(pdev); - if (node == dp->phandle) { + if (dp == of_console_device) { struct fb_var_screeninfo *var = &default_var; unsigned int N, P, Q, M, T, R; u32 v_total, h_total; @@ -3112,9 +3095,9 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, u8 pll_regs[16]; u8 clock_cntl; - crtc.vxres = prom_getintdefault(node, "width", 1024); - crtc.vyres = prom_getintdefault(node, "height", 768); - var->bits_per_pixel = prom_getintdefault(node, "depth", 8); + crtc.vxres = of_getintprop_default(dp, "width", 1024); + crtc.vyres = of_getintprop_default(dp, "height", 768); + var->bits_per_pixel = of_getintprop_default(dp, "depth", 8); var->xoffset = var->yoffset = 0; crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par); crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par); -- cgit v1.2.3