tape-kernel 1.0
a modular modern independent kernel
Loading...
Searching...
No Matches
shell.c
Go to the documentation of this file.
1//shell.c -- kernel shell for raw testing
2#include "shell.h"
3#include "../fs/ide.h" //for ide
4#include "../mem/mem.h" //memory
5#include "../fs/fs.h" //for filesystem
6#include "../io/vga.h" //for rdln and prt
7#include "../io/cm.h" //for cnb
8#include "../lib/err.h" //for panic test
9#include "../lib/utils.h" //for cmds
10#include "../mem/heap.h" //for arena allocator
11#include "editor.h" //for editor
12#include "../fs/ffs.h" //ffs disksize
13#include "../kernel/cpu.h" //cpu funcs
14#include "../io/io.h"
15
16extern arena_t *cmd_arena; //command arena from main.c
17extern arena_t *fs_arena; //filesystem arena from main.c
18
19/**
20 * @brief displays shell help
21 *
22 * the show_help() internal function of shell.c displays kernel help
23 * adding help should be done with:
24 *
25 * @code{.c}
26 * clscr(); //clear screen
27 * int row = 0;
28 * prt(0, row++, "tape kernel commands:", 0x01);
29 * prt(0, row++, "help - this message", 0x0F);
30 * (existing prints)
31 * prt(0, row++, "mycmd [myint] - my description", 0x0F) //YOUR actual help message
32 * row++; //increment cursor so help doesnt overwrite
33 * cob(0, row++); set cursor
34 * @endcode
35 *
36 * please use variable naming convention of '[param]' for ints and '<param>' for strings
37*/
38static void show_help(void) {
39 clscr();
40 int row = 0;
41 prt(0, row++, "tape kernel commands:", 0x01);
42 prt(0, row++, "help - this message", 0x0F);
43 prt(0, row++, "clear - clear screen", 0x0F);
44 prt(0, row++, "ls - list files", 0x0F);
45 prt(0, row++, "read <name> - read file", 0x0F);
46 prt(0, row++, "write <name> - write file", 0x0F);
47 prt(0, row++, "rm <name> - delete file", 0x0F);
48 prt(0, row++, "echo <text> - echo text back", 0x0F);
49 prt(0, row++, "reboot - reboots system", 0x0F);
50 prt(0, row++, "alloc [size] - allocate memory (default 100)", 0x0F);
51 prt(0, row++, "heap - show heap info", 0x0F);
52 prt(0, row++, "panic - test panic", 0x0F);
53 prt(0, row++, "info - show system info", 0x0F);
54 row++;
55 cob(0, row++); //set cursor after help
56}
57
58/**
59 * @brief cmd_writefile writes a text message to a new file
60 *
61 * cmd_writefile is a static function that creates a new file with
62 * a given name and fills it with the provided text content
63 * @param name, the name of the file to create
64 * @param msg, the text content to write
65 *
66 * @see cmd_readfile(), fswrite(), fsadd()
67 */
68static void cmd_writefile(const char *name, const char *msg) {
69 uint32_t lba = fsnextlba();
70 uint8_t sector[512];
71
72 //clear sector
73 for (int i = 0; i < 512; i++) sector[i] = 0;
74
75 //write message
76 for (int i = 0; msg[i] && i < 512; i++) sector[i] = (uint8_t)msg[i];
77
78 iwrt(lba, sector);
79 fsadd(fs_arena, name, lba);
80
81 int cx, cy;
82 cnb(&cx, &cy);
83 prt(0, cy + 1, "wrote file: ", 0x0F);
84 prt(13, cy + 1, name, 0x0F);
85 cob(0, cy + 2); //move cursor to next line after output
86}
87
88/**
89 * @brief cmd_readfile reads and displays a files contents
90 *
91 * cmd_readfile is a static function that looks up a file on disk
92 * by name and prints its contents to the screen
93 * @param name, the name of the file to read
94 *
95 * @see cmd_writefile(), fsread()
96 */
97static void cmd_readfile(const char *name) {
98 uint32_t lba = fsfind(name);
99 int cx, cy;
100 cnb(&cx, &cy);
101
102 if (lba == 0) {
103 prt(0, cy + 1, "file not found: ", 0x0C);
104 prt(17, cy + 1, name, 0x0C);
105 cob(0, cy + 2);
106 return;
107 }
108
109 uint8_t sector[512];
110 irsec(lba, sector);
111
112 if (sector[0] != '\0') {
113 //create a temporary buffer with newline appended
114 char temp[513];
115 int i;
116 for (i = 0; i < 511 && sector[i] != '\0'; i++) {
117 temp[i] = (char)sector[i];
118 } //this stops the prompt from overwriting text
119 temp[i] = '\n';
120 temp[i + 1] = '\0';
121
122 prt(0, cy + 1, temp, 0x0F);
123
124 //count lines including the appended newline
125 int lines = 1;
126 for (int j = 0; temp[j] != '\0'; j++) {
127 if (temp[j] == '\n') lines++;
128 }
129 cob(0, cy + lines);
130 } else {
131 prt(0, cy + 1, "(empty)", 0x0F);
132 cob(0, cy + 2);
133 }
134}
135
136/**
137 * @brief cmd_alloc allocates memory from the command arena
138 *
139 * cmd_alloc is a static function that allocates a block of memory
140 * from cmd_arena and prints the resulting pointer address
141 * @param size, the number of bytes to allocate (defaults to 100)
142 *
143 * @see alc(), cmd_arena, res()
144 */
145static void cmd_alloc(uint32_t size) {
146 if (size == 0) size = 100;
147
148 void *ptr = alc(cmd_arena, size);
149 int cx, cy;
150 cnb(&cx, &cy);
151
152 if (ptr == 0) {
153 prt(0, cy + 1, "alloc fail", 0x0C);
154 } else {
155 prt(0, cy + 1, "alloc ", 0x0F);
156 prtd(6, cy + 1, (int)size, 0x0F);
157 prt(10, cy + 1, " bytes at 0x", 0x0F);
158 prth(22, cy + 1, (uint32_t)ptr, 0x0F);
159 }
160 cob(0, cy + 2);
161}
162
163/**
164 * @brief shell is the interactive kernel command shell
165 *
166 * shell is a function that runs an infinite loop displaying the
167 * tape prompt and processing user commands
168 * @param mb_info, the multiboot info pointer passed from kmain
169 * for memory queries
170 *
171 * shell supports the following commands: help, clear, ls, read,
172 * write, rm, echo, reboot, alloc, heap, panic, and info
173 *
174 * using shell is done with
175 * @code{.c}
176 * #include "../usr/shell.h" //or just shell.h
177 * shell(mb_info);
178 * @endcode
179 *
180 * @see kmain(), show_help(), cmd_arena
181 */
182NORETURN void __shell(void *mb_info) {
183 char inpt[100];
184 char *args[MAX_ARGS];
185 int cx, cy;
186
187 while (1) {
188 res(cmd_arena); //reset command arena before each command
189
190 cnb(&cx, &cy);
191 prt(0, cy, "tape", 0x0F); //prompt
192 prt(4, cy, "@", 0x06);
193 cob(cx + 6, cy);
194 rdln(inpt, 100);
195
196 if (inpt[0] == '\0') {
197 //just move to next line if empty input
198 cnb(&cx, &cy);
199 cob(0, cy + 1);
200 continue;
201 }
202
203 int argc = pargs(inpt, args);
204 if (argc == 0) continue;
205
206 if (strcmp(args[0], "help") == 0) {
207 show_help();
208 }
209 else if (strcmp(args[0], "clear") == 0) {
210 clscr();
211 cob(0, 0);
212 }
213 else if (strcmp(args[0], "ls") == 0) {
214 char *list = fslist();
215 cnb(&cx, &cy);
216 if (list[0] == '\0') {
217 prt(0, cy + 1, "(empty)", 0x0F);
218 cob(0, cy + 2);
219 } else {
220 //append newline to the list
221 char temp[513];
222 int i;
223 for (i = 0; i < 511 && list[i] != '\0'; i++) {
224 temp[i] = list[i];
225 }
226 temp[i] = '\n';
227 temp[i + 1] = '\0';
228
229 prt(0, cy + 1, temp, 0x0F);
230
231 int lines = 1;
232 for (int j = 0; temp[j] != '\0'; j++) {
233 if (temp[j] == '\n') lines++;
234 }
235 cob(0, cy + lines);
236 }
237 }
238 else if (strcmp(args[0], "panic") == 0) {
239 panic("test panic");
240 }
241 else if (strcmp(args[0], "alloc") == 0) {
242 uint32_t size = (argc >= 2) ? (uint32_t)atoi(args[1]) : 100;
243 cmd_alloc(size);
244 }
245 else if (strcmp(args[0], "heap") == 0) {
246 cnb(&cx, &cy);
247 prt(0, cy + 1, "cmd arena start: 0x", 0x0F); //show cmd_arena info
248 prth(19, cy + 1, (uint32_t)cmd_arena->start, 0x0F);
249 prt(0, cy + 2, "cmd arena current: 0x", 0x0F);
250 prth(21, cy + 2, (uint32_t)cmd_arena->current, 0x0F);
251 prt(0, cy + 3, "cmd arena size: ", 0x0F);
252 prtd(17, cy + 3, (int)cmd_arena->size, 0x0F);
253 prt(0, cy + 4, "cmd arena used: ", 0x0F);
254 prtd(17, cy + 4, (int)((uint32_t)cmd_arena->current - (uint32_t)cmd_arena->start), 0x0F);
255 cob(0, cy + 5);
256 }
257 else if (strcmp(args[0], "read") == 0) {
258 if (argc < 2) {
259 cnb(&cx, &cy);
260 prt(0, cy + 1, "usage: read <name>", 0x0C);
261 cob(0, cy + 2);
262 } else {
263 cmd_readfile(args[1]);
264 }
265 }
266 else if (strcmp(args[0], "write") == 0) {
267 if (argc < 2) {
268 cnb(&cx, &cy);
269 prt(0, cy + 1, "usage: write <name>", 0x0C);
270 cob(0, cy + 2);
271 } else if (argc == 3) {
272 cmd_writefile(args[1], args[2]);
273 } else {
274 editor(args[1]);
275 }
276 }
277 else if (strcmp(args[0], "rm") == 0) {
278 if (argc < 2) {
279 cnb(&cx, &cy);
280 prt(0, cy + 1, "usage: rm <name>", 0x0C);
281 cob(0, cy + 2);
282 } else {
283 uint32_t lba = fsfind(args[1]);
284 cnb(&cx, &cy);
285 if (lba == 0) {
286 prt(0, cy + 1, "rm: file not found: ", 0x0C);
287 prt(21, cy + 1, args[1], 0x0C);
288 cob(0, cy + 2);
289 } else {
290 fsdelete(args[1]);
291 prt(0, cy + 1, "rm: deleted ", 0x0F);
292 prt(13, cy + 1, args[1], 0x0F);
293 cob(0, cy + 2);
294 }
295 }
296 }
297 else if (strcmp(args[0], "reboot") == 0) {
298 reboot();
299 }
300 else if (strcmp(args[0], "echo") == 0) {
301 cnb(&cx, &cy);
302
303 //print incrementally
304 int curx = 0;
305 int cury = cy + 1;
306
307 for (int i = 1; i < argc; i++) {
308 //print each argument directly
309 prt(curx, cury, args[i], 0x0F);
310
311 //update cursor position for next print
312 curx += strlen(args[i]);
313
314 if (i < argc - 1) {
315 prt(curx, cury, " ", 0x0F);
316 curx++;
317 }
318
319 //handle line wrapping
320 if (curx >= 80) {
321 curx = 0;
322 cury++;
323 if (cury >= 25) {
324 scrl();
325 cury = 24;
326 }
327 }
328 }
329
330 //set cursor to next line
331 cob(0, cy + 2);
332 }
333 else if (strcmp(args[0], "info") == 0) {
334 cnb(&cx, &cy);
335 prt(0, cy + 1, "sysinfo:", 0x01);
336
337 prt(0, cy + 2, "mem: ", 0x0F);
338 uint32_t msize = memsize(mb_info); //get mem size
339 prtd(5, cy + 2, (int)msize, 0x0F);
340
341 prt(0, cy + 3, "disk: ", 0x0F);
342 uint32_t dsize = disksize(); //get disk sizec
343 prtd(7, cy + 3, (int)dsize, 0x0F);
344
345 char cpu[64];
346 getcpu(cpu, sizeof(cpu)); //get cpu str
347 prt(0, cy + 4, "cpu: ", 0x0F);
348 prt(5, cy + 4, cpu, 0x0F);
349
350 cob(0, cy + 5);
351 }
352 else {
353 cnb(&cx, &cy);
354 prt(0, cy + 1, "unknown: ", 0x0C);
355 prt(9, cy + 1, args[0], 0x0C);
356 cob(0, cy + 2);
357 }
358 }
359}
#define cnb
Definition cm.h:6
#define cob
Definition cm.h:7
#define getcpu
Definition cpu.h:6
static char lines[32][80+1]
Definition editor.c:15
#define editor
Definition editor.h:4
#define panic
Definition err.h:5
#define disksize
Definition ffs.h:7
#define fslist
Definition fs.h:12
#define fsfind
Definition fs.h:11
#define fsdelete
Definition fs.h:16
#define fsadd
Definition fs.h:10
#define fsnextlba
Definition fs.h:13
#define alc
Definition heap.h:25
#define res
Definition heap.h:26
#define iwrt
Definition ide.h:19
#define irsec
Definition ide.h:18
#define reboot
Definition io.h:10
arena_t * fs_arena
the filesystem child arena
Definition main.c:56
arena_t * cmd_arena
the command processing child arena
Definition main.c:66
#define memsize
Definition mem.h:6
static void cmd_readfile(const char *name)
cmd_readfile reads and displays a files contents
Definition shell.c:97
void __shell(void *mb_info)
shell is the interactive kernel command shell
Definition shell.c:182
static void cmd_writefile(const char *name, const char *msg)
cmd_writefile writes a text message to a new file
Definition shell.c:68
static void show_help(void)
displays shell help
Definition shell.c:38
static void cmd_alloc(uint32_t size)
cmd_alloc allocates memory from the command arena
Definition shell.c:145
the arena_t type
Definition heap.h:17
unsigned int uint32_t
Definition types.h:30
#define NORETURN
Definition types.h:40
unsigned char uint8_t
Definition types.h:28
int strcmp(const char *a, const char *b)
Definition utils.c:15
int strlen(const char *s)
Definition utils.c:9
int pargs(char *line, char *args[])
pargs parses a command line into an argument array
Definition utils.c:189
int atoi(const char *str)
atoi converts a decimal string to an integer
Definition utils.c:118
#define MAX_ARGS
Definition utils.h:5
#define prtd
Definition vga.h:12
#define prth
Definition vga.h:13
#define scrl
Definition vga.h:8
#define prt
Definition vga.h:6
#define clscr
Definition vga.h:7
#define rdln
Definition vga.h:9