Files

314 lines
8.1 KiB
C

#include <common.h>
#include <fastboot.h>
#include <fastboot-internal.h>
#include <fb_cus.h>
#include <nand.h>
#define TRACE 0
#define cus_trace(msg...) \
do { \
if (TRACE) \
printf("FastBoot Cus: "msg); \
} while (0)
#ifdef CONFIG_MS_SPINAND
static int cmd_nand_erase(const char *partname);
static int cmd_nand_write(const char *partname, void *download_buffer, unsigned int file_size);
static int cmd_nand_probe_info(const char *partname, struct part_info *part_info);
static int cmd_ubi_erase(const char *partname);
static int cmd_ubi_write(const char *partname, void *download_buffer, unsigned int file_size);
static int cmd_ubi_probe_info(const char *partname, struct part_info *part_info);
#elif defined (CONFIG_MS_PARTITION)
static int cmd_sf_erase(const char *partname);
static int cmd_sf_write(const char *partname, void *download_buffer ,unsigned int file_size);
static int cmd_sf_probe_info(const char *partname, struct part_info *part_info);
#endif
#define PRE_PART_OPS(name, type)\
{name, cmd_##type##_erase, cmd_##type##_write, cmd_##type##_probe_info}
const part_ops_t part_ops_infos[] =
#ifdef CONFIG_MS_SPINAND
{PRE_PART_OPS("IPL0", nand), PRE_PART_OPS("IPL1", nand),
PRE_PART_OPS("IPL_CUST0", nand), PRE_PART_OPS("IPL_CUST1", nand),
PRE_PART_OPS("UBOOT0", nand), PRE_PART_OPS("UBOOT1", nand),
PRE_PART_OPS("KERNEL", nand), PRE_PART_OPS("RECOVERY", nand),
PRE_PART_OPS("rootfs", ubi),//UBI
PRE_PART_OPS("nvrservice", ubi),
PRE_PART_OPS("customer", ubi),
};
#elif defined (CONFIG_MS_PARTITION)
{PRE_PART_OPS("IPL", sf),
PRE_PART_OPS("IPL_CUST", sf),
PRE_PART_OPS("KEY_CUST", sf),
PRE_PART_OPS("MXPT", sf),
PRE_PART_OPS("UBOOT", sf),
PRE_PART_OPS("UBOOT_ENV", sf),
PRE_PART_OPS("BOOT", sf),
PRE_PART_OPS("KERNEL", sf),
PRE_PART_OPS("rootfs", sf),
PRE_PART_OPS("nvrservice", sf),
PRE_PART_OPS("customer", sf)
};
#endif
#ifdef CONFIG_MS_SPINAND
static inline int cmd_nand_erase(const char *partname)
{
char cmd_erase_partition[100] = "\0";
sprintf(cmd_erase_partition, "nand erase.part %s", partname);
cus_trace("[%s] command (%s)\n", __func__, cmd_erase_partition);
return run_command(cmd_erase_partition, 0);
}
static inline int cmd_nand_write(const char *partname, void *download_buffer, unsigned int file_size)
{
char cmd_write_partition[100] = "\0";
sprintf(cmd_write_partition, "nand write 0x%p %s 0x%x", download_buffer, partname, file_size);
cus_trace("[%s] command (%s)\n", __func__, cmd_write_partition);
return run_command(cmd_write_partition, 0);
}
static int set_dev(int dev)
{
if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
!nand_info[dev].name) {
puts("No such device\n");
return -1;
}
if (nand_curr_device == dev)
return 0;
printf("Device %d: %s", dev, nand_info[dev].name);
puts("... is now current device\n");
nand_curr_device = dev;
#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
board_nand_select_device(nand_info[dev].priv, dev);
#endif
return 0;
}
static int get_nand_part_info(const char *partname, struct part_info *part_info)
{
#ifdef CONFIG_CMD_MTDPARTS
struct mtd_device *dev;
struct part_info *part;
u8 pnum;
int ret;
ret = mtdparts_init();
if (ret)
return ret;
ret = find_dev_and_part(partname, &dev, &pnum, &part);
if (ret)
return ret;
if (dev->id->type != MTD_DEV_TYPE_NAND) {
puts("not a NAND device\n");
return -1;
}
#if 0
*off = part->offset;
*size = part->size;
*maxsize = part->size;
*idx = dev->id->num;
#else
part_info->size = part->size;
cus_trace("%s part %s size %llx\n ", __func__, partname, part_info->size);
#endif
ret = set_dev(dev->id->num);
if (ret)
return ret;
return 0;
#else
puts("offset is not a number\n");
return -1;
#endif
}
static inline int cmd_nand_probe_info(const char *partname, struct part_info *part_info)
{
return get_nand_part_info(partname, part_info);//only get total size of ubi part
}
static inline int cmd_ubi_erase(const char *partname)
{
return 0;//do nothing
}
static inline int cmd_ubi_write(const char *partname, void *download_buffer, unsigned int file_size)
{
char cmd_write_partition[100] = "\0";
sprintf(cmd_write_partition, "ubi write 0x%p %s 0x%x", download_buffer, partname, file_size);
cus_trace("[%s] command (%s)\n", __func__, cmd_write_partition);
return run_command(cmd_write_partition, 0);
}
static inline int cmd_ubi_probe_info(const char *partname, struct part_info *part_info)
{
if (get_nand_part_info("UBI", part_info))
return -1;
return run_command("ubi part UBI", 0);
}
#elif defined (CONFIG_MS_PARTITION)
static inline int cmd_sf_erase(const char *partname)
{
return run_command("sf probe 0;sf erase ${sf_part_start} ${sf_part_size}", 0);
}
static inline int cmd_sf_write(const char *partname, void *download_buffer, unsigned int file_size)
{
char cmd_write_partition[100] = "\0";
sprintf(cmd_write_partition, "sf write 0x%p ${sf_part_start} 0x%x", download_buffer, file_size);
cus_trace("[%s] command (%s)\n", __func__, cmd_write_partition);
return run_command(cmd_write_partition, 0);
}
static inline int cmd_sf_probe_info(const char *partname, struct part_info *part_info)
{
int ret;
char cmd_get_partinfo[100] = "\0";
sprintf(cmd_get_partinfo, "mxp r.info %s", partname);
cus_trace("[%s], command (%s)\n", __func__, cmd_get_partinfo);
ret = run_command(cmd_get_partinfo, 0);
if (ret!=CMD_RET_SUCCESS)
return -1;
part_info->size = getenv_hex("sf_part_size", 0);
if (part_info->size <= 0)
return -1;
return 0;
}
#endif
int get_patirion_index(const char *partname)
{
int i;
for(i = 0;i < sizeof(part_ops_infos)/sizeof(part_ops_infos[0]); i++)
{
if (!strcmp(part_ops_infos[i].partname, partname))
return i;
}
return -1;
}
void fastboot_cus_flash_write(const char *partname, void *download_buffer,
unsigned int download_bytes, char *response)
{
int ret, index;
struct part_info part_info = {};
index = get_patirion_index(partname);
if (index < 0)
{
fastboot_fail("no such partition", response);
return;
}
ret = part_ops_infos[index].probe_info(partname, &part_info);
if (ret < 0)
{
fastboot_fail("no such partition", response);
return;
}
if (part_info.size < download_bytes)
{
fastboot_fail("file size is to large", response);
return;
}
ret = part_ops_infos[index].erase(partname);
if (ret!=CMD_RET_SUCCESS)
{
fastboot_fail("no such partition", response);
return;
}
ret = part_ops_infos[index].write(partname, download_buffer, download_bytes);
if (ret!=CMD_RET_SUCCESS)
{
fastboot_fail("no such partition", response);
return;
}
fastboot_okay(NULL, response);
}
void fastboot_cus_erase(const char *partname, char *response)
{
int ret, index;
struct part_info part_info = {};
index = get_patirion_index(partname);
if (index < 0)
{
fastboot_fail("no such partition", response);
return;
}
ret = part_ops_infos[index].probe_info(partname, &part_info);
if (ret < 0)
{
fastboot_fail("no such partition", response);
return;
}
ret = part_ops_infos[index].erase(partname);
if (ret!=CMD_RET_SUCCESS)
{
fastboot_fail("no such partition", response);
return;
}
fastboot_okay(NULL, response);
}
int fastboot_cus_get_part_info(const char *partname,
struct part_info *part_info, char *response)
{
int ret, index;
char *sub;
cus_trace("[%s] partname: (%s)\n", __func__, partname);
//find the string "_a" or "_b"
if(((sub = strpbrk(partname, "_")) && (strpbrk(sub + 1, "a"))) ||
((sub = strpbrk(partname, "_")) && (strpbrk(sub + 1, "b"))))
{
// no support slot
return -1;
}
index = get_patirion_index(partname);
if (index < 0)
{
fastboot_fail("no such partition", response);
return -1;
}
ret = part_ops_infos[index].probe_info(partname, part_info);
if (ret < 0)
{
fastboot_fail("no such partition", response);
return -1;
}
fastboot_okay(NULL, response);
return 0;
}