| 1 |
|
| 2 | #ifndef __LINUX_BCM963XX_NVRAM_H__
|
| 3 | #define __LINUX_BCM963XX_NVRAM_H__
|
| 4 |
|
| 5 | #include <linux/crc32.h>
|
| 6 | #include <linux/if_ether.h>
|
| 7 | #include <linux/sizes.h>
|
| 8 | #include <linux/types.h>
|
| 9 |
|
| 10 | |
| 11 | * Broadcom BCM963xx SoC board nvram data structure.
|
| 12 | *
|
| 13 | * The nvram structure varies in size depending on the SoC board version. Use
|
| 14 | * the appropriate minimum BCM963XX_NVRAM_*_SIZE define for the information
|
| 15 | * you need instead of sizeof(struct bcm963xx_nvram) as this may change.
|
| 16 |
|
| 17 |
|
| 18 | #define BCM963XX_NVRAM_V4_SIZE 300
|
| 19 | #define BCM963XX_NVRAM_V5_SIZE (1 * SZ_1K)
|
| 20 |
|
| 21 | #define BCM963XX_DEFAULT_PSI_SIZE 64
|
| 22 |
|
| 23 | enum bcm963xx_nvram_nand_part {
|
| 24 | BCM963XX_NVRAM_NAND_PART_BOOT = 0,
|
| 25 | BCM963XX_NVRAM_NAND_PART_ROOTFS_1,
|
| 26 | BCM963XX_NVRAM_NAND_PART_ROOTFS_2,
|
| 27 | BCM963XX_NVRAM_NAND_PART_DATA,
|
| 28 | BCM963XX_NVRAM_NAND_PART_BBT,
|
| 29 |
|
| 30 | __BCM963XX_NVRAM_NAND_NR_PARTS
|
| 31 | };
|
| 32 |
|
| 33 | struct bcm963xx_nvram {
|
| 34 | u32 version;
|
| 35 | char bootline[256];
|
| 36 | char name[16];
|
| 37 | u32 main_tp_number;
|
| 38 | u32 psi_size;
|
| 39 | u32 mac_addr_count;
|
| 40 | u8 mac_addr_base[ETH_ALEN];
|
| 41 | u8 __reserved1[2];
|
| 42 | u32 checksum_v4;
|
| 43 |
|
| 44 | u8 __reserved2[292];
|
| 45 | u32 nand_part_offset[__BCM963XX_NVRAM_NAND_NR_PARTS];
|
| 46 | u32 nand_part_size[__BCM963XX_NVRAM_NAND_NR_PARTS];
|
| 47 | u8 __reserved3[388];
|
| 48 | u32 checksum_v5;
|
| 49 | };
|
| 50 |
|
| 51 | #define BCM963XX_NVRAM_NAND_PART_OFFSET(nvram, part) \
|
| 52 | bcm963xx_nvram_nand_part_offset(nvram, BCM963XX_NVRAM_NAND_PART_ ##part)
|
| 53 |
|
| 54 | static inline u64 __pure bcm963xx_nvram_nand_part_offset(
|
| 55 | const struct bcm963xx_nvram *nvram,
|
| 56 | enum bcm963xx_nvram_nand_part part)
|
| 57 | {
|
| 58 | return nvram->nand_part_offset[part] * SZ_1K;
|
| 59 | }
|
| 60 |
|
| 61 | #define BCM963XX_NVRAM_NAND_PART_SIZE(nvram, part) \
|
| 62 | bcm963xx_nvram_nand_part_size(nvram, BCM963XX_NVRAM_NAND_PART_ ##part)
|
| 63 |
|
| 64 | static inline u64 __pure bcm963xx_nvram_nand_part_size(
|
| 65 | const struct bcm963xx_nvram *nvram,
|
| 66 | enum bcm963xx_nvram_nand_part part)
|
| 67 | {
|
| 68 | return nvram->nand_part_size[part] * SZ_1K;
|
| 69 | }
|
| 70 |
|
| 71 | |
| 72 | * bcm963xx_nvram_checksum - Verify nvram checksum
|
| 73 | *
|
| 74 | * @nvram: pointer to full size nvram data structure
|
| 75 | * @expected_out: optional pointer to store expected checksum value
|
| 76 | * @actual_out: optional pointer to store actual checksum value
|
| 77 | *
|
| 78 | * Return: 0 if the checksum is valid, otherwise -EINVAL
|
| 79 |
|
| 80 | static int __maybe_unused bcm963xx_nvram_checksum(
|
| 81 | const struct bcm963xx_nvram *nvram,
|
| 82 | u32 *expected_out, u32 *actual_out)
|
| 83 | {
|
| 84 | const u32 zero = 0;
|
| 85 | u32 expected, actual;
|
| 86 | size_t len;
|
| 87 |
|
| 88 | if (nvram->version <= 4) {
|
| 89 | expected = nvram->checksum_v4;
|
| 90 | len = BCM963XX_NVRAM_V4_SIZE;
|
| 91 | } else {
|
| 92 | expected = nvram->checksum_v5;
|
| 93 | len = BCM963XX_NVRAM_V5_SIZE;
|
| 94 | }
|
| 95 |
|
| 96 |
|
| 97 | actual = crc32_le(~0, nvram, len - sizeof(u32));
|
| 98 | actual = crc32_le(actual, &zero, sizeof(u32));
|
| 99 |
|
| 100 | if (expected_out)
|
| 101 | *expected_out = expected;
|
| 102 |
|
| 103 | if (actual_out)
|
| 104 | *actual_out = actual;
|
| 105 |
|
| 106 | return expected == actual ? 0 : -EINVAL;
|
| 107 | };
|
| 108 |
|
| 109 | #endif
|