blob: c9551effba58ad2b69558ae7b98080080cedbb89 [file] [log] [blame]
Bo Lv72d0e902023-01-02 14:27:34 +00001// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4 */
5
6#include <common.h>
7#include <command.h>
8#include <asm/io.h>
9#include <asm/amlogic/arch/secure_apb.h>
10
11#ifdef CONFIG_CMD_RSVMEM
12
13#if defined(P_AO_SEC_GP_CFG3)
14#define REG_RSVMEM_SIZE P_AO_SEC_GP_CFG3
15#define REG_RSVMEM_BL32_START P_AO_SEC_GP_CFG4
16#define REG_RSVMEM_BL31_START P_AO_SEC_GP_CFG5
17#elif defined(SYSCTRL_SEC_STATUS_REG15)
18#define REG_RSVMEM_SIZE SYSCTRL_SEC_STATUS_REG15
19#define REG_RSVMEM_BL32_START SYSCTRL_SEC_STATUS_REG16
20#define REG_RSVMEM_BL31_START SYSCTRL_SEC_STATUS_REG17
21#endif
22
23//#define RSVMEM_DEBUG_ENABLE
24#ifdef RSVMEM_DEBUG_ENABLE
25#define rsvmem_dbg(fmt...) printf("[rsvmem] "fmt)
26#else
27#define rsvmem_dbg(fmt...)
28#endif
29#define rsvmem_info(fmt...) printf("[rsvmem] "fmt)
30#define rsvmem_err(fmt...) printf("[rsvmem] "fmt)
31
32#ifndef DTB_BIND_KERNEL
Bo Lv72d0e902023-01-02 14:27:34 +000033
Wentao.Sun229fd4a2023-11-16 15:10:11 +080034#define RAMOOP_MEM_SIZE 0x100000
35#define RSV_MEM_ALIGNMENT 0x400000
36
37static int fdt_config_rsv_mem(unsigned int aarch32, unsigned int alignment,
38 unsigned int bl31_start, unsigned int rsv_sz)
Bo Lv72d0e902023-01-02 14:27:34 +000039{
Bo Lv72d0e902023-01-02 14:27:34 +000040 int ret = 0;
Wentao.Sun229fd4a2023-11-16 15:10:11 +080041 char cmdbuf[128] = { 0 };
42 unsigned int ramoops_start = 0;
43 unsigned int rsv_sz_align = 0;
Bo Lv72d0e902023-01-02 14:27:34 +000044
Wentao.Sun229fd4a2023-11-16 15:10:11 +080045 if (bl31_start == 0 || rsv_sz == 0) {
46 rsvmem_err("Bad args secure monitor start: %u, sz: %u.\n", bl31_start, rsv_sz);
47 return -EINVAL;
Bo Lv72d0e902023-01-02 14:27:34 +000048 }
Wentao.Sun229fd4a2023-11-16 15:10:11 +080049
50 if (alignment == 0)
51 alignment = RSV_MEM_ALIGNMENT;
52
53 rsv_sz_align = ((rsv_sz + alignment - 1) / alignment) * alignment;
54 ramoops_start = bl31_start + rsv_sz_align;
55
56 memset(cmdbuf, 0, sizeof(cmdbuf));
57 sprintf(cmdbuf, "fdt set /reserved-memory/linux,secmon no-map;");
58 if (run_command(cmdbuf, 0) != 0) {
59 rsvmem_err("reserved memory set no-map failed.\n");
60 return -ENODEV;
61 }
62
63 sprintf(cmdbuf, "fdt get value temp_rsv_reg /reserved-memory/linux,secmon reg;");
64 ret = run_command(cmdbuf, 0);
65 if (!ret) {
66 if (aarch32)
67 sprintf(cmdbuf, "fdt set /reserved-memory/linux,secmon reg <0x%x 0x%x>;",
68 bl31_start, rsv_sz_align);
69 else
70 sprintf(cmdbuf,
71 "fdt set /reserved-memory/linux,secmon reg <0x0 0x%x 0x0 0x%x>;",
72 bl31_start, rsv_sz_align);
73 rsvmem_dbg("CMD: %s\n", cmdbuf);
74 ret = run_command(cmdbuf, 0);
75 if (ret) {
76 rsvmem_err("reserved memory set reg error.\n");
77 return -ENODEV;
78 }
79 } else {
80 if (aarch32)
81 sprintf(cmdbuf,
82 "fdt set /reserved-memory/linux,secmon size <0x%x>;", rsv_sz_align);
83 else
84 sprintf(cmdbuf,
85 "fdt set /reserved-memory/linux,secmon size <0x0 0x%x>;",
86 rsv_sz_align);
87 rsvmem_dbg("CMD: %s\n", cmdbuf);
88 ret = run_command(cmdbuf, 0);
89 if (ret != 0) {
90 rsvmem_err("reserved memory set size error.\n");
91 return -ENODEV;
92 }
93
94 memset(cmdbuf, 0, sizeof(cmdbuf));
95 if (aarch32)
96 sprintf(cmdbuf,
97 "fdt set /reserved-memory/linux,secmon alloc-ranges <0x%x 0x%x>;",
98 bl31_start, rsv_sz_align);
99 else
100 sprintf(cmdbuf,
101 "fdt set /reserved-memory/linux,secmon alloc-ranges <0x0 0x%x 0x0 0x%x>;",
102 bl31_start, rsv_sz_align);
103 rsvmem_dbg("CMD: %s\n", cmdbuf);
104 ret = run_command(cmdbuf, 0);
105 if (ret != 0) {
106 rsvmem_err("reserved memory set alloc-ranges error.\n");
107 return -ENODEV;
108 }
109 }
110
111 memset(cmdbuf, 0, sizeof(cmdbuf));
112 sprintf(cmdbuf, "fdt get value tmp_rsv_sz /secmon reserve_mem_size;");
113 rsvmem_dbg("CMD: %s\n", cmdbuf);
114 ret = run_command(cmdbuf, 0);
115 if (ret == 0) {
116 memset(cmdbuf, 0, sizeof(cmdbuf));
117 if (aarch32)
118 sprintf(cmdbuf, "fdt set /secmon reserve_mem_size <0x%x>;", rsv_sz);
119 else
120 sprintf(cmdbuf, "fdt set /secmon reserve_mem_size <0x0 0x%x>;", rsv_sz);
121 rsvmem_dbg("CMD: %s\n", cmdbuf);
122 ret = run_command(cmdbuf, 0);
123 if (ret != 0) {
124 rsvmem_err("reserved memory set reserve_mem_size error.\n");
125 return -ENODEV;
126 }
127 }
128
129 memset(cmdbuf, 0, sizeof(cmdbuf));
130 sprintf(cmdbuf, "fdt get value ramoops_reg /reserved-memory/ramoops reg;");
131 if (run_command(cmdbuf, 0) == 0) {
132 memset(cmdbuf, 0, sizeof(cmdbuf));
133 if (aarch32)
134 sprintf(cmdbuf, "fdt set /reserved-memory/ramoops reg <0x%x 0x%x>;",
135 ramoops_start, RAMOOP_MEM_SIZE);
136 else
137 sprintf(cmdbuf,
138 "fdt set /reserved-memory/ramoops reg <0x0 0x%x 0x0 0x%x>;",
139 ramoops_start, RAMOOP_MEM_SIZE);
140
141 rsvmem_dbg("CMD: %s\n", cmdbuf);
142 ret = run_command(cmdbuf, 0);
143 if (ret != 0) {
144 rsvmem_err("reserved memory set /reserved-memory/ramoops reg error.\n");
145 return -ENODEV;
146 }
147 }
148
149 return 0;
150}
151
152static int fdt_setup(unsigned int *alignment, unsigned int *aarch32)
153{
154 int ret = 0;
155 char *fdtaddr = NULL;
156 char *temp_env = NULL;
157 char cmdbuf[128] = { 0 };
158 unsigned int alignment_temp = 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000159
160 fdtaddr = env_get("fdtaddr");
161 if (fdtaddr == NULL) {
162 rsvmem_err("get fdtaddr NULL!\n");
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800163 return -EBADMSG;
Bo Lv72d0e902023-01-02 14:27:34 +0000164 }
165
166 memset(cmdbuf, 0, sizeof(cmdbuf));
167 sprintf(cmdbuf, "fdt addr %s;", fdtaddr);
168 rsvmem_dbg("CMD: %s\n", cmdbuf);
169 ret = run_command(cmdbuf, 0);
170 if (ret != 0 ) {
171 rsvmem_err("fdt addr error.\n");
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800172 return -EFAULT;
Bo Lv72d0e902023-01-02 14:27:34 +0000173 }
174
175 memset(cmdbuf, 0, sizeof(cmdbuf));
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800176 sprintf(cmdbuf, "fdt get value env_compatible /reserved-memory/linux,secmon compatible;");
177 ret = run_command(cmdbuf, 0);
178 if (ret != 0) {
179 rsvmem_err("fdt get linux,secmon compatible failed.\n");
180 return -EBADMSG;
181 }
182 temp_env = env_get("env_compatible");
183
184 if (strcmp(temp_env, "shared-dma-pool")) {
185 rsvmem_err("linux,secmon compatible is not as expected: %s.\n", temp_env);
186 return -EBADMSG;
187 }
188 run_command("setenv env_compatible;", 0);
189
190 memset(cmdbuf, 0, sizeof(cmdbuf));
Bo Lv72d0e902023-01-02 14:27:34 +0000191 sprintf(cmdbuf, "fdt get value temp_env / \\#address-cells;");
192 ret = run_command(cmdbuf, 0);
193 if (ret != 0) {
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800194 rsvmem_err("fdt get #address-cells failed.\n");
195 return -EBADMSG;
Bo Lv72d0e902023-01-02 14:27:34 +0000196 }
197 temp_env = env_get("temp_env");
Bo Lv72d0e902023-01-02 14:27:34 +0000198 if (temp_env && !strcmp(temp_env, "0x00000001"))
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800199 *aarch32 = 1;
Bo Lv72d0e902023-01-02 14:27:34 +0000200
201 /* Get alignment size
202 * If arm64, alignment has 2 parameters
203 * The second parameter need convert big-endian to little-endian
204 */
Bo Lv72d0e902023-01-02 14:27:34 +0000205 memset(cmdbuf, 0, sizeof(cmdbuf));
206 sprintf(cmdbuf, "fdt get value temp_alignment /reserved-memory/linux,secmon alignment;");
207 ret = run_command(cmdbuf, 0);
208 if (!ret) {
209 temp_env = env_get("temp_alignment");
210 alignment_temp = simple_strtoul(temp_env, NULL, 16);
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800211 if (*aarch32) {
212 *alignment = alignment_temp;
Bo Lv72d0e902023-01-02 14:27:34 +0000213 } else {
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800214 *alignment = (alignment_temp & 0xff) << 24;
215 *alignment |= (alignment_temp & 0xff00) << 8;
216 *alignment |= (alignment_temp & 0xff0000) >> 8;
217 *alignment |= (alignment_temp & 0xff000000) >> 24;
Bo Lv72d0e902023-01-02 14:27:34 +0000218 }
219 }
220
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800221 return 0;
222}
Bo Lv72d0e902023-01-02 14:27:34 +0000223
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800224static void get_blx_info(unsigned int *bl31_start, unsigned int *bl31_sz,
225 unsigned int *bl32_start, unsigned int *bl32_sz)
226{
227 unsigned int data = 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000228
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800229 data = readl(REG_RSVMEM_SIZE);
230 /* workaround for bl3x size */
231 *bl31_sz = ((data & 0xffff0000) >> 16) << 16;
232 *bl32_sz = (data & 0x0000ffff) << 16;
Bo Lv72d0e902023-01-02 14:27:34 +0000233
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800234 *bl31_start = readl(REG_RSVMEM_BL31_START);
235 *bl32_start = readl(REG_RSVMEM_BL32_START);
236}
Bo Lv72d0e902023-01-02 14:27:34 +0000237
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800238static int do_rsvmem_check(cmd_tbl_t *cmdtp, int flag, int argc,
239 char *const argv[])
240{
241 int ret = 0;
242 unsigned int aarch32 = 0;
243 unsigned int bl31_start = 0;
244 unsigned int bl31_sz = 0;
245 unsigned int bl32_start = 0;
246 unsigned int bl32_sz = 0;
247 unsigned int rsv_mem_sz = 0;
248 unsigned int alignment = 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000249
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800250 rsvmem_dbg("reserved memory check!\n");
Bo Lv72d0e902023-01-02 14:27:34 +0000251
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800252 ret = fdt_setup(&alignment, &aarch32);
253 if (ret != 0)
254 return ret;
255
256 get_blx_info(&bl31_start, &bl31_sz, &bl32_start, &bl32_sz);
257
258 rsv_mem_sz = bl31_sz + bl32_sz;
259 if (bl31_start + bl31_sz != bl32_start) {
260 rsvmem_info("bl31 and bl32 reserved memory is not continuous");
261 return 0;
Bo Lv72d0e902023-01-02 14:27:34 +0000262 }
263
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800264 return fdt_config_rsv_mem(aarch32, alignment, bl31_start, rsv_mem_sz);
Bo Lv72d0e902023-01-02 14:27:34 +0000265}
266
267static int do_rsvmem_dump(cmd_tbl_t *cmdtp, int flag, int argc,
268 char *const argv[])
269{
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800270 unsigned int bl31_start = 0;
271 unsigned int bl31_sz = 0;
272 unsigned int bl32_start = 0;
273 unsigned int bl32_sz = 0;
274
275 get_blx_info(&bl31_start, &bl31_sz, &bl32_start, &bl32_sz);
Bo Lv72d0e902023-01-02 14:27:34 +0000276
277 rsvmem_info("reserved memory:\n");
Wentao.Sun229fd4a2023-11-16 15:10:11 +0800278 rsvmem_info("bl31 reserved memory start: 0x%08x\n", bl31_start);
279 rsvmem_info("bl31 reserved memory size: 0x%08x\n", bl31_sz);
280 rsvmem_info("bl32 reserved memory start: 0x%08x\n", bl32_start);
281 rsvmem_info("bl32 reserved memory size: 0x%08x\n", bl32_sz);
Bo Lv72d0e902023-01-02 14:27:34 +0000282
283 return 0;
284}
285
286static cmd_tbl_t cmd_rsvmem_sub[] = {
287 U_BOOT_CMD_MKENT(check, 2, 0, do_rsvmem_check, "", ""),
288 U_BOOT_CMD_MKENT(dump, 2, 0, do_rsvmem_dump, "", ""),
289};
290#endif
291
292static int do_rsvmem(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
293{
294#ifdef DTB_BIND_KERNEL
295 rsvmem_err("no check for rsvmem, should check int kernel\n");
296 return 0;
297#else
298 cmd_tbl_t *c;
299
300 /* Strip off leading 'rsvmem' command argument */
301 argc--;
302 argv++;
303
304 c = find_cmd_tbl(argv[0], &cmd_rsvmem_sub[0], ARRAY_SIZE(cmd_rsvmem_sub));
305
306 if (c)
307 return c->cmd(cmdtp, flag, argc, argv);
308 else
309 return CMD_RET_USAGE;
310#endif
311}
312
313U_BOOT_CMD(
314 rsvmem, 2, 0, do_rsvmem,
315 "reserve memory",
316 "check - check reserved memory\n"
317 "rsvmem dump - dump reserved memory\n"
318);
319#endif