Annotation of Net2/arch/i386/netboot/main.c, revision 1.1.1.1

1.1       root        1: /* netboot
                      2:  *
                      3:  * main.c,v
                      4:  * Revision 1.2  1993/07/09  15:24:12  brezak
                      5:  * Cleanup warnings and add netbsd kernel name suffix.
                      6:  *
                      7:  * Revision 1.1  1993/07/08  16:04:02  brezak
                      8:  * Diskless boot prom code from Jim McKim ([email protected])
                      9:  *
                     10:  * Revision 1.4  1993/06/30  20:14:13  mckim
                     11:  * Added BOOTP support.
                     12:  *
                     13:  * Revision 1.3  1993/06/08  14:27:08  mckim
                     14:  * Reboot options (argv[1]) passed to kernel.
                     15:  *
                     16:  * Revision 1.2  1993/05/28  20:01:27  mckim
                     17:  * Fixed various StartProg() problems.
                     18:  *
                     19:  * Revision 1.1.1.1  1993/05/28  11:41:07  mckim
                     20:  * Initial version.
                     21:  *
                     22:  *
                     23:  * source code in this file is from:
                     24:  * 386BSD boot blocks by Julian Elischer ([email protected])
                     25:  * 386BSD Adaptec 1542 SCSI boot blocks by Pace Willisson ([email protected])
                     26:  *
                     27:  * Mach Operating System
                     28:  * Copyright (c) 1992, 1991 Carnegie Mellon University
                     29:  * All Rights Reserved.
                     30:  * 
                     31:  * Permission to use, copy, modify and distribute this software and its
                     32:  * documentation is hereby granted, provided that both the copyright
                     33:  * notice and this permission notice appear in all copies of the
                     34:  * software, derivative works or modified versions, and any portions
                     35:  * thereof, and that both notices appear in supporting documentation.
                     36:  * 
                     37:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     38:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     39:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     40:  * 
                     41:  * Carnegie Mellon requests users of this software to return to
                     42:  * 
                     43:  *  Software Distribution Coordinator  or  [email protected]
                     44:  *  School of Computer Science
                     45:  *  Carnegie Mellon University
                     46:  *  Pittsburgh PA 15213-3890
                     47:  * 
                     48:  * any improvements or extensions that they make and grant Carnegie Mellon
                     49:  * the rights to redistribute these changes.
                     50:  */
                     51: 
                     52: /*
                     53:   Copyright 1988, 1989, 1990, 1991, 1992 
                     54:    by Intel Corporation, Santa Clara, California.
                     55: 
                     56:                 All Rights Reserved
                     57: 
                     58: Permission to use, copy, modify, and distribute this software and
                     59: its documentation for any purpose and without fee is hereby
                     60: granted, provided that the above copyright notice appears in all
                     61: copies and that both the copyright notice and this permission notice
                     62: appear in supporting documentation, and that the name of Intel
                     63: not be used in advertising or publicity pertaining to distribution
                     64: of the software without specific, written prior permission.
                     65: 
                     66: INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
                     67: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
                     68: IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
                     69: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
                     70: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
                     71: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
                     72: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     73: */
                     74: 
                     75: 
                     76: #include "config.h"
                     77: #include "nbtypes.h"
                     78: #include "assert.h"
                     79: #include "param.h"
                     80: #include "packet.h"
                     81: #include "ether.h"
                     82: #include "inet.h"
                     83: #include "arp.h"
                     84: #include "tftp.h"
                     85: 
                     86: #include "proto.h"
                     87: 
                     88: u_long work_area_org = RELOC;
                     89: u_long kernel_size;
                     90: u_short real_cs;
                     91: u_long howto = 0;
                     92: u_char vendor_area[64];
                     93: 
                     94: enum LoadErr {
                     95:   load_success,
                     96:   load_no_answer,
                     97:   load_bad_format,
                     98:   load_bad_size,
                     99: };
                    100: 
                    101: static inline enum LoadErr
                    102: LoadProgFromServer(ipaddr_t server, ipaddr_t gateway, char *file_name) {
                    103:   /* TBD - fail (or at least warn) if we don't get the entire file */
                    104:   u_long start_addr;
                    105:   u_long boot_area_org;
                    106:   u_long tmp_reloc_org;
                    107:   u_long kern_copy_org;
                    108:   u_long kern_copy_p;
                    109:   struct exec head;
                    110:   u_long boot_argv[4];
                    111: #if 1 /* ndef USE_BUFFER */
                    112:   u_char tmpbuf[4096]; /* we need to load the first 4k here */
                    113: #endif
                    114: 
                    115:   SetTftpParms(server, gateway, file_name);
                    116: 
                    117:   /* TBD - heuristics about what we are loading - load linux, ... also */
                    118: 
                    119:   if (Read(&head, sizeof(head)) != sizeof(head))
                    120:     return load_bad_size;
                    121: 
                    122:   if (head.a_magic != 0413 ) {
                    123:     printf("Invalid format!\n");
                    124:     return load_bad_format;
                    125:   }
                    126: 
                    127:   /* Load/tftp the executable to a temporary area beyond 640k - after
                    128:      successful load, copy to correct area. If load fails or is interrrupted,
                    129:      we can recover gracefully
                    130:      */
                    131: 
                    132:   start_addr = (u_long)head.a_entry;
                    133:   boot_area_org = start_addr & 0x00f00000; /* some MEG boundary */
                    134:   tmp_reloc_org = 0x00100000;
                    135: #ifdef USE_BUFFER
                    136:   kern_copy_org = tmp_reloc_org + WORK_AREA_SIZE; /* leave free for relocation */
                    137: #else
                    138:   kern_copy_org = boot_area_org; /* leave free for relocation */
                    139: #endif
                    140:   kern_copy_p = kern_copy_org;
                    141:   kernel_size = head.a_text + head.a_data + head.a_bss;
                    142: 
                    143:   printf("Loading ");
                    144:   IpPrintAddr(server);
                    145:   printf(":%s @ 0x%x\n", file_name, boot_area_org);
                    146: #ifndef USE_BUFFER
                    147:   if(boot_area_org < work_area_org) {
                    148:     if((boot_area_org + head.a_text + head.a_data) > work_area_org) {
                    149:       printf("kernel will not fit below loader\n");
                    150:       return load_bad_size;
                    151:     }
                    152:     if((boot_area_org + head.a_text + head.a_data + head.a_bss) > 0xa0000) {
                    153:       printf("kernel too big, won't fit in 640K with bss\n");
                    154:       printf("Only hope is to link the kernel for > 1MB\n");
                    155:       return load_bad_size;
                    156:     }
                    157:     if(boot_area_org + kernel_size > work_area_org) {
                    158:       printf("loader overlaps bss, kernel must bzero\n");
                    159:     }
                    160:   }
                    161: #else
                    162:   if(boot_area_org + kernel_size > 0xa0000) {
                    163:     printf("kernel too big, won't fit in 640K with bss\n");
                    164:     printf("Only hope is to link the kernel for > 1MB\n");
                    165:     return load_bad_size;
                    166:   }
                    167:   /* check if too large for tmp buffer (TBD) */
                    168: #endif
                    169:   printf("text=0x%x", head.a_text);
                    170: 
                    171: #if 01
                    172:   /* skip to first 4k boundry */
                    173:   Read(tmpbuf, 4096-sizeof(head));
                    174: #endif
                    175: 
                    176: #if 0 /* ndef USE_BUFFER */
                    177:   /********************************************************/
                    178:   /* LOAD THE TEXT SEGMENT                             */
                    179:   /* don't clobber the first 4k yet (BIOS NEEDS IT)    */
                    180:   /********************************************************/
                    181:   Read(tmpbuf, sizeof(tmpbuf));
                    182:   kern_copy_p += sizeof(tmpbuf);
                    183:   PhysRead(kern_copy_p, head.a_text - sizeof(tmpbuf));
                    184:   kern_copy_p += head.a_text - sizeof(tmpbuf);
                    185: #else
                    186:   /********************************************************/
                    187:   /* LOAD THE TEXT SEGMENT                             */
                    188:   /********************************************************/
                    189:   PhysRead(kern_copy_p, head.a_text);
                    190:   kern_copy_p += head.a_text;
                    191: #endif
                    192: 
                    193:   /********************************************************/
                    194:   /* Load the Initialised data after the text          */
                    195:   /********************************************************/
                    196: /* TBD - this is bogus - file system oriented */
                    197: #define CLSIZE 1
                    198: #define NBPG 4096            /* bytes/page */
                    199: #define CLOFSET (CLSIZE*NBPG-1) /* for clusters, like PGOFSET */
                    200: 
                    201:   while (kern_copy_p & CLOFSET)
                    202:     *(char *)kern_copy_p++ = 0;
                    203: 
                    204:   printf(" data=0x%x", head.a_data);
                    205:   PhysRead(kern_copy_p, head.a_data);
                    206:   kern_copy_p += head.a_data;
                    207: 
                    208:   /********************************************************/
                    209:   /* Skip over the uninitialised data                  */
                    210:   /* (but clear it)                                    */
                    211:   /********************************************************/
                    212:   printf(" bss=0x%x", head.a_bss);
                    213:   if (kern_copy_p < RELOC &&
                    214:      (kern_copy_p + head.a_bss) > RELOC) {
                    215:     PhysBzero(kern_copy_p, RELOC-(u_int)kern_copy_p);
                    216:   } else {
                    217:     PhysBzero(kern_copy_p, head.a_bss);
                    218:   }
                    219: 
                    220: #ifdef LOADSYMS /* not yet, haven't worked this out yet */
                    221:   if (kern_copy_p > 0x100000) {
                    222:     /********************************************************/
                    223:     /*copy in the symbol header                                */
                    224:     /********************************************************/
                    225:     PhysBcopy(&head.a_syms, kern_copy_p, sizeof(head.a_syms));
                    226:     kern_copy_p += sizeof(head.a_syms);
                    227: 
                    228:     /********************************************************/
                    229:     /* READ in the symbol table                                */
                    230:     /********************************************************/
                    231:     printf(" symbols=[+0x%x", head.a_syms);
                    232:     Read(kern_copy_p, head.a_syms);
                    233:     kern_copy_p += head.a_syms;
                    234: 
                    235:     /********************************************************/
                    236:     /* Followed by the next integer (another header)   */
                    237:     /* more debug symbols?                                     */
                    238:     /********************************************************/
                    239:     read(&i, sizeof(u_int));
                    240:     PhysBcopy(&i, kern_copy_p, sizeof(u_int));
                    241:     i -= sizeof(u_int);
                    242:     kern_copy_p += sizeof(u_int);
                    243: 
                    244:     /********************************************************/
                    245:     /* and that many bytes of (debug symbols?)         */
                    246:     /********************************************************/
                    247:     printf("+0x%x]", i);
                    248:     Read(kern_copy_p, i);
                    249:     kern_copy_p += i;
                    250:   }
                    251: #endif LOADSYMS
                    252: 
                    253:   /********************************************************/
                    254:   /* and note the end address of all this                      */
                    255:   /********************************************************/
                    256: 
                    257:   printf(" total=0x%x",kern_copy_p - kern_copy_org);
                    258: 
                    259:   boot_argv[0] = 0;
                    260:   boot_argv[1] = howto;
                    261:   boot_argv[2] = 0;
                    262:   boot_argv[3] = 0;
                    263: 
                    264: /* TBD - place vendor_area on stack */
                    265: 
                    266:   printf(" entry point=0x%x\n" ,((u_int)start_addr) & 0xffffff);
                    267: 
                    268:   if (howto) {
                    269:     static char *rb_option_name[9] = {
                    270:       "askname",
                    271:       "single",
                    272:       "nosync",
                    273:       "halt",
                    274:       "initname",
                    275:       "dfltroot",
                    276:       "kdb",
                    277:       "rdonly",
                    278:       "dump",
                    279:       };
                    280:     int i;
                    281:     printf("Starting kernel with options (0x%x): ", howto);
                    282:     for (i=0; i<9; i++) {
                    283:       if (howto & (1<<i)) {
                    284:        printf("%s ", rb_option_name[i]);
                    285:       }
                    286:     }
                    287:     printf("\n");
                    288:   }
                    289: 
                    290: #if 0 /* ndef USE_BUFFER */
                    291:   PhysBcopy(tmpbuf, boot_area_org, sizeof(tmpbuf));
                    292: #endif
                    293: 
                    294:   StartProg(start_addr & 0xffffff, boot_argv);
                    295: 
                    296:   return load_success; /* hah! */
                    297: }
                    298: 
                    299: int GetHex(int old) {
                    300:   int r, c, ch;
                    301:   r = 0;
                    302:   ch = 0;
                    303:   while((c=getchar()) != '\n') {
                    304:     ch = 1;
                    305:     if (c>='0' && c<='9')
                    306:       r = r*16 + (c-'0');
                    307:     else if (c>='a' && c<='f')
                    308:       r = r*16 + (c+10-'a');
                    309:   }
                    310:   if (ch)
                    311:     return r;
                    312:   else
                    313:     return old;
                    314: }
                    315: 
                    316: static char
                    317: ToHex(int n) {
                    318:   n &= 0x0F;
                    319:   return n >= 10 ? n - 10 + 'A' : n + '0';
                    320: }
                    321: 
                    322: static char name_set[][9] = {
                    323:   "xxxxxxxx",
                    324:   "default",
                    325: };
                    326: 
                    327: static char *ext_set[] = {
                    328:   ".netbsd",
                    329:   ".netbsd.old",
                    330:   ".386bsd",
                    331:   ".386bsd.old",
                    332:   ".vmunix",
                    333:   ".vmunix.old",
                    334: };
                    335: 
                    336: static ipaddr_t server_set[2] = {
                    337:   0,
                    338:   IP_BCASTADDR,
                    339: };
                    340: 
                    341: static inline void
                    342: TryToLoadSomething(void) {
                    343:   int nserver;
                    344:   for (nserver=0; nserver<nelt(server_set); nserver++) {
                    345:     int nname;
                    346:     char file_name[MAX_FILE_NAME_LEN+1];
                    347:     file_name[0] = '\0';
                    348:     if (GetIpAddress(&server_set[nserver], &ip_myaddr, &ip_gateway, file_name)) {
                    349:       if (*file_name) {
                    350:        LoadProgFromServer(server_set[nserver], ip_gateway, file_name);
                    351:       }
                    352:       else {
                    353:        /* no file name supplied from server, synthesize one */
                    354:        inetaddr_t ip;
                    355:        ip.a = ip_myaddr;
                    356:        name_set[0][0] = ToHex(ip.s.a0 >> 4);
                    357:        name_set[0][1] = ToHex(ip.s.a0);
                    358:        name_set[0][2] = ToHex(ip.s.a1 >> 4);
                    359:        name_set[0][3] = ToHex(ip.s.a1);
                    360:        name_set[0][4] = ToHex(ip.s.a2 >> 4);
                    361:        name_set[0][5] = ToHex(ip.s.a2);
                    362:        name_set[0][6] = ToHex(ip.s.a3 >> 4);
                    363:        name_set[0][7] = ToHex(ip.s.a3);
                    364:        name_set[0][8] = 0;
                    365:        for (nname=0; nname<nelt(name_set); nname++) {
                    366:          int next;
                    367:          for (next=0; next<nelt(ext_set); next++) {
                    368:            strncpy(file_name, name_set[nname], MAX_FILE_NAME_LEN);
                    369:            strncat(file_name, ext_set[next], MAX_FILE_NAME_LEN-strlen(file_name));
                    370:            LoadProgFromServer(server_set[nserver], ip_gateway, file_name);
                    371:          }
                    372:        }
                    373:       }
                    374:     }
                    375:   }
                    376: }
                    377: 
                    378: 
                    379: static char *
                    380: DecimalToByte(char *s, u_char *n) {
                    381:   for (*n = 0; *s >= '0' && *s <= '9'; s++)
                    382:     *n = (*n * 10) + *s - '0';
                    383:   return s;
                    384: }
                    385: 
                    386: static ipaddr_t
                    387: IpConvertAddr(char *p) {
                    388:   inetaddr_t addr;
                    389: 
                    390:   if (p == (char *)0 || *p == '\0')
                    391:     return IP_ANYADDR;
                    392:   p = DecimalToByte(p, &addr.s.a0);
                    393:   if (*p == '\0' || *p++ != '.')
                    394:     return IP_ANYADDR;
                    395:   p = DecimalToByte(p, &addr.s.a1);
                    396:   if (*p == '\0' || *p++ != '.')
                    397:     return IP_ANYADDR;
                    398:   p = DecimalToByte(p, &addr.s.a2);
                    399:   if (*p == '\0' || *p++ != '.')
                    400:     return IP_ANYADDR;
                    401:   p = DecimalToByte(p, &addr.s.a3);
                    402:   if (*p != '\0')
                    403:     return IP_ANYADDR;
                    404:   return addr.a;
                    405: }
                    406: 
                    407: static int
                    408: GetLine(char **argv, int argvsize) {
                    409:   char *p, ch;
                    410:   static char line[128];
                    411:   int argc;
                    412: 
                    413:   /*
                    414:    * Read command line, implement some simple editing features
                    415:    */
                    416:   p = line;
                    417:   while ((ch = getchar()) != '\r' && ch != '\n' && (p-line) < sizeof(line)) {
                    418:     if (ch == '\b') {
                    419:       if (p > line) {
                    420:        p--;
                    421:        printf(" \b");
                    422:       }
                    423:     } else
                    424:       *p++ = ch;
                    425:   }
                    426:   *p = '\0';
                    427: 
                    428:   /*
                    429:    * Break command line up into an argument vector
                    430:    */
                    431:   argc = 0;
                    432:   for (p = line; *p == ' ' || *p == '\t'; p++)
                    433:     /* skip white spaces */;
                    434:   while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') {
                    435:     if (argc > argvsize) break;
                    436:     argv[(argc)++] = p;
                    437:     for (; *p != ' ' && *p != '\t' && *p != '\n' && *p != '\0'; p++)
                    438:       /* skip word */;
                    439:     if (*p != '\0') *p++ ='\0';
                    440:     for (; *p == ' ' || *p == '\t'; p++)
                    441:       /* skip white spaces */;
                    442:   }
                    443:   argv[(argc)] = (char *)0;
                    444:   return argc;
                    445: }
                    446: 
                    447: enum cmd_token_type {
                    448:   CMD_GO,
                    449:   CMD_HELP,
                    450:   CMD_RESET,
                    451:   CMD_AUTO,
                    452:   CMD_WHO,
                    453:   CMD_REBOOT,
                    454:   CMD_DISKBOOT,
                    455:   CMD_ADDRESS,
                    456:   CMD_GATEWAY,
                    457:   CMD_TFTP,
                    458:   CMD_DEBUG,
                    459:   CMD_SINGLE,
                    460:   CMD_FILE,
                    461:   CMD_SERVER,
                    462: };
                    463: 
                    464: struct commands {
                    465:   enum cmd_token_type cmd_token;
                    466:   char *cmd_name;
                    467:   char *cmd_help;
                    468: } commands[] = {
                    469:   {CMD_GO,     "go",           "                       start loaded binary"},
                    470:   {CMD_HELP,   "help",         "                     this help message"},
                    471:   {CMD_RESET,  "reset",        "                    reset ethernet board"},
                    472:   {CMD_AUTO,   "auto",         "                     continue with auto boot"},
                    473:   {CMD_WHO,    "whoami",       "                       get IP address"},
                    474:   {CMD_REBOOT, "reboot",       "                   hard reboot"},
                    475:   {CMD_DISKBOOT,       "diskboot",     "                 soft reboot (from disk)"},
                    476:   {CMD_ADDRESS,  "address",    "[<addr>]          set IP address"},
                    477:   {CMD_GATEWAY,  "gateway",    "[<addr>]          set IP gateway"},
                    478:   {CMD_SERVER, "server", "[<addr>]           set server IP address"},
                    479:   {CMD_FILE, "file", "[<name>]             set boot file name"},
                    480:   {CMD_TFTP,   "tftp",         "                     TFTP download"},
                    481:   {CMD_DEBUG, "debug", "                    enter kernel debugger at boot"},
                    482:   {CMD_SINGLE, "single", "                   enter single user at boot"},
                    483: };
                    484: 
                    485: #define ARGVECSIZE 100
                    486: 
                    487: /*
                    488:  * A very simple and terse monitor
                    489:  */
                    490: static void
                    491: Monitor(void) {
                    492:   char *argv[ARGVECSIZE];
                    493:   static char file_name[MAX_FILE_NAME_LEN+1] = "default.bsd386";
                    494:   int loaded, argc;
                    495:   int i;
                    496:   int token;
                    497:   static ipaddr_t ip_servaddr = IP_ANYADDR;
                    498: 
                    499:   loaded = 0;
                    500:   printf("\n"
                    501: #ifdef USE_BOOTP
                    502:         "BOOTP/"
                    503: #endif
                    504: #ifdef USE_RARP
                    505:         "RARP/"
                    506: #endif
                    507:         "TFTP monitor mode\n");
                    508:   for (;;) {
                    509:     char filename[MAX_FILE_NAME_LEN+1];
                    510:     ipaddr_t gateway;
                    511:     printf("ethernet boot monitor: ");
                    512:     if ((argc = GetLine(argv, ARGVECSIZE)) > 0) {
                    513: 
                    514:       for (token = -1, i = 0; i < nelt(commands); i++) {
                    515:        if (strcmp(argv[0], commands[i].cmd_name) == 0) {
                    516:          token = commands[i].cmd_token;
                    517:          break;
                    518:        }
                    519:       }
                    520:       switch (token) {
                    521:       case CMD_HELP:
                    522:        for (i = 0; i < nelt(commands); i++)
                    523:          printf("%s %s\n", commands[i].cmd_name, commands[i].cmd_help);
                    524:        break;
                    525:       case CMD_RESET:
                    526:        PktInit();
                    527:        EtherReset();
                    528:        break;
                    529:       case CMD_REBOOT:
                    530:        EtherStop();
                    531:        ResetCpu();
                    532:        break;
                    533:       case CMD_DISKBOOT:
                    534:        EtherStop();
                    535:        exit(0);
                    536:        break;
                    537:       case CMD_AUTO:
                    538:        return;
                    539:       case CMD_WHO:
                    540:        (void) GetIpAddress(&ip_servaddr, &ip_myaddr, &gateway, filename);
                    541:        break;
                    542:       case CMD_ADDRESS:
                    543:        if (argc != 2) {
                    544:          printf("My IP address is ");
                    545:          IpPrintAddr(ip_myaddr);
                    546:          printf("\n");
                    547:        } else
                    548:          ip_myaddr = IpConvertAddr(argv[1]);
                    549:        break;
                    550:       case CMD_SERVER:
                    551:        if (argc != 2) {
                    552:          printf("Server's IP address is ");
                    553:          IpPrintAddr(ip_servaddr);
                    554:          printf("\n");
                    555:        } else
                    556:          ip_servaddr = IpConvertAddr(argv[1]);
                    557:        break;
                    558:       case CMD_FILE:
                    559:        if (argc != 2) {
                    560:          printf("File name is \"%s\"\n", file_name);
                    561:        } else
                    562:          strncpy(file_name, argv[1], MAX_FILE_NAME_LEN);
                    563:        break;
                    564:       case CMD_GATEWAY:
                    565:        if (argc != 2) {
                    566:          printf("Gateway IP address is ");
                    567:          IpPrintAddr(ip_gateway);
                    568:          printf("\n");
                    569:        } else
                    570:          ip_gateway = IpConvertAddr(argv[1]);
                    571:        break;
                    572:       case CMD_DEBUG:
                    573:        howto ^= RB_KDB;
                    574:        break;
                    575:       case CMD_SINGLE:
                    576:        howto ^= RB_SINGLE;
                    577:        break;
                    578:       case CMD_TFTP:
                    579:        if (ip_myaddr == IP_ANYADDR) {
                    580:          printf("This machine's IP address must be set first.\n");
                    581:          goto complain;
                    582:        }
                    583:        loaded = LoadProgFromServer(ip_servaddr, ip_gateway, file_name);
                    584:        printf("File could not be loaded, giving up.\n");
                    585:        break;
                    586:       default:
                    587:        goto complain;
                    588:       }
                    589:     } else
                    590:     complain:
                    591:       printf("Invalid or incorrect command. Type \"help\" for help.\n");
                    592:   }
                    593: }
                    594: 
                    595: static jmp_buf jmp_env;
                    596: 
                    597: void
                    598: HandleKbdAttn(void) {
                    599:   if (IsKbdCharReady())
                    600:     if (getc() == 0x1b) {
                    601:       EtherReset();
                    602:       PktInit();
                    603:       longjmp(jmp_env, 1);
                    604:     }
                    605: }
                    606: 
                    607: int time_zero;
                    608: 
                    609: void
                    610: main(void) {
                    611: 
                    612:   extern char edata[], end[];
                    613:   char volatile * volatile p;
                    614: 
                    615:   /* clear bss */
                    616:   for (p = edata; p < end; p++)
                    617:     *p = 0;
                    618: 
                    619:   printf(
                    620: #ifdef USE_BOOTP
                    621:         "BOOTP/"
                    622: #endif
                    623: #ifdef USE_RARP
                    624:         "RARP/"
                    625: #endif
                    626:         "TFTP bootstrap loader @0x%x: %d/%d k of memory. ^] for attn.\n",
                    627:         work_area_org,
                    628:         GetMemSize(0),
                    629:         GetMemSize(1));
                    630: 
                    631:   gateA20();
                    632: 
                    633:   PktInit();
                    634:   if (!EtherInit()) {
                    635:     printf("No ethernet board found\n");
                    636:     exit(1);
                    637:   }
                    638:   srand((time_zero=timer()) ^ eth_myaddr[5]);
                    639: 
                    640:   printf("Ethernet address is ");
                    641:   EtherPrintAddr(eth_myaddr);
                    642:   printf("\n");
                    643: 
                    644:   for (;;) {
                    645:     if (setjmp(jmp_env))
                    646:       Monitor();
                    647:     else {
                    648:       TryToLoadSomething();
                    649:     }
                    650:   }
                    651: }
                    652: 
                    653: #ifdef __GNUC__
                    654: void
                    655: __main(void) {
                    656: }
                    657: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.