copy_size = header->len; if (copy_size > res_size) {
pr_err("The nvram size according to the header seems to be bigger than the partition on flash\n");
copy_size = res_size;
} if (copy_size >= NVRAM_SPACE) {
pr_err("nvram on flash (%zu bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
copy_size, NVRAM_SPACE - 1);
copy_size = NVRAM_SPACE - 1;
}
/** * bcm47xx_nvram_find_and_copy - find NVRAM on flash mapping & copy it
*/ staticint bcm47xx_nvram_find_and_copy(void __iomem *flash_start, size_t res_size)
{
size_t flash_size;
size_t offset; int i;
if (nvram_len) {
pr_warn("nvram already initialized\n"); return -EEXIST;
}
/* TODO: when nvram is on nand flash check for bad blocks first. */
/* Try every possible flash size and check for NVRAM at its end */ for (flash_size = FLASH_MIN; flash_size <= res_size; flash_size <<= 1) { for (i = 0; i < ARRAY_SIZE(nvram_sizes); i++) {
offset = flash_size - nvram_sizes[i]; if (bcm47xx_nvram_is_valid(flash_start + offset)) goto found;
}
}
/* Try embedded NVRAM at 4 KB and 1 KB as last resorts */
offset = 4096; if (bcm47xx_nvram_is_valid(flash_start + offset)) goto found;
offset = 1024; if (bcm47xx_nvram_is_valid(flash_start + offset)) goto found;
/* * On bcm47xx we need access to the NVRAM very early, so we can't use mtd * subsystem to access flash. We can't even use platform device / driver to * store memory offset. * To handle this we provide following symbol. It's supposed to be called as * soon as we get info about flash device, before any NVRAM entry is needed.
*/ int bcm47xx_nvram_init_from_mem(u32 base, u32 lim)
{ void __iomem *iobase; int err;
iobase = ioremap(base, lim); if (!iobase) return -ENOMEM;
mtd = get_mtd_device_nm("nvram"); if (IS_ERR(mtd)) return -ENODEV;
err = mtd_read(mtd, 0, sizeof(header), &bytes_read, (uint8_t *)&header); if (!err && header.magic == NVRAM_MAGIC &&
header.len > sizeof(header)) {
nvram_len = header.len; if (nvram_len >= NVRAM_SPACE) {
pr_err("nvram on flash (%zu bytes) is bigger than the reserved space in memory, will just copy the first %i bytes\n",
nvram_len, NVRAM_SPACE);
nvram_len = NVRAM_SPACE - 1;
}
int bcm47xx_nvram_getenv(constchar *name, char *val, size_t val_len)
{ char *var, *value, *end, *eq; int err;
if (!name) return -EINVAL;
if (!nvram_len) {
err = nvram_init(); if (err) return err;
}
/* Look for name=value and return value */
var = &nvram_buf[sizeof(struct nvram_header)];
end = nvram_buf + sizeof(nvram_buf); while (var < end && *var) {
eq = strchr(var, '='); if (!eq) break;
value = eq + 1; if (eq - var == strlen(name) &&
strncmp(var, name, eq - var) == 0) return snprintf(val, val_len, "%s", value);
var = value + strlen(value) + 1;
} return -ENOENT;
}
EXPORT_SYMBOL(bcm47xx_nvram_getenv);
int bcm47xx_nvram_gpio_pin(constchar *name)
{ int i, err; char nvram_var[] = "gpioXX"; char buf[NVRAM_MAX_GPIO_VALUE_LEN];
/* TODO: Optimize it to don't call getenv so many times */ for (i = 0; i < NVRAM_MAX_GPIO_ENTRIES; i++) {
err = snprintf(nvram_var, sizeof(nvram_var), "gpio%i", i); if (err <= 0) continue;
err = bcm47xx_nvram_getenv(nvram_var, buf, sizeof(buf)); if (err <= 0) continue; if (!strcmp(name, buf)) return i;
} return -ENOENT;
}
EXPORT_SYMBOL(bcm47xx_nvram_gpio_pin);
char *bcm47xx_nvram_get_contents(size_t *nvram_size)
{ int err; char *nvram;
if (!nvram_len) {
err = nvram_init(); if (err) return NULL;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.