Annotation of Net2/arch/i386/netboot/main.c, revision 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.