diff options
| author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-10-18 19:52:59 +0000 | 
|---|---|---|
| committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2008-10-18 19:52:59 +0000 | 
| commit | 998577a6b4807ba57043d029940923b727d282ea (patch) | |
| tree | 08582461fc7de21bc3849317161767906ab9c133 | |
| parent | ace7dddc4c86fd3896d3db793531b239725b6824 (diff) | |
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)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@13006 3c298f89-4303-0410-b956-a3cf2f4a3e73
| -rw-r--r-- | target/linux/atheros/files/arch/mips/atheros/board.c | 94 | 
1 files changed, 77 insertions, 17 deletions
| diff --git a/target/linux/atheros/files/arch/mips/atheros/board.c b/target/linux/atheros/files/arch/mips/atheros/board.c index ba427883a..4fa0e78bd 100644 --- a/target/linux/atheros/files/arch/mips/atheros/board.c +++ b/target/linux/atheros/files/arch/mips/atheros/board.c @@ -22,16 +22,54 @@  #include <linux/kernel.h>  #include <linux/serial.h>  #include <linux/serial_core.h> +#include <linux/random.h>  #include <asm/bootinfo.h>  #include <asm/irq_cpu.h>  #include <asm/io.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); -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;  	int found = 0; @@ -40,17 +78,14 @@ static u8 *find_board_config(char *flash_limit)  		addr >= (char *) (flash_limit - 0x30000);  		addr -= 0x1000) { -		if ( *(int *)addr == 0x35333131) { -			/* config magic found */ +		if (check_board_data(flash_limit, addr, broken)) {  			found = 1;  			break;  		}  	} -	if (!found) { -		printk("WARNING: No board configuration data found!\n"); +	if (!found)  		addr = NULL; -	}  	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)  {  	int dataFound; -	u32 radio_config; +	char *radio_config;  	/*  	 * 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.  	 */  	dataFound = 0; -	for (radio_config = (u32) board_config + 0x1000; -	     (radio_config < (u32) flash_limit); +	for (radio_config = board_config + 0x1000; +	     (radio_config < flash_limit);  	     radio_config += 0x1000) { -		if (*(int *)radio_config != 0xffffffff) { +		if ((*(u32 *)radio_config != 0xffffffff) && +		    check_radio_magic(radio_config)) {  			dataFound = 1;  			break;  		} @@ -77,10 +113,11 @@ static u8 *find_radio_config(char *flash_limit, char *board_config)  #ifdef CONFIG_ATHEROS_AR5315  	if (!dataFound) { /* AR2316 relocates radio config to new location */ -	    for (radio_config = (u32) board_config + 0xf8; -	     	(radio_config < (u32) flash_limit - 0x1000 + 0xf8); +	    for (radio_config = board_config + 0xf8; +	     	(radio_config < flash_limit - 0x1000 + 0xf8);  			 radio_config += 0x1000) { -			if (*(int *)radio_config != 0xffffffff) { +			if ((*(u32 *)radio_config != 0xffffffff) && +				check_radio_magic(radio_config)) {  				dataFound = 1;  				break;  			} @@ -98,6 +135,7 @@ static u8 *find_radio_config(char *flash_limit, char *board_config)  int __init ar531x_find_config(char *flash_limit)  { +	struct ar531x_boarddata *bd;  	unsigned int rcfg_size;  	char *bcfg, *rcfg; @@ -105,23 +143,45 @@ int __init ar531x_find_config(char *flash_limit)  	 * spiflash driver, accessing the mapped memory directly is no  	 * longer safe */ -	bcfg = find_board_config(flash_limit); +	bcfg = find_board_config(flash_limit, false);  	if (!bcfg) +		bcfg = find_board_config(flash_limit, true); +	if (!bcfg) { +		printk("WARNING: No board configuration data found!\n");  		return -ENODEV; +	}  	board_config = kzalloc(BOARD_CONFIG_BUFSZ, GFP_KERNEL);  	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  	 * 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)  		return -ENODEV;  	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); -	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);  	return 0; | 
