|
|
1.1 root 1: /* builtin.c -- builtin routines for tboot.
2: *
3: * Add new ones by adding a check for them in interpret().
4: *
5: * La Monte H. Yarroll <[email protected]>, September 1991
6: */
7:
8: #include <string.h>
9: #include <sys/inode.h>
10: #include <sys/ino.h>
11: #include <sys/dir.h>
12: #include <sys/typed.h>
13: #include "tboot.h"
14:
15: extern int slow_flag; /* Slow down pacifier. */
16: extern int feet_flag; /* Enable pacifier footprints. */
17:
18: /*
19: * If possible, execute "command".
20: * Return "true" if the command exists, "false" otherwise.
21: */
22: int
23: interpret(command)
24: char *command;
25: {
26: char *argv[MAX_TOKENS+1]; /* Command vector. */
27: char *current_token;
28: char *cmd_name; /* The first token of the command line. */
29: int i;
30:
31: current_token = strtok(command, WS);
32: cmd_name = current_token; /* Extract the command. */
33: /* Build the command argv. */
34: for (i = 0; NULL != current_token && i < MAX_TOKENS; ++i) {
35: argv[i] = current_token;
36: current_token = strtok(NULL, WS);
37: }
38:
39: argv[i] = NULL; /* NULL terminate the list of pointers. */
40:
41: /*
42: * If we ran out of token slots, print a warning.
43: */
44: if (i >= MAX_TOKENS) {
45: puts("\r\nWarning: truncating line to:\r\n");
46: for (i = 0 ; i < MAX_TOKENS; ++i) {
47: puts(argv[i]);
48: puts(" ");
49: }
50: puts("\r\n");
51: }
52:
53: /*
54: * Interpret the lexed command.
55: */
56: if (0 == strcmp(cmd_name, "info")) {
57: dpb();
58: return(TRUE);
59: } else if ((0 == strcmp(cmd_name, "dir")) ||
60: (0 == strcmp(cmd_name, "ls") ) ||
61: (0 == strcmp(cmd_name, "lc") )) {
62: dir();
63: return(TRUE);
64: } else if ( (0 == strncmp(cmd_name, "sys_base", strlen("sys_base")) ) ||
65: (0 == strncmp(cmd_name, "scs", strlen("scs")) )
66: ) {
67: char lbuf[5]; /* 5 == strlen("0000") + 1 */
68: if (NULL != strchr(cmd_name, '=')){
69: puts("Setting sys_base.\r\n");
70: sys_base_set = (1==1);
71: sys_base = (uint16)
72: basetoi(1 + strchr(cmd_name, '='), 16);
73: }
74: if (!sys_base_set) {
75: puts("sys_base will default to ");
76: print16(DEF_SYS_BASE);
77: puts(" for l.out executables,\r\n and to ");
78: print16(COFF_SYS_BASE);
79: puts(" for COFF executables.\r\n");
80: } else {
81: puts("sys_base is ");
82: itobase((uint16) sys_base, lbuf, 16);
83: puts(lbuf);
84: puts("\r\n");
85: }
86: return(TRUE);
87: } else if (0 == strcmp(cmd_name, "monitor")) {
88: monitor();
89: return(TRUE);
90: } else if (0 == strcmp(cmd_name, "cpu_type")) {
91: switch(get_cpu_type()) {
92: case 0: puts("less than 286\r\n"); break;
93: case 1: puts("286\r\n"); break;
94: case 2: puts("386 or better\r\n"); break;
95: }
96: return(TRUE);
97: } else if ((0 == strcmp(cmd_name, "verbose"))) {
98: verbose_flag = TRUE;
99: puts("Verbose mode.\r\n");
100: return(TRUE);
101: } else if ((0 == strcmp(cmd_name, "terse"))) {
102: verbose_flag = FALSE;
103: puts("Terse mode.\r\n");
104: return(TRUE);
105: } else if ((0 == strcmp(cmd_name, "slow"))) {
106: slow_flag = TRUE;
107: puts("Slow pacifier mode.\r\n");
108: return(TRUE);
109: } else if ((0 == strcmp(cmd_name, "fast"))) {
110: slow_flag = FALSE;
111: puts("Normal pacifier mode.\r\n");
112: return(TRUE);
113: } else if ((0 == strcmp(cmd_name, "feet"))) {
114: feet_flag = TRUE;
115: puts("Pacifier footprints enabled.\r\n");
116: return(TRUE);
117: } else if ((0 == strcmp(cmd_name, "nofeet"))) {
118: feet_flag = FALSE;
119: puts("No pacifier footprints.\r\n");
120: return(TRUE);
121: } else if ((0 == strcmp(cmd_name, "gift"))) {
122: dump_gift(); /* Dump boot_gift. */
123: return(TRUE);
124: } else if ((0 == strcmp(cmd_name, "test"))) {
125: if (arg_exist("arg")) {
126: puts("Yep.\r\n");
127: } else {
128: puts("Nope.\r\n");
129: }
130: return(TRUE);
131: } else if ((0 == strcmp(cmd_name, "help")) ||
132: (0 == strcmp(cmd_name, "?")) ) {
133: puts("info Print disk information.\r\n");
134: puts("dir|ls List contents of /.\r\n");
135: puts("?|help Print this list.\r\n");
136: return(TRUE);
137: } else if (0 == strcmp(cmd_name, "mon_on")) {
138: want_monitor = TRUE;
139: puts("Mini-monitor will autoinvoke before running kernel.\r\n");
140: return(TRUE);
141: } else if (0 == strcmp(cmd_name, "??")) {
142: puts("UNSUPPORTED FEATURES: (don't call :-)\r\n");
143: puts("sys_base|scs Print current load segment.\r\n");
144: puts("sys_base=tttt Set current load segment to 0xtttt.\r\n");
145: puts("test arg Test for the presence of arg.\r\n");
146: puts("monitor Invoke the mini-monitor.\r\n");
147: puts("mon_on Autoinvoke the mini-monitor before kernel.\r\n");
148: puts("cpu_type print the cpu type.\r\n");
149: puts("verbose Be verbose.\r\n");
150: puts("terse Do not be verbose.\r\n");
151: puts("slow Slow down pacifier.\r\n");
152: puts("fast Normal speed pacifier.\r\n");
153: puts("feet Enable pacifier footprints.\r\n");
154: puts("nofeet Disable pacifier footprints.\r\n");
155: return(TRUE);
156: } else {
157: execute(argv);
158: return(FALSE);
159: }
160: puts("\r\nUNREACHABLE CODE IN interpret() EXECUTED.\r\n");
161: puts("There is probably a missing return() in interpret().\r\n");
162: return(FALSE); /* This should be an unreachable line. */
163: } /* interpret() */
164:
165: /* Display the BIOS parameters loaded up by the startup code. */
166: void
167: dpb()
168: {
169: char buffer[BLOCK];
170: int i;
171: int num_of_drives;
172: struct reg r;
173:
174:
175: num_of_drives = get_num_of_drives();
176:
177: puts("\r\nHere are the BIOS parameters for your hard drive");
178: if (num_of_drives > 1) { putchar('s'); }
179: puts(".\r\n");
180: puts("Write them down for use during installation.\r\n");
181:
182: for (i = 0; i < num_of_drives; ++i) {
183:
184: r.r_ax = DISK_PARAMS;
185: r.r_dx = HARD_DRIVE + i;
186:
187: intcall(&r, &r, DISKINT); /* Ask the BIOS. */
188:
189: puts("Drive ");
190: itobase((uint16) i, buffer, 10);
191: puts(buffer);
192:
193:
194: /* ch is the lower 8 bits of number of cylinders.
195: * The high two bits of cl are the top two bits of
196: * 10 bit number of cylinders.
197: *
198: * The cylinder count is actually 1 short.
199: */
200: puts(": Cylinders=");
201: itobase((uint16) (
202: ((LOW(r.r_cx) >> 6) * 256) + /* Top two bits... */
203: (HIGH(r.r_cx) + 1)
204: ),
205: buffer, 10);
206: puts(buffer);
207:
208: /* The head count is actually 1 short. */
209: puts(" Heads=");
210: itobase((uint16) HIGH(r.r_dx) + 1, buffer, 10);
211: puts(buffer);
212:
213: /* Only the lower 6 bits of cl are the sectors per track. */
214: puts(" Sectors per track=");
215: itobase((uint16) SIXBITS & LOW(r.r_cx), buffer, 10);
216: puts(buffer);
217:
218: puts("\r\n");
219: } /* for i = 0 to num_of_drives - 1 */
220: } /* dpb() */
221:
222:
223: /*
224: * Ask the BIOS how many drives are attached.
225: *
226: * If the BIOS says more than MAX_DRIVES, ask again. Some BIOS's
227: * seem to answer this question differently on alternate calls, or
228: * on the first call.
229: */
230: #define MAX_DRIVES 8
231: int get_num_of_drives()
232: {
233: struct reg r;
234:
235: r.r_ax = DISK_PARAMS; /* ah = 8 -- Return disk drive parameters */
236: r.r_dx = HARD_DRIVE; /* set bit 7 of dl for hard disk info. */
237:
238: intcall(&r, &r, DISKINT);
239:
240: if ( verbose_flag ) {
241: /*
242: * Print out the flags for debugging purposes.
243: */
244: puts("flags: ");
245: print16(r.r_flags);
246: puts(" ");
247: }
248:
249: if (LOW(r.r_dx) > MAX_DRIVES) {
250: puts("I doubt that you have 0x");
251: print8(LOW(r.r_dx));
252: puts(" disk drives. Let's try again.\r\n");
253:
254: r.r_ax = DISK_PARAMS; /* ah = 8 -- Return disk drive parameters */
255: r.r_dx = HARD_DRIVE; /* set bit 7 of dl for hard disk info. */
256:
257: intcall(&r, &r, DISKINT);
258:
259: if (LOW(r.r_dx) <= MAX_DRIVES) {
260: puts(" That's better!");
261: }
262: }
263:
264: if (LOW(r.r_dx) > MAX_DRIVES) {
265: puts("I simply don't believe that you have 0x");
266: print8(LOW(r.r_dx));
267: puts(" disk drives.\r\n");
268: puts("I'm going to guess that you have 0x");
269: print8(MAX_DRIVES);
270: puts(" drives.\r\n");
271:
272: return(MAX_DRIVES);
273: } else {
274: return(LOW(r.r_dx));
275: }
276: } /* get_num_of_drives() */
277:
278: /* Create a listing of file names in /. */
279: void
280: dir()
281: {
282: int i, j;
283: char outbuff[LINESIZE]; /* Buffer for outputing numbers. */
284: struct inode rootinode;
285: struct direct dirent;
286:
287: /* Open "/" and print out the direct block file entries. */
288: iopen(&rootinode, (ino_t) 2);
289:
290: /* Read each directory entry one at a time. */
291: /* We are careful to print an even fraction of 80 for each
292: * directory entry, so that everything lines up nicely.
293: */
294: for (i = 0; i < rootinode.i_size; i += sizeof(struct direct)) {
295:
296: iread(&rootinode, (char *) &dirent, (fsize_t) i,
297: (uint16) sizeof(struct direct));
298:
299: /* If the entry is not active, skip the rest. */
300: if (0 == dirent.d_ino) {
301: continue;
302: }
303:
304: /* NUL terminate the name. */
305: strncpy(outbuff,
306: dirent.d_name,
307: DIRSIZ);
308: outbuff[DIRSIZ] = '\0';
309: /* Print the file name. */
310: puts(outbuff);
311: for (j = DIRSIZ - strlen(outbuff); j > 0; --j) {
312: putchar(' ');
313: }
314: puts(" :"); /* Bring total to 16 (80/5) characters. */
315: }
316: puts("\r\n");
317:
318: } /* dir() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.