1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * (C) Copyright 2018 Xilinx, Inc. 4 * Siva Durga Prasad Paladugu <siva.durga.paladugu@xilinx.com> 5 */ 6 7 #include <common.h> 8 #include <malloc.h> 9 #include <asm/arch/hardware.h> 10 #include <asm/arch/sys_proto.h> 11 #include <asm/io.h> 12 13 static int do_zynqmp_verify_secure(cmd_tbl_t *cmdtp, int flag, int argc, 14 char * const argv[]) 15 { 16 u64 src_addr, addr; 17 u32 len, src_lo, src_hi; 18 u8 *key_ptr = NULL; 19 int ret; 20 u32 key_lo = 0; 21 u32 key_hi = 0; 22 u32 ret_payload[PAYLOAD_ARG_CNT]; 23 24 if (argc < 4) 25 return CMD_RET_USAGE; 26 27 src_addr = simple_strtoull(argv[2], NULL, 16); 28 len = simple_strtoul(argv[3], NULL, 16); 29 30 if (argc == 5) 31 key_ptr = (uint8_t *)(uintptr_t)simple_strtoull(argv[4], 32 NULL, 16); 33 34 if ((ulong)src_addr != ALIGN((ulong)src_addr, 35 CONFIG_SYS_CACHELINE_SIZE)) { 36 printf("Failed: source address not aligned:%lx\n", 37 (ulong)src_addr); 38 return -EINVAL; 39 } 40 41 src_lo = lower_32_bits((ulong)src_addr); 42 src_hi = upper_32_bits((ulong)src_addr); 43 flush_dcache_range((ulong)src_addr, (ulong)(src_addr + len)); 44 45 if (key_ptr) { 46 key_lo = lower_32_bits((ulong)key_ptr); 47 key_hi = upper_32_bits((ulong)key_ptr); 48 flush_dcache_range((ulong)key_ptr, 49 (ulong)(key_ptr + KEY_PTR_LEN)); 50 } 51 52 ret = invoke_smc(ZYNQMP_SIP_SVC_PM_SECURE_IMG_LOAD, src_lo, src_hi, 53 key_lo, key_hi, ret_payload); 54 if (ret) { 55 printf("Failed: secure op status:0x%x\n", ret); 56 } else { 57 addr = (u64)ret_payload[1] << 32 | ret_payload[2]; 58 printf("Verified image at 0x%llx\n", addr); 59 env_set_hex("zynqmp_verified_img_addr", addr); 60 } 61 62 return ret; 63 } 64 65 static int do_zynqmp_mmio_read(cmd_tbl_t *cmdtp, int flag, int argc, 66 char * const argv[]) 67 { 68 u32 read_val, addr; 69 int ret; 70 71 if (argc != cmdtp->maxargs) 72 return CMD_RET_USAGE; 73 74 addr = simple_strtoul(argv[2], NULL, 16); 75 76 ret = zynqmp_mmio_read(addr, &read_val); 77 if (!ret) 78 printf("mmio read value at 0x%x = 0x%x\n", 79 addr, read_val); 80 else 81 printf("Failed: mmio read\n"); 82 83 return ret; 84 } 85 86 static int do_zynqmp_mmio_write(cmd_tbl_t *cmdtp, int flag, int argc, 87 char * const argv[]) 88 { 89 u32 addr, mask, val; 90 int ret; 91 92 if (argc != cmdtp->maxargs) 93 return CMD_RET_USAGE; 94 95 addr = simple_strtoul(argv[2], NULL, 16); 96 mask = simple_strtoul(argv[3], NULL, 16); 97 val = simple_strtoul(argv[4], NULL, 16); 98 99 ret = zynqmp_mmio_write(addr, mask, val); 100 if (ret != 0) 101 printf("Failed: mmio write\n"); 102 103 return ret; 104 } 105 106 #ifdef CONFIG_DEFINE_TCM_OCM_MMAP 107 static int do_zynqmp_tcm_init(cmd_tbl_t *cmdtp, int flag, int argc, 108 char * const argv[]) 109 { 110 u8 mode; 111 112 if (argc != cmdtp->maxargs) 113 return CMD_RET_USAGE; 114 115 mode = simple_strtoul(argv[2], NULL, 16); 116 if (mode != TCM_LOCK && mode != TCM_SPLIT) { 117 printf("Mode should be either 0(lock)/1(split)\n"); 118 return CMD_RET_FAILURE; 119 } 120 121 dcache_disable(); 122 tcm_init(mode); 123 dcache_enable(); 124 125 return CMD_RET_SUCCESS; 126 } 127 #endif 128 129 static cmd_tbl_t cmd_zynqmp_sub[] = { 130 U_BOOT_CMD_MKENT(secure, 5, 0, do_zynqmp_verify_secure, "", ""), 131 U_BOOT_CMD_MKENT(mmio_read, 3, 0, do_zynqmp_mmio_read, "", ""), 132 U_BOOT_CMD_MKENT(mmio_write, 5, 0, do_zynqmp_mmio_write, "", ""), 133 #ifdef CONFIG_DEFINE_TCM_OCM_MMAP 134 U_BOOT_CMD_MKENT(tcminit, 3, 0, do_zynqmp_tcm_init, "", ""), 135 #endif 136 }; 137 138 /** 139 * do_zynqmp - Handle the "zynqmp" command-line command 140 * @cmdtp: Command data struct pointer 141 * @flag: Command flag 142 * @argc: Command-line argument count 143 * @argv: Array of command-line arguments 144 * 145 * Processes the zynqmp specific commands 146 * 147 * Return: return 0 on success and CMD_RET_USAGE incase of misuse and error 148 */ 149 static int do_zynqmp(cmd_tbl_t *cmdtp, int flag, int argc, 150 char *const argv[]) 151 { 152 cmd_tbl_t *c; 153 154 if (argc < 2) 155 return CMD_RET_USAGE; 156 157 c = find_cmd_tbl(argv[1], &cmd_zynqmp_sub[0], 158 ARRAY_SIZE(cmd_zynqmp_sub)); 159 160 if (c) 161 return c->cmd(c, flag, argc, argv); 162 else 163 return CMD_RET_USAGE; 164 } 165 166 /***************************************************/ 167 #ifdef CONFIG_SYS_LONGHELP 168 static char zynqmp_help_text[] = 169 "secure src len [key_addr] - verifies secure images of $len bytes\n" 170 " long at address $src. Optional key_addr\n" 171 " can be specified if user key needs to\n" 172 " be used for decryption\n" 173 "zynqmp mmio_read address - read from address\n" 174 "zynqmp mmio_write address mask value - write value after masking to\n" 175 " address\n" 176 #ifdef CONFIG_DEFINE_TCM_OCM_MMAP 177 "zynqmp tcminit mode - Initialize the TCM with zeros. TCM needs to be\n" 178 " initialized before accessing to avoid ECC\n" 179 " errors. mode specifies in which mode TCM has\n" 180 " to be initialized. Supported modes will be\n" 181 " lock(0)/split(1)\n" 182 #endif 183 ; 184 #endif 185 186 U_BOOT_CMD( 187 zynqmp, 5, 1, do_zynqmp, 188 "ZynqMP sub-system", 189 zynqmp_help_text 190 ) 191