1
2 #include <stdbool.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <errno.h>
6
7 #include <sys/kassert.h>
8 #include <sys/kdebug.h>
9 #include <sys/sysctl.h>
10
11 typedef struct SysCtlEntry {
12 char path[64];
13 int type;
14 int flags;
15 char description[128];
16 void *node;
17 } SysCtlEntry;
18
19 #define SYSCTL_STR(_PATH, _FLAGS, _DESCRIPTION, _DEFAULT) \
20 { #_PATH, SYSCTL_TYPE_STR, _FLAGS, _DESCRIPTION, &SYSCTL_##_PATH },
21 #define SYSCTL_INT(_PATH, _FLAGS, _DESCRIPTION, _DEFAULT) \
22 { #_PATH, SYSCTL_TYPE_INT, _FLAGS, _DESCRIPTION, &SYSCTL_##_PATH },
23 #define SYSCTL_BOOL(_PATH, _FLAGS, _DESCRIPTION, _DEFAULT) \
24 { #_PATH, SYSCTL_TYPE_BOOL, _FLAGS, _DESCRIPTION, &SYSCTL_##_PATH },
25 SysCtlEntry SYSCTLTable[] = {
26 SYSCTL_LIST
27 { "", 0, 0, "", NULL },
28 };
29 #undef SYSCTL_STR
30 #undef SYSCTL_INT
31 #undef SYSCTL_BOOL
32
33 #define SYSCTL_STR(_PATH, _FLAGS, _DESCRIPTION, _DEFAULT) \
34 SysCtlString SYSCTL_##_PATH = { #_PATH, _DEFAULT };
35 #define SYSCTL_INT(_PATH, _FLAGS, _DESCRIPTION, _DEFAULT) \
36 SysCtlInt SYSCTL_##_PATH = { #_PATH, _DEFAULT };
37 #define SYSCTL_BOOL(_PATH, _FLAGS, _DESCRIPTION, _DEFAULT) \
38 SysCtlBool SYSCTL_##_PATH = { #_PATH, _DEFAULT };
39 SYSCTL_LIST
40 #undef SYSCTL_STR
41 #undef SYSCTL_INT
42 #undef SYSCTL_BOOL
43
44 int
SysCtl_Lookup(const char * path)45 SysCtl_Lookup(const char *path)
46 {
47 int i;
48
49 for (i = 0; SYSCTLTable[i].path[0] != '\0'; i++) {
50 if (strcmp(path, SYSCTLTable[i].path) == 0)
51 return i;
52 }
53
54 return -1;
55 }
56
57 uint64_t
SysCtl_GetType(const char * node)58 SysCtl_GetType(const char *node)
59 {
60 int i = SysCtl_Lookup(node);
61 if (i == -1) {
62 return SYSCTL_TYPE_INVALID;
63 }
64
65 return SYSCTLTable[i].type;
66 }
67
68 void *
SysCtl_GetObject(const char * node)69 SysCtl_GetObject(const char *node)
70 {
71 int i = SysCtl_Lookup(node);
72 if (i == -1) {
73 return NULL;
74 }
75
76 return SYSCTLTable[i].node;
77 }
78
79 uint64_t
SysCtl_SetObject(const char * node,void * obj)80 SysCtl_SetObject(const char *node, void *obj)
81 {
82 int i = SysCtl_Lookup(node);
83 if (i == -1) {
84 return ENOENT;
85 }
86
87 if (SYSCTLTable[i].flags == SYSCTL_FLAG_RO) {
88 kprintf("Sysctl node is read-only!\n");
89 return EACCES;
90 }
91
92 switch (SYSCTLTable[i].type) {
93 case SYSCTL_TYPE_STR: {
94 SysCtlString *val = (SysCtlString *)SYSCTLTable[i].node;
95 memcpy(val, obj, sizeof(*val));
96 }
97 case SYSCTL_TYPE_INT: {
98 SysCtlInt *val = (SysCtlInt *)SYSCTLTable[i].node;
99 memcpy(val, obj, sizeof(*val));
100 }
101 case SYSCTL_TYPE_BOOL: {
102 SysCtlBool *val = (SysCtlBool *)SYSCTLTable[i].node;
103 memcpy(val, obj, sizeof(*val));
104 }
105 }
106
107 return 0;
108 }
109
110 void
Debug_SysCtl(int argc,const char * argv[])111 Debug_SysCtl(int argc, const char *argv[])
112 {
113 int i;
114
115 if (argc == 1) {
116 kprintf("%-20s %s\n", "Name", "Description");
117 for (i = 0; SYSCTLTable[i].path[0] != '\0'; i++) {
118 kprintf("%-20s %s\n", SYSCTLTable[i].path, SYSCTLTable[i].description);
119 }
120
121 return;
122 }
123
124 if (argc != 2 && argc != 3) {
125 kprintf("Usage: sysctl NODE [VALUE]\n");
126 return;
127 }
128
129 i = SysCtl_Lookup(argv[1]);
130 if (i == -1) {
131 kprintf("Unknown sysctl node!\n");
132 return;
133 }
134
135 if (argc == 2) {
136 switch (SYSCTLTable[i].type) {
137 case SYSCTL_TYPE_STR: {
138 SysCtlString *val = (SysCtlString *)SYSCTLTable[i].node;
139 kprintf("%s: %s\n", argv[1], val->value);
140 break;
141 }
142 case SYSCTL_TYPE_INT: {
143 SysCtlInt *val = (SysCtlInt *)SYSCTLTable[i].node;
144 kprintf("%s: %ld\n", argv[1], val->value);
145 break;
146 }
147 case SYSCTL_TYPE_BOOL: {
148 SysCtlBool *val = (SysCtlBool *)SYSCTLTable[i].node;
149 kprintf("%s: %s\n", argv[1], val->value ? "true" : "false");
150 break;
151 }
152 }
153
154 return;
155 }
156
157 if (argc == 3) {
158 if (SYSCTLTable[i].flags == SYSCTL_FLAG_RO) {
159 kprintf("Sysctl node is read-only!\n");
160 return;
161 }
162
163 switch (SYSCTLTable[i].type) {
164 case SYSCTL_TYPE_STR: {
165 SysCtlString *val = (SysCtlString *)SYSCTLTable[i].node;
166 strncpy(&val->value[0], argv[2], SYSCTL_STR_MAXLENGTH);
167 break;
168 }
169 case SYSCTL_TYPE_INT: {
170 SysCtlInt *val = (SysCtlInt *)SYSCTLTable[i].node;
171 val->value = Debug_StrToInt(argv[2]);
172 break;
173 }
174 case SYSCTL_TYPE_BOOL: {
175 SysCtlBool *val = (SysCtlBool *)SYSCTLTable[i].node;
176 if (strcmp(argv[2], "0") == 0) {
177 val->value = false;
178 } else if (strcmp(argv[2], "1") == 0) {
179 val->value = true;
180 } else {
181 kprintf("Invalid value!\n");
182 }
183 break;
184 }
185 }
186 }
187 }
188
189 REGISTER_DBGCMD(sysctl, "SYSCTL", Debug_SysCtl);
190
191