atheros: clean up the board data detection code and attempt to boot the kernel even when the board data was not found (radio data still needs to be present)

SVN-Revision: 13006
master
Felix Fietkau 17 years ago
parent 87e0a3cf0f
commit 81b05ae1a2
  1. 94
      target/linux/atheros/files/arch/mips/atheros/board.c

@ -22,16 +22,54 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/random.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/irq_cpu.h> #include <asm/irq_cpu.h>
#include <asm/io.h> #include <asm/io.h>
#include <ar531x.h> #include <ar531x.h>
char *board_config, *radio_config; char *board_config = NULL;
char *radio_config = NULL;
int broken_boarddata = 0;
extern int early_serial_setup(struct uart_port *port); extern int early_serial_setup(struct uart_port *port);
static u8 *find_board_config(char *flash_limit) static inline bool
check_radio_magic(unsigned char *addr)
{
addr += 0x7a; /* offset for flash magic */
if ((addr[0] == 0x5a) && (addr[1] == 0xa5)) {
return 1;
}
return 0;
}
static inline bool
check_board_data(unsigned char *flash_limit, unsigned char *addr, bool broken)
{
/* config magic found */
if ( *(int *)addr == 0x35333132)
return 1;
if (!broken)
return 0;
if (check_radio_magic(addr + 0xf8))
radio_config = addr + 0xf8;
if ((addr < flash_limit + 0x10000) &&
check_radio_magic(addr + 0x10000))
radio_config = addr + 0x10000;
if (radio_config) {
/* broken board data detected, use radio data to find the offset,
* user will fix this */
broken_boarddata = 1;
return 1;
}
return 0;
}
static u8 *find_board_config(char *flash_limit, bool broken)
{ {
char *addr; char *addr;
int found = 0; int found = 0;
@ -40,17 +78,14 @@ static u8 *find_board_config(char *flash_limit)
addr >= (char *) (flash_limit - 0x30000); addr >= (char *) (flash_limit - 0x30000);
addr -= 0x1000) { addr -= 0x1000) {
if ( *(int *)addr == 0x35333131) { if (check_board_data(flash_limit, addr, broken)) {
/* config magic found */
found = 1; found = 1;
break; break;
} }
} }
if (!found) { if (!found)
printk("WARNING: No board configuration data found!\n");
addr = NULL; addr = NULL;
}
return addr; return addr;
} }
@ -58,7 +93,7 @@ static u8 *find_board_config(char *flash_limit)
static u8 *find_radio_config(char *flash_limit, char *board_config) static u8 *find_radio_config(char *flash_limit, char *board_config)
{ {
int dataFound; int dataFound;
u32 radio_config; char *radio_config;
/* /*
* Now find the start of Radio Configuration data, using heuristics: * Now find the start of Radio Configuration data, using heuristics:
@ -66,10 +101,11 @@ static u8 *find_radio_config(char *flash_limit, char *board_config)
* at a time until we find non-0xffffffff. * at a time until we find non-0xffffffff.
*/ */
dataFound = 0; dataFound = 0;
for (radio_config = (u32) board_config + 0x1000; for (radio_config = board_config + 0x1000;
(radio_config < (u32) flash_limit); (radio_config < flash_limit);
radio_config += 0x1000) { radio_config += 0x1000) {
if (*(int *)radio_config != 0xffffffff) { if ((*(u32 *)radio_config != 0xffffffff) &&
check_radio_magic(radio_config)) {
dataFound = 1; dataFound = 1;
break; break;
} }
@ -77,10 +113,11 @@ static u8 *find_radio_config(char *flash_limit, char *board_config)
#ifdef CONFIG_ATHEROS_AR5315 #ifdef CONFIG_ATHEROS_AR5315
if (!dataFound) { /* AR2316 relocates radio config to new location */ if (!dataFound) { /* AR2316 relocates radio config to new location */
for (radio_config = (u32) board_config + 0xf8; for (radio_config = board_config + 0xf8;
(radio_config < (u32) flash_limit - 0x1000 + 0xf8); (radio_config < flash_limit - 0x1000 + 0xf8);
radio_config += 0x1000) { radio_config += 0x1000) {
if (*(int *)radio_config != 0xffffffff) { if ((*(u32 *)radio_config != 0xffffffff) &&
check_radio_magic(radio_config)) {
dataFound = 1; dataFound = 1;
break; break;
} }
@ -98,6 +135,7 @@ static u8 *find_radio_config(char *flash_limit, char *board_config)
int __init ar531x_find_config(char *flash_limit) int __init ar531x_find_config(char *flash_limit)
{ {
struct ar531x_boarddata *bd;
unsigned int rcfg_size; unsigned int rcfg_size;
char *bcfg, *rcfg; char *bcfg, *rcfg;
@ -105,23 +143,45 @@ int __init ar531x_find_config(char *flash_limit)
* spiflash driver, accessing the mapped memory directly is no * spiflash driver, accessing the mapped memory directly is no
* longer safe */ * longer safe */
bcfg = find_board_config(flash_limit); bcfg = find_board_config(flash_limit, false);
if (!bcfg) if (!bcfg)
bcfg = find_board_config(flash_limit, true);
if (!bcfg) {
printk("WARNING: No board configuration data found!\n");
return -ENODEV; return -ENODEV;
}
board_config = kzalloc(BOARD_CONFIG_BUFSZ, GFP_KERNEL); board_config = kzalloc(BOARD_CONFIG_BUFSZ, GFP_KERNEL);
memcpy(board_config, bcfg, 0x100); memcpy(board_config, bcfg, 0x100);
if (broken_boarddata) {
printk("WARNING: broken board data detected\n");
bd = (struct ar531x_boarddata *)board_config;
if (!memcmp(bd->enet0Mac, "\x00\x00\x00\x00\x00\x00", 6)) {
printk("Fixing up empty mac addresses\n");
bd->enet0Mac[1] = 0x13;
bd->enet0Mac[2] = 0x37;
get_random_bytes(bd->enet0Mac + 3, 3);
bd->wlan0Mac[1] = 0x13;
bd->wlan0Mac[2] = 0x37;
get_random_bytes(bd->wlan0Mac + 3, 3);
}
}
/* Radio config starts 0x100 bytes after board config, regardless /* Radio config starts 0x100 bytes after board config, regardless
* of what the physical layout on the flash chip looks like */ * of what the physical layout on the flash chip looks like */
rcfg = find_radio_config(flash_limit, bcfg); if (radio_config)
rcfg = radio_config;
else
rcfg = find_radio_config(flash_limit, bcfg);
if (!rcfg) if (!rcfg)
return -ENODEV; return -ENODEV;
radio_config = board_config + 0x100 + ((rcfg - bcfg) & 0xfff); radio_config = board_config + 0x100 + ((rcfg - bcfg) & 0xfff);
printk("Radio config found at offset 0x%x(0x%x)\n", rcfg - bcfg, radio_config - board_config); printk("Radio config found at offset 0x%x(0x%x)\n", rcfg - bcfg, radio_config - board_config);
rcfg_size = BOARD_CONFIG_BUFSZ - ((0x100 + rcfg - bcfg) & (BOARD_CONFIG_BUFSZ - 1)); rcfg_size = BOARD_CONFIG_BUFSZ - (radio_config - board_config);
memcpy(radio_config, rcfg, rcfg_size); memcpy(radio_config, rcfg, rcfg_size);
return 0; return 0;

Loading…
Cancel
Save