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