blob: 085aabead2928f0e25b8b780437333f85205d444 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/* uint64_t ...*/
2#include <inttypes.h>
3#include <stdbool.h>
4
5/* vprintf, vsnprintf */
6#include <stdio.h>
7
8/* exit(), atoi() */
9#include <stdlib.h>
10
11/* getopt, optind */
12#include <unistd.h>
13
14/* sysenv */
15#include "mrdump_defaults.h"
16
17/* strcmp */
18#include <string.h>
19
20#include <getopt.h>
21/* mrdump related */
22#include "mrdump_log.h"
23#include "mrdump_common.h"
24#include "mrdump_status.h"
25#include "mrdump_support_ext4.h"
26#include "mrdump_support_mpart.h"
27
28static void usage(const char *prog) __attribute__((noreturn));
29static void usage(const char *prog)
30{
31 printf("Usage\n"
32 "\t%1$s is-supported\n\n"
33 "\t%1$s status-get\n"
34 "\t%1$s status-log\n"
35 "\t%1$s status-clear\n\n"
36 "\t%1$s file-setup\n"
37 "\t%1$s file-allocate n\n"
38 "\t\tn is 0(disable file output) 1(halfmem) 2(fullmem) >256\n"
39 "\t%1$s file-extract-core [-r] filename\n"
40 "\t\t-r\tre-init pre-allocated file\n"
41 "\t%1$s file-info\n\n"
42 "\t%1$s mem-size-set n\n"
43 "\t\tn is between 64 ~ 16384(m), 0 is output total-mem-size\n\n"
44 "\t%1$s output-set output\n"
45 "\t\tsetting mrdump output device\n"
46 "\t\t none\n"
47 "\t\t null\n"
48 "\t\t usb\n"
49 "\t\t partition: mrdump partition\n"
50 "\t\t internal-storage: ext4, f2fs\n"
51 "\t%1$s output-get\n"
52 "\t\tgetting mrdump output device\n",
53 prog);
54 exit(1);
55}
56
57static void dump_status_ok(const struct mrdump_status_result *result)
58{
59 printf("Ok\n");
60 printf("\tMode: %s\n\tOutput: ", result->mode);
61
62 switch (result->output) {
63 case MRDUMP_OUTPUT_NULL:
64 printf("null\n");
65 break;
66 case MRDUMP_OUTPUT_USB:
67 printf("usb\n");
68 break;
69 case MRDUMP_OUTPUT_DATA_FS:
70 printf("ext4/data partition\n");
71 break;
72 case MRDUMP_OUTPUT_PARTITION:
73 printf("dynamic mrdump partition\n");
74 break;
75 default:
76 printf("not supported\n");
77 break;
78 }
79}
80
81static int file_setup_command(int argc, char * __attribute__((unused)) argv[])
82{
83 if (!mrdump_is_supported()) {
84 error("file-setup not allowed in this mode.\n");
85 }
86 if (argc != 1) {
87 error("Invalid file-setup command argument\n");
88 }
89 mrdump_file_setup(false);
90 return 0;
91}
92
93static void file_allocate_command(int argc, char *argv[])
94{
95 if (!mrdump_is_supported()) {
96 error("file-allocate not allowed in this mode.\n");
97 }
98 if (argc != 2) {
99 error("Invaid file-allocate command argument\n");
100 }
101 int size_m = atoi(argv[1]);
102
103 if (size_m < 0)
104 size_m = 0;
105
106 if ((size_m <= 2) || (size_m >= MRDUMP_EXT4_MIN_ALLOCATE)) {
107 // enable condition: only 0, 1, 2, >256
108 mrdump_file_set_maxsize(size_m);
109 }
110 else {
111 error("Invalid dump size %d\n", size_m);
112 }
113}
114
115static int file_extract_core_command(int argc, char *argv[])
116{
117 int opt;
118 bool reinit = false;
119
120 while ((opt = getopt(argc, argv, "r")) != -1) {
121 switch (opt) {
122 case 'r':
123 reinit = true;
124 break;
125 default:
126 error("Invalid file-extract-core parameter\n");
127 }
128 }
129 if (optind >= argc) {
130 error("Expected filename after options\n");
131 }
132
133 const char *fn = argv[optind];
134 const char *output_dev = sysenv_get("mrdump_output");
135
136 MD_LOGI("%s: mrdump_output= %s\n",__func__, output_dev);
137
138 if (output_dev) {
139 if (!strncmp(output_dev, "partition", 9)) {
140 MD_LOGI("%s: partition solution\n",__func__);
141 if (mrdump_file_fetch_zip_coredump_partition(fn)) {
142 return 0;
143 }
144 }
145 else if (!strncmp(output_dev, "internal-storage", 21)) {
146 MD_LOGI("%s: ext4 solution\n",__func__);
147 if (mrdump_file_fetch_zip_coredump(fn)) {
148 mrdump_file_setup(reinit);
149 return 0;
150 }
151 }
152 }
153
154 error("Fetching Coredump data failed\n");
155}
156
157static int file_info_command(int argc, char * __attribute__((unused)) argv[])
158{
159 if (argc != 1) {
160 error("Invalid file-info command argument\n");
161 }
162
163 struct mrdump_pafile_info info;
164 if (mrdump_file_get_info(MRDUMP_EXT4_ALLOCATE_FILE, &info)) {
165 printf("\tInfo LBA : %" PRIu32 "\n"
166 "\tAddress LBA : %" PRIu32 "\n"
167 "\tFile Size : %" PRIu64 "\n"
168 "\tCoredump Size : %" PRIu64 "\n"
169 "\tTimestamp : %" PRIx64 "\n",
170 info.info_lba, info.addr_lba,
171 info.filesize, info.coredump_size,
172 info.timestamp
173 );
174 return 0;
175 }
176 else {
177 error("Cannot get pre-allocate file info\n");
178 }
179}
180
181static void mem_size_set_command(int argc, char *argv[])
182{
183 char msize[5];
184
185 if (argc != 2) {
186 error("Invaid mem-size-set command argument\n");
187 }
188
189 int size_m = atoi(argv[1]);
190 if ((size_m == 0) || ((size_m >= 64) && (size_m <= 16 * 1024))) {
191 if (size_m != 0) {
192 snprintf(msize, sizeof(msize), "%d", size_m);
193 if (sysenv_set("mrdump_mem_size", msize) == 0) {
194 MD_LOGI("mem-size-set done.\n");
195 }
196 }
197 else {
198 if (sysenv_set("mrdump_mem_size", "") == 0) {
199 MD_LOGI("total-mem-size done.\n");
200 }
201 else {
202 error("failed to set memory dump size, plz try again later.\n");
203 }
204 }
205 }
206 else {
207 error("Invalid memory dump size\n");
208 }
209}
210
211static void output_set_command(int argc, char *argv[])
212{
213 if(argc < 2) {
214 error("Invalid output device, valid input [none, null, usb, partition, internal-storage]\n");
215 }
216 else {
217 const char *output_dev = argv[1];
218 int need_reboot = 0;
219 const char *prev_output_dev = sysenv_get("mrdump_output");
220
221 if (strcmp(prev_output_dev, "partition") == 0) {
222 if (mrdump_check_partition()) {
223 need_reboot = 1;
224 }
225 }
226 if (strcmp(output_dev, "partition") == 0) {
227 if (!mrdump_check_partition()) {
228 error("mrdump partition doesn't exist, cannot dump to partition.\n");
229 }
230 need_reboot = 1;
231 }
232 else if (strcmp(output_dev, "none") &&
233 strcmp(output_dev, "null") &&
234 strcmp(output_dev, "usb") &&
235 strcmp(output_dev, "internal-storage")) {
236 error("Unknown output %s\n", output_dev);
237 }
238
239 if (sysenv_set("mrdump_output", output_dev) == 0) {
240 MD_LOGI("mrdump_output = %s\n", output_dev);
241 }
242 else {
243 error("output-set failed.(%s)\n", output_dev);
244 }
245
246 if (strcmp(output_dev, "internal-storage") == 0) {
247 mrdump_file_set_maxsize(DEFAULT_FULLMEM);
248 }
249 else {
250 mrdump_file_set_maxsize(DEFAULT_DISABLE);
251 }
252
253 if (need_reboot) {
254 if (0 > execl("/system/bin/reboot", "reboot", NULL, NULL))
255 error("%s: failed to reboot into LK for partition resize.\n", __func__);
256 }
257 }
258}
259
260static void status_get_command(int __attribute((unused)) argc,
261 char * __attribute ((unused)) argv[])
262{
263 struct mrdump_status_result result;
264 if (mrdump_status_get(&result)) {
265 printf("MT-RAMDUMP\n\tStatus:");
266 switch (result.status) {
267 case MRDUMP_STATUS_NONE:
268 printf("None\n");
269 break;
270 case MRDUMP_STATUS_FAILED:
271 printf("Failed\n");
272 break;
273 case MRDUMP_STATUS_OK:
274 dump_status_ok(&result);
275 break;
276 }
277 }
278 else {
279 error("MT-RAMDUMP get status failed\n");
280 }
281}
282
283static int parse_log_level(const char *log_level)
284{
285 if (strcmp(log_level, "debug") == 0)
286 return LOG_DEBUG;
287 else if (strcmp(log_level, "info") == 0)
288 return LOG_INFO;
289 else if (strcmp(log_level, "warn") == 0)
290 return LOG_WARNING;
291 else if (strcmp(log_level, "error") == 0)
292 return LOG_ERR;
293 return LOG_WARNING;
294}
295
296int main(int argc, char *argv[])
297{
298 int log_level = LOG_WARNING;
299 int log_syslog = 0;
300
301 static struct option long_options[]= {
302 {"help", no_argument, 0, 0},
303 {"log-level", required_argument, 0, 0},
304 {"log-syslog", no_argument, 0, 0},
305 {0, 0, 0, 0},
306 };
307
308 while (1) {
309 int option_index, c;
310 c = getopt_long(argc, argv, "+", long_options, &option_index);
311 if (c == -1)
312 break;
313
314 switch (c) {
315 case 0:
316 if (strcmp(long_options[option_index].name, "log-level") == 0) {
317 log_level = parse_log_level(optarg);
318 }
319 else if (strcmp(long_options[option_index].name, "log-syslog") == 0) {
320 log_syslog = 1;
321 }
322 else if (strcmp(long_options[option_index].name, "help") == 0) {
323 usage(argv[0]);
324 }
325 break;
326
327 default:
328 usage(argv[0]);
329 }
330 }
331
332 mdlog_init(log_level, log_syslog);
333
334 const int command_argc = argc - optind;
335 if (command_argc < 1) {
336 error("No command given\n");
337 }
338 const char *command = argv[optind];
339 char **command_argv = &argv[optind];
340
341 if (strcmp(command, "is-supported") == 0) {
342 if (mrdump_is_supported()) {
343 printf("MT-RAMDUMP support ok\n");
344 }
345 else {
346 printf("MT-RAMDUMP not support\n");
347 }
348 }
349 else if (strcmp(command, "status-get") == 0) {
350 status_get_command(command_argc, command_argv);
351 }
352 else if (strcmp(command, "status-log") == 0) {
353 struct mrdump_status_result result;
354 bool res = mrdump_status_get(&result);
355
356 printf("=>status line:\n%s\n=>log:\n%s\n", result.status_line, result.log_buf);
357 if (!res) {
358 error("MT-RAMDUMP get status failed\n");
359 }
360 }
361 else if (strcmp(command, "status-clear") == 0) {
362 if (!mrdump_is_supported()) {
363 error("MT-RAMDUMP not support\n");
364 }
365 if (!mrdump_status_clear()) {
366 error("MT-RAMDUMP Status clear failed\n");
367 }
368 }
369 else if (strcmp(command, "file-setup") == 0) {
370 file_setup_command(command_argc, command_argv);
371 }
372 else if (strcmp(command, "file-allocate") == 0) {
373 file_allocate_command(command_argc, command_argv);
374 }
375 else if (strcmp(command, "file-extract-core") == 0) {
376 file_extract_core_command(command_argc, command_argv);
377 }
378 else if (strcmp(command, "file-info") == 0) {
379 file_info_command(command_argc, command_argv);
380 }
381 else if (strcmp(command, "mem-size-set") == 0) {
382 mem_size_set_command(command_argc, command_argv);
383 }
384 else if (strcmp(command, "output-set") == 0) {
385 output_set_command(command_argc, command_argv);
386 }
387 else if (strcmp(command, "partition") == 0) {
388 /* ignored "-Wunused-result" */
389 if (1 == mrdump_check_partition()) {;}
390 }
391 else if (strcmp(command, "output-get") == 0) {
392 const char *output_dev = sysenv_get("mrdump_output");
393 if (!output_dev) {
394 printf("default\n");
395 }
396 else {
397 printf("%s\n", output_dev);
398 }
399 }
400 else {
401 error("Unknown command %s\n", command);
402 }
403
404 return 0;
405}