0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) "bcm63xx_nvram: " fmt
0012
0013 #include <linux/bcm963xx_nvram.h>
0014 #include <linux/init.h>
0015 #include <linux/crc32.h>
0016 #include <linux/export.h>
0017 #include <linux/kernel.h>
0018 #include <linux/if_ether.h>
0019
0020 #include <bcm63xx_nvram.h>
0021
0022 #define BCM63XX_DEFAULT_PSI_SIZE 64
0023
0024 static struct bcm963xx_nvram nvram;
0025 static int mac_addr_used;
0026
0027 void __init bcm63xx_nvram_init(void *addr)
0028 {
0029 u32 crc, expected_crc;
0030 u8 hcs_mac_addr[ETH_ALEN] = { 0x00, 0x10, 0x18, 0xff, 0xff, 0xff };
0031
0032
0033 memcpy(&nvram, addr, BCM963XX_NVRAM_V5_SIZE);
0034
0035
0036 if (bcm963xx_nvram_checksum(&nvram, &expected_crc, &crc))
0037 pr_warn("nvram checksum failed, contents may be invalid (expected %08x, got %08x)\n",
0038 expected_crc, crc);
0039
0040
0041
0042
0043
0044 if (BCMCPU_IS_3368()) {
0045 memcpy(nvram.mac_addr_base, hcs_mac_addr, ETH_ALEN);
0046 nvram.mac_addr_count = 2;
0047 }
0048 }
0049
0050 u8 *bcm63xx_nvram_get_name(void)
0051 {
0052 return nvram.name;
0053 }
0054 EXPORT_SYMBOL(bcm63xx_nvram_get_name);
0055
0056 int bcm63xx_nvram_get_mac_address(u8 *mac)
0057 {
0058 u8 *oui;
0059 int count;
0060
0061 if (mac_addr_used >= nvram.mac_addr_count) {
0062 pr_err("not enough mac addresses\n");
0063 return -ENODEV;
0064 }
0065
0066 memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
0067 oui = mac + ETH_ALEN/2 - 1;
0068 count = mac_addr_used;
0069
0070 while (count--) {
0071 u8 *p = mac + ETH_ALEN - 1;
0072
0073 do {
0074 (*p)++;
0075 if (*p != 0)
0076 break;
0077 p--;
0078 } while (p != oui);
0079
0080 if (p == oui) {
0081 pr_err("unable to fetch mac address\n");
0082 return -ENODEV;
0083 }
0084 }
0085
0086 mac_addr_used++;
0087 return 0;
0088 }
0089 EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
0090
0091 int bcm63xx_nvram_get_psi_size(void)
0092 {
0093 if (nvram.psi_size > 0)
0094 return nvram.psi_size;
0095
0096 return BCM63XX_DEFAULT_PSI_SIZE;
0097 }
0098 EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size);