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
11 #include <fwk_status.h>
12
13 #include <stdbool.h>
14 #include <stdlib.h>
15 #include <string.h>
16
17 checkpoint_st checkpoint_table[CHECKPOINT_NUM] = {0};
18
19 /* Reset value for bypass. */
20 static volatile int32_t bypass_reset = CHECKPOINT_DISABLED;
21
checkpoint_enable_all(void)22 void checkpoint_enable_all(void)
23 {
24 uint32_t i = 0;
25
26 for (i = 0; i < CHECKPOINT_NUM; i++) {
27 /*
28 * Bypass set to 0 to ensure thread stops at the next checkpoint. Tag
29 * is set to empty string to keep things clean.
30 */
31 checkpoint_table[i].bypass = CHECKPOINT_ENABLED;
32 checkpoint_table[i].tag[0] = 0;
33 }
34
35 /* Changing reset value to enabled by default. */
36 bypass_reset = CHECKPOINT_ENABLED;
37 }
38
checkpoint_disable_all(void)39 void checkpoint_disable_all(void)
40 {
41 uint32_t i = 0;
42
43 for (i = 0; i < CHECKPOINT_NUM; i++) {
44 /*
45 * Bypass is set to -1 and tag is set to an empty string so checkpoint
46 * will be skipped.
47 */
48 checkpoint_table[i].bypass = CHECKPOINT_DISABLED;
49 checkpoint_table[i].tag[0] = 0;
50 }
51 }
52
checkpoint_register(checkpoint_st ** c,char * name)53 int32_t checkpoint_register(checkpoint_st **c, char *name)
54 {
55 uint32_t i = 0;
56
57 for (i = 0; i < CHECKPOINT_NUM; i++) {
58 if (checkpoint_table[i].in_use == false) {
59 checkpoint_table[i].in_use = true;
60 checkpoint_table[i].index = i;
61 strncpy(checkpoint_table[i].name, name, CHECKPOINT_NAME_LEN);
62 checkpoint_table[i].name[CHECKPOINT_NAME_LEN - 1] = 0;
63 checkpoint_table[i].bypass = bypass_reset;
64 *c = &checkpoint_table[i];
65 return FWK_SUCCESS;
66 }
67 }
68
69 return FWK_E_NOMEM;
70 }
71
checkpoint(checkpoint_st * c,char * file,int32_t line,char * tag)72 void checkpoint(checkpoint_st *c, char *file, int32_t line, char *tag)
73 {
74 /* If tags match or if bypass == 0, stop here. */
75 if ((c->bypass == CHECKPOINT_ENABLED) ||
76 ((tag != NULL) && (strncmp(tag, c->tag, CHECKPOINT_TAG_LEN) == 0))) {
77 cli_printf(NONE,
78 "SCP Debugger has stopped at a checkpoint.\n"
79 "Tag: %s\n File: %s\n Line: %d\n",
80 tag,
81 file,
82 line);
83
84 c->tag[0] = 0;
85 c->bypass = CHECKPOINT_ENABLED;
86
87 cli_start();
88
89 cli_printf(NONE,
90 "SCP execution resume at a checkpoint.\n"
91 "Tag: %s\n File: %s\n Line: %d\n",
92 tag,
93 file,
94 line);
95
96 return;
97 }
98
99 /* If bypass is less than 0 (-1), checkpoint is disabled so return. */
100 if (c->bypass == CHECKPOINT_DISABLED)
101 return;
102 else {
103 /* If bypass is greater than 0, decrement and return. */
104 c->bypass = c->bypass - 1;
105 return;
106 }
107 }
108