Added .gitignore
[comos.git] / kernel / shell.c
blob34bf548176003694b45b351ec79d532b18316014
1 #include "general.h"
2 #include "shell.h"
3 #include "console.h"
4 #include "keyboard.h"
5 #include "critical.h"
6 #include "stdlib.h"
7 #include "task.h"
8 #include "cpuid.h"
9 #include "interrupt.h"
11 /* the character buffer is a ring buffer */
12 #define key_buf_size 256
13 uint8_t key_buffer[key_buf_size]; /* character buffer */
14 uint8_t next_key;
15 fnList fnFunctions[255] = {0};
16 char fnCommands[255][50];
17 char fnDescriptions[255][50];
18 volatile uint8_t fnPos = 0;
20 uint8_t show_cmd_pos = 0;
21 static fnList show_cmd_functions[256] = {0};
22 static char show_cmds[256][32];
24 typedef struct lastCom
26 char buffer[256];
27 uint8_t length;
28 struct lastCom *prevCom;
29 struct lastCom *nextCom;
30 } lastCom_t;
32 lastCom_t *root_com;
33 lastCom_t *tail_com;
34 lastCom_t *cur_com;
36 /* shell_keypress(key) takes input directly from the keyboard
37 handler, places it in the buffer, and decrements the
38 buffer pointer */
39 uint32_t key_pos_head = 0;
40 void shell_keypress(uint8_t key)
42 key_buffer[(key_pos_head % key_buf_size)] = key;
43 key_pos_head += 1;
46 /* shell_get_next_key() finds the top of the character buffer
47 and returns the character. If the buffer is empty, return 0. */
48 uint32_t key_pos_tail = 0;
49 uint8_t shell_get_next_key()
51 if((key_pos_tail % key_buf_size) == (key_pos_head % key_buf_size))
52 {return 0;}
54 next_key = key_buffer[(key_pos_tail % key_buf_size)];
55 if(!next_key){return 0;}
57 key_pos_tail += 1;
58 return next_key;
61 /* shell_task() starts by telling the keyboard handler to
62 send the ascii key to shell_keypress(key). This places
63 the key into our ring buffer. Then this task function
64 searches the buffer using a head-tail method and prints
65 the characters to the screen. */
66 void kshell_task()
68 critical_enter();
69 uint8_t lkey = 0;
70 uint8_t temp = 0;
71 uint8_t keyBPos = 0;
72 uint8_t commandBuffer[key_buf_size-1] = {0};
74 key_pos_head = key_pos_tail = 0;
75 keyboard_register_listener(&shell_keypress);
76 //Register useable shell functions
77 kshell_function("ver",&shell_ver,"Displays the kernel version.");
78 kshell_function("cmds",&shell_cmds,"Lists the available commands.");
79 kshell_function("clear",&shell_clear,"Clears the screen.");
80 kshell_function("ps",&shell_ps,"Lists the currently running tasks.");
81 kshell_function("show",&shell_show,"Lists object info. (usage: show <object>)");
83 kshell_add_show_child("version", &shell_ver);
84 kshell_add_show_child("commands", &shell_cmds);
85 kshell_add_show_child("processes", &shell_ps);
86 kshell_add_show_child("tasks", &shell_ps);
87 kshell_add_show_child("cpuid", &shell_cpuid);
88 kshell_add_show_child("system-info", &shell_system_info);
89 kshell_add_show_child("interrupts", &shell_interrupts);
90 ///////////////////////////////////
91 critical_exit();
93 for(;;)
95 while(1)
97 critical_enter();
98 console_printf(get_vterm(0), "\n$%s>", "/home/");
99 critical_exit();
101 while(lkey != '\n')
103 lkey = shell_get_next_key();
105 if(lkey == '\b')
107 if(keyBPos > 0)
109 critical_enter();
110 console_printf(get_vterm(0), "\b \b");
111 critical_exit();
112 keyBPos--;
115 else if(lkey == '\t')
117 console_printf(get_vterm(0), " ");
119 else if(lkey == K_VTERM_1 ||
120 lkey == K_VTERM_2 ||
121 lkey == K_VTERM_3 ||
122 lkey == K_VTERM_4)
124 critical_enter();
125 if(keyBPos){keyBPos--;}
126 console_printf(get_vterm(0), "\nswitching to vterm(%u)",lkey-K_VTERM_1);
127 console_printf(get_vterm(0), "\n$%s>", "/home/");
128 switch_vterm(get_vterm(lkey - K_VTERM_1));
129 critical_exit();
131 else if(lkey == K_UP /* up */)
133 while(keyBPos>0)
134 { //This can be dramaticly optimized...like..one line of code...
135 critical_enter();
136 console_printf(get_vterm(0), "\b \b");
137 critical_exit();
138 keyBPos--;
140 if(cur_com != 0)
142 for(temp = 0; temp < cur_com->length; temp++)
144 critical_enter();
145 console_printf(get_vterm(0), "%c",cur_com->buffer[temp]);
146 critical_exit();
147 commandBuffer[keyBPos] = cur_com->buffer[temp];
148 if(keyBPos < 254){ keyBPos++; }
149 else{ break; }
151 if(cur_com->prevCom != 0){ cur_com = cur_com->prevCom; }
155 else if(lkey == K_DOWN /* down */)
157 while(keyBPos > 0)
158 { //This can be dramaticly optimized...like..one line of code...
159 critical_enter();
160 console_printf(get_vterm(0), "\b \b");
161 critical_exit();
162 keyBPos--;
165 if(cur_com != 0)
167 for(temp = 0; temp < cur_com->length; temp++)
169 critical_enter();
170 console_printf(get_vterm(0), "%c",cur_com->buffer[temp]);
171 critical_exit();
172 commandBuffer[keyBPos] = cur_com->buffer[temp];
173 if(keyBPos < 254){ keyBPos++; }
174 else{ break; }
176 if(cur_com->nextCom != 0) cur_com = cur_com->nextCom;
181 else if(lkey > 0)
183 if(lkey!='\n')
185 critical_enter();
186 console_printf(get_vterm(0), "%c",lkey);
187 commandBuffer[keyBPos] = lkey;
188 if(keyBPos < 254){ keyBPos++; }
189 else{ break; }
190 critical_exit();
195 critical_enter();
196 console_printf(get_vterm(0), "1\n");
197 commandBuffer[keyBPos] = '\0';
198 console_printf(get_vterm(0), "2\n");
199 cur_com = tail_com;
201 cur_com->nextCom = (lastCom_t*)malloc(sizeof(lastCom_t));
202 console_printf(get_vterm(0), "3\n");
203 cur_com->nextCom->prevCom = cur_com;
204 cur_com->nextCom->nextCom = 0;
205 cur_com->nextCom->length = keyBPos;
206 console_printf(get_vterm(0), "4\n");
207 strcpy((char *)cur_com->nextCom->buffer,(char *)commandBuffer);
208 console_printf(get_vterm(0), "5\n");
209 cur_com = cur_com->nextCom;
210 tail_com = cur_com;
211 cur_com = tail_com;
212 console_printf(get_vterm(0), "6\n");
213 critical_exit();
214 kshell_lookup((char*)commandBuffer);
215 lkey = 0;
216 keyBPos = 0;
221 uint8_t tmp[key_buf_size];
223 void kshell_lookup(char buffer[key_buf_size-1])
225 uint8_t x = 0;
227 critical_enter();
229 while(buffer[x]!='\n' && buffer[x]!=' ' && buffer[x]!='\0' && x < key_buf_size-1)
231 tmp[x] = buffer[x];
232 x++;
235 console_printf(get_vterm(0), "7\n");
237 if(x < key_buf_size-1)
239 tmp[x] = 0;
240 for(x = 0; x < fnPos; x++)
242 console_printf(get_vterm(0), ":%u, ", x);
243 console_printf(get_vterm(0), "\"%s\", ", (char *)tmp);
244 console_printf(get_vterm(0), "\"%s\", ", (char *)fnCommands[x]);
245 console_printf(get_vterm(0), "0x%X, ", (uint32_t)tmp);
246 console_printf(get_vterm(0), "%u\n", fnPos);
248 if(!strcmp((char *)tmp, fnCommands[x]))
250 console_printf(get_vterm(0), "8\n");
251 console_printf(get_vterm(0), "fnFunctions[%u](0x%X)\n", x, (uint32_t)buffer);
252 critical_exit();
253 fnFunctions[x](buffer);
254 return;
257 buffer[x] = 0;
260 buffer[key_buf_size-2] = 0; // just in case
261 console_printf(get_vterm(0), "\nCommand %s not found.", buffer);
265 void kshell_function(char fname[50], fnList fFunction, char *fdesc)
267 critical_enter();
268 fnFunctions[fnPos] = fFunction;
269 memset(fnCommands[fnPos], 0, 50);
270 memcpy(fnCommands[fnPos], fname, 50);
271 memset(fnDescriptions[fnPos], 0, 50);
272 strcpy(fnDescriptions[fnPos++], fdesc);
273 critical_exit();
276 void kshell_add_show_child(char *fname, fnList fFunction)
278 show_cmd_functions[show_cmd_pos] = fFunction;
279 memset(show_cmds[show_cmd_pos], 0, 32);
280 strcpy(show_cmds[show_cmd_pos++], fname);
283 /***************************************
284 Place all shell functions below here.
285 ***************************************/
286 void shell_ver(char * buffer)
288 critical_enter();
289 console_printf(get_vterm(0), "\nCommunity OS version %s i386 (codenamed: %s)", kernel_version, kernel_codename);
290 critical_exit();
293 void shell_cmds(char * buffer)
295 int x;
296 critical_enter();
297 for(x=0;x<fnPos;x++)
299 console_printf(get_vterm(0), "\nindex = {%i}, command = {%s}, desc = {%s}", x,fnCommands[x],fnDescriptions[x]);
301 critical_exit();
304 void shell_clear(char * buffer)
306 console_clear(curcons);
309 void shell_ps(char * buffer)
311 uint32_t i, tasks_found = 0;
313 critical_enter();
315 console_printf(get_vterm(0), "\nactive tasks: %u, sleeping tasks: %u, maximum tasks allowed: %u \n", num_active_tasks,
316 num_sleeping_tasks,
317 MAX_TASKS);
318 for(i = 0; i < MAX_TASKS; i++)
320 if(task[i].state == TASK_READY)
322 tasks_found++;
323 console_printf(get_vterm(0), "\ntask(%u): priority: %u, name: \"%s\"", i, task[i].priority, task[i].name);
325 if(tasks_found >= num_active_tasks){
326 break;
330 critical_exit();
333 void shell_cpuid(char * buffer)
335 critical_enter();
336 console_printf(get_vterm(0), "\n ******************************************************* ");
337 console_printf(get_vterm(0), "\n *** CPUID Information: *** ");
338 console_printf(get_vterm(0), "\n ** - This function prints the information parsed ** ");
339 console_printf(get_vterm(0), "\n * from all available CPUID instructions. * ");
340 console_printf(get_vterm(0), "\n * - If information is missing, it has been * ");
341 console_printf(get_vterm(0), "\n ** detected as unavailable or erroneous. ** ");
342 console_printf(get_vterm(0), "\n *** - Written by: 01000101 *** ");
343 console_printf(get_vterm(0), "\n ******************************************************* \n");
345 console_printf(get_vterm(0), "\nmax normal EAX input: 0x%X\nmax extended EAX input: 0x%X", cpuid.max_basic_input_val,
346 cpuid.max_ext_input_val);
348 if(cpuid.max_basic_input_val >= 1){
349 console_printf(get_vterm(0), "\ncpuid(1).ecx: 0x%X\ncpuid(1).edx: 0x%X", cpuid.features_ecx, cpuid.features_edx);
350 console_printf(get_vterm(0), "\nstepping: 0x%X, model: 0x%X, family: 0x%X, type: 0x%X", cpuid.stepping,
351 cpuid.model,
352 cpuid.family,
353 cpuid.type);
354 console_printf(get_vterm(0), "\ncache-line size: %u bytes", cpuid.cache_line_size);
357 console_printf(get_vterm(0), "\nmanufacturer: \"%s\"", cpuid.manufacturer_string);
359 if(cpuid.max_ext_input_val >= 0x80000004){
360 console_printf(get_vterm(0), "\ncpu brand: \"%s\"", cpuid.cpu_brand);
363 console_printf(get_vterm(0), "\n");
365 critical_exit();
368 void shell_interrupts(char * buffer)
370 critical_enter();
372 console_printf(get_vterm(0), "\ninstalled interrupt service routines: %u\n", num_installed_interrupts);
373 console_printf(get_vterm(0), "\nexceptions are mapped to irqs 0-31, irqs 32-255 are user defined");
374 console_printf(get_vterm(0), "\ninterrupt controller: PIC"); // will be replaced with IOAPIC/PIC detection
375 uint32_t i = 0;
376 for(i = 0; i < 256; i++)
378 if((uint32_t)interrupt_handlers[i] != default_handler_ptr)
380 console_printf(get_vterm(0), "\nirq(%u) routes to address 0x%X", i, interrupt_handlers[i]);
383 critical_exit();
386 void shell_system_info(char * buffer)
388 critical_enter();
389 console_printf(get_vterm(0), "\nfunction not yet implemented");
390 critical_exit();
393 void shell_show(char * buffer)
395 uint8_t i = 0;
397 for(i = 0; i < show_cmd_pos; i++)
399 if(!strcmp(buffer + 5, show_cmds[i])){ show_cmd_functions[i](buffer); return; }
402 critical_enter();
403 console_printf(get_vterm(0), "\nshow usage: show <object>");
404 critical_exit();