blob: b69f8123ee2da405f8b606de46a4931d78021377 [file] [log] [blame]
Alexey Romanov68c4a372023-01-10 13:56:47 +03001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2016 Beniamino Galvani
4 *
5 * Author: Beniamino Galvani <b.galvani@gmail.com>
6 * Author: Vyacheslav Bocharov <adeep@lexina.in>
7 * Author: Neil Armstrong <narmstrong@baylibre.com>
Alexey Romanov7eeb9a22023-01-10 13:56:49 +03008 * Author: Alexey Romanov <avromanov@sberdevices.ru>
Alexey Romanov68c4a372023-01-10 13:56:47 +03009 */
10
11#include <command.h>
Alexey Romanov68c4a372023-01-10 13:56:47 +030012#include <env.h>
13#include <asm/arch/sm.h>
14#include <stdlib.h>
Alexey Romanov7eeb9a22023-01-10 13:56:49 +030015#include <display_options.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060016#include <vsprintf.h>
Alexey Romanov68c4a372023-01-10 13:56:47 +030017
18static int do_sm_serial(struct cmd_tbl *cmdtp, int flag, int argc,
19 char *const argv[])
20{
21 ulong address;
22 int ret;
23
24 if (argc < 2)
25 return CMD_RET_USAGE;
26
27 address = simple_strtoul(argv[1], NULL, 0);
28
29 ret = meson_sm_get_serial((void *)address, SM_SERIAL_SIZE);
30 if (ret)
31 return CMD_RET_FAILURE;
32
33 return CMD_RET_SUCCESS;
34}
35
36#define MAX_REBOOT_REASONS 14
37
38static const char *reboot_reasons[MAX_REBOOT_REASONS] = {
39 [REBOOT_REASON_COLD] = "cold_boot",
40 [REBOOT_REASON_NORMAL] = "normal",
41 [REBOOT_REASON_RECOVERY] = "recovery",
42 [REBOOT_REASON_UPDATE] = "update",
43 [REBOOT_REASON_FASTBOOT] = "fastboot",
44 [REBOOT_REASON_SUSPEND_OFF] = "suspend_off",
45 [REBOOT_REASON_HIBERNATE] = "hibernate",
46 [REBOOT_REASON_BOOTLOADER] = "bootloader",
47 [REBOOT_REASON_SHUTDOWN_REBOOT] = "shutdown_reboot",
48 [REBOOT_REASON_RPMBP] = "rpmbp",
49 [REBOOT_REASON_CRASH_DUMP] = "crash_dump",
50 [REBOOT_REASON_KERNEL_PANIC] = "kernel_panic",
51 [REBOOT_REASON_WATCHDOG_REBOOT] = "watchdog_reboot",
52};
53
54static int do_sm_reboot_reason(struct cmd_tbl *cmdtp, int flag, int argc,
55 char *const argv[])
56{
57 const char *reason_str;
58 char *destarg = NULL;
59 int reason;
60
61 if (argc > 1)
62 destarg = argv[1];
63
64 reason = meson_sm_get_reboot_reason();
65 if (reason < 0)
66 return CMD_RET_FAILURE;
67
68 if (reason >= MAX_REBOOT_REASONS ||
69 !reboot_reasons[reason])
70 reason_str = "unknown";
71 else
72 reason_str = reboot_reasons[reason];
73
74 if (destarg)
75 env_set(destarg, reason_str);
76 else
77 printf("reboot reason: %s (%x)\n", reason_str, reason);
78
79 return CMD_RET_SUCCESS;
80}
81
82static int do_efuse_read(struct cmd_tbl *cmdtp, int flag, int argc,
83 char *const argv[])
84{
85 ulong address, offset, size;
86 int ret;
87
88 if (argc < 4)
89 return CMD_RET_USAGE;
90
91 offset = simple_strtoul(argv[1], NULL, 0);
92 size = simple_strtoul(argv[2], NULL, 0);
93
94 address = simple_strtoul(argv[3], NULL, 0);
95
96 ret = meson_sm_read_efuse(offset, (void *)address, size);
97 if (ret != size)
98 return CMD_RET_FAILURE;
99
100 return CMD_RET_SUCCESS;
101}
102
103static int do_efuse_write(struct cmd_tbl *cmdtp, int flag, int argc,
104 char *const argv[])
105{
106 ulong address, offset, size;
107 int ret;
108
109 if (argc < 4)
110 return CMD_RET_USAGE;
111
112 offset = simple_strtoul(argv[1], NULL, 0);
113 size = simple_strtoul(argv[2], NULL, 0);
114
115 address = simple_strtoul(argv[3], NULL, 0);
116
117 ret = meson_sm_write_efuse(offset, (void *)address, size);
118 if (ret != size)
119 return CMD_RET_FAILURE;
120
121 return CMD_RET_SUCCESS;
122}
123
Alexey Romanov7eeb9a22023-01-10 13:56:49 +0300124static int do_efuse_dump(struct cmd_tbl *cmdtp, int flag, int argc,
125 char *const argv[])
126{
127 ulong offset, size;
128 u8 *buffer;
129 int ret;
130
131 if (argc != 3)
132 return CMD_RET_USAGE;
133
134 offset = simple_strtoul(argv[1], NULL, 0);
135 size = simple_strtoul(argv[2], NULL, 0);
136 buffer = malloc(size);
137 if (!buffer) {
138 pr_err("Failed to allocate %lu bytes\n", size);
139 return CMD_RET_FAILURE;
140 }
141
142 ret = meson_sm_read_efuse(offset, (void *)buffer, size);
143 if (ret != size) {
144 ret = CMD_RET_FAILURE;
145 goto free_buffer;
146 }
147
148 print_buffer(0, buffer, 1, size, 0);
149
150free_buffer:
151 free(buffer);
152 return ret;
153}
154
Alexey Romanov68c4a372023-01-10 13:56:47 +0300155static struct cmd_tbl cmd_sm_sub[] = {
156 U_BOOT_CMD_MKENT(serial, 2, 1, do_sm_serial, "", ""),
157 U_BOOT_CMD_MKENT(reboot_reason, 1, 1, do_sm_reboot_reason, "", ""),
158 U_BOOT_CMD_MKENT(efuseread, 4, 1, do_efuse_read, "", ""),
159 U_BOOT_CMD_MKENT(efusewrite, 4, 0, do_efuse_write, "", ""),
Alexey Romanov7eeb9a22023-01-10 13:56:49 +0300160 U_BOOT_CMD_MKENT(efusedump, 3, 1, do_efuse_dump, "", ""),
Alexey Romanov68c4a372023-01-10 13:56:47 +0300161};
162
163static int do_sm(struct cmd_tbl *cmdtp, int flag, int argc,
164 char *const argv[])
165{
166 struct cmd_tbl *c;
167
168 if (argc < 2)
169 return CMD_RET_USAGE;
170
171 /* Strip off leading 'sm' command argument */
172 argc--;
173 argv++;
174
175 c = find_cmd_tbl(argv[0], &cmd_sm_sub[0], ARRAY_SIZE(cmd_sm_sub));
176
177 if (c)
178 return c->cmd(cmdtp, flag, argc, argv);
179 else
180 return CMD_RET_USAGE;
181}
182
183U_BOOT_CMD(
184 sm, 5, 0, do_sm,
185 "Secure Monitor Control",
186 "serial <address> - read chip unique id to memory address\n"
187 "sm reboot_reason [name] - get reboot reason and store to environment\n"
188 "sm efuseread <offset> <size> <address> - read efuse to memory address\n"
Alexey Romanov7eeb9a22023-01-10 13:56:49 +0300189 "sm efusewrite <offset> <size> <address> - write into efuse from memory address\n"
190 "sm efusedump <offset> <size> - dump efuse data range to console"
Alexey Romanov68c4a372023-01-10 13:56:47 +0300191);