blob: 757bcf832feacd8403b16485d19910f43d78b86b [file] [log] [blame]
/*
* Copyright (c) 2011 Quantenna Communications, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**/
#include "bootcfg_drv.h"
#include "bootcfg_store_init.h"
#include <common/ruby_partitions.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/string.h>
#include <linux/slab.h>
#define STORE_NAME_MTD "mtd"
#define STORE_NAME_EEPROM "eeprom"
static char *store = STORE_NAME_MTD;
module_param(store, charp, S_IRUGO);
MODULE_PARM_DESC(store, "Datastore name");
#define LOG_FAIL(_r) \
do { \
printk("%s failed at line %d, %s = %d\n", \
__FUNCTION__, __LINE__, #_r, (int)(_r)); \
} while(0)
#ifdef CONFIG_MTD
static __init int bootcfg_copy_mtd_to_eeprom(void)
{
struct bootcfg_store_ops *mtd;
struct bootcfg_store_ops *eeprom;
size_t mtd_size_lim = BOOT_CFG_SIZE;
size_t eeprom_size_lim = BOOT_CFG_SIZE;
uint8_t *buf = NULL;
int ret = -1;
buf = kmalloc(BOOT_CFG_SIZE, GFP_KERNEL);
if (buf == NULL) {
LOG_FAIL(buf);
goto out;
}
mtd = bootcfg_flash_get_ops();
if (mtd == NULL) {
LOG_FAIL(mtd);
goto out;
}
eeprom = bootcfg_compression_adapter(bootcfg_eeprom_get_ops());
if (eeprom == NULL) {
LOG_FAIL(eeprom);
goto out;
}
ret = mtd->init(mtd, &mtd_size_lim);
if (ret) {
LOG_FAIL(ret);
kfree(eeprom);
goto out;
}
ret = eeprom->init(eeprom, &eeprom_size_lim);
if (ret) {
LOG_FAIL(ret);
goto out_exit_mtd;
}
ret = mtd->read(mtd, buf, mtd_size_lim);
if (ret) {
LOG_FAIL(ret);
goto out_exit_both;
}
ret = eeprom->write(eeprom, buf, eeprom_size_lim);
if (ret) {
LOG_FAIL(ret);
goto out_exit_both;
}
out_exit_both:
eeprom->exit(eeprom);
out_exit_mtd:
mtd->exit(mtd);
out:
if (buf) {
kfree(buf);
}
return ret;
}
#endif
/*
* Provide different storage implementation depending on module parameter
*/
__init struct bootcfg_store_ops *bootcfg_get_datastore(void)
{
#ifdef CONFIG_MTD
if (strcmp(store, STORE_NAME_MTD) == 0) {
return bootcfg_flash_get_ops();
} else if (strcmp(store, STORE_NAME_EEPROM) == 0) {
return bootcfg_compression_adapter(bootcfg_eeprom_get_ops());
} else if (strcmp(store, "mtd_to_eeprom") == 0) {
bootcfg_copy_mtd_to_eeprom();
} else {
return bootcfg_file_get_ops(store);
}
return NULL;
#else
return bootcfg_file_get_ops(store);
#endif
}