| /* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ |
| /* |
| * common/store_interface.c |
| * |
| * Copyright (C) 2020 Amlogic, Inc. All rights reserved. |
| * |
| */ |
| |
| #include <config.h> |
| #include <common.h> |
| #include <command.h> |
| //#include <watchdog.h> |
| #include <malloc.h> |
| #if defined(CONFIG_AML_NAND) || defined (CONFIG_AML_MTD) |
| #include <nand.h> |
| #endif |
| #include <mmc.h> |
| #include <linux/ctype.h> |
| #include <asm/byteorder.h> |
| #include <div64.h> |
| #include <linux/err.h> |
| #include <partition_table.h> |
| #include <emmc_partitions.h> |
| #include <libfdt.h> |
| #include <linux/string.h> |
| #include <asm/cpu_id.h> |
| #include <asm/arch/bl31_apis.h> |
| #include <asm/arch/cpu_config.h> |
| #include <asm/arch/secure_apb.h> |
| |
| extern int amlmmc_check_and_update_boot_info(void); |
| #if defined(CONFIG_AML_NAND) || defined (CONFIG_AML_MTD) |
| extern int amlnf_init(unsigned int flag); |
| extern void nand_init(void); |
| //extern int amlnf_key_write(u8 *buf, int len, u32 *actual_length); |
| //extern int amlnf_key_read(u8 *buf, int len, u32 *actual_length); |
| extern int amlnf_ddr_parameter_read(u8 *buf, int len); |
| extern int amlnf_ddr_parameter_write(u8 *buf, int len); |
| extern int amlnf_ddr_parameter_erase(void); |
| #endif |
| |
| #if defined(CONFIG_DISCRETE_BOOTLOADER) |
| #ifndef CONFIG_TPL_VAL_NUM_MIN |
| #define CONFIG_TPL_VAL_NUM_MIN (CONFIG_TPL_COPY_NUM/2) |
| #endif// #ifndef CONFIG_TPL_VAL_NUM_MIN |
| #ifndef CONFIG_BL2_VAL_NUM_MIN |
| #define CONFIG_BL2_VAL_NUM_MIN (CONFIG_BL2_COPY_NUM/2) |
| #endif// #ifndef CONFIG_BL2_VAL_NUM_MIN |
| static u32 _bootloaderOrgCrc[2]; //0 for bl2, 1 for tpl |
| #endif// #if defined(CONFIG_DISCRETE_BOOTLOADER) |
| |
| extern int get_partition_from_dts(unsigned char *buffer); |
| |
| /* key operations of emmc */ |
| extern int mmc_key_read(unsigned char *buf, |
| unsigned int size, u32 *actual_length); |
| extern int mmc_key_write(unsigned char *buf, |
| unsigned int size, u32 *actual_length); |
| extern int mmc_key_erase(void); |
| extern int find_dev_num_by_partition_name (char *name); |
| //extern unsigned int emmc_cur_partition; |
| |
| extern int mmc_ddr_parameter_read(unsigned char *buf, unsigned int size); |
| extern int mmc_ddr_parameter_write(unsigned char *buf, unsigned int size); |
| extern int mmc_ddr_parameter_erase(void); |
| |
| #define debugP(fmt...) //printf("Dbg[store]L%d:", __LINE__),printf(fmt) |
| #define MsgP(fmt...) printf("[store]"fmt) |
| #define ErrP(fmt...) printf("[store]Err:%s,L%d:", __func__, __LINE__),printf(fmt) |
| |
| #define NAND_INIT_FAILED 20 |
| #define STORE_BOOT_NORMAL 0 |
| #define STORE_BOOT_UPGRATE 1 |
| #define STORE_BOOT_ERASE_PROTECT_CACHE 2 |
| #define STORE_BOOT_ERASE_ALL 3 |
| #define STORE_BOOT_SCRUB_ALL 4 |
| |
| #define _SPI_FLASH_ERASE_SZ (CONFIG_ENV_IN_SPI_OFFSET + CONFIG_ENV_SIZE) |
| #define CONFIG_ENV_IN_SPI_OFFSET 0 |
| //Ignore mbr since mmc driver already handled |
| //#define MMC_UBOOT_CLEAR_MBR |
| |
| #ifdef MMC_UBOOT_CLEAR_MBR |
| static char _mbrFlag[4] ; |
| #endif |
| |
| #ifdef CONFIG_AML_MTD |
| static int mtd_find_phy_off_by_lgc_off(const char *partname, |
| const loff_t logicaddr, loff_t *phyaddr) |
| { |
| nand_info_t *mtdpartinf = NULL; |
| loff_t off = 0; |
| static struct { |
| loff_t lastblkphyoff; |
| loff_t lastblklgcoff; |
| char partname[64]; |
| } _map4speedup = {0}; |
| int canspeedup = 0; |
| |
| if (!(NAND_BOOT_FLAG == device_boot_flag || SPI_NAND_FLAG == device_boot_flag)) { |
| return 0; |
| } |
| |
| mtdpartinf = get_mtd_device_nm(partname); |
| if (IS_ERR(mtdpartinf)) { |
| ErrP("device(%s) is err\n", partname); |
| return CMD_RET_FAILURE; |
| } |
| const unsigned int erasesz = mtdpartinf->erasesize; |
| const unsigned int offsetinblk = logicaddr & (erasesz - 1); |
| |
| if (!strcmp(partname, _map4speedup.partname) && logicaddr >= _map4speedup.lastblklgcoff) { |
| canspeedup = 1; |
| } else { |
| _map4speedup.lastblklgcoff = 0; |
| _map4speedup.lastblkphyoff = 0; |
| strncpy(_map4speedup.partname, partname, 63); |
| } |
| |
| if (canspeedup) { |
| if (logicaddr >= _map4speedup.lastblklgcoff && |
| logicaddr < _map4speedup.lastblklgcoff + erasesz) { |
| *phyaddr = _map4speedup.lastblkphyoff + offsetinblk; |
| return 0; |
| } |
| _map4speedup.lastblkphyoff += erasesz; |
| _map4speedup.lastblklgcoff += erasesz; |
| off = _map4speedup.lastblkphyoff; |
| } |
| for (; off < mtdpartinf->size; |
| off += erasesz, _map4speedup.lastblkphyoff += erasesz) { |
| if (nand_block_isbad(mtdpartinf, off)) { |
| MsgP(" %08llx\n", (unsigned long long)off); |
| } else { |
| if (logicaddr >= _map4speedup.lastblklgcoff && |
| logicaddr < _map4speedup.lastblklgcoff + erasesz) { |
| *phyaddr = _map4speedup.lastblkphyoff + offsetinblk; |
| return 0; |
| } |
| _map4speedup.lastblklgcoff += erasesz; |
| } |
| } |
| |
| return __LINE__; |
| } |
| #endif// #ifdef CONFIG_AML_MTD |
| |
| |
| /* mmcinfo 1 will clear info_disprotect before run_command("mmc erase 1") */ |
| static int _info_disprotect_back_before_mmcinfo1 = 0; |
| extern int info_disprotect; |
| /* |
| static inline int isstring(char *p) |
| { |
| char *endptr = p; |
| while (*endptr != '\0') { |
| if (!(((*endptr >= '0') && (*endptr <= '9')) |
| || ((*endptr >= 'a') && (*endptr <= 'f')) |
| || ((*endptr >= 'A') && (*endptr <= 'F')) |
| || (*endptr == 'x') || (*endptr == 'X'))) |
| return 1; |
| endptr++; |
| } |
| |
| return 0; |
| } |
| */ |
| /* |
| static inline int str2long(char *p, ulong *num) |
| { |
| char *endptr; |
| *num = simple_strtoul(p, &endptr, 16); |
| return (*p != '\0' && *endptr == '\0') ? 1 : 0; |
| } |
| */ |
| |
| static inline int str2longlong(char *p, unsigned long long *num) |
| { |
| char *endptr; |
| |
| *num = simple_strtoull(p, &endptr, 16); |
| if (*endptr != '\0') |
| { |
| switch (*endptr) |
| { |
| case 'g': |
| case 'G': |
| *num<<=30; |
| endptr++; |
| break; |
| case 'm': |
| case 'M': |
| *num<<=20; |
| endptr++; |
| break; |
| case 'k': |
| case 'K': |
| *num<<=10; |
| endptr++; |
| break; |
| } |
| } |
| |
| return (*p != '\0' && *endptr == '\0') ? 1 : 0; |
| } |
| |
| static int emmc_init(void) |
| { |
| int ret = -1; |
| struct mmc *mmc = NULL; |
| mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV); |
| if (mmc) { |
| ret = mmc_init(mmc); // init eMMC/tSD+ |
| } |
| return ret; |
| } |
| |
| static int get_device_boot_flag(void) |
| { |
| int ret=0; |
| if (1) {//nand and emmc |
| //try eMMC init |
| device_boot_flag = EMMC_BOOT_FLAG; |
| ret = emmc_init(); |
| if (!ret) { |
| printf("XXXXXXX======enter EMMC boot======XXXXXX\n"); |
| return 0; |
| } |
| printf("EMMC init failed\n"); |
| |
| #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| //try nand first |
| #if defined(CONFIG_AML_NAND) |
| ret = amlnf_init(0x5); |
| #elif defined(CONFIG_AML_MTD) |
| nand_init(); |
| #endif |
| ret = (device_boot_flag == NAND_BOOT_FLAG) ? 0 : __LINE__; |
| if (!ret) { |
| printf("XXXXXXX======enter NAND boot======XXXXXX\n"); |
| return 0; |
| } |
| printf("NAND init failed\n"); |
| #else |
| printf("check again, may error code used!\n"); |
| #endif |
| } |
| |
| printf("device_boot_flag=%d\n",device_boot_flag); |
| return -1; |
| } |
| |
| static int get_off_size(int argc, char *argv[], loff_t *off, loff_t *size) |
| { |
| if (argc >= 1) { |
| if (!(str2longlong(argv[0], (unsigned long long*)off))) { |
| store_msg("'%s' is not a number\n", argv[0]); |
| return -1; |
| } |
| } else { |
| *off = 0; |
| *size = 0; |
| } |
| |
| if (argc >= 2) { |
| if (!(str2longlong(argv[1], (unsigned long long *)size))) { |
| store_msg("'%s' is not a number\n", argv[1]); |
| return -1; |
| } |
| } else { |
| *size = 0; |
| } |
| |
| store_dbg("offset 0x%llx, size 0x%llx", *off, *size); |
| |
| return 0; |
| } |
| |
| static int do_decrypt_dtb(char *dtbaddr) { |
| int ret = 0; |
| unsigned long dtimgaddr = simple_strtoul(dtbaddr, NULL, 16); |
| |
| ret = fdt_check_header((char *)dtimgaddr); |
| if (!ret) { |
| MsgP("Is good fdt check header, no need decrypt!\n"); |
| return ret; |
| } |
| |
| #ifndef CONFIG_SKIP_KERNEL_DTB_SECBOOT_CHECK |
| flush_cache(dtimgaddr, AML_DTB_IMG_MAX_SZ); |
| ret = aml_sec_boot_check(AML_D_P_IMG_DECRYPT, dtimgaddr, AML_DTB_IMG_MAX_SZ, 0); |
| if (ret) { |
| MsgP("decrypt dtb: Sig Check %d\n",ret); |
| return ret; |
| } |
| |
| ulong nCheckOffset; |
| nCheckOffset = aml_sec_boot_check(AML_D_Q_IMG_SIG_HDR_SIZE, |
| GXB_IMG_LOAD_ADDR, GXB_EFUSE_PATTERN_SIZE, GXB_IMG_DEC_ALL); |
| if (AML_D_Q_IMG_SIG_HDR_SIZE == (nCheckOffset & 0xFFFF)) |
| nCheckOffset = (nCheckOffset >> 16) & 0xFFFF; |
| else |
| nCheckOffset = 0; |
| |
| if (nCheckOffset) |
| memmove((char *)dtimgaddr, |
| (char *)dtimgaddr + nCheckOffset, AML_DTB_IMG_MAX_SZ); |
| #endif//#ifndef CONFIG_SKIP_KERNEL_DTB_SECBOOT_CHECK |
| |
| #ifdef CONFIG_MULTI_DTB |
| extern unsigned long get_multi_dt_entry(unsigned long fdt_addr); |
| |
| unsigned long fdtaddr = get_multi_dt_entry(dtimgaddr); |
| |
| ret = fdt_check_header((char *)fdtaddr); |
| if (ret) { |
| ErrP("Fail in fdt check header\n"); |
| return CMD_RET_FAILURE; |
| } |
| |
| unsigned int fdtsz = fdt_totalsize((char *)fdtaddr); |
| |
| if (fdtsz > AML_DTB_IMG_MAX_SZ) |
| return CMD_RET_FAILURE; |
| |
| memmove((void *)dtimgaddr, (void *)fdtaddr, fdtsz); |
| #endif// #ifdef CONFIG_MULTI_DTB |
| |
| return ret; |
| } |
| |
| //store dtb read/write buff size |
| static int do_store_dtb_ops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| int ret = 0; |
| char _cmdbuf[128]; |
| char *ops = argv[2]; |
| const unsigned int maxdtbsz = 256 * 1024; |
| unsigned int actualdtbsz = 0; |
| char *devcmd = NULL; |
| char *dtbloadaddr = argv[3]; |
| |
| if (argc < 4) |
| return CMD_RET_USAGE; |
| |
| const int is_decrypt = !strcmp("decrypt", ops); |
| if (is_decrypt) { |
| return do_decrypt_dtb(dtbloadaddr); |
| } |
| |
| const int is_write = !strcmp("write", ops); |
| if (!is_write) { |
| ret = !strcmp("read", ops) || !strcmp("iread", ops);//must be 0 |
| if (!ret) |
| return CMD_RET_USAGE; |
| } |
| |
| actualdtbsz = maxdtbsz; |
| if (argc > 4) { |
| const unsigned int bufsz = simple_strtoul(argv[4], NULL, 0); |
| |
| if (bufsz > maxdtbsz) { |
| ErrP("bufsz (%s) > max 0x%x\n", argv[4], maxdtbsz); |
| return CMD_RET_FAILURE; |
| } |
| } |
| |
| ops = is_write ? "dtb_write" : "dtb_read"; |
| |
| switch (device_boot_flag) |
| { |
| case NAND_BOOT_FLAG: |
| case SPI_NAND_FLAG: |
| { |
| devcmd = "amlnf"; |
| } |
| break; |
| |
| case EMMC_BOOT_FLAG: |
| case SPI_EMMC_FLAG: |
| { |
| devcmd = "emmc"; |
| } |
| break; |
| |
| default: |
| ErrP("device_boot_flag=0x%x err\n", device_boot_flag); |
| return CMD_RET_FAILURE; |
| } |
| |
| sprintf(_cmdbuf, "%s %s %s 0x%x", devcmd, ops, dtbloadaddr, actualdtbsz); |
| MsgP("To run cmd[%s]\n", _cmdbuf); |
| ret = run_command(_cmdbuf, 0); |
| |
| unsigned long dtimgaddr = simple_strtoul(dtbloadaddr, NULL, 16); |
| // |
| //ONLY need decrypting when 'store dtb read' |
| if (!strcmp("read", argv[2])) |
| { |
| flush_cache(dtimgaddr, AML_DTB_IMG_MAX_SZ); |
| #ifndef CONFIG_SKIP_KERNEL_DTB_SECBOOT_CHECK |
| |
| ret = aml_sec_boot_check(AML_D_P_IMG_DECRYPT, dtimgaddr, AML_DTB_IMG_MAX_SZ, 0); |
| if (ret) { |
| MsgP("decrypt dtb: Sig Check %d\n",ret); |
| return ret; |
| } |
| #endif |
| } |
| |
| #ifndef CONFIG_SKIP_KERNEL_DTB_SECBOOT_CHECK |
| if (!is_write && strcmp("iread", argv[2])) |
| { |
| ulong nCheckOffset; |
| |
| nCheckOffset = aml_sec_boot_check(AML_D_Q_IMG_SIG_HDR_SIZE, |
| GXB_IMG_LOAD_ADDR, GXB_EFUSE_PATTERN_SIZE, GXB_IMG_DEC_ALL); |
| if (AML_D_Q_IMG_SIG_HDR_SIZE == (nCheckOffset & 0xFFFF)) |
| nCheckOffset = (nCheckOffset >> 16) & 0xFFFF; |
| else |
| nCheckOffset = 0; |
| |
| if (nCheckOffset) |
| memmove((char *)dtimgaddr, |
| (char *)dtimgaddr + nCheckOffset, |
| AML_DTB_IMG_MAX_SZ); |
| } |
| #endif//#ifndef CONFIG_SKIP_KERNEL_DTB_SECBOOT_CHECK |
| #ifdef CONFIG_MULTI_DTB |
| if (!is_write && strcmp("iread", argv[2])) |
| { |
| extern unsigned long get_multi_dt_entry(unsigned long fdt_addr); |
| unsigned long fdtaddr = get_multi_dt_entry(dtimgaddr); |
| |
| ret = fdt_check_header((char *)fdtaddr); |
| if (ret) { |
| ErrP("Fail in fdt check header\n"); |
| return CMD_RET_FAILURE; |
| } |
| unsigned int fdtsz = fdt_totalsize((char *)fdtaddr); |
| |
| if (fdtsz > AML_DTB_IMG_MAX_SZ) |
| return CMD_RET_FAILURE; |
| |
| memmove((char *)dtimgaddr, (char *)fdtaddr, fdtsz); |
| } |
| #endif// #ifdef CONFIG_MULTI_DTB |
| |
| return ret; |
| } |
| |
| /* |
| write mbr to emmc only. |
| store mbr Addr |
| */ |
| extern int emmc_update_mbr(unsigned char *buffer); |
| static int do_store_mbr_ops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| int ret = 0; |
| unsigned char *buffer; |
| cpu_id_t cpu_id = get_cpu_id(); |
| |
| if (cpu_id.family_id < MESON_CPU_MAJOR_ID_GXL || |
| device_boot_flag != EMMC_BOOT_FLAG) { |
| ret = -1; |
| ErrP("MBR not support, try [store dtb write Addr]\n"); |
| goto _out; |
| } |
| |
| if (argc < 3) |
| return CMD_RET_USAGE; |
| |
| buffer = (unsigned char *)simple_strtoul(argv[2], NULL, 16); |
| ret = emmc_update_mbr(buffer); |
| if (ret) { |
| ErrP("fail to update mbr\n"); |
| goto _out; |
| } |
| _out: |
| return ret; |
| } |
| |
| static int do_store_bootlog(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| int ret = 0; |
| unsigned int val; |
| |
| if (argc < 2) |
| return CMD_RET_USAGE; |
| |
| val = readl(AO_SEC_GP_CFG2); |
| printf("Boot logs:\n\t bl2: %d\n\tfip: %d\n", (val >> 25) & 0x7, (val >> 22) & 0x7); |
| |
| return ret; |
| } |
| |
| #define IS_STORAGE_EMMC_BOOT(device) (((device) == EMMC_BOOT_FLAG) \ |
| || ((device) == SPI_EMMC_FLAG)) |
| |
| #define STORAGE_BOOT_UNKNOWN(device) (((device) != EMMC_BOOT_FLAG) \ |
| && ((device) != SPI_EMMC_FLAG) \ |
| && ((device) != NAND_BOOT_FLAG) \ |
| && ((device) != SPI_NAND_FLAG)) |
| |
| int store_ddr_parameter_read(u8 *buffer, |
| u32 length) |
| { |
| int ret = 0; |
| |
| if (STORAGE_BOOT_UNKNOWN(device_boot_flag)) { |
| ErrP("device_boot_flag=0x%x err\n", device_boot_flag); |
| return -ENODEV; |
| } |
| |
| if (IS_STORAGE_EMMC_BOOT(device_boot_flag)) { |
| amlmmc_check_and_update_boot_info(); |
| ret = mmc_ddr_parameter_read(buffer, (int)length); |
| } |
| #if defined(CONFIG_AML_MTD) || defined(CONFIG_AML_NAND) |
| else |
| ret = amlnf_ddr_parameter_read(buffer, (int)length); |
| #endif |
| return ret; |
| } |
| |
| int store_ddr_parameter_write(u8 *buffer, u32 length) |
| { |
| int ret = 0; |
| |
| if (STORAGE_BOOT_UNKNOWN(device_boot_flag)) { |
| ErrP("device_boot_flag=0x%x err\n", device_boot_flag); |
| return -ENODEV; |
| } |
| |
| if (IS_STORAGE_EMMC_BOOT(device_boot_flag)) { |
| amlmmc_check_and_update_boot_info(); |
| ret = mmc_ddr_parameter_write(buffer, (int)length); |
| #if defined(CONFIG_AML_MTD) || defined(CONFIG_AML_NAND) |
| } else |
| ret = amlnf_ddr_parameter_write(buffer, (int)length); |
| #else |
| } |
| #endif |
| return ret; |
| } |
| |
| int store_ddr_parameter_erase(void) |
| { |
| int ret = 0; |
| |
| if (STORAGE_BOOT_UNKNOWN(device_boot_flag)) { |
| ErrP("device_boot_flag=0x%x err\n", device_boot_flag); |
| return -ENODEV; |
| } |
| |
| if (IS_STORAGE_EMMC_BOOT(device_boot_flag)) |
| ret = mmc_ddr_parameter_erase(); |
| #if defined(CONFIG_AML_MTD) || defined(CONFIG_AML_NAND) |
| else |
| ret = amlnf_ddr_parameter_erase(); |
| #endif |
| return ret; |
| } |
| |
| int store_key_read(u8 *buffer, |
| u32 length, u32 *actual_length) |
| { |
| int ret = 0; |
| |
| if (STORAGE_BOOT_UNKNOWN(device_boot_flag)) { |
| ErrP("device_boot_flag=0x%x err\n", device_boot_flag); |
| return -ENODEV; |
| } |
| |
| if (IS_STORAGE_EMMC_BOOT(device_boot_flag)) |
| ret = mmc_key_read(buffer, (int)length, actual_length); |
| #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| else |
| ret = amlnf_key_read(buffer, (int)length, actual_length); |
| #endif |
| return ret; |
| } |
| |
| int store_key_write(u8 *buffer, |
| u32 length, u32 *actual_length) |
| { |
| int ret = 0; |
| |
| if (STORAGE_BOOT_UNKNOWN(device_boot_flag)) { |
| ErrP("device_boot_flag=0x%x err\n", device_boot_flag); |
| return -ENODEV; |
| } |
| |
| if (IS_STORAGE_EMMC_BOOT(device_boot_flag)) |
| ret = mmc_key_write(buffer, (int)length, actual_length); |
| #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| else |
| ret = amlnf_key_write(buffer, (int)length, actual_length); |
| #endif |
| return ret; |
| } |
| |
| static int do_store_key_ops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| int ret = 0; |
| char _cmdbuf[128]; |
| char *ops = argv[2]; |
| const unsigned int maxkyesz = 256 * 1024; |
| unsigned int actualdtbsz = 0; |
| char *devcmd = NULL; |
| |
| if (argc < 4) |
| return CMD_RET_USAGE; |
| |
| const int is_write = !strcmp("write", ops); |
| if (!is_write) { |
| ret = strcmp("read", ops);//must be 0 |
| if (ret) |
| return CMD_RET_USAGE; |
| } |
| |
| actualdtbsz = maxkyesz; |
| if (argc > 4) { |
| const unsigned int bufsz = simple_strtoul(argv[4], NULL, 0); |
| |
| if (bufsz > maxkyesz) { |
| ErrP("bufsz (%s) > max 0x%x\n", argv[4], maxkyesz); |
| return CMD_RET_FAILURE; |
| } |
| } |
| |
| ops = is_write ? "key_write" : "key_read"; |
| |
| switch (device_boot_flag) { |
| case NAND_BOOT_FLAG: |
| case SPI_NAND_FLAG: |
| devcmd = "amlnf"; |
| break; |
| case EMMC_BOOT_FLAG: |
| case SPI_EMMC_FLAG: |
| devcmd = "emmc"; |
| break; |
| default: |
| ErrP("device_boot_flag=0x%x err\n", device_boot_flag); |
| return CMD_RET_FAILURE; |
| } |
| |
| sprintf(_cmdbuf, "%s %s %s 0x%x", devcmd, ops, argv[3], actualdtbsz); |
| MsgP("To run cmd[%s]\n", _cmdbuf); |
| ret = run_command(_cmdbuf, 0); |
| |
| return ret; |
| } |
| |
| static int do_store_ddr_parameter_ops(cmd_tbl_t *cmdtp, |
| int flag, int argc, char * const argv[]) |
| { |
| unsigned long addr; |
| int ret = 0; |
| char *ops = argv[2]; |
| const unsigned int maxddrpsz = 2 * 1024; |
| unsigned int actualdtbsz = 0; |
| |
| if (!strcmp("erase", ops) && (argc == 3)) { |
| ret = store_ddr_parameter_erase(); |
| return ret; |
| } |
| |
| if (argc < 4) |
| return CMD_RET_USAGE; |
| |
| const int is_write = !strcmp("write", ops); |
| if (!is_write) { |
| ret = strcmp("read", ops);//must be 0 |
| if (ret) |
| return CMD_RET_USAGE; |
| } |
| actualdtbsz = maxddrpsz; |
| if (argc > 4) { |
| const unsigned int bufsz = simple_strtoul(argv[4], NULL, 0); |
| |
| if (bufsz > maxddrpsz) { |
| ErrP("bufsz (%s) > max 0x%x\n", argv[4], maxddrpsz); |
| return CMD_RET_FAILURE; |
| } |
| } |
| |
| addr = (ulong)simple_strtoul(argv[3], NULL, 16); |
| if (is_write) |
| store_ddr_parameter_write((u8 *)addr, actualdtbsz); |
| else |
| store_ddr_parameter_read((u8 *)addr, actualdtbsz); |
| |
| return ret; |
| } |
| |
| static int do_store_init(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| int i, init_flag=0, ret = 0; |
| char str[128]; |
| |
| init_flag = (argc > 2) ? (int)simple_strtoul(argv[2], NULL, 16) : 0; |
| store_dbg("init_flag %d",init_flag); |
| |
| //Forcing updating device_boot_flag every time 'store init' |
| if (device_boot_flag == _AML_DEVICE_BOOT_FLAG_DEFAULT || 1) { |
| i = get_device_boot_flag(); |
| if (i) { |
| MsgP("ERR:FAILED in get_device_boot_flag\n"); |
| return __LINE__; |
| } |
| } |
| |
| switch (device_boot_flag) |
| { |
| #if defined(CONFIG_AML_NAND) |
| case NAND_BOOT_FLAG: |
| { |
| if (init_flag >= STORE_BOOT_ERASE_PROTECT_CACHE && |
| init_flag <= STORE_BOOT_SCRUB_ALL) { |
| sprintf(str, "amlnf init %d ",init_flag); |
| run_command(str, 0); |
| } |
| |
| sprintf(str, "amlnf init %d ",1); |
| printf("command: %s <- %d\n", str, init_flag); |
| device_boot_flag = NAND_BOOT_FLAG; |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| return -1; |
| } |
| return ret; |
| } |
| break; |
| #endif// #if defined(CONFIG_AML_NAND) |
| #ifdef CONFIG_AML_MTD |
| case NAND_BOOT_FLAG: |
| { |
| ret = run_command("nand init", 0); |
| if (init_flag >= STORE_BOOT_ERASE_PROTECT_CACHE) { |
| ret |= run_command("amlnf rom_erase",0); |
| ret |= run_command("nand device 1", 0); |
| ret |= run_command("nand erase.chip", 0); |
| } |
| } |
| return ret; |
| break; |
| #endif// #ifdef CONFIG_AML_MTD |
| case EMMC_BOOT_FLAG: |
| { |
| store_dbg("MMC BOOT, %s %d\n", __func__, __LINE__); |
| device_boot_flag = EMMC_BOOT_FLAG; |
| sprintf(str, "mmc dev %d", CONFIG_SYS_MMC_ENV_DEV); |
| run_command(str,0); |
| ret = run_command("mmcinfo", 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed \n"); |
| return -1; |
| } |
| if (init_flag == STORE_BOOT_ERASE_PROTECT_CACHE) { |
| ret = run_command("amlmmc erase non_cache", 0); |
| } else if (init_flag >= STORE_BOOT_ERASE_ALL) { |
| if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) { |
| MsgP("amlmmc key\n"); |
| run_command("amlmmc key", 0); |
| } |
| sprintf(str, "amlmmc erase %d", CONFIG_SYS_MMC_ENV_DEV); |
| MsgP("amlmmc erase %d", CONFIG_SYS_MMC_ENV_DEV); |
| ret = run_command(str, 0); |
| } |
| |
| return ret; |
| } |
| break; |
| case SPI_EMMC_FLAG: |
| { |
| store_dbg("spi+mmc , %s %d ", __func__, __LINE__); |
| ret = run_command("mmcinfo 1", 0); |
| |
| if (init_flag == STORE_BOOT_ERASE_PROTECT_CACHE) { |
| store_msg("amlmmc erase non_cache \n"); |
| ret = run_command("amlmmc erase non_cache", 0); |
| } else if (init_flag == STORE_BOOT_ERASE_ALL) { |
| if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) { |
| run_command("mmc key", 0); |
| } |
| MsgP("amlmmc erase 1 \n"); |
| ret = run_command("amlmmc erase 1", 0); |
| } |
| if (init_flag > STORE_BOOT_ERASE_PROTECT_CACHE && |
| init_flag <= STORE_BOOT_SCRUB_ALL) { |
| ret = run_command("sf probe 2", 0); |
| if (ret != 0) { |
| store_msg("sf probe failed"); |
| return -1; |
| } |
| sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ); |
| ret = run_command(str,0); |
| } |
| if (ret != 0) { |
| store_msg("cmd failed \n"); |
| return -1; |
| } |
| |
| return ret; |
| } |
| break; |
| case SPI_NAND_FLAG: |
| { |
| store_dbg("spi+nand , %s %d ", __func__, __LINE__); |
| #if defined(CONFIG_AML_NAND) |
| if (init_flag >= STORE_BOOT_ERASE_PROTECT_CACHE && |
| init_flag <= STORE_BOOT_SCRUB_ALL) { |
| sprintf(str, "amlnf init %d ",init_flag); |
| run_command(str, 0); |
| } |
| sprintf(str, "amlnf init %d ",1); |
| store_dbg("command: %s", str); |
| ret = run_command(str, 0); |
| #else |
| ret = NAND_INIT_FAILED; |
| #endif |
| |
| if (ret == NAND_INIT_FAILED) { |
| return -1; |
| #if defined(CONFIG_AML_NAND) |
| } else { |
| if (init_flag > STORE_BOOT_ERASE_PROTECT_CACHE && |
| init_flag <= STORE_BOOT_SCRUB_ALL) { |
| ret = run_command("sf probe 2", 0); |
| sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ); |
| ret = run_command(str,0); |
| } |
| |
| if (ret != 0) { |
| store_msg("cmd failed \n"); |
| return -1; |
| } |
| |
| return ret; |
| #endif |
| } |
| } |
| default: |
| store_dbg("CARD BOOT, %s %d", __func__, __LINE__); |
| return CMD_RET_FAILURE; |
| } |
| |
| return 0; |
| } |
| |
| static int do_store_exit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| #if defined(CONFIG_AML_NAND) |
| if (device_boot_flag == NAND_BOOT_FLAG) { |
| int ret = run_command("amlnf exit", 0); |
| if (ret != 0) { |
| MsgP("amlnf exit failed"); |
| return -1; |
| } |
| } |
| #endif |
| if (device_boot_flag == EMMC_BOOT_FLAG) { |
| /* partition table need renew */ |
| is_partition_checked = false; |
| } |
| return 0; |
| } |
| |
| static int do_store_disprotect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| char *area; |
| |
| area = argv[2]; |
| if (strcmp(area, "key") == 0) { |
| MsgP("disprotect key\n"); |
| info_disprotect |= DISPROTECT_KEY; |
| _info_disprotect_back_before_mmcinfo1 |= DISPROTECT_KEY; |
| } |
| if (strcmp(area, "fbbt") == 0) { |
| store_msg("disprotect fbbt"); |
| info_disprotect |= DISPROTECT_FBBT; |
| } |
| if (strcmp(area, "hynix") == 0) { |
| store_msg("disprotect hynix"); |
| info_disprotect |= DISPROTECT_HYNIX; |
| } |
| |
| return 0; |
| } |
| |
| static int do_store_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| int ret = 0; |
| u64 addr; |
| char *s = NULL; |
| char str[128]; |
| |
| if (argc < 4) |
| return CMD_RET_USAGE; |
| |
| s = argv[2]; |
| addr = (ulong)simple_strtoul(argv[3], NULL, 16); |
| if (!addr) { |
| ErrP("addr(%s) is invalid\n", argv[3]); |
| return CMD_RET_FAILURE; |
| } |
| |
| if (device_boot_flag == NAND_BOOT_FLAG) { |
| #if defined(CONFIG_AML_NAND) |
| sprintf(str, "amlnf size %s %llx",s,addr); |
| store_dbg("command: %s", str); |
| ret = run_command(str, 0); |
| #elif defined(CONFIG_AML_MTD) |
| {//get mtd part logic size (i.e, not including the bad blocks) |
| nand_info_t *mtdpartinf = NULL; |
| loff_t off = 0; |
| u64 partszlgc = 0; |
| const char *partname = s; |
| |
| mtdpartinf = get_mtd_device_nm(partname); |
| if (IS_ERR(mtdpartinf)) { |
| ErrP("device(%s) is err\n", partname); |
| return CMD_RET_FAILURE; |
| } |
| const unsigned int erasesz = mtdpartinf->erasesize; |
| const u64 partszphy = mtdpartinf->size; |
| |
| partszlgc = partszphy; |
| for (; off < partszphy; off += erasesz) { |
| if (nand_block_isbad(mtdpartinf, off)) |
| partszlgc -= erasesz; |
| } |
| u64 *paddr = (u64 *)addr; |
| *paddr = partszlgc; |
| } |
| #else |
| ret = -1; |
| #endif// #if defined(CONFIG_AML_NAND) |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| } else { |
| return ret; |
| #endif |
| } |
| } else if (device_boot_flag == SPI_NAND_FLAG) { |
| #if defined(CONFIG_AML_NAND) |
| sprintf(str, "amlnf size %s %llx",s,addr); |
| store_dbg("command: %s", str); |
| ret = run_command(str, 0); |
| #else |
| ret = -1; |
| #endif |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| #if defined(CONFIG_AML_NAND) |
| } else { |
| return ret; |
| #endif |
| } |
| } else if (device_boot_flag == SPI_EMMC_FLAG) { |
| store_dbg("MMC , %s %d ", __func__, __LINE__); |
| sprintf(str, "amlmmc size %s %llx",s,addr); |
| store_dbg("command: %s", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed"); |
| return -1; |
| } |
| return ret; |
| } else if (device_boot_flag == EMMC_BOOT_FLAG) { |
| store_dbg("MMC , %s %d ", __func__, __LINE__); |
| sprintf(str, "amlmmc size %s %llx",s,addr); |
| store_dbg("command: %s", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed"); |
| return -1; |
| } |
| return ret; |
| } else if (device_boot_flag == CARD_BOOT_FLAG) { |
| store_dbg("CARD BOOT , %s %d ", __func__, __LINE__); |
| return CMD_RET_FAILURE; |
| } |
| |
| return CMD_RET_FAILURE; |
| } |
| |
| static int do_store_erase(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| int i, erase = 2, ret = 0; |
| //loff_t size=0; |
| char *area; |
| char str[128]; |
| //loff_t off = 0; |
| |
| if (argc < 3) |
| return CMD_RET_USAGE; |
| |
| area = argv[2]; |
| |
| if (strcmp(area, "boot") == 0) { |
| //off = argc > 3 ? simple_strtoul(argv[3], NULL, 16) : 0; |
| //size = argc > 4 ? simple_strtoul(argv[4], NULL, 16) : 0x60000; |
| if (device_boot_flag == NAND_BOOT_FLAG) { |
| #if defined(CONFIG_AML_NAND) |
| store_dbg("NAND BOOT,erase uboot : %s %d off =%llx ,size=%llx", |
| __func__, __LINE__, off, size); |
| |
| ret = run_command("amlnf deverase boot 0",0); |
| #elif defined(CONFIG_AML_MTD) |
| ret = run_command("amlnf rom_erase",0); |
| #else |
| ret = -1; |
| #endif |
| /* |
| * Need consider that CONFIG_AML_NAND was not defined. |
| */ |
| /* coverity[dead_error_line] */ |
| if (ret != 0) { |
| store_msg("nand cmd failed "); |
| return -1; |
| } |
| /* |
| * Need consider that CONFIG_AML_NAND was not defined. |
| */ |
| /* coverity[dead_error_line] */ |
| return ret; |
| } else if ((device_boot_flag == SPI_EMMC_FLAG) || |
| (device_boot_flag == SPI_NAND_FLAG)) { |
| store_dbg("SPI BOOT,erase uboot : %s %d off =%llx ,size=%llx", |
| __func__, __LINE__, off, size); |
| |
| ret = run_command("sf probe 2",0); |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| sprintf(str, "sf erase 0 0x%x", CONFIG_ENV_IN_SPI_OFFSET);//store erase boot should NOT erase ENV in flash! |
| ret = run_command(str,0); |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| return ret; |
| } else if (device_boot_flag == EMMC_BOOT_FLAG) { |
| store_dbg("MMC BOOT,erase uboot : %s %d off =%llx ,size=%llx", |
| __func__, __LINE__, off, size); |
| |
| sprintf(str, "amlmmc erase bootloader"); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed"); |
| return -1; |
| } |
| |
| #ifdef MMC_BOOT_PARTITION_SUPPORT |
| #ifdef CONFIG_EMMC_KEEP_BOOT1 |
| /* do not erase the BOOT1 for TM2 revA ONLY*/ |
| if (get_cpu_id().family_id != MESON_CPU_MAJOR_ID_TM2) { |
| store_msg("WRONG CONFIG_EMMC_KEEP_BOOT1 enabled!\n"); |
| return -1; |
| } |
| if (get_cpu_id().chip_rev == 0xA) |
| erase = 1; |
| #endif |
| for (i=0; i < erase; i++) { |
| printf("%s() %d, i = %d\n", __func__, __LINE__, i); |
| //switch to boot partition here |
| sprintf(str, "amlmmc switch 1 boot%d", i); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| if (ret == -1) { |
| //store_msg("mmc cmd failed \n"); |
| return 0; |
| } else if (ret != 0) { |
| store_msg("amlmmc cmd failed"); |
| //return -1; |
| goto E_SWITCH_BACK; |
| } |
| |
| //erase boot partition |
| sprintf(str, "amlmmc erase bootloader"); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed"); |
| //return -1; |
| goto E_SWITCH_BACK; |
| } |
| } |
| |
| E_SWITCH_BACK: |
| //switch back to urs partition |
| sprintf(str, "amlmmc switch 1 user"); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed \n"); |
| return -1; |
| } |
| |
| #endif |
| |
| return ret; |
| } else { |
| store_dbg("CARD BOOT,erase uboot : %s %d off =%llx ,size=%llx", |
| __func__, __LINE__, off, size); |
| return 0; |
| } |
| } else if (strcmp(area, "data") == 0) { |
| if (device_boot_flag == NAND_BOOT_FLAG) { |
| store_dbg("NAND BOOT,erase data : %s %d off =%llx ,size=%llx", |
| __func__, __LINE__, off, size); |
| #if defined(CONFIG_AML_NAND) |
| ret = run_command("amlnf deverase data 0",0); |
| if (ret != 0) { |
| store_msg("nand cmd failed "); |
| return -1; |
| } |
| ret = run_command("amlnf deverase code 0",0); |
| if (ret != 0) { |
| store_msg("nand cmd failed "); |
| return -1; |
| } |
| ret = run_command("amlnf deverase cache 0",0); |
| if (ret != 0) { |
| store_msg("nand cmd failed "); |
| return -1; |
| } |
| #elif defined(CONFIG_AML_MTD) |
| ret = run_command("nand device 1", 0); |
| ret |= run_command("nand erase.chip", 0); |
| #endif |
| return ret; |
| } else if (device_boot_flag == SPI_NAND_FLAG) { |
| store_dbg("spi+nand , %s %d ", __func__, __LINE__); |
| #if defined(CONFIG_AML_NAND) |
| /*case for uboot in nor flash,system in nand flash*/ |
| ret = run_command("amlnf deverase data 0",0); |
| if (ret != 0) { |
| store_msg("nand cmd failed "); |
| return -1; |
| } |
| |
| ret = run_command("amlnf deverase code 0",0); |
| if (ret != 0) { |
| store_msg("nand cmd failed "); |
| return -1; |
| } |
| ret = run_command("amlnf deverase cache 0",0); |
| if (ret != 0) { |
| store_msg("nand cmd failed "); |
| return -1; |
| } |
| #endif |
| return ret; |
| } else if (device_boot_flag == SPI_EMMC_FLAG) { |
| store_dbg("spi+mmc , %s %d ", __func__, __LINE__); |
| ret = run_command("mmc erase 1",0); // whole |
| if (ret != 0) { |
| store_msg("mmc cmd failed "); |
| return -1; |
| } |
| |
| return ret; |
| } else if (device_boot_flag == EMMC_BOOT_FLAG) { |
| store_dbg("MMC BOOT,erase data : %s %d off =%llx ,size=%llx", |
| __func__, __LINE__, off, size); |
| MsgP("amlmmc erase non_loader\n"); |
| ret = run_command("amlmmc erase non_loader",0); //whole |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed "); |
| return -1; |
| } |
| return ret; |
| } else { |
| store_dbg("CARD BOOT,erase data : %s %d off =%llx ,size=%llx", |
| __func__, __LINE__, off, size); |
| return 0; |
| } |
| } else if (strcmp(area, "key") == 0) { |
| if (device_boot_flag == EMMC_BOOT_FLAG) { |
| sprintf(str, "emmc erase key"); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("emmc cmd failed"); |
| return CMD_RET_USAGE; |
| } |
| } else if (device_boot_flag == NAND_BOOT_FLAG) { |
| #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| sprintf(str, "amlnf key_erase"); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("emmc cmd failed"); |
| return CMD_RET_USAGE; |
| } |
| #endif |
| } |
| } else if (strcmp(area, "dtb") == 0) { |
| if (device_boot_flag == EMMC_BOOT_FLAG) { |
| sprintf(str, "emmc erase dtb"); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("emmc cmd failed"); |
| return CMD_RET_USAGE; |
| } |
| } else if (device_boot_flag == NAND_BOOT_FLAG) { |
| #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| sprintf(str, "amlnf dtb_erase"); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("emmc cmd failed"); |
| return CMD_RET_USAGE; |
| } |
| #endif |
| } |
| } else if (strcmp(area, "partition") == 0) { |
| if (device_boot_flag == EMMC_BOOT_FLAG) { |
| int blk_shift; |
| int dev, n; |
| u64 cnt=0, blk =0; |
| struct partitions *part_info; |
| struct mmc *mmc = NULL; |
| char *p_name = NULL; |
| |
| p_name = argv[3]; |
| if (!p_name) |
| return CMD_RET_USAGE; |
| |
| dev = find_dev_num_by_partition_name(p_name); |
| if (dev < 0) |
| return CMD_RET_USAGE; |
| mmc = find_mmc_device(dev); |
| if (!mmc) |
| return CMD_RET_FAILURE; |
| |
| mmc_init(mmc); |
| if (!ffs(mmc->read_bl_len)) |
| return CMD_RET_FAILURE; |
| blk_shift = ffs(mmc->read_bl_len) -1; |
| if (!(info_disprotect & DISPROTECT_KEY) |
| && (strncmp(p_name, MMC_RESERVED_NAME, |
| sizeof(MMC_RESERVED_NAME)) == 0x00)) { |
| printf("\"%s-partition\" is been protecting and should no be erased!\n", |
| MMC_RESERVED_NAME); |
| return CMD_RET_FAILURE; |
| } |
| |
| part_info = find_mmc_partition_by_name(p_name); |
| if (part_info == NULL) |
| return CMD_RET_FAILURE; |
| |
| blk = part_info->offset>> blk_shift; |
| if (emmc_cur_partition |
| && !strncmp(p_name, "bootloader", strlen("bootloader"))) |
| cnt = mmc->boot_size>> blk_shift; |
| else |
| cnt = part_info->size>> blk_shift; |
| n = mmc->block_dev.block_erase(dev, blk, cnt); |
| printf("store erase \"%s-partition\" is %s\n", p_name, n ? "fail" : "ok"); |
| if (n) |
| return CMD_RET_FAILURE; |
| } else if (device_boot_flag == NAND_BOOT_FLAG) { |
| #ifdef CONFIG_AML_MTD |
| if (argc < 4) |
| return CMD_RET_USAGE; |
| sprintf(str, "nand erase.part %s", argv[3]); |
| return run_command(str, 0); |
| #else |
| return CMD_RET_USAGE; |
| #endif//#ifdef CONFIG_AML_MTD |
| } else { |
| return CMD_RET_USAGE; |
| } |
| } else |
| return CMD_RET_USAGE; |
| |
| return 0; |
| } |
| |
| static int do_store_scrub(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| int ret = 0; |
| loff_t off=0; |
| char str[128]; |
| |
| off = (ulong)simple_strtoul(argv[2], NULL, 16); |
| sprintf(str, "amlnf scrub %d", (int)off); |
| if (device_boot_flag == NAND_BOOT_FLAG) { |
| #if defined(CONFIG_AML_NAND) |
| ret = run_command(str, 0); |
| #elif defined(CONFIG_AML_MTD) |
| printf("%s() fixme, to do...\n", __func__); |
| #else |
| ret = -1; |
| #endif |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| } else if (device_boot_flag == SPI_NAND_FLAG) { |
| store_dbg("spi+nand , %s %d ", __func__, __LINE__); |
| #if defined(CONFIG_AML_NAND) |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| #endif |
| |
| ret = run_command("sf probe 2", 0); |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| sprintf(str, "sf erase 0 0x%x", _SPI_FLASH_ERASE_SZ); |
| ret = run_command(str,0); |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| return ret; |
| } else if (device_boot_flag == SPI_EMMC_FLAG) { |
| store_dbg("spi+mmc , %s %d\n", __func__, __LINE__); |
| ret = run_command("amlmmc erase whole",0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed\n"); |
| return -1; |
| } |
| return ret; |
| } else if (device_boot_flag == EMMC_BOOT_FLAG) { |
| store_dbg("MMC BOOT, %s %d\n", __func__, __LINE__); |
| device_boot_flag = EMMC_BOOT_FLAG; |
| run_command("mmc dev 1", 0); |
| ret = run_command("mmcinfo", 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed\n"); |
| return -1; |
| } |
| if (_info_disprotect_back_before_mmcinfo1 & DISPROTECT_KEY) { |
| MsgP("mmc key\n"); |
| run_command("mmc key", 0); |
| } |
| MsgP("amlmmc erase 1"); |
| ret = run_command("amlmmc erase 1", 0); |
| } |
| |
| return ret; |
| } |
| |
| static int do_store_rom_protect(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| |
| #if defined(CONFIG_AML_NAND) |
| char str[128]; |
| char *area = argv[2]; |
| #endif |
| |
| if (argc < 3) |
| return CMD_RET_USAGE; |
| |
| if (device_boot_flag == NAND_BOOT_FLAG) { |
| #if defined(CONFIG_AML_NAND) |
| sprintf(str, "amlnf rom_protect %s", area); |
| store_dbg("command: %s", str); |
| int ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| #elif defined(CONFIG_AML_MTD) |
| printf("%s() fixme, to do...\n", __func__); |
| #else |
| return -1; |
| #endif |
| } |
| |
| return CMD_RET_SUCCESS; |
| } |
| |
| static int do_store_rom_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| u64 addr; |
| loff_t off=0, size=0; |
| char str[128]; |
| int ret = 0; |
| if (argc < 5) |
| return CMD_RET_USAGE; |
| |
| addr = (ulong)simple_strtoul(argv[2], NULL, 16); |
| if (get_off_size(argc - 3, (char **)(argv + 3), &off, &size) != 0) |
| return CMD_RET_FAILURE; |
| |
| if (device_boot_flag == NAND_BOOT_FLAG) { |
| #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| #ifndef CONFIG_DISCRETE_BOOTLOADER |
| sprintf(str, "amlnf rom_write 0x%llx 0x%llx 0x%llx", addr, off, size); |
| store_dbg("command: %s", str); |
| ret = run_command(str, 0); |
| #else |
| /* |
| *store rom_write addr offset size <iCopy> |
| //Used to update the whole bootloader, i.e, update 'bl2 + tpl' at the same time |
| @iCopy is optional, |
| if used, must < min(tplcpynum, bl2cpynum), and update only the specified copy |
| if not used, update all the copies of bl2 and tpl |
| */ |
| const int bl2size = BL2_SIZE; |
| const int bl2cpynum = CONFIG_BL2_COPY_NUM; //TODO: decided by efuse, no macro |
| const int tplcapsize = CONFIG_TPL_SIZE_PER_COPY; |
| const int tplcpynum = CONFIG_TPL_COPY_NUM; |
| const int bootloadermaxsz = bl2size + tplcapsize; |
| const int tplwritesz = size - bl2size; |
| loff_t copyoff = 0; |
| const int icopy2update = argc > 5 ? simple_strtoul(argv[5], NULL, 0) : -1; |
| const int TPL_MIN_SZ = (1U << 16); |
| const int updatetpl = tplwritesz > TPL_MIN_SZ; |
| int i = 0; |
| |
| if (bootloadermaxsz < size) { |
| ErrP("bootloader sz 0x%llx too large,max sz 0x%x\n", |
| size, bootloadermaxsz); |
| return CMD_RET_FAILURE; |
| } |
| if (!updatetpl) |
| MsgP("Warn:tplwritesz 0x%x too small,update bl2 but not tpl\n", |
| tplwritesz); |
| if (icopy2update >= tplcpynum || icopy2update >= bl2cpynum) { |
| ErrP("icopy2update[%s] invalid, must < min(%d, %d)\n", |
| argv[5], tplcpynum, bl2cpynum); |
| return CMD_RET_FAILURE; |
| } |
| for (i = 0; i < bl2cpynum; ++i) |
| { |
| if (icopy2update >= 0 && icopy2update != i) |
| continue; |
| |
| sprintf(str, "amlnf rom_erase %d", i); |
| ret = run_command(str, 0); |
| if (ret) { |
| ErrP("Failed at erase bl2[%d],ret=%d\n", i, ret); |
| return CMD_RET_FAILURE; |
| } |
| |
| //copyoff = i * bl2size; |
| sprintf(str, "amlnf bl2_write 0x%llx %d 0x%x", addr, i, bl2size); |
| debugP("runCmd[%s]\n", str); |
| ret = run_command(str, 0); |
| if (ret) { |
| ErrP("Failed at pgram bl2[%d],ret=%d\n", i, ret); |
| return CMD_RET_FAILURE; |
| } |
| } |
| addr += bl2size; |
| for (i = 0; i < tplcpynum && updatetpl; ++i) |
| { |
| if (icopy2update >= 0 && icopy2update != i) |
| continue; |
| |
| sprintf(str, "amlnf fip_erase %d", i); |
| ret = run_command(str, 0); |
| if (ret) { |
| ErrP("Failed at erase tpl[%d],ret=%d\n", i, ret); |
| return CMD_RET_FAILURE; |
| } |
| |
| copyoff = i * tplcapsize; |
| sprintf(str, "amlnf fip_write 0x%llx %llx 0x%x", addr, copyoff, tplwritesz); |
| debugP("runCmd[%s]\n", str); |
| ret = run_command(str, 0); |
| if (ret) { |
| ErrP("Failed at pgram bl2[%d],ret=%d\n", i, ret); |
| return CMD_RET_FAILURE; |
| } |
| } |
| #if CONFIG_TPL_VAL_NUM_MIN |
| _bootloaderOrgCrc[0] = crc32(0, |
| (unsigned char *)(addr - bl2size), bl2size); |
| _bootloaderOrgCrc[1] = crc32(0, |
| (unsigned char *)addr, tplwritesz); |
| #endif// #if CONFIG_TPL_VAL_NUM_MIN |
| #endif//#ifndef CONFIG_DISCRETE_BOOTLOADER |
| #else |
| ret = -1; |
| #endif |
| /* |
| * Need consider that CONFIG_AML_NAND was not defined. |
| */ |
| /* coverity[dead_error_line] */ |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| /* |
| * Need consider that CONFIG_AML_NAND was not defined. |
| */ |
| /* coverity[dead_error_line] */ |
| return ret; |
| } else if ((device_boot_flag == SPI_EMMC_FLAG) || |
| (device_boot_flag == SPI_NAND_FLAG)) { |
| ret = run_command("sf probe 2",0); |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| sprintf(str, "sf erase 0x%llx 0x%llx ", off, size); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| sprintf(str, "sf write 0x%llx 0x%llx 0x%llx ",addr, off, size); |
| store_dbg("command: %s", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| return ret; |
| } else if (device_boot_flag == EMMC_BOOT_FLAG) { |
| store_dbg("MMC BOOT, %s %d\n", __func__, __LINE__); |
| #ifndef CONFIG_AML_SECU_BOOT_V2 |
| #ifdef MMC_UBOOT_CLEAR_MBR |
| //modify the 55 AA info for emmc uboot |
| unsigned char *tmp_buf= (unsigned char *)addr; |
| _mbrFlag[0] = tmp_buf[510]; |
| _mbrFlag[1] = tmp_buf[511]; |
| tmp_buf[510]=0; |
| tmp_buf[511]=0; |
| #endif |
| #endif// #if defined(CONFIG_AML_SECU_BOOT_V2) |
| sprintf(str, "amlmmc write bootloader 0x%llx 0x%llx 0x%llx", |
| addr, off, size); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed \n"); |
| return -1; |
| } |
| return ret; |
| } else { |
| store_dbg("CARD BOOT, %s %d", __func__, __LINE__); |
| return 0; |
| } |
| } |
| |
| static int do_store_rom_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| u64 addr; |
| loff_t off=0, size=0; |
| char str[128]; |
| int ret = 0; |
| int i = 0, read = 2; |
| cpu_id_t cpu_id = get_cpu_id(); |
| |
| if (argc < 5) |
| return CMD_RET_USAGE; |
| |
| addr = (ulong)simple_strtoul(argv[2], NULL, 16); |
| if (get_off_size(argc - 3, (char **)(argv + 3), &off, &size) != 0) |
| return CMD_RET_FAILURE; |
| |
| if (device_boot_flag == NAND_BOOT_FLAG) { |
| #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| #ifndef CONFIG_DISCRETE_BOOTLOADER |
| sprintf(str, "amlnf rom_read 0x%llx 0x%llx 0x%llx", addr, off, size); |
| store_dbg("command: %s", str); |
| ret = run_command(str, 0); |
| #else |
| /* |
| *store rom_read addr offset size <iCopy> |
| //Used to read the whole bootloader, i.e, update 'bl2 + tpl' at the same time |
| @iCopy is optional, |
| if used, must < min(tplcpynum, bl2cpynum), and read only the specified copy |
| if not used, check if all the copies of 'bl2 + tpl' are same content |
| */ |
| const int bl2size = BL2_SIZE; |
| const int bl2cpynum = CONFIG_BL2_COPY_NUM; //TODO: decided by efuse, no macro |
| const int tplcapsize = CONFIG_TPL_SIZE_PER_COPY; |
| const int tplcpynum = CONFIG_TPL_COPY_NUM; |
| const int bootloadermaxsz = bl2size + tplcapsize; |
| const int tplrealsz = size - bl2size; |
| loff_t copyoff = 0; |
| int icopy2update = argc > 5 ? simple_strtoul(argv[5], NULL, 0) : -1; |
| char *tmpbuf = NULL; |
| int okcrcnum = 0; |
| const int verifymode = |
| (off == (1ULL << 62) - 1) && (icopy2update < 0); //verify mode |
| |
| if (!verifymode && icopy2update < 0) |
| icopy2update = 0; //default read copy 0 if no verify mode |
| |
| if (bootloadermaxsz < size || tplrealsz < 0) { |
| ErrP("bootloader sz 0x%llx invalid, max sz %d\n", size, bootloadermaxsz); |
| return CMD_RET_FAILURE; |
| } |
| if (icopy2update >= tplcpynum || icopy2update >= bl2cpynum) { |
| ErrP("icopy2update[%s] invalid, must < min(%d, %d)\n", |
| argv[5], tplcpynum, bl2cpynum); |
| return CMD_RET_FAILURE; |
| } |
| |
| tmpbuf = (char *)malloc(size); |
| if (!tmpbuf) { |
| ErrP("Failed malloc 0x%llx bytes\n", size); |
| return CMD_RET_FAILURE; |
| } |
| memset(tmpbuf, 0, size); |
| |
| char *readbuf = tmpbuf; |
| const u32 orgbl2crc = _bootloaderOrgCrc[0]; |
| |
| for (i = 0; i < bl2cpynum; ++i) |
| { |
| if (icopy2update >= 0 && icopy2update != i) |
| continue; |
| |
| sprintf(str, "amlnf bl2_read 0x%p %x 0x%x", readbuf, i, bl2size); |
| debugP("runCmd[%s]\n", str); |
| ret = run_command(str, 0); |
| if (ret) { |
| ErrP("Failed at pgram bl2[%d],ret=%d\n", i, ret); |
| free(tmpbuf); |
| return CMD_RET_FAILURE; |
| } |
| #if CONFIG_BL2_VAL_NUM_MIN |
| if (verifymode) {//copy index not specified, need read all copies |
| const u32 readcrc = crc32(0, (unsigned char *)readbuf, bl2size); |
| |
| if (readcrc == orgbl2crc) { |
| okcrcnum += 1; |
| if (okcrcnum >= CONFIG_BL2_VAL_NUM_MIN) |
| break; |
| } |
| } |
| #endif//#if CONFIG_BL2_VAL_NUM_MIN |
| } |
| #if CONFIG_BL2_VAL_NUM_MIN |
| if (okcrcnum < CONFIG_BL2_VAL_NUM_MIN && verifymode) { |
| ErrP("okcrcnum(%d) < CONFIG_BL2_VAL_NUM_MIN(%d)\n", |
| okcrcnum, CONFIG_BL2_VAL_NUM_MIN); |
| free(tmpbuf); |
| return CMD_RET_FAILURE; |
| } |
| okcrcnum = 0; |
| #endif//#if CONFIG_BL2_VAL_NUM_MIN |
| memcpy((char *)addr, readbuf, bl2size); |
| |
| if (tplrealsz > 0) // to support dump only bl2 |
| { |
| const u32 orgtplcrc = _bootloaderOrgCrc[1]; |
| |
| for (i = 0; i < tplcpynum && !ret; ++i) |
| { |
| if (icopy2update >= 0 && icopy2update != i) |
| continue; |
| |
| copyoff = i * tplcapsize; |
| sprintf(str, "amlnf fip_read 0x%p %llx 0x%x", |
| readbuf, copyoff, tplrealsz); |
| debugP("runCmd[%s]\n", str); |
| ret = run_command(str, 0); |
| if (ret) { |
| ErrP("Failed at pgram bl2[%d],ret=%d\n", i, ret); |
| free(tmpbuf); |
| return CMD_RET_FAILURE; |
| } |
| #if CONFIG_TPL_VAL_NUM_MIN |
| if (verifymode) //copy index not specified, need read all copies |
| { |
| const u32 readcrc = crc32(0, |
| (unsigned char *)readbuf, tplrealsz); |
| |
| if (orgtplcrc == readcrc) |
| okcrcnum += 1; |
| if (okcrcnum >= CONFIG_TPL_VAL_NUM_MIN) |
| break; |
| } |
| #endif//#if CONFIG_TPL_VAL_NUM_MIN |
| } |
| #if CONFIG_TPL_VAL_NUM_MIN |
| if (okcrcnum < CONFIG_TPL_VAL_NUM_MIN && verifymode) { |
| ErrP("okcrcnum(%d) < CONFIG_TPL_VAL_NUM_MIN(%d)\n", |
| okcrcnum, CONFIG_TPL_VAL_NUM_MIN); |
| free(tmpbuf); |
| return CMD_RET_FAILURE; |
| } |
| #endif//#if CONFIG_TPL_VAL_NUM_MIN |
| memcpy((char *)addr + bl2size, (unsigned char *)readbuf, tplrealsz); |
| } |
| free(tmpbuf); |
| #endif// #ifndef CONFIG_DISCRETE_BOOTLOADER |
| #else |
| ret = -1; |
| #endif// #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| /* |
| * Need consider that CONFIG_AML_NAND was not defined. |
| */ |
| /* coverity[dead_error_line] */ |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| /* |
| * Need consider that CONFIG_AML_NAND was not defined. |
| */ |
| /* coverity[dead_error_line] */ |
| return ret; |
| } else if ((device_boot_flag == SPI_EMMC_FLAG) || |
| (device_boot_flag == SPI_NAND_FLAG)) { |
| ret = run_command("sf probe 2",0); |
| if (ret != 0) { |
| return -1; |
| } |
| sprintf(str, "sf read 0x%llx 0x%llx 0x%llx ", |
| addr, off, size); |
| store_dbg("command: %s", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("nand cmd failed"); |
| return -1; |
| } |
| return ret; |
| } else if (device_boot_flag == EMMC_BOOT_FLAG) { |
| if (cpu_id.family_id >= MESON_CPU_MAJOR_ID_GXL) |
| off += 512; |
| store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__); |
| sprintf(str, "amlmmc read bootloader 0x%llx 0x%llx 0x%llx", |
| addr, off, size); |
| store_dbg("command: %s\n", str); |
| //tmp_buf= (unsigned char *)addr; |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed \n"); |
| return -1; |
| } |
| |
| #ifdef MMC_BOOT_PARTITION_SUPPORT |
| #ifdef CONFIG_EMMC_KEEP_BOOT1 |
| if (get_cpu_id().family_id != MESON_CPU_MAJOR_ID_TM2) { |
| store_msg("WRONG CONFIG_EMMC_KEEP_BOOT1 enabled!\n"); |
| return -1; |
| } |
| if (get_cpu_id().chip_rev == 0xA) |
| read = 1; |
| #endif |
| for (i = 0; i < read; i++) { |
| //switch to boot partition here |
| sprintf(str, "amlmmc switch 1 boot%d", i); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| if (ret == -1) { |
| return 0; |
| } else if (ret != 0) { |
| store_msg("amlmmc cmd failed"); |
| goto R_SWITCH_BACK; |
| //return -1; |
| } |
| |
| //write uboot to boot partition |
| sprintf(str, "amlmmc read bootloader 0x%llx 0x%llx 0x%llx", |
| addr, off, size); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed \n"); |
| //return -1; |
| goto R_SWITCH_BACK; |
| } |
| } |
| |
| R_SWITCH_BACK: |
| //switch back to urs partition |
| sprintf(str, "amlmmc switch 1 user"); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed \n"); |
| return -1; |
| } |
| |
| #endif |
| #ifndef CONFIG_AML_SECU_BOOT_V2 |
| #ifdef MMC_UBOOT_CLEAR_MBR |
| unsigned char *tmp_buf= (unsigned char *)addr; |
| tmp_buf[510]= _mbrFlag[0]; |
| tmp_buf[511]= _mbrFlag[1]; |
| #endif |
| #endif// #ifndef CONFIG_AML_SECU_BOOT_V2 |
| return ret; |
| } else { |
| store_dbg("CARD BOOT, %s %d ",__func__,__LINE__); |
| return 0; |
| } |
| |
| } |
| |
| static int do_store_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| u64 addr; |
| loff_t off=0, size=0; |
| char str[128]; |
| int ret = 0; |
| char *s = argv[2]; |
| |
| if (argc < 6) |
| return CMD_RET_USAGE; |
| |
| addr = (ulong)simple_strtoul(argv[3], NULL, 16); |
| |
| if (get_off_size(argc - 4, (char **)(argv + 4), &off, &size) != 0) |
| return CMD_RET_FAILURE; |
| |
| store_dbg("addr = %llx off= 0x%llx size=0x%llx",addr,off,size); |
| if (device_boot_flag == NAND_BOOT_FLAG) { |
| #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| #if defined(CONFIG_AML_NAND) |
| sprintf(str, "amlnf read_byte %s 0x%llx 0x%llx 0x%llx", |
| s, addr, off, size); |
| #elif defined(CONFIG_AML_MTD) |
| #if defined(CONFIG_DISCRETE_BOOTLOADER) |
| if (!strcmp(CONFIG_TPL_PART_NAME, s)) { |
| const int tplcapsize = CONFIG_TPL_SIZE_PER_COPY; |
| const int tplcpynum = CONFIG_TPL_COPY_NUM; |
| const int icopy2update = |
| argc > 6 ? simple_strtoul(argv[6], NULL, 0) : 0;//0 copy at default |
| |
| if (icopy2update >= tplcpynum) { |
| ErrP("icopy2update[%s] invalid, must < max(%d)\n", |
| argv[6], tplcpynum); |
| return CMD_RET_FAILURE; |
| } |
| |
| loff_t copyoff = icopy2update * tplcapsize; |
| |
| sprintf(str, "amlnf fip_read 0x%llx %llx 0x%llx", |
| addr, copyoff, size); |
| } else { |
| #endif // #if defined(CONFIG_DISCRETE_BOOTLOADER) |
| ret = mtd_find_phy_off_by_lgc_off(s, off, &off); |
| if (ret) { |
| ErrP("Fail in find phy addr by logic off (0x%llx),ret(%d)\n", |
| off, ret); |
| return CMD_RET_FAILURE; |
| } |
| sprintf(str, "nand read %s 0x%llx 0x%llx 0x%llx", |
| s, addr, off, size); |
| } |
| #endif // #if defined(CONFIG_AML_NAND) |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("nand cmd [%s] failed ",str); |
| return -1; |
| } |
| #else |
| ret = -1; |
| #endif |
| /* |
| * Need consider that CONFIG_AML_NAND was not defined. |
| */ |
| /* coverity[dead_error_line] */ |
| return ret; |
| } else if (device_boot_flag == SPI_NAND_FLAG) { |
| #if defined(CONFIG_AML_NAND) |
| sprintf(str, "amlnf read_byte %s 0x%llx 0x%llx 0x%llx", |
| s, addr, off, size); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| #else |
| return -1; |
| #endif |
| |
| #if defined(CONFIG_AML_NAND) |
| if (ret != 0) { |
| store_msg("nand cmd failed \n"); |
| return -1; |
| } else { |
| return ret; |
| } |
| #endif |
| } else if (device_boot_flag == SPI_EMMC_FLAG) { |
| store_dbg("spi+mmc , %s %d ",__func__,__LINE__); |
| sprintf(str, "amlmmc read %s 0x%llx 0x%llx 0x%llx", |
| s, addr, off, size); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed \n"); |
| return -1; |
| } |
| return ret; |
| } else if (device_boot_flag == EMMC_BOOT_FLAG) { |
| store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__); |
| sprintf(str, "amlmmc read %s 0x%llx 0x%llx 0x%llx", |
| s, addr, off, size); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed \n"); |
| return -1; |
| } |
| return ret; |
| } else { |
| store_dbg("CARD BOOT, %s %d ",__func__,__LINE__); |
| |
| return 0; |
| } |
| } |
| |
| static int do_store_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| u64 addr; |
| loff_t off=0, size=0; |
| char str[128]; |
| int ret = -1; |
| char *s = argv[2]; |
| |
| if (argc < 6) |
| return CMD_RET_USAGE; |
| |
| addr = (ulong)simple_strtoul(argv[3], NULL, 16); |
| if (get_off_size(argc - 4, (char **)(argv + 4), &off, &size) != 0) |
| return CMD_RET_FAILURE; |
| |
| if (device_boot_flag == NAND_BOOT_FLAG) { |
| #if defined(CONFIG_AML_NAND) || defined(CONFIG_AML_MTD) |
| #if defined(CONFIG_AML_NAND) |
| sprintf(str, "amlnf write_byte %s 0x%llx 0x%llx 0x%llx", |
| s, addr, off, size); |
| ret = run_command(str, 0); |
| #elif defined(CONFIG_AML_MTD) |
| #if defined(CONFIG_DISCRETE_BOOTLOADER) |
| if (!strcmp(CONFIG_TPL_PART_NAME, s)) { |
| const int tplcapsize = CONFIG_TPL_SIZE_PER_COPY; |
| const int tplcpynum = CONFIG_TPL_COPY_NUM; |
| const int icopy2update = |
| argc > 6 ? simple_strtoul(argv[6], NULL, 0) : -1; |
| int i = 0; |
| |
| debugP("icopy2update=%d, tplcpynum=%d\n", icopy2update, tplcpynum); |
| if (icopy2update >= tplcpynum) { |
| ErrP("icopy2update[%s] invalid, must < max(%d)\n", |
| argv[6], tplcpynum); |
| return CMD_RET_FAILURE; |
| } |
| |
| for (i = 0; i < tplcpynum; ++i) |
| { |
| if (icopy2update >= 0 && icopy2update != i) |
| continue; |
| |
| sprintf(str, "amlnf fip_erase %d", i); |
| ret = run_command(str, 0); |
| if (ret) { |
| ErrP("Failed at erase tpl[%d],ret=%d\n", i, ret); |
| return CMD_RET_FAILURE; |
| } |
| |
| loff_t copyoff = i * tplcapsize; |
| |
| sprintf(str, "amlnf fip_write 0x%llx %llx 0x%llx", |
| addr, copyoff, size); |
| debugP("runCmd[%s]\n", str); |
| ret = run_command(str, 0); |
| if (ret) { |
| ErrP("Failed at pgram bl2[%d],ret=%d\n", i, ret); |
| return CMD_RET_FAILURE; |
| } |
| } |
| } else |
| #endif // #if defined(CONFIG_DISCRETE_BOOTLOADER) |
| { |
| ret = mtd_find_phy_off_by_lgc_off(s, off, &off); |
| if (ret) { |
| ErrP("Fail in find phy addr by logic off (0x%llx),ret(%d)\n", off, ret); |
| } |
| sprintf(str, "nand write %s 0x%llx 0x%llx 0x%llx",s, addr, off, size); |
| ret = run_command(str, 0); |
| } |
| #endif |
| #endif |
| if (ret != 0) { |
| store_msg("nand cmd failed "); |
| return -1; |
| } |
| } else if (device_boot_flag == SPI_NAND_FLAG) { |
| store_dbg("spi+nand , %s %d ",__func__,__LINE__); |
| #if defined(CONFIG_AML_NAND) |
| sprintf(str, "amlnf write_byte %s 0x%llx 0x%llx 0x%llx", s, addr, off, size); |
| store_dbg("command: %s", str); |
| ret = run_command(str, 0); |
| #else |
| ret = -1; |
| #endif |
| |
| if (ret != 0) { |
| store_msg("nand cmd failed \n"); |
| return -1; |
| #if defined(CONFIG_AML_NAND) |
| } else { |
| return ret; |
| #endif |
| } |
| } else if (device_boot_flag == SPI_EMMC_FLAG) { |
| store_dbg("spi+mmc , %s %d ",__func__,__LINE__); |
| sprintf(str, "amlmmc write %s 0x%llx 0x%llx 0x%llx", s, addr, off, size); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed \n"); |
| return -1; |
| } |
| } else if (device_boot_flag == EMMC_BOOT_FLAG) { |
| store_dbg("MMC BOOT, %s %d \n",__func__,__LINE__); |
| sprintf(str, "amlmmc write %s 0x%llx 0x%llx 0x%llx", s, addr, off, size); |
| store_dbg("command: %s\n", str); |
| ret = run_command(str, 0); |
| if (ret != 0) { |
| store_msg("amlmmc cmd failed \n"); |
| return -1; |
| } |
| } else { |
| store_dbg("CARD BOOT, %s %d ",__func__,__LINE__); |
| ret = CMD_RET_FAILURE; |
| } |
| return ret; |
| } |
| |
| static cmd_tbl_t cmd_store_sub[] = { |
| U_BOOT_CMD_MKENT(init, 4, 0, do_store_init, "", ""), |
| U_BOOT_CMD_MKENT(exit, 3, 0, do_store_exit, "", ""), |
| U_BOOT_CMD_MKENT(disprotect, 3, 0, do_store_disprotect, "", ""), |
| U_BOOT_CMD_MKENT(rom_protect, 5, 0, do_store_rom_protect, "", ""), |
| U_BOOT_CMD_MKENT(size, 5, 0, do_store_size, "", ""), |
| U_BOOT_CMD_MKENT(scrub, 3, 0, do_store_scrub, "", ""), |
| U_BOOT_CMD_MKENT(erase, 5, 0, do_store_erase, "", ""), |
| U_BOOT_CMD_MKENT(read, 7, 0, do_store_read, "", ""), |
| U_BOOT_CMD_MKENT(write, 7, 0, do_store_write, "", ""), |
| U_BOOT_CMD_MKENT(rom_read, 5, 0, do_store_rom_read, "", ""), |
| U_BOOT_CMD_MKENT(rom_write, 5, 0, do_store_rom_write, "", ""), |
| U_BOOT_CMD_MKENT(dtb, 5, 0, do_store_dtb_ops, "", ""), |
| U_BOOT_CMD_MKENT(key, 5, 0, do_store_key_ops, "", ""), |
| U_BOOT_CMD_MKENT(ddr_parameter, 5, 0, do_store_ddr_parameter_ops, "", ""), |
| U_BOOT_CMD_MKENT(mbr, 3, 0, do_store_mbr_ops, "", ""), |
| U_BOOT_CMD_MKENT(bootlog, 2, 0, do_store_bootlog, "", ""), |
| }; |
| |
| static int do_store(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
| { |
| cmd_tbl_t *c; |
| |
| if (argc < 2) |
| return CMD_RET_USAGE; |
| c = find_cmd_tbl(argv[1], cmd_store_sub, ARRAY_SIZE(cmd_store_sub)); |
| if (c) |
| return c->cmd(cmdtp, flag, argc, argv); |
| |
| return CMD_RET_USAGE; |
| } |
| |
| U_BOOT_CMD(store, CONFIG_SYS_MAXARGS, 1, do_store, |
| "STORE sub-system", |
| "init flag\n" |
| "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 rom_write add off size.\n" |
| " write uboot to the boot device\n" |
| "store erase boot/data: \n" |
| " erase the area which is uboot or data \n" |
| "store erase partition <partition_name>: \n" |
| " erase the area which partition in u-boot \n" |
| "store erase dtb \n" |
| "store erase key \n" |
| "store disprotect key \n" |
| "store rom_protect on/off \n" |
| "store scrub off|partition size\n" |
| " scrub the area from offset and size \n" |
| "store dtb iread/read/write addr <size>\n" |
| " read/write dtb, size is optional \n" |
| "store key read/write addr <size>\n" |
| " read/write key, size is optional \n" |
| "store ddr_parameter read/write addr <size>\n" |
| " read/write ddr parameter, size is optional \n" |
| "store mbr addr\n" |
| " update mbr/partition table by dtb\n" |
| "store bootlog\n" |
| " show boot logs\n" |
| ); |
| |