1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <checkpoint.h>
9 #include <cli.h>
10 #include <cli_platform.h>
11
12 #include <fwk_io.h>
13 #include <fwk_status.h>
14
15 #include <stdint.h>
16 #include <stdlib.h>
17 #include <string.h>
18
19 extern checkpoint_st checkpoint_table[CHECKPOINT_NUM];
20
21 const char checkpoint_call[] = "checkpoint";
22 const char checkpoint_help[] =
23 " Show all current checkpoints.\n"
24 " Usage: checkpoint list\n"
25 " Skip N future checkpoints.\n"
26 " Usage: checkpoint <CP ID> skip N\n"
27 " Disable checkpoints until given tag reached.\n"
28 " Usage: checkpoint <CP ID> tag <tag>\n"
29 " Enable or disable a checkpoint.\n"
30 " Usage: checkpoint <CP ID> <enable|disable>\n"
31 " Enable or disable all checkpoints.\n"
32 " Usage: checkpoint <enableall|disableall>";
33
checkpoint_f(int32_t argc,char ** argv)34 int32_t checkpoint_f(int32_t argc, char **argv)
35 {
36 uint32_t id;
37 uint32_t run_cnt;
38 uint32_t i = 0;
39
40 if ((argc == 2) && (cli_strncmp(argv[1], "list", 4) == 0)) {
41 for (i = 0; i < CHECKPOINT_NUM; i++) {
42 if (checkpoint_table[i].in_use == true)
43 cli_printf(NONE, "%d: %s\n", i, checkpoint_table[i].name);
44 }
45 return FWK_SUCCESS;
46 }
47
48 else if ((argc == 4) && (cli_strncmp(argv[2], "skip", 4) == 0)) {
49 id = strtoul(argv[1], NULL, 0);
50 run_cnt = strtoul(argv[3], NULL, 0);
51 if (id >= CHECKPOINT_NUM) {
52 cli_print("CP ID out of range.\n");
53 return FWK_E_PARAM;
54 }
55 checkpoint_table[id].tag[0] = 0;
56 checkpoint_table[id].bypass = run_cnt;
57 return FWK_SUCCESS;
58 }
59
60 else if ((argc == 4) && (cli_strncmp(argv[2], "tag", 3) == 0)) {
61 id = strtoul(argv[1], NULL, 0);
62 if (id >= CHECKPOINT_NUM) {
63 cli_print("Checkpoint number out of range.\n");
64 return FWK_E_PARAM;
65 }
66 strncpy(checkpoint_table[id].tag, argv[3], CHECKPOINT_TAG_LEN);
67 checkpoint_table[id].bypass = CHECKPOINT_DISABLED;
68 return FWK_SUCCESS;
69 }
70
71 else if ((argc == 3) && (cli_strncmp(argv[2], "enable", 6) == 0)) {
72 id = strtoul(argv[1], NULL, 0);
73 if (id >= CHECKPOINT_NUM) {
74 cli_print("CP ID out of range.\n");
75 return FWK_E_PARAM;
76 }
77 checkpoint_table[id].bypass = CHECKPOINT_ENABLED;
78 return FWK_SUCCESS;
79 }
80
81 else if ((argc == 3) && (cli_strncmp(argv[2], "disable", 7) == 0)) {
82 id = strtoul(argv[1], NULL, 0);
83 if (id >= CHECKPOINT_NUM) {
84 cli_print("CP ID out of range.\n");
85 return FWK_E_PARAM;
86 }
87 checkpoint_table[id].bypass = CHECKPOINT_DISABLED;
88 return FWK_SUCCESS;
89 }
90
91 else if ((argc == 2) && (cli_strncmp(argv[1], "enableall", 9) == 0)) {
92 checkpoint_enable_all();
93 return FWK_SUCCESS;
94 }
95
96 else if ((argc == 2) && (cli_strncmp(argv[1], "disableall", 10) == 0)) {
97 checkpoint_disable_all();
98 return FWK_SUCCESS;
99 }
100
101 cli_print("CLI: Invalid command received:\n");
102 for (i = 0; i < (uint32_t)argc; i++)
103 cli_printf(NONE, "Parameter %d is %s\n", i, argv[i]);
104
105 return FWK_E_PARAM;
106 }
107
checkpoint_boot_state(uint32_t timeout_s)108 void checkpoint_boot_state(uint32_t timeout_s)
109 {
110 char c = 0;
111
112 /* Make sure nothing is waiting in UART buffer. */
113 while (fwk_io_getch(fwk_io_stdin, &c) == FWK_SUCCESS)
114 ;
115
116 cli_print("Press any key to enable checkpoints before boot... ");
117 while (timeout_s != 0) {
118 if (fwk_io_getch(fwk_io_stdin, &c) == FWK_SUCCESS) {
119 cli_print("\nCheckpoints enabled.\n");
120 checkpoint_enable_all();
121 return;
122 }
123 cli_printf(NONE, "%c%d", 0x8, timeout_s);
124 timeout_s = timeout_s - 1;
125 }
126 cli_printf(NONE, "%c0\n", 0x8);
127
128 return;
129 }
130