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