Commit 55cab93b authored by Hante Meuleman's avatar Hante Meuleman Committed by Ralf Baechle

mips: bcm47xx: allow retrieval of complete nvram contents

Host platforms such as routers supported by OpenWrt can
support NVRAM reading directly from internal NVRAM store.
The brcmfmac for one requires the complete nvram contents
to select what needs to be sent to wireless device.
Signed-off-by: default avatarArend van Spriel <arend@broadcom.com>
Signed-off-by: default avatarHante Meuleman <meuleman@broadcom.com>
Reviewed-by: default avatarArend Van Spriel <arend@broadcom.com>
Reviewed-by: default avatarFranky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: default avatarPieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: default avatarDaniel (Deognyoun) Kim <dekim@broadcom.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/10093/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 30ad29bb
...@@ -94,17 +94,22 @@ static int nvram_find_and_copy(void __iomem *iobase, u32 lim) ...@@ -94,17 +94,22 @@ static int nvram_find_and_copy(void __iomem *iobase, u32 lim)
return -ENXIO; return -ENXIO;
found: found:
if (header->len > size)
pr_err("The nvram size accoridng to the header seems to be bigger than the partition on flash\n");
if (header->len > NVRAM_SPACE)
pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
header->len, NVRAM_SPACE - 1);
src = (u32 *)header; src = (u32 *)header;
dst = (u32 *)nvram_buf; dst = (u32 *)nvram_buf;
for (i = 0; i < sizeof(struct nvram_header); i += 4) for (i = 0; i < sizeof(struct nvram_header); i += 4)
*dst++ = __raw_readl(src++); *dst++ = __raw_readl(src++);
for (; i < header->len && i < NVRAM_SPACE && i < size; i += 4) header = (struct nvram_header *)nvram_buf;
if (header->len > size) {
pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n");
header->len = size;
}
if (header->len >= NVRAM_SPACE) {
pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
header->len, NVRAM_SPACE - 1);
header->len = NVRAM_SPACE - 1;
}
/* proceed reading data after header */
for (; i < header->len; i += 4)
*dst++ = readl(src++); *dst++ = readl(src++);
nvram_buf[NVRAM_SPACE - 1] = '\0'; nvram_buf[NVRAM_SPACE - 1] = '\0';
...@@ -139,6 +144,7 @@ static int nvram_init(void) ...@@ -139,6 +144,7 @@ static int nvram_init(void)
#ifdef CONFIG_MTD #ifdef CONFIG_MTD
struct mtd_info *mtd; struct mtd_info *mtd;
struct nvram_header header; struct nvram_header header;
struct nvram_header *pheader;
size_t bytes_read; size_t bytes_read;
int err; int err;
...@@ -147,20 +153,21 @@ static int nvram_init(void) ...@@ -147,20 +153,21 @@ static int nvram_init(void)
return -ENODEV; return -ENODEV;
err = mtd_read(mtd, 0, sizeof(header), &bytes_read, (uint8_t *)&header); err = mtd_read(mtd, 0, sizeof(header), &bytes_read, (uint8_t *)&header);
if (!err && header.magic == NVRAM_MAGIC) { if (!err && header.magic == NVRAM_MAGIC &&
u8 *dst = (uint8_t *)nvram_buf; header.len > sizeof(header)) {
size_t len = header.len; if (header.len >= NVRAM_SPACE) {
if (len >= NVRAM_SPACE) {
len = NVRAM_SPACE - 1;
pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n", pr_err("nvram on flash (%i bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
header.len, len); header.len, NVRAM_SPACE);
header.len = NVRAM_SPACE - 1;
} }
err = mtd_read(mtd, 0, len, &bytes_read, dst); err = mtd_read(mtd, 0, header.len, &bytes_read,
(u8 *)nvram_buf);
if (err) if (err)
return err; return err;
pheader = (struct nvram_header *)nvram_buf;
pheader->len = header.len;
return 0; return 0;
} }
#endif #endif
...@@ -219,3 +226,26 @@ int bcm47xx_nvram_gpio_pin(const char *name) ...@@ -219,3 +226,26 @@ int bcm47xx_nvram_gpio_pin(const char *name)
return -ENOENT; return -ENOENT;
} }
EXPORT_SYMBOL(bcm47xx_nvram_gpio_pin); EXPORT_SYMBOL(bcm47xx_nvram_gpio_pin);
char *bcm47xx_nvram_get_contents(size_t *nvram_size)
{
int err;
char *nvram;
struct nvram_header *header;
if (!nvram_buf[0]) {
err = nvram_init();
if (err)
return NULL;
}
header = (struct nvram_header *)nvram_buf;
*nvram_size = header->len - sizeof(struct nvram_header);
nvram = vmalloc(*nvram_size);
if (!nvram)
return NULL;
memcpy(nvram, &nvram_buf[sizeof(struct nvram_header)], *nvram_size);
return nvram;
}
EXPORT_SYMBOL(bcm47xx_nvram_get_contents);
...@@ -10,11 +10,17 @@ ...@@ -10,11 +10,17 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/vmalloc.h>
#ifdef CONFIG_BCM47XX #ifdef CONFIG_BCM47XX
int bcm47xx_nvram_init_from_mem(u32 base, u32 lim); int bcm47xx_nvram_init_from_mem(u32 base, u32 lim);
int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len); int bcm47xx_nvram_getenv(const char *name, char *val, size_t val_len);
int bcm47xx_nvram_gpio_pin(const char *name); int bcm47xx_nvram_gpio_pin(const char *name);
char *bcm47xx_nvram_get_contents(size_t *val_len);
static inline void bcm47xx_nvram_release_contents(char *nvram)
{
vfree(nvram);
};
#else #else
static inline int bcm47xx_nvram_init_from_mem(u32 base, u32 lim) static inline int bcm47xx_nvram_init_from_mem(u32 base, u32 lim)
{ {
...@@ -29,6 +35,15 @@ static inline int bcm47xx_nvram_gpio_pin(const char *name) ...@@ -29,6 +35,15 @@ static inline int bcm47xx_nvram_gpio_pin(const char *name)
{ {
return -ENOTSUPP; return -ENOTSUPP;
}; };
static inline char *bcm47xx_nvram_get_contents(size_t *val_len)
{
return NULL;
};
static inline void bcm47xx_nvram_release_contents(char *nvram)
{
};
#endif #endif
#endif /* __BCM47XX_NVRAM_H */ #endif /* __BCM47XX_NVRAM_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment