blob: e022094744205110317687e31879baa75e0b631e [file] [log] [blame] [edit]
/*
* Copyright (C) 2017 Amlogic, 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.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* *
Description:
*/
#include <command.h>
#include <watchdog.h>
#include <malloc.h>
#include <common.h>
#include <linux/ctype.h>
#include <asm/byteorder.h>
#include <div64.h>
#include <linux/err.h>
#include <partition_table.h>
#include <mmc.h>
#define DbgP(fmt...) //printf("[burnupDbg]"fmt)
#define MsgP(fmt...) printf("[burnup]"fmt)
#define ErrP(fmt...) printf("[burnup]Err:%s,L%d:", __func__, __LINE__),printf(fmt)
static unsigned char *cmd_name = (unsigned char *)("store");
const char* _usbDownPartImgType = "";
#define MtdAlignBits (12) //32k
#define MtdAlignSz (1U << MtdAlignBits)
#define MtdAlignMask (MtdAlignSz - 1)
/***
upgrade_read_ops:
partition_name: env / logo / recovery /boot / system /cache /media
***/
int store_read_ops(unsigned char *partition_name,unsigned char * buf, uint64_t off, uint64_t size)
{
unsigned char *name;
uint64_t addr;
char str[128];
int ret =0;
if (!buf) {
ErrP("upgrade: no buf!!");
return -1;
}
name = partition_name;
addr = (unsigned long)buf;
if ((EMMC_BOOT_FLAG == device_boot_flag) && !strcmp("1", (char*)name))
{
if (off & 0x1ff) {
ErrP("emmc1 invalid offset 0x%llx\n", off);
return -__LINE__;
}
if (size & 0xff) {
MsgP("NOT align sz 0x%llx\n", size);
}
sprintf(str, "mmc read 0x%p 0x%llx 0x%llx", buf, (off>>9), (size>>9));
ret = run_command(str, 0);
if (ret) {
ErrP("Fail in cmd[%s]\n", str);
return -__LINE__;
}
return ret;
}
#if CONFIG_AML_MTD
if ((size & MtdAlignMask) && (NAND_BOOT_FLAG == device_boot_flag )) {
MsgP("Rd:Up sz 0x%llx to align 0x%x\n", size, MtdAlignSz);
size = ((size + MtdAlignMask)>>MtdAlignBits) << MtdAlignBits;
}
#if defined(UBIFS_IMG) || defined(CONFIG_CMD_UBIFS)
if (!strcmp(_usbDownPartImgType, "ubifs")) {
sprintf(str, "%s read 0x%llx %s 0x%llx", "ubi", addr, name, size);
MsgP("cmd[%s]", str);
} else
#endif
#endif//#if CONFIG_AML_MTD
{// not ubi part
sprintf(str, "%s read %s 0x%llx 0x%llx 0x%llx", cmd_name, name, addr, off, size);
}
DbgP("run cmd[%s]\n", str);
ret = run_command(str, 0);
if (ret != 0) {
ErrP("cmd failed, ret=%d, [%s]\n", ret, str);
return -1;
}
return 0;
}
/***
upgrade_write_ops:
partition_name: env / logo / recovery /boot / system /cache /media
***/
int store_write_ops(unsigned char *partition_name,unsigned char * buf, uint64_t off, uint64_t size)
{
unsigned char *name;
uint64_t addr;
char str[128];
int ret =0;
if (!buf) {
store_msg("upgrade: no buf!!");
return -1;
}
name = partition_name;
addr = (unsigned long)buf;
if ((EMMC_BOOT_FLAG == device_boot_flag) && !strcmp("1", (char*)name))
{
if (off & 0x1ff) {
ErrP("emmc1 invalid offset 0x%llx\n", off);
return -__LINE__;
}
if (size & 0xff) {
MsgP("NOT align sz 0x%llx\n", size);
}
sprintf(str, "mmc write 0x%p 0x%llx 0x%llx", buf, (off>>9), (size>>9));
ret = run_command(str, 0);
if (ret) {
ErrP("Fail in cmd[%s]\n", str);
return -__LINE__;
}
return ret;
}
#if CONFIG_AML_MTD
if ((size & MtdAlignMask) && (NAND_BOOT_FLAG == device_boot_flag )) {
MsgP("Wr:Up sz 0x%llx to align 0x%x\n", size, MtdAlignSz);
size = ((size + MtdAlignMask)>>MtdAlignBits) << MtdAlignBits;
}
#if defined(UBIFS_IMG) || defined(CONFIG_CMD_UBIFS)
if (!strcmp(_usbDownPartImgType, "ubifs")) {//ubi part
sprintf(str, "%s write 0x%llx %s 0x%llx ", "ubi", addr, name, size);
} else
#endif// #if defined(UBIFS_IMG) || defined(CONFIG_CMD_UBIFS)
#endif// #if CONFIG_AML_MTD
{
sprintf(str, "%s write %s 0x%llx 0x%llx 0x%llx", cmd_name, name, addr, off, size);
}
DbgP("run cmd[%s]\n", str);
ret = run_command(str, 0);
if (ret != 0) {
ErrP("cmd [%s] failed ", str);
return -1;
}
return 0;
}
/***
upgrade_write_ops:
partition_name: env / logo / recovery /boot / system /cache /media
***/
int store_get_partititon_size(unsigned char *partition_name, uint64_t *size)
{
char str[128];
int ret=0;
if (isdigit(*partition_name) && 1 == strlen((char*)partition_name))
{
const int curDev = *partition_name - '0';
sprintf(str, "mmc dev %d", curDev);
MsgP("cmd[%s]\n", str);
if (run_command(str, 0)) {
ErrP("Fail probe dev %d\n", curDev);
return 0;
}
struct mmc *mmc = find_mmc_device(curDev);
if (!mmc) {
ErrP("Fail find mmc %s\n", partition_name);
return 0;
}
if (mmc_init(mmc)) {
ErrP("FAil init mmc %s\n", partition_name);
return 0;
}
MsgP("mmc %s capacity 0x%llx\n", partition_name, mmc->capacity);
*size = mmc->capacity;
run_command("store disprotect key", 0);
MsgP("cmd[%s]\n", str);
return 0;
}
sprintf(str, "%s size %s 0x%p ",cmd_name, partition_name, size);
store_dbg("command: %s", str);
ret = run_command(str, 0);
if (ret != 0) {
ErrP("cmd [%s] size failed ", str);
return -1;
}
return ret;
}
/***
upgrade_erase_ops:
partition_name: boot / data
flag = 0; indicate erase partition ;
flag = 1; indicate scurb whole nand;
***/
int store_erase_ops(unsigned char *par_name, uint64_t off, uint64_t size, unsigned char flag)
{
unsigned char *name;
char str[128];
int ret=0;
name = par_name;
if (flag == 0) {
sprintf(str, "%s erase %s 0x%llx 0x%llx",cmd_name, name, off, size);
store_dbg("command: %s", str);
ret = run_command(str, 0);
if (ret != 0) {
store_msg("cmd %s erase failed",cmd_name);
return -1;
}
}else if(flag == 1){
sprintf(str, "%s rom_protect off ",cmd_name);
store_dbg("command: %s", str);
ret = run_command(str, 0);
if (ret != 0) {
store_msg("cmd %s scrub failed ",cmd_name);
return -1;
}
sprintf(str, "%s scrub 0x%llx ",cmd_name, (long long unsigned int)0);
store_dbg("command: %s", str);
ret = run_command(str, 0);
if (ret != 0) {
store_msg("cmd %s scrub failed",cmd_name);
return -1;
}
}
return 0;
}
/***
bootloader:
***/
int store_boot_read(unsigned char * buf, uint64_t off, uint64_t size)
{
//unsigned char *name;
uint64_t addr;
char str[128];
int ret =0;
if (!buf) {
store_msg("upgrade: no buf!!");
return -1;
}
addr = (unsigned long)buf;
store_dbg("store_boot_read: addr 0x%llx\n",addr);
sprintf(str, "%s rom_read 0x%llx 0x%llx 0x%llx",cmd_name, addr, off, size);
store_dbg("command: %s", str);
ret = run_command(str, 0);
if (ret != 0) {
store_msg("cmd %s rom_read failed",cmd_name);
return -1;
}
return 0;
}
int store_boot_write(unsigned char * buf,uint64_t off, uint64_t size)
{
//unsigned char *name;
uint64_t addr;
char str[128];
int ret =0;
if (!buf) {
store_msg("upgrade: no buf!!");
return -1;
}
addr = (unsigned long)buf;
sprintf(str, "%s rom_write 0x%llx 0x%llx 0x%llx",cmd_name, addr, off, size);
store_dbg("command: %s", str);
ret = run_command(str, 0);
if (ret != 0) {
store_msg("cmd %s rom_write failed",cmd_name);
return -1;
}
return 0;
}
int store_init(unsigned flag)
{
//unsigned char *name;
//unsigned long addr;
char str[128];
int ret =0;
store_dbg("flag : %d",flag);
sprintf(str, "%s init %d",cmd_name,flag);
store_dbg("command: %s", str);
ret = run_command(str, 0);
if (ret != 0) {
store_msg("cmd [%s] init failed ",str);
return -1;
}
return 0;
}
int store_exit(void)
{
//unsigned char *name;
//unsigned long addr;
char str[128];
int ret =0;
sprintf(str, "%s exit",cmd_name);
printf("command: %s\n", str);
ret = run_command(str, 0);
if (ret != 0) {
store_msg("cmd %s exit failed",cmd_name);
return -1;
}
return 0;
}
//store dtb read/write buf sz
//@rwFlag: 0---read, 1---write, 2---iread
int store_dtb_rw(void* buf, unsigned dtbSz, int rwFlag)
{
char _cmdBuf[128];
char* ops = !rwFlag ? "read" : ((1==rwFlag) ? "write" : "iread");
sprintf(_cmdBuf, "store dtb %s 0x%p 0x%x", ops, buf, dtbSz);
return run_command(_cmdBuf, 0);
}
#if 0
int do_store_test(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
int i, init_flag=0,dev, ret = 0;
ulong addr;
uint64_t off, size;
char *cmd, *s, *area;
char str[128];
unsigned char *buf;
cmd = argv[1];
buf = malloc(0x400000);
if (!buf) {
printf("do_store_test : malloc failed\n");
return -1;
}
area ="logo";
if (strcmp(cmd, "read") == 0) {
ret = store_read_ops(area,buf,0x0,0x40000);
if (ret < 0) {
printf("store read failed\n");
return -1;
}
printf("store read OK\n");
}
if (strcmp(cmd, "boot_read") == 0) {
ret = store_boot_read(buf,0x0,0x60000);
if (ret < 0) {
printf("store boot_read failed\n");
return -1;
}
printf("store boot_read OK\n");
}
if (strcmp(cmd, "init") == 0) {
ret = store_init(0x0);
if (ret < 0) {
printf("store init failed\n");
return -1;
}
printf("store init OK\n");
}
if (strcmp(cmd, "write") == 0) {
memset(buf,0xa5,0x400000);
ret = store_write_ops(area,buf,0x0,0x40000);
if (ret < 0) {
printf("store write failed\n");
return -1;
}
printf("store write OK\n");
}
if (strcmp(cmd, "erase") == 0) {
area = "data";
ret = store_erase_ops(area,0x0,0,0);
if (ret < 0) {
printf("store write failed\n");
return -1;
}
}
if (strcmp(cmd, "size") == 0) {
uint64_t off=0, size;
ret = store_get_partititon_size(area,&size);
if (ret < 0) {
printf("store write failed\n");
return -1;
}
printf("off =%llx size=%llx\n",off,size);
}
if (buf)
kfree(buf);
return 0;
}
U_BOOT_CMD(store_test, CONFIG_SYS_MAXARGS, 1, do_store_test,
"NAND sub-system",
"store read name addr off|partition size\n"
" read 'size' bytes starting at offset 'off'\n"
" to/from memory address 'addr', skipping bad blocks.\n"
"store write name addr off|partition size\n"
" write 'size' bytes starting at offset 'off'\n"
" to/from memory address 'addr', skipping bad blocks.\n"
"store erase boot/data: \n"
"erase the area which is uboot or datas \n"
"store scrub off|partition size\n"
"scrub the area from offset and size \n"
);
#endif