diff options
Diffstat (limited to 'package/kernel')
-rw-r--r-- | package/kernel/broadcom-wl/patches/120-fixup-mac-addresses.patch | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/package/kernel/broadcom-wl/patches/120-fixup-mac-addresses.patch b/package/kernel/broadcom-wl/patches/120-fixup-mac-addresses.patch new file mode 100644 index 0000000..f3d7c24 --- /dev/null +++ b/package/kernel/broadcom-wl/patches/120-fixup-mac-addresses.patch @@ -0,0 +1,92 @@ +--- a/driver/nvram_stub.c ++++ b/driver/nvram_stub.c +@@ -5,6 +5,7 @@ + #include <siutils.h> + #include <bcmendian.h> + #include <bcmnvram.h> ++#include <proto/ethernet.h> + + #ifdef BCMDBG_ERR + #define NVR_MSG(x) printf x +@@ -24,6 +25,7 @@ typedef struct _vars { + static vars_t *vars = NULL; + static int nvram_init_done = 0; + extern char *nvram_buf[]; ++static void fixup_mac_addr(vars_t *new); + + int + BCMATTACHFN(nvram_init)(void *si) +@@ -55,6 +57,7 @@ BCMATTACHFN(nvram_init)(void *si) + vars = new; + + bcopy((char *)(&nvh[1]), new->vars, nvs); ++ fixup_mac_addr(new); + return 0; + } + +@@ -164,3 +167,65 @@ nvram_getall(char *buf, int count) + *buf = '\0'; + return 0; + } ++ ++static bool nvram_is_valid_mac(struct ether_addr *mac) ++{ ++ return mac && !(mac->octet[0] == 0x00 && mac->octet[1] == 0x90 && mac->octet[2] == 0x4c); ++} ++ ++static int nvram_increase_mac_addr(struct ether_addr *mac, u8 num) ++{ ++ u8 *oui = mac->octet + ETHER_ADDR_LEN/2 - 1; ++ u8 *p = mac->octet + ETHER_ADDR_LEN - 1; ++ ++ do { ++ (*p) += num; ++ if (*p > num) ++ break; ++ p--; ++ num = 1; ++ } while (p != oui); ++ ++ if (p == oui) { ++ pr_err("unable to fetch mac address\n"); ++ return -ENOENT; ++ } ++ return 0; ++} ++ ++static void nvram_change_mac_addr(vars_t *new, struct ether_addr *valid, const char *name) ++{ ++ char *macaddr_c; ++ struct ether_addr macaddr; ++ ++ macaddr_c = findvar(new->vars, new->vars + new->size, name); ++ if (!macaddr_c) ++ return; ++ ++ bcm_ether_atoe(macaddr_c, &macaddr); ++ if (nvram_is_valid_mac(&macaddr)) ++ return; ++ nvram_increase_mac_addr(valid, 1); ++ bcm_ether_ntoa(valid, macaddr_c); ++} ++ ++static void fixup_mac_addr(vars_t *new) ++{ ++ char *macaddr_base_c; ++ struct ether_addr macaddr_base; ++ ++ macaddr_base_c = findvar(new->vars, new->vars + new->size, "et0macaddr"); ++ if (!macaddr_base_c) ++ return; ++ ++ bcm_ether_atoe(macaddr_base_c, &macaddr_base); ++ if (!nvram_is_valid_mac(&macaddr_base)) ++ return; ++ ++ /* jump over the first free address so it can be used for wan */ ++ nvram_increase_mac_addr(&macaddr_base, 1); ++ nvram_change_mac_addr(new, &macaddr_base, "pci/1/1/macaddr"); ++ nvram_change_mac_addr(new, &macaddr_base, "pci/1/2/macaddr"); ++ nvram_change_mac_addr(new, &macaddr_base, "pci/2/1/macaddr"); ++ nvram_change_mac_addr(new, &macaddr_base, "sb/1/macaddr"); ++} |