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