diff --git a/arch/arm/cpu/armv7/qca/common/scm.c b/arch/arm/cpu/armv7/qca/common/scm.c index e0ab2b4eb7..9e697d6fcb 100644 --- a/arch/arm/cpu/armv7/qca/common/scm.c +++ b/arch/arm/cpu/armv7/qca/common/scm.c @@ -266,7 +266,7 @@ int __qca_scm_call_armv8_32(u32 x0, u32 x1, u32 x2, u32 x3, u32 x4, u32 x5, /** - * qca_scm_call() - Invoke a syscall in the secure world + * scm_call_64() - Invoke a syscall in the secure world * svc_id: service identifier * cmd_id: command identifier * fn_id: The function ID for this syscall @@ -275,7 +275,7 @@ int __qca_scm_call_armv8_32(u32 x0, u32 x1, u32 x2, u32 x3, u32 x4, u32 x5, * Sends a command to the SCM and waits for the command to finish processing. * */ -static int qca_scm_call(u32 svc_id, u32 cmd_id, struct qca_scm_desc *desc) +static int scm_call_64(u32 svc_id, u32 cmd_id, struct qca_scm_desc *desc) { int arglen = desc->arginfo & 0xf; int ret; @@ -313,7 +313,7 @@ void __attribute__ ((noreturn)) jump_kernel64(void *kernel_entry, desc.args[1] = sizeof(param); printf("Jumping to AARCH64 kernel via monitor\n"); - ret = qca_scm_call(SCM_ARCH64_SWITCH_ID, SCM_EL1SWITCH_CMD_ID, + ret = scm_call_64(SCM_ARCH64_SWITCH_ID, SCM_EL1SWITCH_CMD_ID, &desc); printf("Can't boot kernel: %d\n", ret); @@ -321,3 +321,19 @@ void __attribute__ ((noreturn)) jump_kernel64(void *kernel_entry, } #endif + +int qca_scm_call(u32 svc_id, u32 cmd_id, void *buf, size_t len) +{ + struct qca_scm_desc desc = {0}; + int ret = 0; + + desc.arginfo = QCA_SCM_ARGS(2, SCM_READ_OP); + desc.args[0] = buf; + desc.args[1] = len; +#ifdef CONFIG_SCM_TZ64 + ret = scm_call_64(svc_id, cmd_id, &desc); +#else + ret = scm_call(svc_id, cmd_id, NULL, 0, buf, len); +#endif + return ret; +} diff --git a/arch/arm/include/asm/arch-qcom-common/qca_common.h b/arch/arm/include/asm/arch-qcom-common/qca_common.h index 7e73d5e362..926712111b 100644 --- a/arch/arm/include/asm/arch-qcom-common/qca_common.h +++ b/arch/arm/include/asm/arch-qcom-common/qca_common.h @@ -39,6 +39,15 @@ typedef struct { int qca_mmc_init(bd_t *, qca_mmc *); void board_mmc_deinit(void); +struct dumpinfo_t{ + char name[16]; /* use only file name in 8.3 format */ + uint32_t start; + uint32_t size; + int is_aligned_access; /* non zero represent 4 byte access */ +}; +extern struct dumpinfo_t dumpinfo[]; +extern int dump_entries; + #define MSM_SDC1_BASE 0x7824000 #define MMC_IDENTIFY_MODE 0 #define MMC_DATA_TRANSFER_MODE 1 diff --git a/arch/arm/include/asm/arch-qcom-common/scm.h b/arch/arm/include/asm/arch-qcom-common/scm.h index 1fe908a7d4..041a39c680 100644 --- a/arch/arm/include/asm/arch-qcom-common/scm.h +++ b/arch/arm/include/asm/arch-qcom-common/scm.h @@ -90,11 +90,31 @@ struct scm_response { int scm_init(void); extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, void *resp_buf, size_t resp_len); +extern int qca_scm_call(u32 svc_id, u32 cmd_id, void *buf, size_t len); -#ifdef CONFIG_SCM_TZ64 +#define MAX_QCA_SCM_RETS 3 +#define MAX_QCA_SCM_ARGS 10 +#define SCM_READ_OP 1 -#define QCA_SCM_SIP_FNID(s, c) (((((s) & 0xFF) << 8) | \ - ((c) & 0xFF)) | 0x02000000) +/** + * struct qca_scm_desc + * arginfo: Metadata describi`ng the arguments in args[] + * args: The array of arguments for the secure syscall + * ret: The values returned by the secure syscall + * extra_arg_buf: The buffer containing extra arguments + (that don't fit in available registers) + * x5: The 4rd argument to the secure syscall or physical address of + extra_arg_buf + */ +struct qca_scm_desc { + u32 arginfo; + u32 args[MAX_QCA_SCM_ARGS]; + u32 ret[MAX_QCA_SCM_RETS]; + + /* private */ + void *extra_arg_buf; + u64 x5; +}; #define QCA_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\ (((a) & 0xff) << 4) | \ @@ -112,6 +132,11 @@ extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, #define QCA_SCM_ARGS(...) QCA_SCM_ARGS_IMPL(__VA_ARGS__, \ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) +#ifdef CONFIG_SCM_TZ64 + +#define QCA_SCM_SIP_FNID(s, c) (((((s) & 0xFF) << 8) | \ + ((c) & 0xFF)) | 0x02000000) + #define QCA_MAX_ARG_LEN 5 typedef struct { @@ -131,33 +156,9 @@ typedef struct { #define SCM_EL1SWITCH_CMD_ID 0xf #define SCM_NULL_OP 0 -#define SCM_READ_OP 1 #define SCM_RW_OP 2 #define SCM_BUF_VAL 3 -#define MAX_QCA_SCM_RETS 3 -#define MAX_QCA_SCM_ARGS 10 - -/** - * struct qca_scm_desc - * arginfo: Metadata describi`ng the arguments in args[] - * args: The array of arguments for the secure syscall - * ret: The values returned by the secure syscall - * extra_arg_buf: The buffer containing extra arguments - (that don't fit in available registers) - * x5: The 4rd argument to the secure syscall or physical address of - extra_arg_buf - */ -struct qca_scm_desc { - u32 arginfo; - u32 args[MAX_QCA_SCM_ARGS]; - u32 ret[MAX_QCA_SCM_RETS]; - - /* private */ - void *extra_arg_buf; - u64 x5; -}; - void __attribute__ ((noreturn)) jump_kernel64(void *kernel_entry, void *fdt_addr); diff --git a/board/qca/common/cmd_bootqca.c b/board/qca/common/cmd_bootqca.c index d613ccb2e7..35f8358894 100644 --- a/board/qca/common/cmd_bootqca.c +++ b/board/qca/common/cmd_bootqca.c @@ -25,7 +25,7 @@ #include #include "fdt_info.h" -#define DLOAD_MAGIC_COOKIE0x10 +#define DLOAD_MAGIC_COOKIE 0x10 #define XMK_STR(x)#x #define MK_STR(x)XMK_STR(x) @@ -61,6 +61,55 @@ typedef struct { kernel_img_info_t kernel_img_info; +static int do_dumpqca_data(cmd_tbl_t *cmdtp, int flag, int argc, + char *const argv[]) +{ + char runcmd[128]; + char *serverip = NULL; + /* dump to root of TFTP server if none specified */ + char *dumpdir; + uint32_t memaddr; + int indx; + + if (argc == 2) { + serverip = argv[1]; + printf("Using given serverip %s\n", serverip); + setenv("serverip", serverip); + } else { + serverip = getenv("serverip"); + if (serverip != NULL) { + printf("Using serverip from env %s\n", serverip); + } else { + printf("\nServer ip not found, run dhcp or configure\n"); + return CMD_RET_FAILURE; + } + } + if ((dumpdir = getenv("dumpdir")) != NULL) { + printf("Using directory %s in TFTP server\n", dumpdir); + } else { + dumpdir = ""; + printf("Env 'dumpdir' not set. Using / dir in TFTP server\n"); + } + + for (indx = 0; indx < dump_entries; indx++) { + printf("\nProcessing %s:", dumpinfo[indx].name); + memaddr = dumpinfo[indx].start; + + snprintf(runcmd, sizeof(runcmd), "tftpput 0x%x 0x%x %s/%s", + memaddr, dumpinfo[indx].size, + dumpdir, dumpinfo[indx].name); + + if (run_command(runcmd, 0) != CMD_RET_SUCCESS) + return CMD_RET_FAILURE; + udelay(10000); /* give some delay for server */ + } + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD(dumpipq_data, 2, 0, do_dumpqca_data, + "dumpipq_data crashdump collection from memory", + "dumpipq_data [serverip] - Crashdump collection from memory vi tftp\n"); + /** * Inovke the dump routine and in case of failure, do not stop unless the user * requested to stop @@ -202,14 +251,12 @@ static int do_boot_signedimg(cmd_tbl_t *cmdtp, int flag, int argc, char *const a #ifdef CONFIG_QCA_APPSBL_DLOAD - ret = scm_call(SCM_SVC_BOOT, SCM_SVC_RD, NULL, - 0, (void *)&val, sizeof(val)); + ret = qca_scm_call(SCM_SVC_BOOT, SCM_SVC_RD, (void *)&val, sizeof(val)); /* check if we are in download mode */ if (val == DLOAD_MAGIC_COOKIE) { /* clear the magic and run the dump command */ val = 0x0; - ret = scm_call(SCM_SVC_BOOT, SCM_SVC_WR, - (void *)&val, sizeof(val), NULL, 0); + ret = qca_scm_call(SCM_SVC_BOOT, SCM_SVC_WR, (void *)&val, sizeof(val)); if (ret) printf ("Error in reseting the Magic cookie\n"); @@ -338,8 +385,8 @@ static int do_boot_signedimg(cmd_tbl_t *cmdtp, int flag, int argc, char *const a request += sizeof(mbn_header_t); - ret = scm_call(SCM_SVC_BOOT, KERNEL_AUTH_CMD, &kernel_img_info, - sizeof(kernel_img_info_t), NULL, 0); + ret = qca_scm_call(SCM_SVC_BOOT, KERNEL_AUTH_CMD, + (void *)&kernel_img_info, sizeof(kernel_img_info_t)); if (ret) { printf("Kernel image authentication failed \n"); @@ -388,14 +435,12 @@ static int do_boot_unsignedimg(cmd_tbl_t *cmdtp, int flag, int argc, char *const if (argc == 2 && strncmp(argv[1], "debug", 5) == 0) debug = 1; #ifdef CONFIG_QCA_APPSBL_DLOAD - ret = scm_call(SCM_SVC_BOOT, SCM_SVC_RD, NULL, - 0, (void *)&val, sizeof(val)); + ret = qca_scm_call(SCM_SVC_BOOT, SCM_SVC_RD, (void *)&val, sizeof(val)); /* check if we are in download mode */ if (val == DLOAD_MAGIC_COOKIE) { /* clear the magic and run the dump command */ val = 0x0; - ret = scm_call(SCM_SVC_BOOT, SCM_SVC_WR, - (void *)&val, sizeof(val), NULL, 0); + ret = qca_scm_call(SCM_SVC_BOOT, SCM_SVC_WR, (void *)&val, sizeof(val)); if (ret) printf ("Error in reseting the Magic cookie\n"); @@ -568,8 +613,7 @@ static int do_bootipq(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_FAILURE; } - ret = scm_call(SCM_SVC_FUSE, QFPROM_IS_AUTHENTICATE_CMD, - NULL, 0, &buf, sizeof(char)); + ret = qca_scm_call(SCM_SVC_FUSE, QFPROM_IS_AUTHENTICATE_CMD, &buf, sizeof(char)); if (ret == 0 && buf == 1) { return do_boot_signedimg(cmdtp, flag, argc, argv); diff --git a/board/qca/ipq40xx/ipq40xx.c b/board/qca/ipq40xx/ipq40xx.c index c3a354f3c5..73c32a8a66 100644 --- a/board/qca/ipq40xx/ipq40xx.c +++ b/board/qca/ipq40xx/ipq40xx.c @@ -52,6 +52,12 @@ const add_node_t add_node[] = { } }; +struct dumpinfo_t dumpinfo[] = { + { "EBICS0.BIN", 0x80000000, 0x10000000, 0 }, +}; + +int dump_entries = ARRAY_SIZE(dumpinfo); + extern loff_t board_env_offset; extern loff_t board_env_range; extern loff_t board_env_size; diff --git a/include/configs/ipq40xx.h b/include/configs/ipq40xx.h index acf802cfbc..b0043b7626 100644 --- a/include/configs/ipq40xx.h +++ b/include/configs/ipq40xx.h @@ -238,6 +238,21 @@ typedef struct { #define CONFIG_LIB_UUID +/* + * CRASH DUMP ENABLE + */ + +#define CONFIG_QCA_APPSBL_DLOAD 1 + +#ifdef CONFIG_QCA_APPSBL_DLOAD +#define CONFIG_CMD_TFTPPUT +/* We will be uploading very big files */ +#undef CONFIG_NET_RETRY_COUNT +#define CONFIG_NET_RETRY_COUNT 500 + +#endif + + #define CONFIG_QCA_MMC 1 #ifdef CONFIG_QCA_MMC diff --git a/net/tftp.c b/net/tftp.c index f2889fe4c9..5eb0f6d8cb 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -498,6 +498,7 @@ static void tftp_handler(uchar *pkt, unsigned dest, struct in_addr sip, int block = ntohs(*s); int ack_ok = (tftp_cur_block == block); + tftp_prev_block = tftp_cur_block; tftp_cur_block = (unsigned short)(block + 1); update_block_number(); if (ack_ok)