|
|
|
@ -12,6 +12,7 @@ |
|
|
|
|
#include <linux/kernel.h> |
|
|
|
|
#include <linux/init.h> |
|
|
|
|
#include <linux/io.h> |
|
|
|
|
#include <linux/string.h> |
|
|
|
|
|
|
|
|
|
#include <asm/bootinfo.h> |
|
|
|
|
#include <asm/addrspace.h> |
|
|
|
@ -26,10 +27,6 @@ struct board_rec { |
|
|
|
|
enum ar71xx_mach_type mach_type; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static int ar71xx_prom_argc __initdata; |
|
|
|
|
static char **ar71xx_prom_argv __initdata; |
|
|
|
|
static char **ar71xx_prom_envp __initdata; |
|
|
|
|
|
|
|
|
|
static struct board_rec boards[] __initdata = { |
|
|
|
|
{ |
|
|
|
|
.name = "411", |
|
|
|
@ -91,6 +88,9 @@ static struct board_rec boards[] __initdata = { |
|
|
|
|
}, { |
|
|
|
|
.name = "WRT160NL", |
|
|
|
|
.mach_type = AR71XX_MACH_WRT160NL, |
|
|
|
|
}, { |
|
|
|
|
.name = "WP543", |
|
|
|
|
.mach_type = AR71XX_MACH_WP543, |
|
|
|
|
}, { |
|
|
|
|
.name = "WRT400N", |
|
|
|
|
.mach_type = AR71XX_MACH_WRT400N, |
|
|
|
@ -109,6 +109,34 @@ static struct board_rec boards[] __initdata = { |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static int __init ar71xx_board_setup(char *name) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(boards); i++) |
|
|
|
|
if (strcmp(name, boards[i].name) == 0) { |
|
|
|
|
ar71xx_mach = boards[i].mach_type; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
__setup("board=", ar71xx_board_setup); |
|
|
|
|
|
|
|
|
|
static int __init ar71xx_ethaddr_setup(char *str) |
|
|
|
|
{ |
|
|
|
|
ar71xx_parse_mac_addr(str); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
__setup("ethaddr=", ar71xx_ethaddr_setup); |
|
|
|
|
|
|
|
|
|
static int __init ar71xx_kmac_setup(char *str) |
|
|
|
|
{ |
|
|
|
|
ar71xx_parse_mac_addr(str); |
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
__setup("kmac=", ar71xx_kmac_setup); |
|
|
|
|
|
|
|
|
|
static inline int is_valid_ram_addr(void *addr) |
|
|
|
|
{ |
|
|
|
|
if (((u32) addr > KSEG0) && |
|
|
|
@ -122,62 +150,43 @@ static inline int is_valid_ram_addr(void *addr) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static __init char *ar71xx_prom_getargv(const char *name) |
|
|
|
|
static void __init ar71xx_prom_append_cmdline(const char *name, |
|
|
|
|
const char *value) |
|
|
|
|
{ |
|
|
|
|
int len = strlen(name); |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
if (!is_valid_ram_addr(ar71xx_prom_argv)) |
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ar71xx_prom_argc; i++) { |
|
|
|
|
char *argv = ar71xx_prom_argv[i]; |
|
|
|
|
|
|
|
|
|
if (!is_valid_ram_addr(argv)) |
|
|
|
|
continue; |
|
|
|
|
char buf[CL_SIZE]; |
|
|
|
|
|
|
|
|
|
if (strncmp(name, argv, len) == 0 && (argv)[len] == '=') |
|
|
|
|
return argv + len + 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
snprintf(buf, sizeof(buf), " %s=%s", name, value); |
|
|
|
|
strlcat(arcs_cmdline, buf, sizeof(arcs_cmdline)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static __init char *ar71xx_prom_getenv(const char *envname) |
|
|
|
|
static void __init ar71xx_prom_find_env(char **envp, const char *name) |
|
|
|
|
{ |
|
|
|
|
int len = strlen(envname); |
|
|
|
|
char **env; |
|
|
|
|
int len = strlen(name); |
|
|
|
|
char **p; |
|
|
|
|
|
|
|
|
|
if (!is_valid_ram_addr(ar71xx_prom_envp)) |
|
|
|
|
return NULL; |
|
|
|
|
if (!is_valid_ram_addr(envp)) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
for (env = ar71xx_prom_envp; is_valid_ram_addr(*env); env++) { |
|
|
|
|
if (strncmp(envname, *env, len) == 0 && (*env)[len] == '=') |
|
|
|
|
return *env + len + 1; |
|
|
|
|
for (p = envp; is_valid_ram_addr(*p); p++) { |
|
|
|
|
if (strncmp(name, *p, len) == 0 && (*p)[len] == '=') { |
|
|
|
|
ar71xx_prom_append_cmdline(name, *p + len + 1); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* RedBoot env comes in pointer pairs - key, value */ |
|
|
|
|
if (strncmp(envname, *env, len) == 0 && (*env)[len] == 0) |
|
|
|
|
if (is_valid_ram_addr(*(++env))) |
|
|
|
|
return *env; |
|
|
|
|
if (strncmp(name, *p, len) == 0 && (*p)[len] == 0) |
|
|
|
|
if (is_valid_ram_addr(*(++p))) { |
|
|
|
|
ar71xx_prom_append_cmdline(name, *p); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static __init unsigned long find_board_byname(char *name) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(boards); i++) |
|
|
|
|
if (strcmp(name, boards[i].name) == 0) |
|
|
|
|
return boards[i].mach_type; |
|
|
|
|
|
|
|
|
|
return AR71XX_MACH_GENERIC; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int ar71xx_prom_init_myloader(void) |
|
|
|
|
static int __init ar71xx_prom_init_myloader(void) |
|
|
|
|
{ |
|
|
|
|
struct myloader_info *mylo; |
|
|
|
|
char mac_buf[32]; |
|
|
|
|
char *mac; |
|
|
|
|
|
|
|
|
|
mylo = myloader_get_info(); |
|
|
|
|
if (!mylo) |
|
|
|
@ -185,51 +194,89 @@ static int ar71xx_prom_init_myloader(void) |
|
|
|
|
|
|
|
|
|
switch (mylo->did) { |
|
|
|
|
case DEVID_COMPEX_WP543: |
|
|
|
|
ar71xx_mach = AR71XX_MACH_WP543; |
|
|
|
|
ar71xx_prom_append_cmdline("board", "WP543"); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
printk(KERN_WARNING "prom: unknown device id: %x\n", |
|
|
|
|
mylo->did); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
ar71xx_set_mac_base(mylo->macs[0]); |
|
|
|
|
|
|
|
|
|
mac = mylo->macs[0]; |
|
|
|
|
snprintf(mac_buf, sizeof(mac_buf), "%02x:%02x:%02x:%02x:%02x:%02x", |
|
|
|
|
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); |
|
|
|
|
|
|
|
|
|
ar71xx_prom_append_cmdline("ethaddr", mac_buf); |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ar71xx_prom_init_generic(void) |
|
|
|
|
#ifdef CONFIG_IMAGE_CMDLINE_HACK |
|
|
|
|
extern char __image_cmdline[]; |
|
|
|
|
|
|
|
|
|
static int __init ar71xx_use__image_cmdline(void) |
|
|
|
|
{ |
|
|
|
|
char *p; |
|
|
|
|
|
|
|
|
|
ar71xx_prom_argc = fw_arg0; |
|
|
|
|
ar71xx_prom_argv = (char **)fw_arg1; |
|
|
|
|
ar71xx_prom_envp = (char **)fw_arg2; |
|
|
|
|
|
|
|
|
|
p = ar71xx_prom_getargv("board"); |
|
|
|
|
if (!p) |
|
|
|
|
p = ar71xx_prom_getenv("board"); |
|
|
|
|
if (p) |
|
|
|
|
ar71xx_mach = find_board_byname(p); |
|
|
|
|
|
|
|
|
|
p = ar71xx_prom_getenv("ethaddr"); |
|
|
|
|
if (!p) |
|
|
|
|
p = ar71xx_prom_getargv("kmac"); |
|
|
|
|
if (p) |
|
|
|
|
ar71xx_parse_mac_addr(p); |
|
|
|
|
char *p = __image_cmdline; |
|
|
|
|
int replace = 0; |
|
|
|
|
|
|
|
|
|
if (*p == '-') { |
|
|
|
|
replace = 1; |
|
|
|
|
p++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (*p == '\0') |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
if (replace) { |
|
|
|
|
strlcpy(arcs_cmdline, p, sizeof(arcs_cmdline)); |
|
|
|
|
} else { |
|
|
|
|
strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); |
|
|
|
|
strlcat(arcs_cmdline, p, sizeof(arcs_cmdline)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
} |
|
|
|
|
#else |
|
|
|
|
static int inline ar71xx_use__image_cmdline(void) { return 0; } |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
static __init void ar71xx_prom_init_cmdline(int argc, char **argv) |
|
|
|
|
{ |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
if (ar71xx_use__image_cmdline()) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
if (!is_valid_ram_addr(argv)) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < argc; i++) |
|
|
|
|
if (is_valid_ram_addr(argv[i])) { |
|
|
|
|
strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); |
|
|
|
|
strlcat(arcs_cmdline, argv[i], sizeof(arcs_cmdline)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void __init prom_init(void) |
|
|
|
|
{ |
|
|
|
|
char **envp; |
|
|
|
|
|
|
|
|
|
printk(KERN_DEBUG "prom: fw_arg0=%08x, fw_arg1=%08x, " |
|
|
|
|
"fw_arg2=%08x, fw_arg3=%08x\n", |
|
|
|
|
(unsigned int)fw_arg0, (unsigned int)fw_arg1, |
|
|
|
|
(unsigned int)fw_arg2, (unsigned int)fw_arg3); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ar71xx_mach = AR71XX_MACH_GENERIC; |
|
|
|
|
|
|
|
|
|
if (ar71xx_prom_init_myloader()) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
ar71xx_prom_init_generic(); |
|
|
|
|
ar71xx_prom_init_cmdline(fw_arg0, (char **)fw_arg1); |
|
|
|
|
|
|
|
|
|
envp = (char **)fw_arg2; |
|
|
|
|
ar71xx_prom_find_env(envp, "board"); |
|
|
|
|
ar71xx_prom_find_env(envp, "ethaddr"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void __init prom_free_prom_memory(void) |
|
|
|
|