00001
00002
00003
00004
00005 char version[]= "2.20";
00006
00007 #define BIOS (!UNIX)
00008
00009 #define nil 0
00010 #define _POSIX_SOURCE 1
00011 #define _MINIX 1
00012 #include <stddef.h>
00013 #include <sys/types.h>
00014 #include <sys/stat.h>
00015 #include <stdlib.h>
00016 #include <stdio.h>
00017 #include <limits.h>
00018 #include <string.h>
00019 #include <errno.h>
00020 #include <ibm/partition.h>
00021 #include <minix/config.h>
00022 #include <minix/type.h>
00023 #include <minix/com.h>
00024 #include <minix/dmap.h>
00025 #include <minix/const.h>
00026 #include <minix/minlib.h>
00027 #include <minix/syslib.h>
00028 #if BIOS
00029 #include <kernel/const.h>
00030 #include <kernel/type.h>
00031 #endif
00032 #if UNIX
00033 #include <stdio.h>
00034 #include <time.h>
00035 #include <unistd.h>
00036 #include <fcntl.h>
00037 #include <signal.h>
00038 #include <termios.h>
00039 #endif
00040 #include "rawfs.h"
00041 #undef EXTERN
00042 #define EXTERN
00043 #include "boot.h"
00044
00045 #define arraysize(a) (sizeof(a) / sizeof((a)[0]))
00046 #define arraylimit(a) ((a) + arraysize(a))
00047 #define between(a, c, z) ((unsigned) ((c) - (a)) <= ((z) - (a)))
00048
00049 int fsok= -1;
00050
00051 static int block_size;
00052
00053 #if BIOS
00054
00055
00056
00057
00058
00059 unsigned char boot_spec[24];
00060
00061 char *bios_err(int err)
00062
00063
00064
00065
00066 {
00067 static struct errlist {
00068 int err;
00069 char *what;
00070 } errlist[] = {
00071 #if !DOS
00072 { 0x00, "No error" },
00073 { 0x01, "Invalid command" },
00074 { 0x02, "Address mark not found" },
00075 { 0x03, "Disk write-protected" },
00076 { 0x04, "Sector not found" },
00077 { 0x05, "Reset failed" },
00078 { 0x06, "Floppy disk removed" },
00079 { 0x07, "Bad parameter table" },
00080 { 0x08, "DMA overrun" },
00081 { 0x09, "DMA crossed 64 KB boundary" },
00082 { 0x0A, "Bad sector flag" },
00083 { 0x0B, "Bad track flag" },
00084 { 0x0C, "Media type not found" },
00085 { 0x0D, "Invalid number of sectors on format" },
00086 { 0x0E, "Control data address mark detected" },
00087 { 0x0F, "DMA arbitration level out of range" },
00088 { 0x10, "Uncorrectable CRC or ECC data error" },
00089 { 0x11, "ECC corrected data error" },
00090 { 0x20, "Controller failed" },
00091 { 0x40, "Seek failed" },
00092 { 0x80, "Disk timed-out" },
00093 { 0xAA, "Drive not ready" },
00094 { 0xBB, "Undefined error" },
00095 { 0xCC, "Write fault" },
00096 { 0xE0, "Status register error" },
00097 { 0xFF, "Sense operation failed" }
00098 #else
00099 { 0x00, "No error" },
00100 { 0x01, "Function number invalid" },
00101 { 0x02, "File not found" },
00102 { 0x03, "Path not found" },
00103 { 0x04, "Too many open files" },
00104 { 0x05, "Access denied" },
00105 { 0x06, "Invalid handle" },
00106 { 0x0C, "Access code invalid" },
00107 #endif
00108 };
00109 struct errlist *errp;
00110
00111 for (errp= errlist; errp < arraylimit(errlist); errp++) {
00112 if (errp->err == err) return errp->what;
00113 }
00114 return "Unknown error";
00115 }
00116
00117 char *unix_err(int err)
00118
00119 {
00120 switch (err) {
00121 case ENOENT: return "No such file or directory";
00122 case ENOTDIR: return "Not a directory";
00123 default: return "Unknown error";
00124 }
00125 }
00126
00127 void rwerr(char *rw, off_t sec, int err)
00128 {
00129 printf("\n%s error 0x%02x (%s) at sector %ld absolute\n",
00130 rw, err, bios_err(err), sec);
00131 }
00132
00133 void readerr(off_t sec, int err) { rwerr("Read", sec, err); }
00134 void writerr(off_t sec, int err) { rwerr("Write", sec, err); }
00135
00136 void readblock(off_t blk, char *buf, int block_size)
00137
00138 {
00139 int r;
00140 u32_t sec= lowsec + blk * RATIO(block_size);
00141
00142 if(!block_size) {
00143 printf("block_size 0\n");
00144 exit(1);
00145 }
00146
00147 if ((r= readsectors(mon2abs(buf), sec, 1 * RATIO(block_size))) != 0) {
00148 readerr(sec, r); exit(1);
00149 }
00150 }
00151
00152 #define istty (1)
00153 #define alarm(n) (0)
00154
00155 #endif
00156
00157 #if UNIX
00158
00159
00160 char boot_magic[] = { 0x31, 0xC0, 0x8E, 0xD8, 0xFA, 0x8E, 0xD0, 0xBC };
00161
00162 struct biosdev {
00163 char *name;
00164 int device;
00165 } bootdev;
00166
00167 struct termios termbuf;
00168 int istty;
00169
00170 void quit(int status)
00171 {
00172 if (istty) (void) tcsetattr(0, TCSANOW, &termbuf);
00173 exit(status);
00174 }
00175
00176 #define exit(s) quit(s)
00177
00178 void report(char *label)
00179
00180 {
00181 fprintf(stderr, "edparams: %s: %s\n", label, strerror(errno));
00182 }
00183
00184 void fatal(char *label)
00185 {
00186 report(label);
00187 exit(1);
00188 }
00189
00190 void *alloc(void *m, size_t n)
00191 {
00192 m= m == nil ? malloc(n) : realloc(m, n);
00193 if (m == nil) fatal("");
00194 return m;
00195 }
00196
00197 #define malloc(n) alloc(nil, n)
00198 #define realloc(m, n) alloc(m, n)
00199
00200 #define mon2abs(addr) ((void *) (addr))
00201
00202 int rwsectors(int rw, void *addr, u32_t sec, int nsec)
00203 {
00204 ssize_t r;
00205 size_t len= nsec * SECTOR_SIZE;
00206
00207 if (lseek(bootdev.device, sec * SECTOR_SIZE, SEEK_SET) == -1)
00208 return errno;
00209
00210 if (rw == 0) {
00211 r= read(bootdev.device, (char *) addr, len);
00212 } else {
00213 r= write(bootdev.device, (char *) addr, len);
00214 }
00215 if (r == -1) return errno;
00216 if (r != len) return EIO;
00217 return 0;
00218 }
00219
00220 #define readsectors(a, s, n) rwsectors(0, (a), (s), (n))
00221 #define writesectors(a, s, n) rwsectors(1, (a), (s), (n))
00222 #define readerr(sec, err) (errno= (err), report(bootdev.name))
00223 #define writerr(sec, err) (errno= (err), report(bootdev.name))
00224 #define putch(c) putchar(c)
00225 #define unix_err(err) strerror(err)
00226
00227 void readblock(off_t blk, char *buf, int block_size)
00228
00229 {
00230 if(!block_size) fatal("block_size 0");
00231 errno= EIO;
00232 if (lseek(bootdev.device, blk * block_size, SEEK_SET) == -1
00233 || read(bootdev.device, buf, block_size) != block_size)
00234 {
00235 fatal(bootdev.name);
00236 }
00237 }
00238
00239 sig_atomic_t trapsig;
00240
00241 void trap(int sig)
00242 {
00243 trapsig= sig;
00244 signal(sig, trap);
00245 }
00246
00247 int escape(void)
00248 {
00249 if (trapsig == SIGINT) {
00250 trapsig= 0;
00251 return 1;
00252 }
00253 return 0;
00254 }
00255
00256 static unsigned char unchar;
00257
00258 int getch(void)
00259 {
00260 unsigned char c;
00261
00262 fflush(stdout);
00263
00264 if (unchar != 0) {
00265 c= unchar;
00266 unchar= 0;
00267 return c;
00268 }
00269
00270 switch (read(0, &c, 1)) {
00271 case -1:
00272 if (errno != EINTR) fatal("");
00273 return(ESC);
00274 case 0:
00275 if (istty) putch('\n');
00276 exit(0);
00277 default:
00278 if (istty && c == termbuf.c_cc[VEOF]) {
00279 putch('\n');
00280 exit(0);
00281 }
00282 return c;
00283 }
00284 }
00285
00286 #define ungetch(c) ((void) (unchar = (c)))
00287
00288 #define get_tick() ((u32_t) time(nil))
00289 #define clear_screen() printf("[clear]")
00290 #define boot_device(device) printf("[boot %s]\n", device)
00291 #define ctty(line) printf("[ctty %s]\n", line)
00292 #define bootminix() (run_trailer() && printf("[boot]\n"))
00293 #define off() printf("[off]")
00294
00295 #endif
00296
00297 char *readline(void)
00298
00299 {
00300 char *line;
00301 size_t i, z;
00302 int c;
00303
00304 i= 0;
00305 z= 20;
00306 line= malloc(z * sizeof(char));
00307
00308 do {
00309 c= getch();
00310
00311 if (strchr("\b\177\25\30", c) != nil) {
00312
00313 do {
00314 if (i == 0) break;
00315 printf("\b \b");
00316 i--;
00317 } while (c == '\25' || c == '\30');
00318 } else
00319 if (c < ' ' && c != '\n') {
00320 putch('\7');
00321 } else {
00322 putch(c);
00323 line[i++]= c;
00324 if (i == z) {
00325 z*= 2;
00326 line= realloc(line, z * sizeof(char));
00327 }
00328 }
00329 } while (c != '\n');
00330 line[i]= 0;
00331 return line;
00332 }
00333
00334 int sugar(char *tok)
00335
00336 {
00337 return strchr("=(){};\n", tok[0]) != nil;
00338 }
00339
00340 char *onetoken(char **aline)
00341
00342 {
00343 char *line= *aline;
00344 size_t n;
00345 char *tok;
00346
00347
00348 while (*line == ' ' || (*line == '\n' && line[1] == '\n')) line++;
00349
00350 *aline= line;
00351
00352
00353 if ((unsigned) *line < ' ' && *line != '\n') return nil;
00354
00355 if (*line == '(') {
00356
00357 int depth= 0;
00358
00359 while ((unsigned) *line >= ' ') {
00360 if (*line == '(') depth++;
00361 if (*line++ == ')' && --depth == 0) break;
00362 }
00363 } else
00364 if (sugar(line)) {
00365
00366 line++;
00367 } else {
00368
00369 do line++; while ((unsigned) *line > ' ' && !sugar(line));
00370 }
00371 n= line - *aline;
00372 tok= malloc((n + 1) * sizeof(char));
00373 memcpy(tok, *aline, n);
00374 tok[n]= 0;
00375 if (tok[0] == '\n') tok[0]= ';';
00376
00377 *aline= line;
00378 return tok;
00379 }
00380
00381
00382
00383 typedef struct token {
00384 struct token *next;
00385 char *token;
00386 } token;
00387
00388 token **tokenize(token **acmds, char *line)
00389
00390
00391
00392
00393
00394
00395 {
00396 char *tok;
00397 token *newcmd;
00398
00399 while ((tok= onetoken(&line)) != nil) {
00400 newcmd= malloc(sizeof(*newcmd));
00401 newcmd->token= tok;
00402 newcmd->next= *acmds;
00403 *acmds= newcmd;
00404 acmds= &newcmd->next;
00405 }
00406 return acmds;
00407 }
00408
00409 token *cmds;
00410 int err;
00411
00412 char *poptoken(void)
00413
00414 {
00415 token *cmd= cmds;
00416 char *tok= cmd->token;
00417
00418 cmds= cmd->next;
00419 free(cmd);
00420
00421 return tok;
00422 }
00423
00424 void voidtoken(void)
00425
00426 {
00427 free(poptoken());
00428 }
00429
00430 void parse_code(char *code)
00431
00432
00433
00434 {
00435 if (cmds != nil && cmds->token[0] != ';') (void) tokenize(&cmds, ";");
00436 (void) tokenize(&cmds, code);
00437 }
00438
00439 int interrupt(void)
00440
00441 {
00442 if (escape()) {
00443 printf("[ESC]\n");
00444 err= 1;
00445 return 1;
00446 }
00447 return 0;
00448 }
00449
00450 #if BIOS
00451
00452 int activate;
00453
00454 struct biosdev {
00455 char name[8];
00456 int device, primary, secondary;
00457 } bootdev, tmpdev;
00458
00459 int get_master(char *master, struct part_entry **table, u32_t pos)
00460
00461 {
00462 int r, n;
00463 struct part_entry *pe, **pt;
00464
00465 if ((r= readsectors(mon2abs(master), pos, 1)) != 0) return r;
00466
00467 pe= (struct part_entry *) (master + PART_TABLE_OFF);
00468 for (pt= table; pt < table + NR_PARTITIONS; pt++) *pt= pe++;
00469
00470
00471 if (pos != 0) return 0;
00472
00473 n= NR_PARTITIONS;
00474 do {
00475 for (pt= table; pt < table + NR_PARTITIONS-1; pt++) {
00476 if (pt[0]->sysind == NO_PART
00477 || pt[0]->lowsec > pt[1]->lowsec) {
00478 pe= pt[0]; pt[0]= pt[1]; pt[1]= pe;
00479 }
00480 }
00481 } while (--n > 0);
00482 return 0;
00483 }
00484
00485 void initialize(void)
00486 {
00487 char master[SECTOR_SIZE];
00488 struct part_entry *table[NR_PARTITIONS];
00489 int r, p;
00490 u32_t masterpos;
00491 char *argp;
00492
00493
00494
00495
00496
00497 u32_t oldaddr= caddr;
00498 u32_t memend= mem[0].base + mem[0].size;
00499 u32_t newaddr= (memend - runsize) & ~0x0000FL;
00500 #if !DOS
00501 u32_t dma64k= (memend - 1) & ~0x0FFFFL;
00502
00503
00504
00505 if (newaddr + (daddr - caddr) < dma64k) {
00506 newaddr= (dma64k - runsize) & ~0x0000FL;
00507 }
00508 #endif
00509
00510
00511 caddr= newaddr;
00512
00513
00514 raw_copy(newaddr, oldaddr, runsize);
00515
00516
00517 relocate();
00518
00519 #if !DOS
00520
00521
00522
00523
00524
00525 if (mon_return = (mem[1].size > 512*1024L)) mem[0].size = newaddr;
00526 mem[0].base += 2048;
00527 mem[0].size -= 2048;
00528
00529
00530 bootdev.name[0]= 0;
00531 bootdev.device= device;
00532 bootdev.primary= -1;
00533 bootdev.secondary= -1;
00534
00535 if (device < 0x80) {
00536
00537 strcpy(bootdev.name, "fd0");
00538 bootdev.name[2] += bootdev.device;
00539 return;
00540 }
00541
00542
00543
00544
00545
00546
00547 raw_copy(mon2abs(&lowsec),
00548 vec2abs(&rem_part) + offsetof(struct part_entry, lowsec),
00549 sizeof(lowsec));
00550
00551 masterpos= 0;
00552
00553 for (;;) {
00554
00555 if ((r= get_master(master, table, masterpos)) != 0) {
00556 readerr(masterpos, r); exit(1);
00557 }
00558
00559
00560 for (p= 0; p < NR_PARTITIONS; p++) {
00561 if (lowsec - table[p]->lowsec < table[p]->size) break;
00562 }
00563
00564 if (lowsec == table[p]->lowsec) {
00565 if (bootdev.primary < 0)
00566 bootdev.primary= p;
00567 else
00568 bootdev.secondary= p;
00569 break;
00570 }
00571
00572 if (p == NR_PARTITIONS || bootdev.primary >= 0
00573 || table[p]->sysind != MINIX_PART) {
00574
00575
00576
00577 bootdev.device= -1;
00578 return;
00579 }
00580
00581
00582 bootdev.primary= p;
00583 masterpos= table[p]->lowsec;
00584 }
00585 strcpy(bootdev.name, "d0p0");
00586 bootdev.name[1] += (device - 0x80);
00587 bootdev.name[3] += bootdev.primary;
00588 if (bootdev.secondary >= 0) {
00589 strcat(bootdev.name, "s0");
00590 bootdev.name[5] += bootdev.secondary;
00591 }
00592
00593 #else
00594
00595
00596
00597
00598 if (mem[1].size > 0) mem[0].size = newaddr + 0x80 - mem[0].base;
00599
00600
00601 argp= PSP + 0x81;
00602 argp[PSP[0x80]]= 0;
00603 while (between('\1', *argp, ' ')) argp++;
00604 vdisk= argp;
00605 while (!between('\0', *argp, ' ')) argp++;
00606 while (between('\1', *argp, ' ')) *argp++= 0;
00607 if (*vdisk == 0) {
00608 printf("\nUsage: boot <vdisk> [commands ...]\n");
00609 exit(1);
00610 }
00611 drun= *argp == 0 ? "main" : argp;
00612
00613 if ((r= dev_open()) != 0) {
00614 printf("\n%s: Error %02x (%s)\n", vdisk, r, bios_err(r));
00615 exit(1);
00616 }
00617
00618
00619 if ((r= get_master(master, table, 0)) != 0) {
00620 readerr(0, r); exit(1);
00621 }
00622
00623 strcpy(bootdev.name, "d0");
00624 bootdev.primary= -1;
00625 for (p= 0; p < NR_PARTITIONS; p++) {
00626 if (table[p]->bootind != 0 && table[p]->sysind == MINIX_PART) {
00627 bootdev.primary= p;
00628 strcat(bootdev.name, "p0");
00629 bootdev.name[3] += p;
00630 lowsec= table[p]->lowsec;
00631 break;
00632 }
00633 }
00634 #endif
00635 }
00636
00637 #endif
00638
00639
00640 enum resnames {
00641 R_NULL, R_BOOT, R_CTTY, R_DELAY, R_ECHO, R_EXIT, R_HELP,
00642 R_LS, R_MENU, R_OFF, R_SAVE, R_SET, R_TRAP, R_UNSET
00643 };
00644
00645 char resnames[][6] = {
00646 "", "boot", "ctty", "delay", "echo", "exit", "help",
00647 "ls", "menu", "off", "save", "set", "trap", "unset",
00648 };
00649
00650
00651 #define null (resnames[0])
00652
00653 int reserved(char *s)
00654
00655 {
00656 int r;
00657
00658 for (r= R_BOOT; r <= R_UNSET; r++) {
00659 if (strcmp(s, resnames[r]) == 0) return r;
00660 }
00661 return R_NULL;
00662 }
00663
00664 void sfree(char *s)
00665
00666 {
00667 if (s != nil && s != null) free(s);
00668 }
00669
00670 char *copystr(char *s)
00671
00672 {
00673 char *c;
00674
00675 if (*s == 0) return null;
00676 c= malloc((strlen(s) + 1) * sizeof(char));
00677 strcpy(c, s);
00678 return c;
00679 }
00680
00681 int is_default(environment *e)
00682 {
00683 return (e->flags & E_SPECIAL) && e->defval == nil;
00684 }
00685
00686 environment **searchenv(char *name)
00687 {
00688 environment **aenv= &env;
00689
00690 while (*aenv != nil && strcmp((*aenv)->name, name) != 0) {
00691 aenv= &(*aenv)->next;
00692 }
00693
00694 return aenv;
00695 }
00696
00697 #define b_getenv(name) (*searchenv(name))
00698
00699
00700 char *b_value(char *name)
00701
00702 {
00703 environment *e= b_getenv(name);
00704
00705 return e == nil || !(e->flags & E_VAR) ? nil : e->value;
00706 }
00707
00708 char *b_body(char *name)
00709
00710 {
00711 environment *e= b_getenv(name);
00712
00713 return e == nil || !(e->flags & E_FUNCTION) ? nil : e->value;
00714 }
00715
00716 int b_setenv(int flags, char *name, char *arg, char *value)
00717
00718
00719
00720 {
00721 environment **aenv, *e;
00722
00723 if (*(aenv= searchenv(name)) == nil) {
00724 if (reserved(name)) return E_RESERVED;
00725 e= malloc(sizeof(*e));
00726 e->name= copystr(name);
00727 e->flags= flags;
00728 e->defval= nil;
00729 e->next= nil;
00730 *aenv= e;
00731 } else {
00732 e= *aenv;
00733
00734
00735 if (e->flags & E_SPECIAL
00736 && (e->flags & E_FUNCTION) != (flags & E_FUNCTION)
00737 ) return e->flags;
00738
00739 e->flags= (e->flags & E_STICKY) | flags;
00740 if (is_default(e)) {
00741 e->defval= e->value;
00742 } else {
00743 sfree(e->value);
00744 }
00745 sfree(e->arg);
00746 }
00747 e->arg= copystr(arg);
00748 e->value= copystr(value);
00749
00750 return 0;
00751 }
00752
00753 int b_setvar(int flags, char *name, char *value)
00754
00755 {
00756 int r;
00757
00758 if((r=b_setenv(flags, name, null, value))) {
00759 return r;
00760 }
00761
00762 return r;
00763 }
00764
00765 void b_unset(char *name)
00766
00767
00768
00769 {
00770 environment **aenv, *e;
00771
00772 if ((e= *(aenv= searchenv(name))) == nil) return;
00773
00774 if (e->flags & E_SPECIAL) {
00775 if (e->defval != nil) {
00776 sfree(e->arg);
00777 e->arg= null;
00778 sfree(e->value);
00779 e->value= e->defval;
00780 e->defval= nil;
00781 }
00782 } else {
00783 sfree(e->name);
00784 sfree(e->arg);
00785 sfree(e->value);
00786 *aenv= e->next;
00787 free(e);
00788 }
00789 }
00790
00791 long a2l(char *a)
00792
00793 {
00794 int sign= 1;
00795 long n= 0;
00796
00797 if (*a == '-') { sign= -1; a++; }
00798
00799 while (between('0', *a, '9')) n= n * 10 + (*a++ - '0');
00800
00801 return sign * n;
00802 }
00803
00804 char *ul2a(u32_t n, unsigned b)
00805
00806 {
00807 static char num[(CHAR_BIT * sizeof(n) + 2) / 3 + 1];
00808 char *a= arraylimit(num) - 1;
00809 static char hex[16] = "0123456789ABCDEF";
00810
00811 do *--a = hex[(int) (n % b)]; while ((n/= b) > 0);
00812 return a;
00813 }
00814
00815 char *ul2a10(u32_t n)
00816
00817 {
00818 return ul2a(n, 10);
00819 }
00820
00821 unsigned a2x(char *a)
00822
00823 {
00824 unsigned n= 0;
00825 int c;
00826
00827 for (;;) {
00828 c= *a;
00829 if (between('0', c, '9')) c= c - '0' + 0x0;
00830 else
00831 if (between('A', c, 'F')) c= c - 'A' + 0xA;
00832 else
00833 if (between('a', c, 'f')) c= c - 'a' + 0xa;
00834 else
00835 break;
00836 n= (n<<4) | c;
00837 a++;
00838 }
00839 return n;
00840 }
00841
00842 void get_parameters(void)
00843 {
00844 char params[SECTOR_SIZE + 1];
00845 token **acmds;
00846 int r, bus, processor;
00847 memory *mp;
00848 static char bus_type[][4] = {
00849 "xt", "at", "mca"
00850 };
00851 static char vid_type[][4] = {
00852 "mda", "cga", "ega", "ega", "vga", "vga"
00853 };
00854 static char vid_chrome[][6] = {
00855 "mono", "color"
00856 };
00857
00858
00859 b_setvar(E_SPECIAL|E_VAR|E_DEV, "rootdev", "ram");
00860 b_setvar(E_SPECIAL|E_VAR|E_DEV, "ramimagedev", "bootdev");
00861 b_setvar(E_SPECIAL|E_VAR, "ramsize", "0");
00862 #if BIOS
00863 processor = getprocessor();
00864 if(processor == 1586) processor = 686;
00865 b_setvar(E_SPECIAL|E_VAR, "processor", ul2a10(processor));
00866 b_setvar(E_SPECIAL|E_VAR, "bus", bus_type[get_bus()]);
00867 b_setvar(E_SPECIAL|E_VAR, "video", vid_type[get_video()]);
00868 b_setvar(E_SPECIAL|E_VAR, "chrome", vid_chrome[get_video() & 1]);
00869 params[0]= 0;
00870 for (mp= mem; mp < arraylimit(mem); mp++) {
00871 if (mp->size == 0) continue;
00872 if (params[0] != 0) strcat(params, ",");
00873 strcat(params, ul2a(mp->base, 0x10));
00874 strcat(params, ":");
00875 strcat(params, ul2a(mp->size, 0x10));
00876 }
00877 b_setvar(E_SPECIAL|E_VAR, "memory", params);
00878
00879 #if DOS
00880 b_setvar(E_SPECIAL|E_VAR, "dosfile-d0", vdisk);
00881 #endif
00882
00883 #endif
00884 #if UNIX
00885 b_setvar(E_SPECIAL|E_VAR, "processor", "?");
00886 b_setvar(E_SPECIAL|E_VAR, "bus", "?");
00887 b_setvar(E_SPECIAL|E_VAR, "video", "?");
00888 b_setvar(E_SPECIAL|E_VAR, "chrome", "?");
00889 b_setvar(E_SPECIAL|E_VAR, "memory", "?");
00890 b_setvar(E_SPECIAL|E_VAR, "c0", "?");
00891 #endif
00892
00893
00894 b_setvar(E_SPECIAL|E_VAR, "image", "boot/image");
00895 b_setvar(E_SPECIAL|E_FUNCTION, "leader",
00896 "echo --- Welcome to MINIX 3. This is the boot monitor. ---\\n");
00897 b_setvar(E_SPECIAL|E_FUNCTION, "main", "menu");
00898 b_setvar(E_SPECIAL|E_FUNCTION, "trailer", "");
00899
00900
00901 b_setenv(E_RESERVED|E_FUNCTION, null, "=,Start MINIX", "boot");
00902
00903
00904 if ((r= readsectors(mon2abs(params), lowsec+PARAMSEC, 1)) != 0) {
00905 readerr(lowsec+PARAMSEC, r);
00906 exit(1);
00907 }
00908 params[SECTOR_SIZE]= 0;
00909 acmds= tokenize(&cmds, params);
00910
00911
00912 #if UNIX
00913 (void) tokenize(acmds, ":;");
00914 #elif DOS
00915 (void) tokenize(tokenize(acmds, ":;leader;"), drun);
00916 #else
00917 (void) tokenize(acmds, ":;leader;main");
00918 #endif
00919 }
00920
00921 char *addptr;
00922
00923 void addparm(char *n)
00924 {
00925 while (*n != 0 && *addptr != 0) *addptr++ = *n++;
00926 }
00927
00928 void save_parameters(void)
00929
00930 {
00931 environment *e;
00932 char params[SECTOR_SIZE + 1];
00933 int r;
00934
00935
00936 memset(params, '\n', SECTOR_SIZE);
00937
00938
00939 params[SECTOR_SIZE]= 0;
00940 addptr= params;
00941
00942 for (e= env; e != nil; e= e->next) {
00943 if (e->flags & E_RESERVED || is_default(e)) continue;
00944
00945 addparm(e->name);
00946 if (e->flags & E_FUNCTION) {
00947 addparm("(");
00948 addparm(e->arg);
00949 addparm(")");
00950 } else {
00951 addparm((e->flags & (E_DEV|E_SPECIAL)) != E_DEV
00952 ? "=" : "=d ");
00953 }
00954 addparm(e->value);
00955 if (*addptr == 0) {
00956 printf("The environment is too big\n");
00957 return;
00958 }
00959 *addptr++= '\n';
00960 }
00961
00962
00963 if ((r= writesectors(mon2abs(params), lowsec+PARAMSEC, 1)) != 0) {
00964 writerr(lowsec+PARAMSEC, r);
00965 printf("Can't save environment\n");
00966 }
00967 }
00968
00969 void show_env(void)
00970
00971 {
00972 environment *e;
00973 unsigned more= 0;
00974 int c;
00975
00976 for (e= env; e != nil; e= e->next) {
00977 if (e->flags & E_RESERVED) continue;
00978 if (!istty && is_default(e)) continue;
00979
00980 if (e->flags & E_FUNCTION) {
00981 printf("%s(%s) %s\n", e->name, e->arg, e->value);
00982 } else {
00983 printf(is_default(e) ? "%s = (%s)\n" : "%s = %s\n",
00984 e->name, e->value);
00985 }
00986
00987 if (e->next != nil && istty && ++more % 20 == 0) {
00988 printf("More? ");
00989 c= getch();
00990 if (c == ESC || c > ' ') {
00991 putch('\n');
00992 if (c > ' ') ungetch(c);
00993 break;
00994 }
00995 printf("\b\b\b\b\b\b");
00996 }
00997 }
00998 }
00999
01000 int numprefix(char *s, char **ps)
01001
01002
01003
01004 {
01005 char *n= s;
01006
01007 while (between('0', *n, '9')) n++;
01008
01009 if (n == s) return 0;
01010
01011 if (ps == nil) return *n == 0;
01012
01013 *ps= n;
01014 return 1;
01015 }
01016
01017 int numeric(char *s)
01018 {
01019 return numprefix(s, (char **) nil);
01020 }
01021
01022 #if BIOS
01023
01024
01025 #define DEV_FD0 0x0200
01026 static dev_t dev_cNd0[] = { 0x0300, 0x0800, 0x0A00, 0x0C00, 0x1000 };
01027 #define minor_p0s0 128
01028
01029 static int block_size;
01030
01031 dev_t name2dev(char *name)
01032
01033
01034
01035
01036
01037 {
01038 dev_t dev;
01039 ino_t ino;
01040 int drive;
01041 struct stat st;
01042 char *n, *s;
01043
01044
01045 if ((activate= (name[0] == '*'))) name++;
01046
01047
01048 if (strcmp(name, "bootdev") == 0) {
01049 if (bootdev.device == -1) {
01050 printf("The boot device could not be named\n");
01051 errno= 0;
01052 return -1;
01053 }
01054 name= bootdev.name;
01055 }
01056
01057
01058
01059
01060
01061 tmpdev.device= tmpdev.primary= tmpdev.secondary= -1;
01062 dev= -1;
01063 n= name;
01064 if (strncmp(n, "/dev/", 5) == 0) n+= 5;
01065
01066 if (strcmp(n, "ram") == 0) {
01067 dev= DEV_RAM;
01068 } else
01069 if (strcmp(n, "boot") == 0) {
01070 dev= DEV_BOOT;
01071 } else
01072 if (n[0] == 'f' && n[1] == 'd' && numeric(n+2)) {
01073
01074 tmpdev.device= a2l(n+2);
01075 dev= DEV_FD0 + tmpdev.device;
01076 } else
01077 if ((n[0] == 'h' || n[0] == 's') && n[1] == 'd' && numprefix(n+2, &s)
01078 && (*s == 0 || (between('a', *s, 'd') && s[1] == 0))
01079 ) {
01080
01081 dev= a2l(n+2);
01082 tmpdev.device= dev / (1 + NR_PARTITIONS);
01083 tmpdev.primary= (dev % (1 + NR_PARTITIONS)) - 1;
01084 if (*s != 0) {
01085
01086 tmpdev.secondary= *s - 'a';
01087 dev= minor_p0s0
01088 + (tmpdev.device * NR_PARTITIONS
01089 + tmpdev.primary) * NR_PARTITIONS
01090 + tmpdev.secondary;
01091 }
01092 tmpdev.device+= 0x80;
01093 dev+= n[0] == 'h' ? dev_cNd0[0] : dev_cNd0[2];
01094 } else {
01095
01096 int ctrlr= 0;
01097
01098 if (n[0] == 'c' && between('0', n[1], '4')) {
01099 ctrlr= (n[1] - '0');
01100 tmpdev.device= 0;
01101 n+= 2;
01102 }
01103 if (n[0] == 'd' && between('0', n[1], '7')) {
01104 tmpdev.device= (n[1] - '0');
01105 n+= 2;
01106 if (n[0] == 'p' && between('0', n[1], '3')) {
01107 tmpdev.primary= (n[1] - '0');
01108 n+= 2;
01109 if (n[0] == 's' && between('0', n[1], '3')) {
01110 tmpdev.secondary= (n[1] - '0');
01111 n+= 2;
01112 }
01113 }
01114 }
01115 if (*n == 0) {
01116 dev= dev_cNd0[ctrlr];
01117 if (tmpdev.secondary < 0) {
01118 dev += tmpdev.device * (NR_PARTITIONS+1)
01119 + (tmpdev.primary + 1);
01120 } else {
01121 dev += minor_p0s0
01122 + (tmpdev.device * NR_PARTITIONS
01123 + tmpdev.primary) * NR_PARTITIONS
01124 + tmpdev.secondary;
01125 }
01126 tmpdev.device+= 0x80;
01127 }
01128 }
01129
01130
01131 if (fsok == -1) fsok= r_super(&block_size) != 0;
01132 if (fsok) {
01133
01134 ino= r_lookup(r_lookup(ROOT_INO, "dev"), name);
01135
01136 if (ino != 0) {
01137
01138 r_stat(ino, &st);
01139 if (!S_ISBLK(st.st_mode)) {
01140 printf("%s is not a block device\n", name);
01141 errno= 0;
01142 return (dev_t) -1;
01143 }
01144 dev= st.st_rdev;
01145 }
01146 }
01147
01148 if (tmpdev.primary < 0) activate= 0;
01149
01150 if (dev == -1) {
01151 printf("Can't recognize '%s' as a device\n", name);
01152 errno= 0;
01153 }
01154 return dev;
01155 }
01156
01157 #if DEBUG
01158 static void apm_perror(char *label, u16_t ax)
01159 {
01160 unsigned ah;
01161 char *str;
01162
01163 ah= (ax >> 8);
01164 switch(ah)
01165 {
01166 case 0x01: str= "APM functionality disabled"; break;
01167 case 0x03: str= "interface not connected"; break;
01168 case 0x09: str= "unrecognized device ID"; break;
01169 case 0x0A: str= "parameter value out of range"; break;
01170 case 0x0B: str= "interface not engaged"; break;
01171 case 0x60: str= "unable to enter requested state"; break;
01172 case 0x86: str= "APM not present"; break;
01173 default: printf("%s: error 0x%02x\n", label, ah); return;
01174 }
01175 printf("%s: %s\n", label, str);
01176 }
01177
01178 #define apm_printf printf
01179 #else
01180 #define apm_perror(label, ax) ((void)0)
01181 #define apm_printf
01182 #endif
01183
01184 static void off(void)
01185 {
01186 bios_env_t be;
01187 unsigned al, ah;
01188
01189
01190
01191
01192
01193 be.ax= 0x5300;
01194 be.bx= 0;
01195 int15(&be);
01196 if (be.flags & FL_CARRY)
01197 {
01198 apm_perror("APM installation check failed", be.ax);
01199 return;
01200 }
01201 if (be.bx != (('P' << 8) | 'M'))
01202 {
01203 apm_printf("APM signature not found (got 0x%04x)\n", be.bx);
01204 return;
01205 }
01206
01207 ah= be.ax >> 8;
01208 if (ah > 9)
01209 ah= (ah >> 4)*10 + (ah & 0xf);
01210 al= be.ax & 0xff;
01211 if (al > 9)
01212 al= (al >> 4)*10 + (al & 0xf);
01213 apm_printf("APM version %u.%u%s%s%s%s%s\n",
01214 ah, al,
01215 (be.cx & 0x1) ? ", 16-bit PM" : "",
01216 (be.cx & 0x2) ? ", 32-bit PM" : "",
01217 (be.cx & 0x4) ? ", CPU-Idle" : "",
01218 (be.cx & 0x8) ? ", APM-disabled" : "",
01219 (be.cx & 0x10) ? ", APM-disengaged" : "");
01220
01221
01222 be.ax= 0x5301;
01223 be.bx= 0x0000;
01224 int15(&be);
01225 if (be.flags & FL_CARRY)
01226 {
01227 apm_perror("APM real mode connect failed", be.ax);
01228 return;
01229 }
01230
01231
01232 be.ax= 0x530e;
01233 be.bx= 0x0000;
01234 be.cx= 0x0102;
01235 int15(&be);
01236 if (be.flags & FL_CARRY)
01237 {
01238 apm_perror("Set driver version failed", be.ax);
01239 goto disco;
01240 }
01241
01242
01243
01244
01245 ah= be.ax >> 8;
01246 if (ah > 9)
01247 ah= (ah >> 4)*10 + (ah & 0xf);
01248 al= be.ax & 0xff;
01249 if (al > 9)
01250 al= (al >> 4)*10 + (al & 0xf);
01251 apm_printf("Got APM connection version %u.%u\n", ah, al);
01252
01253
01254 be.ax= 0x5308;
01255 be.bx= 0x0001;
01256 #if 0
01257
01258
01259
01260 be.bx= 0xffff;
01261 #endif
01262 be.cx= 0x0001;
01263 int15(&be);
01264 if (be.flags & FL_CARRY)
01265 {
01266 apm_perror("Enable power management failed", be.ax);
01267 goto disco;
01268 }
01269
01270
01271 be.ax= 0x5307;
01272 be.bx= 0x0001;
01273 be.cx= 0x0003;
01274 int15(&be);
01275 if (be.flags & FL_CARRY)
01276 {
01277 apm_perror("Set power state failed", be.ax);
01278 goto disco;
01279 }
01280
01281 apm_printf("Power off sequence successfully completed.\n\n");
01282 apm_printf("Ha, ha, just kidding!\n");
01283
01284 disco:
01285
01286 be.ax= 0x5304;
01287 be.bx= 0x0000;
01288 int15(&be);
01289 if (be.flags & FL_CARRY)
01290 {
01291 apm_perror("APM interface disconnect failed", be.ax);
01292 return;
01293 }
01294 }
01295
01296 #if !DOS
01297 #define B_NOSIG -1
01298
01299 int exec_bootstrap(void)
01300
01301
01302 {
01303 int r, n, dirty= 0;
01304 char master[SECTOR_SIZE];
01305 struct part_entry *table[NR_PARTITIONS], dummy, *active= &dummy;
01306 u32_t masterpos;
01307
01308 active->lowsec= 0;
01309
01310
01311 while (tmpdev.primary >= 0) {
01312 masterpos= active->lowsec;
01313
01314 if ((r= get_master(master, table, masterpos)) != 0) return r;
01315
01316 active= table[tmpdev.primary];
01317
01318
01319 if (active->sysind == NO_PART) return B_NOSIG;
01320
01321 tmpdev.primary= tmpdev.secondary;
01322 tmpdev.secondary= -1;
01323 }
01324
01325 if (activate && !active->bootind) {
01326 for (n= 0; n < NR_PARTITIONS; n++) table[n]->bootind= 0;
01327 active->bootind= ACTIVE_FLAG;
01328 dirty= 1;
01329 }
01330
01331
01332 if ((r= readsectors(BOOTPOS, active->lowsec, 1)) != 0) return r;
01333
01334
01335 if (get_word(BOOTPOS+SIGNATOFF) != SIGNATURE) return B_NOSIG;
01336
01337
01338 if (dirty && (r= writesectors(mon2abs(master), masterpos, 1)) != 0)
01339 return r;
01340
01341 bootstrap(device, active);
01342 }
01343
01344 void boot_device(char *devname)
01345
01346 {
01347 dev_t dev= name2dev(devname);
01348 int save_dev= device;
01349 int r;
01350 char *err;
01351
01352 if (tmpdev.device < 0) {
01353 if (dev != -1) printf("Can't boot from %s\n", devname);
01354 return;
01355 }
01356
01357
01358 device= tmpdev.device;
01359
01360 if ((r= dev_open()) == 0) r= exec_bootstrap();
01361
01362 err= r == B_NOSIG ? "Not bootable" : bios_err(r);
01363 printf("Can't boot %s: %s\n", devname, err);
01364
01365
01366 device= save_dev;
01367 (void) dev_open();
01368 }
01369
01370 void ctty(char *line)
01371 {
01372 if (between('0', line[0], '3') && line[1] == 0) {
01373 serial_init(line[0] - '0');
01374 } else {
01375 printf("Bad serial line number: %s\n", line);
01376 }
01377 }
01378
01379 #else
01380
01381 void boot_device(char *devname)
01382
01383 {
01384 printf("Can't boot devices under DOS\n");
01385 }
01386
01387 void ctty(char *line)
01388
01389 {
01390 printf("No serial line support under DOS\n");
01391 }
01392
01393 #endif
01394 #endif
01395
01396 void ls(char *dir)
01397
01398 {
01399 ino_t ino;
01400 struct stat st;
01401 char name[NAME_MAX+1];
01402
01403 if (fsok == -1) fsok= r_super(&block_size) != 0;
01404 if (!fsok) return;
01405
01406
01407 if ((ino= r_lookup(ROOT_INO, dir)) == 0 ||
01408 (r_stat(ino, &st), r_readdir(name)) == -1)
01409 {
01410 printf("ls: %s: %s\n", dir, unix_err(errno));
01411 return;
01412 }
01413 (void) r_readdir(name);
01414
01415 while ((ino= r_readdir(name)) != 0) printf("%s/%s\n", dir, name);
01416 }
01417
01418 u32_t milli_time(void)
01419 {
01420 return get_tick() * MSEC_PER_TICK;
01421 }
01422
01423 u32_t milli_since(u32_t base)
01424 {
01425 return (milli_time() + (TICKS_PER_DAY*MSEC_PER_TICK) - base)
01426 % (TICKS_PER_DAY*MSEC_PER_TICK);
01427 }
01428
01429 char *Thandler;
01430 u32_t Tbase, Tcount;
01431
01432 void unschedule(void)
01433
01434 {
01435 alarm(0);
01436
01437 if (Thandler != nil) {
01438 free(Thandler);
01439 Thandler= nil;
01440 }
01441 }
01442
01443 void schedule(long msec, char *cmd)
01444
01445 {
01446 unschedule();
01447 Thandler= cmd;
01448 Tbase= milli_time();
01449 Tcount= msec;
01450 alarm(1);
01451 }
01452
01453 int expired(void)
01454
01455 {
01456 return (Thandler != nil && milli_since(Tbase) >= Tcount);
01457 }
01458
01459 void delay(char *msec)
01460
01461 {
01462 u32_t base, count;
01463
01464 if ((count= a2l(msec)) == 0) return;
01465 base= milli_time();
01466
01467 alarm(1);
01468
01469 do {
01470 pause();
01471 } while (!interrupt() && !expired() && milli_since(base) < count);
01472 }
01473
01474 enum whatfun { NOFUN, SELECT, DEFFUN, USERFUN } menufun(environment *e)
01475 {
01476 if (!(e->flags & E_FUNCTION) || e->arg[0] == 0) return NOFUN;
01477 if (e->arg[1] != ',') return SELECT;
01478 return e->flags & E_RESERVED ? DEFFUN : USERFUN;
01479 }
01480
01481 void menu(void)
01482
01483
01484
01485
01486
01487 {
01488 int c, def= 1;
01489 char *choice= nil;
01490 environment *e;
01491
01492
01493 for (e= env; e != nil; e= e->next) if (menufun(e) == USERFUN) def= 0;
01494
01495 printf("\nHit a key as follows:\n\n");
01496
01497
01498 for (e= env; e != nil; e= e->next) {
01499 switch (menufun(e)) {
01500 case DEFFUN:
01501 if (!def) break;
01502
01503 case USERFUN:
01504 printf(" %c %s\n", e->arg[0], e->arg+2);
01505 break;
01506 case SELECT:
01507 printf(" %c Select %s kernel\n", e->arg[0],e->name);
01508 break;
01509 default:;
01510 }
01511 }
01512
01513
01514 do {
01515 c= getch();
01516 if (interrupt() || expired()) return;
01517
01518 unschedule();
01519
01520 for (e= env; e != nil; e= e->next) {
01521 switch (menufun(e)) {
01522 case DEFFUN:
01523 if (!def) break;
01524 case USERFUN:
01525 case SELECT:
01526 if (c == e->arg[0]) choice= e->value;
01527 }
01528 }
01529 } while (choice == nil);
01530
01531
01532 printf("%c\n", c);
01533 (void) tokenize(&cmds, choice);
01534 }
01535
01536 void help(void)
01537
01538 {
01539 struct help {
01540 char *thing;
01541 char *help;
01542 } *pi;
01543 static struct help info[] = {
01544 { nil, "Names:" },
01545 { "rootdev", "Root device" },
01546 { "ramimagedev", "Device to use as RAM disk image " },
01547 { "ramsize", "RAM disk size (if no image device) " },
01548 { "bootdev", "Special name for the boot device" },
01549 { "fd0, d0p2, c0d0p1s0", "Devices (as in /dev)" },
01550 { "image", "Name of the boot image to use" },
01551 { "main", "Startup function" },
01552 { "bootdelay", "Delay in msec after loading image" },
01553 { nil, "Commands:" },
01554 { "name = [device] value", "Set environment variable" },
01555 { "name() { ... }", "Define function" },
01556 { "name(key,text) { ... }",
01557 "A menu option like: minix(=,Start MINIX) {boot}" },
01558 { "name", "Call function" },
01559 { "boot [device]", "Boot Minix or another O.S." },
01560 { "ctty [line]", "Duplicate to serial line" },
01561 { "delay [msec]", "Delay (500 msec default)" },
01562 { "echo word ...", "Display the words" },
01563 { "ls [directory]", "List contents of directory" },
01564 { "menu", "Show menu and choose menu option" },
01565 { "save / set", "Save or show environment" },
01566 { "trap msec command", "Schedule command " },
01567 { "unset name ...", "Unset variable or set to default" },
01568 { "exit / off", "Exit the Monitor / Power off" },
01569 };
01570
01571 for (pi= info; pi < arraylimit(info); pi++) {
01572 if (pi->thing != nil) printf(" %-24s- ", pi->thing);
01573 printf("%s\n", pi->help);
01574 }
01575 }
01576
01577 void execute(void)
01578
01579 {
01580 token *second, *third, *fourth, *sep;
01581 char *name;
01582 int res;
01583 size_t n= 0;
01584
01585 if (err) {
01586
01587 while (cmds != nil) voidtoken();
01588 return;
01589 }
01590
01591 if (expired()) {
01592 parse_code(Thandler);
01593 unschedule();
01594 }
01595
01596
01597 for (sep= cmds; sep != nil && sep->token[0] != ';'; sep= sep->next) n++;
01598
01599 name= cmds->token;
01600 res= reserved(name);
01601 if ((second= cmds->next) != nil
01602 && (third= second->next) != nil)
01603 fourth= third->next;
01604
01605
01606 if (n == 0) {
01607 voidtoken();
01608 return;
01609 } else
01610
01611 if ((n == 3 || n == 4)
01612 && !sugar(name)
01613 && second->token[0] == '='
01614 && !sugar(third->token)
01615 && (n == 3 || (n == 4 && third->token[0] == 'd'
01616 && !sugar(fourth->token)
01617 ))) {
01618 char *value= third->token;
01619 int flags= E_VAR;
01620
01621 if (n == 4) { value= fourth->token; flags|= E_DEV; }
01622
01623 if ((flags= b_setvar(flags, name, value)) != 0) {
01624 printf("%s is a %s\n", name,
01625 flags & E_RESERVED ? "reserved word" :
01626 "special function");
01627 err= 1;
01628 }
01629 while (cmds != sep) voidtoken();
01630 return;
01631 } else
01632
01633 if (n >= 3
01634 && !sugar(name)
01635 && second->token[0] == '('
01636 ) {
01637 token *fun;
01638 int c, flags, depth;
01639 char *body;
01640 size_t len;
01641
01642 sep= fun= third;
01643 depth= 0;
01644 len= 1;
01645 while (sep != nil) {
01646 if ((c= sep->token[0]) == ';' && depth == 0) break;
01647 len+= strlen(sep->token) + 1;
01648 sep= sep->next;
01649 if (c == '{') depth++;
01650 if (c == '}' && --depth == 0) break;
01651 }
01652
01653 body= malloc(len * sizeof(char));
01654 *body= 0;
01655
01656 while (fun != sep) {
01657 strcat(body, fun->token);
01658 if (!sugar(fun->token)
01659 && !sugar(fun->next->token)
01660 ) strcat(body, " ");
01661 fun= fun->next;
01662 }
01663 second->token[strlen(second->token)-1]= 0;
01664
01665 if (depth != 0) {
01666 printf("Missing '}'\n");
01667 err= 1;
01668 } else
01669 if ((flags= b_setenv(E_FUNCTION, name,
01670 second->token+1, body)) != 0) {
01671 printf("%s is a %s\n", name,
01672 flags & E_RESERVED ? "reserved word" :
01673 "special variable");
01674 err= 1;
01675 }
01676 while (cmds != sep) voidtoken();
01677 free(body);
01678 return;
01679 } else
01680
01681 if (name[0] == '{') {
01682 token **acmds= &cmds->next;
01683 char *t;
01684 int depth= 1;
01685
01686
01687 depth= 1;
01688 while (*acmds != nil) {
01689 t= (*acmds)->token;
01690 if (t[0] == '{') depth++;
01691 if (t[0] == '}' && --depth == 0) { t[0]= ';'; break; }
01692 acmds= &(*acmds)->next;
01693 }
01694 voidtoken();
01695 return;
01696 } else
01697
01698 if (interrupt()) {
01699 return;
01700 } else
01701
01702 if (n >= 1 && (res == R_UNSET || res == R_ECHO)) {
01703 char *arg= poptoken(), *p;
01704
01705 for (;;) {
01706 free(arg);
01707 if (cmds == sep) break;
01708 arg= poptoken();
01709 if (res == R_UNSET) {
01710 b_unset(arg);
01711 } else {
01712 p= arg;
01713 while (*p != 0) {
01714 if (*p != '\\') {
01715 putch(*p);
01716 } else
01717 switch (*++p) {
01718 case 0:
01719 if (cmds == sep) return;
01720 continue;
01721 case 'n':
01722 putch('\n');
01723 break;
01724 case 'v':
01725 printf(version);
01726 break;
01727 case 'c':
01728 clear_screen();
01729 break;
01730 case 'w':
01731 for (;;) {
01732 if (interrupt())
01733 return;
01734 if (getch() == '\n')
01735 break;
01736 }
01737 break;
01738 default:
01739 putch(*p);
01740 }
01741 p++;
01742 }
01743 putch(cmds != sep ? ' ' : '\n');
01744 }
01745 }
01746 return;
01747 } else
01748
01749 if (n == 2 && res == R_BOOT && second->token[0] == '-') {
01750 static char optsvar[]= "bootopts";
01751 (void) b_setvar(E_VAR, optsvar, second->token);
01752 voidtoken();
01753 voidtoken();
01754 bootminix();
01755 b_unset(optsvar);
01756 return;
01757 } else
01758
01759 if (n == 2 && (res == R_BOOT || res == R_CTTY
01760 || res == R_DELAY || res == R_LS)
01761 ) {
01762 if (res == R_BOOT) boot_device(second->token);
01763 if (res == R_CTTY) ctty(second->token);
01764 if (res == R_DELAY) delay(second->token);
01765 if (res == R_LS) ls(second->token);
01766 voidtoken();
01767 voidtoken();
01768 return;
01769 } else
01770
01771 if (n == 3 && res == R_TRAP && numeric(second->token)) {
01772 long msec= a2l(second->token);
01773
01774 voidtoken();
01775 voidtoken();
01776 schedule(msec, poptoken());
01777 return;
01778 } else
01779
01780 if (n == 1) {
01781 char *body;
01782 int ok= 0;
01783
01784 name= poptoken();
01785
01786 switch (res) {
01787 case R_BOOT: bootminix(); ok= 1; break;
01788 case R_DELAY: delay("500"); ok= 1; break;
01789 case R_LS: ls(null); ok= 1; break;
01790 case R_MENU: menu(); ok= 1; break;
01791 case R_SAVE: save_parameters(); ok= 1;break;
01792 case R_SET: show_env(); ok= 1; break;
01793 case R_HELP: help(); ok= 1; break;
01794 case R_EXIT: exit(0);
01795 case R_OFF: off(); ok= 1; break;
01796 }
01797
01798
01799 if (strcmp(name, ":") == 0) ok= 1;
01800
01801
01802 if (!ok && (body= b_body(name)) != nil) {
01803 (void) tokenize(&cmds, body);
01804 ok= 1;
01805 }
01806 if (!ok) printf("%s: unknown function", name);
01807 free(name);
01808 if (ok) return;
01809 } else {
01810
01811 printf("Can't parse:");
01812 while (cmds != sep) {
01813 printf(" %s", cmds->token); voidtoken();
01814 }
01815 }
01816
01817
01818 printf("\nTry 'help'\n");
01819 err= 1;
01820 }
01821
01822 int run_trailer(void)
01823
01824
01825
01826 {
01827 token *save_cmds= cmds;
01828
01829 cmds= nil;
01830 (void) tokenize(&cmds, "trailer");
01831 while (cmds != nil) execute();
01832 cmds= save_cmds;
01833 return !err;
01834 }
01835
01836 void monitor(void)
01837
01838 {
01839 char *line;
01840
01841 unschedule();
01842 err= 0;
01843
01844 if (istty) printf("%s>", bootdev.name);
01845 line= readline();
01846 (void) tokenize(&cmds, line);
01847 free(line);
01848 (void) escape();
01849 }
01850
01851 #if BIOS
01852
01853 unsigned char cdspec[25];
01854 void bootcdinfo(u32_t, int *, int drive);
01855
01856 void boot(void)
01857
01858 {
01859
01860
01861 initialize();
01862
01863
01864 get_parameters();
01865
01866 while (1) {
01867
01868
01869 while (cmds != nil) execute();
01870
01871
01872 monitor();
01873 }
01874 }
01875 #endif
01876
01877 #if UNIX
01878
01879 void main(int argc, char **argv)
01880
01881 {
01882 int i;
01883 char bootcode[SECTOR_SIZE];
01884 struct termios rawterm;
01885
01886 istty= (argc <= 2 && tcgetattr(0, &termbuf) == 0);
01887
01888 if (argc < 2) {
01889 fprintf(stderr, "Usage: edparams device [command ...]\n");
01890 exit(1);
01891 }
01892
01893
01894 for (i= 2; i < argc; i++) {
01895 char *p;
01896
01897 for (p= argv[i]; *p != 0; p++) {
01898 if ((unsigned) *p < ' ' && *p != '\n') *p= ' ';
01899 }
01900 }
01901
01902 bootdev.name= argv[1];
01903 if (strncmp(bootdev.name, "/dev/", 5) == 0) bootdev.name+= 5;
01904 if ((bootdev.device= open(argv[1], O_RDWR, 0666)) < 0)
01905 fatal(bootdev.name);
01906
01907
01908 if (readsectors(mon2abs(bootcode), lowsec, 1) != 0
01909 || memcmp(bootcode, boot_magic, sizeof(boot_magic)) != 0) {
01910 fprintf(stderr, "edparams: %s: not a bootable Minix device\n",
01911 bootdev.name);
01912 exit(1);
01913 }
01914
01915
01916 if (istty) printf("Boot parameters editor.\n");
01917
01918 signal(SIGINT, trap);
01919 signal(SIGALRM, trap);
01920
01921 if (istty) {
01922 rawterm= termbuf;
01923 rawterm.c_lflag&= ~(ICANON|ECHO|IEXTEN);
01924 rawterm.c_cc[VINTR]= ESC;
01925 if (tcsetattr(0, TCSANOW, &rawterm) < 0) fatal("");
01926 }
01927
01928
01929 get_parameters();
01930
01931 i= 2;
01932 for (;;) {
01933
01934 while (cmds != nil || i < argc) {
01935 if (cmds == nil) {
01936
01937 parse_code(argv[i++]);
01938 }
01939 execute();
01940
01941
01942 if (err && !istty) exit(1);
01943 }
01944
01945
01946 if (argc > 2) break;
01947
01948
01949 monitor();
01950 }
01951 exit(0);
01952 }
01953 #endif
01954
01955
01956
01957