您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. /**************************************************************************
  2. ETHERBOOT - BOOTP/TFTP Bootstrap Program
  3. Author: Martin Renters
  4. Date: Dec/93
  5. Literature dealing with the network protocols:
  6. ARP - RFC826
  7. RARP - RFC903
  8. UDP - RFC768
  9. BOOTP - RFC951, RFC2132 (vendor extensions)
  10. DHCP - RFC2131, RFC2132 (options)
  11. TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
  12. RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
  13. NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
  14. **************************************************************************/
  15. /* #define MDEBUG */
  16. #include "etherboot.h"
  17. #include "nic.h"
  18. int jmp_bootmenu[10];
  19. struct arptable_t arptable[MAX_ARP];
  20. const char *kernel;
  21. char kernel_buf[128];
  22. struct rom_info rom;
  23. #ifdef IMAGE_MENU
  24. static char *imagelist[RFC1533_VENDOR_NUMOFIMG];
  25. static int useimagemenu;
  26. int menutmo,menudefault;
  27. unsigned char *defparams = NULL;
  28. int defparams_max = 0;
  29. #endif
  30. #ifdef MOTD
  31. char *motd[RFC1533_VENDOR_NUMOFMOTD];
  32. #endif
  33. #ifdef IMAGE_FREEBSD
  34. int freebsd_howto = 0;
  35. #endif
  36. int vendorext_isvalid;
  37. char config_buffer[TFTP_MAX_PACKET+1]; /* +1 for null byte */
  38. unsigned long netmask;
  39. char *hostname = "";
  40. int hostnamelen = 0;
  41. #if defined(ETHERBOOT16) || defined(INTERNAL_BOOTP_DATA)
  42. struct bootpd_t bootp_data;
  43. #endif
  44. unsigned long xid;
  45. unsigned char *end_of_rfc1533 = NULL;
  46. #ifndef NO_DHCP_SUPPORT
  47. int dhcp_reply;
  48. in_addr dhcp_server = { 0L };
  49. in_addr dhcp_addr = { 0L };
  50. #endif /* NO_DHCP_SUPPORT */
  51. unsigned char vendorext_magic[] = {0xE4,0x45,0x74,0x68}; /* äEth */
  52. #ifdef NO_DHCP_SUPPORT
  53. char rfc1533_cookie[5] = { RFC1533_COOKIE, RFC1533_END };
  54. #else
  55. char rfc1533_cookie[] = { RFC1533_COOKIE};
  56. char rfc1533_end[]={RFC1533_END };
  57. static const char dhcpdiscover[]={
  58. RFC2132_MSG_TYPE,1,DHCPDISCOVER,
  59. RFC2132_MAX_SIZE,2, /* request as much as we can */
  60. sizeof(struct bootpd_t) / 256, sizeof(struct bootpd_t) % 256,
  61. RFC2132_PARAM_LIST,4,RFC1533_NETMASK,RFC1533_GATEWAY,
  62. RFC1533_HOSTNAME
  63. };
  64. static const char dhcprequest []={
  65. RFC2132_MSG_TYPE,1,DHCPREQUEST,
  66. RFC2132_SRV_ID,4,0,0,0,0,
  67. RFC2132_REQ_ADDR,4,0,0,0,0,
  68. RFC2132_MAX_SIZE,2, /* request as much as we can */
  69. sizeof(struct bootpd_t) / 256, sizeof(struct bootpd_t) % 256,
  70. /* request parameters */
  71. RFC2132_PARAM_LIST,
  72. #ifdef IMAGE_FREEBSD
  73. /* 4 standard + 6 vendortags + 8 motd + 16 menu items */
  74. 4 + 6 + 8 + 16,
  75. #else
  76. /* 4 standard + 5 vendortags + 8 motd + 16 menu items */
  77. 4 + 5 + 8 + 16,
  78. #endif
  79. /* Standard parameters */
  80. RFC1533_NETMASK, RFC1533_GATEWAY,
  81. RFC1533_HOSTNAME,
  82. RFC1533_ROOTPATH, /* only passed to the booted image */
  83. /* Etherboot vendortags */
  84. RFC1533_VENDOR_MAGIC,
  85. RFC1533_VENDOR_ADDPARM,
  86. RFC1533_VENDOR_ETHDEV,
  87. #ifdef IMAGE_FREEBSD
  88. RFC1533_VENDOR_HOWTO,
  89. #endif
  90. RFC1533_VENDOR_MNUOPTS, RFC1533_VENDOR_SELECTION,
  91. /* 8 MOTD entries */
  92. RFC1533_VENDOR_MOTD,
  93. RFC1533_VENDOR_MOTD+1,
  94. RFC1533_VENDOR_MOTD+2,
  95. RFC1533_VENDOR_MOTD+3,
  96. RFC1533_VENDOR_MOTD+4,
  97. RFC1533_VENDOR_MOTD+5,
  98. RFC1533_VENDOR_MOTD+6,
  99. RFC1533_VENDOR_MOTD+7,
  100. /* 16 image entries */
  101. RFC1533_VENDOR_IMG,
  102. RFC1533_VENDOR_IMG+1,
  103. RFC1533_VENDOR_IMG+2,
  104. RFC1533_VENDOR_IMG+3,
  105. RFC1533_VENDOR_IMG+4,
  106. RFC1533_VENDOR_IMG+5,
  107. RFC1533_VENDOR_IMG+6,
  108. RFC1533_VENDOR_IMG+7,
  109. RFC1533_VENDOR_IMG+8,
  110. RFC1533_VENDOR_IMG+9,
  111. RFC1533_VENDOR_IMG+10,
  112. RFC1533_VENDOR_IMG+11,
  113. RFC1533_VENDOR_IMG+12,
  114. RFC1533_VENDOR_IMG+13,
  115. RFC1533_VENDOR_IMG+14,
  116. RFC1533_VENDOR_IMG+15,
  117. };
  118. #endif /* NO_DHCP_SUPPORT */
  119. static const char broadcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
  120. /**************************************************************************
  121. MAIN - Kick off routine
  122. **************************************************************************/
  123. int main(void)
  124. {
  125. char *p;
  126. static int card_retries = 0;
  127. int i;
  128. for (p=_edata; p<_end; p++)
  129. *p = 0; /* Zero BSS */
  130. #ifdef CONSOLE_SERIAL
  131. (void)serial_init();
  132. #endif
  133. #ifdef DELIMITERLINES
  134. for (i=0; i<80; i++) putchar('=');
  135. #endif
  136. #ifdef ETHERBOOT32
  137. rom = *(struct rom_info *)ROM_INFO_LOCATION;
  138. printf("ROM segment %#x length %#x reloc %#x\n", rom.rom_segment,
  139. rom.rom_length << 1, ((unsigned long)_start) >> 4);
  140. #endif
  141. #ifdef ETHERBOOT16
  142. fmemcpy(&rom, (Address)ROM_INFO_LOCATION, sizeof(rom));
  143. printf("ROM segment %#x length %#x\n", rom.rom_segment,
  144. rom.rom_length << 1);
  145. #endif
  146. #ifdef ASK_BOOT
  147. while (1) {
  148. int c;
  149. unsigned long time;
  150. printf(ASK_PROMPT);
  151. #if ASK_BOOT > 0
  152. for (time = currticks() + ASK_BOOT*TICKS_PER_SEC; !iskey(); )
  153. if (currticks() > time) {
  154. c = ANS_DEFAULT;
  155. goto done;
  156. }
  157. #endif
  158. c = getchar();
  159. if ((c >= 'a') && (c <= 'z')) c &= 0x5F;
  160. if (c == '\n') c = ANS_DEFAULT;
  161. done:
  162. if ((c >= ' ') && (c <= '~')) putchar(c);
  163. putchar('\n');
  164. if (c == ANS_LOCAL)
  165. exit(0);
  166. if (c == ANS_NETWORK)
  167. break;
  168. }
  169. #endif
  170. #if (TRY_FLOPPY_FIRST > 0) && defined(FLOPPY)
  171. disk_init();
  172. printf("Trying floppy");
  173. for (i = TRY_FLOPPY_FIRST; i-- > 0; ) {
  174. putchar('.');
  175. if (disk_read(0, 0, 0, 0, ((char *) FLOPPY_BOOT_LOCATION)) != 0x8000) {
  176. printf("using floppy\n");
  177. exit(0);
  178. }
  179. }
  180. printf("no floppy\n");
  181. #endif /* TRY_FLOPPY_FIRST && FLOPPY */
  182. print_config();
  183. gateA20_set();
  184. #ifdef EMERGENCYDISKBOOT
  185. if (!eth_probe()) {
  186. printf("No adapter found\n");
  187. exit(0);
  188. }
  189. #else
  190. while (!eth_probe()) {
  191. printf("No adapter found");
  192. if (!setjmp(jmp_bootmenu))
  193. rfc951_sleep(++card_retries);
  194. }
  195. #endif
  196. kernel = DEFAULT_BOOTFILE;
  197. while (1) {
  198. if ((i = setjmp(jmp_bootmenu)) != 0) {
  199. #if defined(ANSIESC) && defined(CONSOLE_CRT)
  200. ansi_reset();
  201. #endif
  202. bootmenu(--i);
  203. } else {
  204. load();
  205. }
  206. #if defined(ANSIESC) && defined(CONSOLE_CRT)
  207. ansi_reset();
  208. #endif
  209. }
  210. }
  211. /**************************************************************************
  212. LOADKERNEL - Try to load kernel image
  213. **************************************************************************/
  214. #ifndef FLOPPY
  215. #define loadkernel(s) download((s),downloadkernel)
  216. #else
  217. static int loadkernel(const char *fname)
  218. {
  219. if (!memcmp(fname,"/dev/",5) && fname[6] == 'd') {
  220. int dev, part = 0;
  221. if (fname[5] == 'f') {
  222. if ((dev = fname[7] - '0') < 0 || dev > 3)
  223. goto nodisk; }
  224. else if (fname[5] == 'h' || fname[5] == 's') {
  225. if ((dev = 0x80 + fname[7] - 'a') < 0x80 || dev > 0x83)
  226. goto nodisk;
  227. if (fname[8]) {
  228. part = fname[8] - '0';
  229. if (fname[9])
  230. part = 10*part + fname[9] - '0'; }
  231. /* bootdisk cannot cope with more than eight partitions */
  232. if (part < 0 || part > 8)
  233. goto nodisk; }
  234. else
  235. goto nodisk;
  236. return(bootdisk(dev,part)); }
  237. nodisk:
  238. return download(fname, downloadkernel);
  239. }
  240. #endif
  241. /**************************************************************************
  242. LOAD - Try to get booted
  243. **************************************************************************/
  244. void load()
  245. {
  246. static int bootp_completed = 0;
  247. /* Find a server to get BOOTP reply from */
  248. if (!bootp_completed ||
  249. !arptable[ARP_CLIENT].ipaddr.s_addr || !arptable[ARP_SERVER].ipaddr.s_addr) {
  250. retry:
  251. bootp_completed = 0;
  252. #ifdef RARP_NOT_BOOTP
  253. printf("Searching for server (RARP)...\n");
  254. #else
  255. #ifndef NO_DHCP_SUPPORT
  256. printf("Searching for server (DHCP)...\n");
  257. #else
  258. printf("Searching for server (BOOTP)...\n");
  259. #endif
  260. #endif
  261. #ifdef RARP_NOT_BOOTP
  262. if (!rarp()) {
  263. #else
  264. if (!bootp()) {
  265. #endif
  266. printf("No Server found\n");
  267. #ifdef EMERGENCYDISKBOOT
  268. exit(0);
  269. #else
  270. goto retry;
  271. #endif
  272. }
  273. bootp_completed++;
  274. }
  275. printf("Me: %I, Server: %I",
  276. arptable[ARP_CLIENT].ipaddr.s_addr,
  277. arptable[ARP_SERVER].ipaddr.s_addr);
  278. if (BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr)
  279. printf(", Relay: %I",
  280. BOOTP_DATA_ADDR->bootp_reply.bp_giaddr.s_addr);
  281. if (arptable[ARP_GATEWAY].ipaddr.s_addr)
  282. printf(", Gateway %I", arptable[ARP_GATEWAY].ipaddr.s_addr);
  283. putchar('\n');
  284. #ifdef MDEBUG
  285. printf("\n=>>"); getchar();
  286. #endif
  287. #ifdef MOTD
  288. if (vendorext_isvalid)
  289. show_motd();
  290. #endif
  291. /* Now use TFTP to load file */
  292. #ifdef IMAGE_MENU
  293. if (vendorext_isvalid && useimagemenu) {
  294. selectImage(imagelist);
  295. bootp_completed = 0;
  296. }
  297. #endif
  298. #ifdef DOWNLOAD_PROTO_NFS
  299. rpc_init();
  300. #endif
  301. for (;;) {
  302. printf("Loading %s ",kernel);
  303. while (!loadkernel(kernel)) {
  304. printf("Unable to load file.\n");
  305. sleep(2); /* lay off server for a while */
  306. }
  307. }
  308. }
  309. /**************************************************************************
  310. DEFAULT_NETMASK - Return default netmask for IP address
  311. **************************************************************************/
  312. static inline unsigned long default_netmask(void)
  313. {
  314. int net = ntohl(arptable[ARP_CLIENT].ipaddr.s_addr) >> 24;
  315. if (net <= 127)
  316. return(htonl(0xff000000));
  317. else if (net < 192)
  318. return(htonl(0xffff0000));
  319. else
  320. return(htonl(0xffffff00));
  321. }
  322. /**************************************************************************
  323. UDP_TRANSMIT - Send a UDP datagram
  324. **************************************************************************/
  325. int udp_transmit(unsigned long destip, unsigned int srcsock,
  326. unsigned int destsock, int len, const void *buf)
  327. {
  328. struct iphdr *ip;
  329. struct udphdr *udp;
  330. struct arprequest arpreq;
  331. int arpentry, i;
  332. int retry;
  333. ip = (struct iphdr *)buf;
  334. udp = (struct udphdr *)((long)buf + sizeof(struct iphdr));
  335. ip->verhdrlen = 0x45;
  336. ip->service = 0;
  337. ip->len = htons(len);
  338. ip->ident = 0;
  339. ip->frags = 0;
  340. ip->ttl = 60;
  341. ip->protocol = IP_UDP;
  342. ip->chksum = 0;
  343. ip->src.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
  344. ip->dest.s_addr = destip;
  345. ip->chksum = ipchksum((unsigned short *)buf, sizeof(struct iphdr));
  346. udp->src = htons(srcsock);
  347. udp->dest = htons(destsock);
  348. udp->len = htons(len - sizeof(struct iphdr));
  349. udp->chksum = 0;
  350. if (destip == IP_BROADCAST) {
  351. eth_transmit(broadcast, IP, len, buf);
  352. } else {
  353. if (((destip & netmask) !=
  354. (arptable[ARP_CLIENT].ipaddr.s_addr & netmask)) &&
  355. arptable[ARP_GATEWAY].ipaddr.s_addr)
  356. destip = arptable[ARP_GATEWAY].ipaddr.s_addr;
  357. for(arpentry = 0; arpentry<MAX_ARP; arpentry++)
  358. if (arptable[arpentry].ipaddr.s_addr == destip) break;
  359. if (arpentry == MAX_ARP) {
  360. printf("%I is not in my arp table!\n", destip);
  361. return(0);
  362. }
  363. for (i = 0; i<ETHER_ADDR_SIZE; i++)
  364. if (arptable[arpentry].node[i]) break;
  365. if (i == ETHER_ADDR_SIZE) { /* Need to do arp request */
  366. arpreq.hwtype = htons(1);
  367. arpreq.protocol = htons(IP);
  368. arpreq.hwlen = ETHER_ADDR_SIZE;
  369. arpreq.protolen = 4;
  370. arpreq.opcode = htons(ARP_REQUEST);
  371. memcpy(arpreq.shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
  372. memcpy(arpreq.sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
  373. memset(arpreq.thwaddr, 0, ETHER_ADDR_SIZE);
  374. memcpy(arpreq.tipaddr, &destip, sizeof(in_addr));
  375. for (retry = 1; retry <= MAX_ARP_RETRIES; retry++) {
  376. eth_transmit(broadcast, ARP, sizeof(arpreq),
  377. &arpreq);
  378. if (await_reply(AWAIT_ARP, arpentry,
  379. arpreq.tipaddr, TIMEOUT)) goto xmit;
  380. rfc951_sleep(retry);
  381. /* We have slept for a while - the packet may
  382. * have arrived by now. If not, we have at
  383. * least some room in the Rx buffer for the
  384. * next reply. */
  385. if (await_reply(AWAIT_ARP, arpentry,
  386. arpreq.tipaddr, 0)) goto xmit;
  387. }
  388. return(0);
  389. }
  390. xmit:
  391. eth_transmit(arptable[arpentry].node, IP, len, buf);
  392. }
  393. return(1);
  394. }
  395. /**************************************************************************
  396. DOWNLOADKERNEL - Try to load file
  397. **************************************************************************/
  398. int downloadkernel(data, block, len, eof)
  399. unsigned char *data;
  400. int block, len, eof;
  401. {
  402. #ifdef SIZEINDICATOR
  403. static int rlen = 0;
  404. if (!(block % 4) || eof) {
  405. int size;
  406. size = ((block-1) * rlen + len) / 1024;
  407. putchar('\b');
  408. putchar('\b');
  409. putchar('\b');
  410. putchar('\b');
  411. putchar('0' + (size/1000)%10);
  412. putchar('0' + (size/100)%10);
  413. putchar('0' + (size/10)%10);
  414. putchar('0' + (size/1)%10);
  415. }
  416. #endif
  417. if (block == 1)
  418. {
  419. #ifdef SIZEINDICATOR
  420. rlen=len;
  421. #endif
  422. if (!eof && (
  423. #ifdef TAGGED_IMAGE
  424. *((unsigned long *)data) == 0x1B031336L ||
  425. #endif
  426. #ifdef ELF_IMAGE
  427. *((unsigned long *)data) == 0x464C457FL ||
  428. #endif
  429. #ifdef AOUT_IMAGE
  430. *((unsigned short *)data) == 0x010BL ||
  431. #endif
  432. ((unsigned short *)data)[255] == 0xAA55))
  433. {
  434. ;
  435. }
  436. else if (eof)
  437. {
  438. memcpy(config_buffer, data, len);
  439. config_buffer[len] = 0;
  440. return (1); /* done */
  441. }
  442. else
  443. {
  444. printf("error: not a tagged image\n");
  445. return(0); /* error */
  446. }
  447. }
  448. if (len != 0) {
  449. if (!os_download(block, data, len))
  450. return(0); /* error */
  451. }
  452. if (eof) {
  453. os_download(block+1, data, 0); /* does not return */
  454. return(0); /* error */
  455. }
  456. return(-1); /* there is more data */
  457. }
  458. #ifdef DOWNLOAD_PROTO_TFTP
  459. /**************************************************************************
  460. TFTP - Download extended BOOTP data, or kernel image
  461. **************************************************************************/
  462. int tftp(const char *name, int (*fnc)(unsigned char *, int, int, int))
  463. {
  464. int retry = 0;
  465. static unsigned short iport = 2000;
  466. unsigned short oport;
  467. unsigned short len, block = 0, prevblock = 0;
  468. int bcounter = 0;
  469. struct tftp_t *tr;
  470. struct tftp_t tp;
  471. int rc;
  472. int packetsize = TFTP_DEFAULTSIZE_PACKET;
  473. /* Clear out the Rx queue first. It contains nothing of interest,
  474. * except possibly ARP requests from the DHCP/TFTP server. We use
  475. * polling throughout Etherboot, so some time may have passed since we
  476. * last polled the receive queue, which may now be filled with
  477. * broadcast packets. This will cause the reply to the packets we are
  478. * about to send to be lost immediately. Not very clever. */
  479. await_reply(AWAIT_QDRAIN, 0, NULL, 0);
  480. tp.opcode = htons(TFTP_RRQ);
  481. len = (sprintf((char *)tp.u.rrq, "%s%coctet%cblksize%c%d",
  482. name, 0, 0, 0, TFTP_MAX_PACKET) - ((char *)&tp)) + 1;
  483. if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, ++iport,
  484. TFTP_PORT, len, &tp))
  485. return (0);
  486. for (;;)
  487. {
  488. #ifdef CONGESTED
  489. if (!await_reply(AWAIT_TFTP, iport, NULL, (block ? TFTP_REXMT : TIMEOUT)))
  490. #else
  491. if (!await_reply(AWAIT_TFTP, iport, NULL, TIMEOUT))
  492. #endif
  493. {
  494. if (!block && retry++ < MAX_TFTP_RETRIES)
  495. { /* maybe initial request was lost */
  496. rfc951_sleep(retry);
  497. if (!udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,
  498. ++iport, TFTP_PORT, len, &tp))
  499. return (0);
  500. continue;
  501. }
  502. #ifdef CONGESTED
  503. if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT))
  504. { /* we resend our last ack */
  505. #ifdef MDEBUG
  506. printf("<REXMT>\n");
  507. #endif
  508. udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,
  509. iport, oport,
  510. TFTP_MIN_PACKET, &tp);
  511. continue;
  512. }
  513. #endif
  514. break; /* timeout */
  515. }
  516. tr = (struct tftp_t *)&nic.packet[ETHER_HDR_SIZE];
  517. if (tr->opcode == ntohs(TFTP_ERROR))
  518. {
  519. printf("TFTP error %d (%s)\n",
  520. ntohs(tr->u.err.errcode),
  521. tr->u.err.errmsg);
  522. break;
  523. }
  524. if (tr->opcode == ntohs(TFTP_OACK)) {
  525. char *p = tr->u.oack.data, *e;
  526. if (prevblock) /* shouldn't happen */
  527. continue; /* ignore it */
  528. len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 2;
  529. if (len > TFTP_MAX_PACKET)
  530. goto noak;
  531. e = p + len;
  532. while (*p != '\000' && p < e) {
  533. if (!strcasecmp("blksize", p)) {
  534. p += 8;
  535. if ((packetsize = getdec(&p)) <
  536. TFTP_DEFAULTSIZE_PACKET)
  537. goto noak;
  538. while (p < e && *p) p++;
  539. if (p < e)
  540. p++;
  541. }
  542. else {
  543. noak:
  544. tp.opcode = htons(TFTP_ERROR);
  545. tp.u.err.errcode = 8;
  546. len = (sprintf((char *)tp.u.err.errmsg,
  547. "RFC1782 error")
  548. - ((char *)&tp)) + 1;
  549. udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr,
  550. iport, ntohs(tr->udp.src),
  551. len, &tp);
  552. return (0);
  553. }
  554. }
  555. if (p > e)
  556. goto noak;
  557. block = tp.u.ack.block = 0; /* this ensures, that */
  558. /* the packet does not get */
  559. /* processed as data! */
  560. }
  561. else if (tr->opcode == ntohs(TFTP_DATA)) {
  562. len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 4;
  563. if (len > packetsize) /* shouldn't happen */
  564. continue; /* ignore it */
  565. block = ntohs(tp.u.ack.block = tr->u.data.block); }
  566. else /* neither TFTP_OACK nor TFTP_DATA */
  567. break;
  568. if ((block || bcounter) && (block != prevblock+1)) {
  569. /* Block order should be continuous */
  570. tp.u.ack.block = htons(block = prevblock);
  571. }
  572. tp.opcode = htons(TFTP_ACK);
  573. oport = ntohs(tr->udp.src);
  574. udp_transmit(arptable[ARP_SERVER].ipaddr.s_addr, iport,
  575. oport, TFTP_MIN_PACKET, &tp); /* ack */
  576. if ((unsigned short)(block-prevblock) != 1) {
  577. /* Retransmission or OACK, don't process via callback
  578. * and don't change the value of prevblock. */
  579. continue;
  580. }
  581. prevblock = block;
  582. retry = 0; /* It's the right place to zero the timer? */
  583. if ((rc = fnc(tr->u.data.download,
  584. ++bcounter, len, len < packetsize)) >= 0)
  585. return(rc);
  586. if (len < packetsize) /* End of data */
  587. return (1);
  588. }
  589. return (0);
  590. }
  591. #endif /* DOWNLOAD_PROTO_TFTP */
  592. #ifdef RARP_NOT_BOOTP
  593. /**************************************************************************
  594. RARP - Get my IP address and load information
  595. **************************************************************************/
  596. int rarp()
  597. {
  598. int retry;
  599. /* arp and rarp requests share the same packet structure. */
  600. struct arprequest rarpreq;
  601. memset(&rarpreq, 0, sizeof(rarpreq));
  602. rarpreq.hwtype = htons(1);
  603. rarpreq.protocol = htons(IP);
  604. rarpreq.hwlen = ETHER_ADDR_SIZE;
  605. rarpreq.protolen = 4;
  606. rarpreq.opcode = htons(RARP_REQUEST);
  607. memcpy(&rarpreq.shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
  608. /* sipaddr is already zeroed out */
  609. memcpy(&rarpreq.thwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
  610. /* tipaddr is already zeroed out */
  611. for (retry = 0; retry < MAX_ARP_RETRIES; rfc951_sleep(++retry)) {
  612. eth_transmit(broadcast, RARP, sizeof(rarpreq), &rarpreq);
  613. if (await_reply(AWAIT_RARP, 0, rarpreq.shwaddr, TIMEOUT))
  614. break;
  615. }
  616. if (retry < MAX_ARP_RETRIES) {
  617. sprintf(kernel = kernel_buf, "/tftpboot/kernel.%I", arptable[ARP_CLIENT].ipaddr);
  618. return (1);
  619. }
  620. return (0);
  621. }
  622. #else
  623. /**************************************************************************
  624. BOOTP - Get my IP address and load information
  625. **************************************************************************/
  626. int bootp()
  627. {
  628. int retry;
  629. #ifndef NO_DHCP_SUPPORT
  630. int retry1;
  631. #endif /* NO_DHCP_SUPPORT */
  632. struct bootp_t bp;
  633. unsigned long starttime;
  634. #ifdef T509HACK
  635. int flag;
  636. flag = 1;
  637. #endif
  638. memset(&bp, 0, sizeof(struct bootp_t));
  639. bp.bp_op = BOOTP_REQUEST;
  640. bp.bp_htype = 1;
  641. bp.bp_hlen = ETHER_ADDR_SIZE;
  642. bp.bp_xid = xid = starttime = currticks();
  643. memcpy(bp.bp_hwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
  644. #ifdef NO_DHCP_SUPPORT
  645. memcpy(bp.bp_vend, rfc1533_cookie, 5); /* request RFC-style options */
  646. #else
  647. memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie); /* request RFC-style options */
  648. memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcpdiscover, sizeof dhcpdiscover);
  649. memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcpdiscover, rfc1533_end, sizeof rfc1533_end);
  650. #endif /* NO_DHCP_SUPPORT */
  651. for (retry = 0; retry < MAX_BOOTP_RETRIES; ) {
  652. /* Clear out the Rx queue first. It contains nothing of
  653. * interest, except possibly ARP requests from the DHCP/TFTP
  654. * server. We use polling throughout Etherboot, so some time
  655. * may have passed since we last polled the receive queue,
  656. * which may now be filled with broadcast packets. This will
  657. * cause the reply to the packets we are about to send to be
  658. * lost immediately. Not very clever. */
  659. await_reply(AWAIT_QDRAIN, 0, NULL, 0);
  660. udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
  661. sizeof(struct bootp_t), &bp);
  662. #ifdef T509HACK
  663. if (flag) {
  664. flag--;
  665. } else {
  666. if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))
  667. return(1);
  668. rfc951_sleep(++retry);
  669. }
  670. #else
  671. #ifdef NO_DHCP_SUPPORT
  672. if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))
  673. #else
  674. if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT)){
  675. if (dhcp_reply==DHCPOFFER){
  676. dhcp_reply=0;
  677. memcpy(bp.bp_vend, rfc1533_cookie, sizeof rfc1533_cookie);
  678. memcpy(bp.bp_vend+sizeof rfc1533_cookie, dhcprequest, sizeof dhcprequest);
  679. memcpy(bp.bp_vend+sizeof rfc1533_cookie +sizeof dhcprequest, rfc1533_end, sizeof rfc1533_end);
  680. memcpy(bp.bp_vend+9, &dhcp_server, sizeof(in_addr));
  681. memcpy(bp.bp_vend+15, &dhcp_addr, sizeof(in_addr));
  682. for (retry1 = 0; retry1 < MAX_BOOTP_RETRIES;) {
  683. udp_transmit(IP_BROADCAST, BOOTP_CLIENT, BOOTP_SERVER,
  684. sizeof(struct bootp_t), &bp);
  685. dhcp_reply=0;
  686. if (await_reply(AWAIT_BOOTP, 0, NULL, TIMEOUT))
  687. if (dhcp_reply==DHCPACK)
  688. return(1);
  689. rfc951_sleep(++retry1);
  690. }
  691. } else
  692. #endif /* NO_DHCP_SUPPORT */
  693. return(1);
  694. #ifndef NO_DHCP_SUPPORT
  695. }
  696. rfc951_sleep(++retry);
  697. #endif /* NO_DHCP_SUPPORT */
  698. #endif
  699. bp.bp_secs = htons((currticks()-starttime)/20);
  700. }
  701. return(0);
  702. }
  703. #endif /* RARP_NOT_BOOTP */
  704. /**************************************************************************
  705. AWAIT_REPLY - Wait until we get a response for our request
  706. **************************************************************************/
  707. int await_reply(int type, int ival, void *ptr, int timeout)
  708. {
  709. unsigned long time;
  710. struct iphdr *ip;
  711. struct udphdr *udp;
  712. struct arprequest *arpreply;
  713. struct bootp_t *bootpreply;
  714. struct rpc_t *rpc;
  715. unsigned short ptype;
  716. unsigned int protohdrlen = ETHER_HDR_SIZE + sizeof(struct iphdr) +
  717. sizeof(struct udphdr);
  718. time = timeout + currticks();
  719. /* The timeout check is done below. The timeout is only checked if
  720. * there is no packet in the Rx queue. This assumes that eth_poll()
  721. * needs a negligible amount of time. */
  722. for (;;) {
  723. if (eth_poll()) { /* We have something! */
  724. /* Check for ARP - No IP hdr */
  725. if (nic.packetlen >= ETHER_HDR_SIZE) {
  726. ptype = ((unsigned short) nic.packet[12]) << 8
  727. | ((unsigned short) nic.packet[13]);
  728. } else continue; /* what else could we do with it? */
  729. if ((nic.packetlen >= ETHER_HDR_SIZE +
  730. sizeof(struct arprequest)) &&
  731. (ptype == ARP) ) {
  732. unsigned long tmp;
  733. arpreply = (struct arprequest *)
  734. &nic.packet[ETHER_HDR_SIZE];
  735. if ((arpreply->opcode == ntohs(ARP_REPLY)) &&
  736. !memcmp(arpreply->sipaddr, ptr, sizeof(in_addr)) &&
  737. (type == AWAIT_ARP)) {
  738. memcpy(arptable[ival].node, arpreply->shwaddr, ETHER_ADDR_SIZE);
  739. return(1);
  740. }
  741. memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
  742. if ((arpreply->opcode == ntohs(ARP_REQUEST)) &&
  743. (tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
  744. arpreply->opcode = htons(ARP_REPLY);
  745. memcpy(arpreply->tipaddr, arpreply->sipaddr, sizeof(in_addr));
  746. memcpy(arpreply->thwaddr, arpreply->shwaddr, ETHER_ADDR_SIZE);
  747. memcpy(arpreply->sipaddr, &arptable[ARP_CLIENT].ipaddr, sizeof(in_addr));
  748. memcpy(arpreply->shwaddr, arptable[ARP_CLIENT].node, ETHER_ADDR_SIZE);
  749. eth_transmit(arpreply->thwaddr, ARP,
  750. sizeof(struct arprequest),
  751. arpreply);
  752. #ifdef MDEBUG
  753. memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
  754. printf("Sent ARP reply to: %I\n",tmp);
  755. #endif MDEBUG
  756. }
  757. continue;
  758. }
  759. if (type == AWAIT_QDRAIN) {
  760. continue;
  761. }
  762. /* Check for RARP - No IP hdr */
  763. if ((type == AWAIT_RARP) &&
  764. (nic.packetlen >= ETHER_HDR_SIZE +
  765. sizeof(struct arprequest)) &&
  766. (ptype == RARP)) {
  767. arpreply = (struct arprequest *)
  768. &nic.packet[ETHER_HDR_SIZE];
  769. if ((arpreply->opcode == ntohs(RARP_REPLY)) &&
  770. !memcmp(arpreply->thwaddr, ptr, ETHER_ADDR_SIZE)) {
  771. memcpy(arptable[ARP_SERVER].node, arpreply->shwaddr, ETHER_ADDR_SIZE);
  772. memcpy(& arptable[ARP_SERVER].ipaddr, arpreply->sipaddr, sizeof(in_addr));
  773. memcpy(& arptable[ARP_CLIENT].ipaddr, arpreply->tipaddr, sizeof(in_addr));
  774. return(1);
  775. }
  776. continue;
  777. }
  778. /* Anything else has IP header */
  779. if ((nic.packetlen < protohdrlen) ||
  780. (ptype != IP) ) continue;
  781. ip = (struct iphdr *)&nic.packet[ETHER_HDR_SIZE];
  782. if ((ip->verhdrlen != 0x45) ||
  783. ipchksum((unsigned short *)ip, sizeof(struct iphdr)) ||
  784. (ip->protocol != IP_UDP)) continue;
  785. udp = (struct udphdr *)&nic.packet[ETHER_HDR_SIZE +
  786. sizeof(struct iphdr)];
  787. /* BOOTP ? */
  788. bootpreply = (struct bootp_t *)&nic.packet[ETHER_HDR_SIZE];
  789. if ((type == AWAIT_BOOTP) &&
  790. (nic.packetlen >= (ETHER_HDR_SIZE +
  791. #ifdef NO_DHCP_SUPPORT
  792. sizeof(struct bootp_t))) &&
  793. #else
  794. sizeof(struct bootp_t))-DHCP_OPT_LEN) &&
  795. #endif /* NO_DHCP_SUPPORT */
  796. (ntohs(udp->dest) == BOOTP_CLIENT) &&
  797. (bootpreply->bp_op == BOOTP_REPLY) &&
  798. (bootpreply->bp_xid == xid)) {
  799. arptable[ARP_CLIENT].ipaddr.s_addr =
  800. bootpreply->bp_yiaddr.s_addr;
  801. #ifndef NO_DHCP_SUPPORT
  802. dhcp_addr.s_addr = bootpreply->bp_yiaddr.s_addr;
  803. #endif /* NO_DHCP_SUPPORT */
  804. netmask = default_netmask();
  805. arptable[ARP_SERVER].ipaddr.s_addr =
  806. bootpreply->bp_siaddr.s_addr;
  807. memset(arptable[ARP_SERVER].node, 0, ETHER_ADDR_SIZE); /* Kill arp */
  808. arptable[ARP_GATEWAY].ipaddr.s_addr =
  809. bootpreply->bp_giaddr.s_addr;
  810. memset(arptable[ARP_GATEWAY].node, 0, ETHER_ADDR_SIZE); /* Kill arp */
  811. if (bootpreply->bp_file[0]) {
  812. memcpy(kernel_buf, bootpreply->bp_file, 128);
  813. kernel = kernel_buf;
  814. }
  815. memcpy((char *)BOOTP_DATA_ADDR, (char *)bootpreply, sizeof(struct bootpd_t));
  816. decode_rfc1533(BOOTP_DATA_ADDR->bootp_reply.bp_vend,
  817. #ifdef NO_DHCP_SUPPORT
  818. 0, BOOTP_VENDOR_LEN + MAX_BOOTP_EXTLEN, 1);
  819. #else
  820. 0, DHCP_OPT_LEN + MAX_BOOTP_EXTLEN, 1);
  821. #endif /* NO_DHCP_SUPPORT */
  822. return(1);
  823. }
  824. #ifdef DOWNLOAD_PROTO_TFTP
  825. /* TFTP ? */
  826. if ((type == AWAIT_TFTP) &&
  827. (ntohs(udp->dest) == ival)) return(1);
  828. #endif /* DOWNLOAD_PROTO_TFTP */
  829. #ifdef DOWNLOAD_PROTO_NFS
  830. /* RPC ? */
  831. rpc = (struct rpc_t *)&nic.packet[ETHER_HDR_SIZE];
  832. if ((type == AWAIT_RPC) &&
  833. (ntohs(udp->dest) == ival) &&
  834. (*(unsigned long *)ptr == ntohl(rpc->u.reply.id)) &&
  835. (ntohl(rpc->u.reply.type) == MSG_REPLY)) {
  836. return (1);
  837. }
  838. #endif /* DOWNLOAD_PROTO_NFS */
  839. } else {
  840. /* Check for abort key only if the Rx queue is empty -
  841. * as long as we have something to process, don't
  842. * assume that something failed. It is unlikely that
  843. * we have no processing time left between packets. */
  844. if (iskey() && (getchar() == ESC))
  845. #ifdef EMERGENCYDISKBOOT
  846. exit(0);
  847. #else
  848. longjmp(jmp_bootmenu,1);
  849. #endif
  850. /* Do the timeout after at least a full queue walk. */
  851. if ((timeout == 0) || (currticks() > time)) {
  852. break;
  853. }
  854. }
  855. }
  856. return(0);
  857. }
  858. /**************************************************************************
  859. DECODE_RFC1533 - Decodes RFC1533 header
  860. **************************************************************************/
  861. int decode_rfc1533(p, block, len, eof)
  862. register unsigned char *p;
  863. int block, len, eof;
  864. {
  865. static unsigned char *extdata = NULL, *extend = NULL;
  866. unsigned char *extpath = NULL;
  867. unsigned char *endp;
  868. if (block == 0) {
  869. #ifdef IMAGE_MENU
  870. memset(imagelist, 0, sizeof(imagelist));
  871. menudefault = useimagemenu = 0;
  872. menutmo = -1;
  873. #endif
  874. #ifdef MOTD
  875. memset(motd, 0, sizeof(motd));
  876. #endif
  877. end_of_rfc1533 = NULL;
  878. vendorext_isvalid = 0;
  879. if (memcmp(p, rfc1533_cookie, 4))
  880. return(0); /* no RFC 1533 header found */
  881. p += 4;
  882. endp = p + len; }
  883. else {
  884. if (block == 1) {
  885. if (memcmp(p, rfc1533_cookie, 4))
  886. return(0); /* no RFC 1533 header found */
  887. p += 4;
  888. len -= 4; }
  889. if (extend + len <= (unsigned char *)&(BOOTP_DATA_ADDR->bootp_extension[MAX_BOOTP_EXTLEN])) {
  890. memcpy(extend, p, len);
  891. extend += len;
  892. } else {
  893. printf("Overflow in vendor data buffer! Aborting...\n");
  894. *extdata = RFC1533_END;
  895. return(0);
  896. }
  897. p = extdata; endp = extend;
  898. }
  899. if (eof) {
  900. while(p < endp) {
  901. unsigned char c = *p;
  902. if (c == RFC1533_PAD) {p++; continue;}
  903. else if (c == RFC1533_END) {
  904. end_of_rfc1533 = endp = p; continue; }
  905. else if (c == RFC1533_NETMASK) {memcpy(&netmask, p+2, sizeof(in_addr));}
  906. else if (c == RFC1533_GATEWAY) {
  907. /* This is a little simplistic, but it will
  908. usually be sufficient.
  909. Take only the first entry */
  910. if (TAG_LEN(p) >= sizeof(in_addr))
  911. memcpy(&arptable[ARP_GATEWAY].ipaddr, p+2, sizeof(in_addr));
  912. }
  913. else if (c == RFC1533_EXTENSIONPATH)
  914. extpath = p;
  915. #ifndef NO_DHCP_SUPPORT
  916. else if (c == RFC2132_MSG_TYPE)
  917. { dhcp_reply=*(p+2);
  918. }
  919. else if (c == RFC2132_SRV_ID)
  920. {
  921. memcpy(&dhcp_server, p+2, sizeof(in_addr));
  922. }
  923. #endif /* NO_DHCP_SUPPORT */
  924. else if (c == RFC1533_HOSTNAME)
  925. {
  926. hostname = p + 2;
  927. hostnamelen = *(p + 1);
  928. }
  929. else if (c == RFC1533_VENDOR_MAGIC
  930. #ifndef IMAGE_FREEBSD /* since FreeBSD uses tag 128 for swap definition */
  931. && TAG_LEN(p) >= 6 &&
  932. !memcmp(p+2,vendorext_magic,4) &&
  933. p[6] == RFC1533_VENDOR_MAJOR
  934. #endif
  935. )
  936. vendorext_isvalid++;
  937. #ifdef IMAGE_FREEBSD
  938. else if (c == RFC1533_VENDOR_HOWTO) {
  939. freebsd_howto = ((p[2]*256+p[3])*256+p[4])*256+p[5];
  940. }
  941. #endif
  942. #ifdef IMAGE_MENU
  943. else if (c == RFC1533_VENDOR_MNUOPTS) {
  944. parse_menuopts(p+2, TAG_LEN(p));
  945. }
  946. else if (c >= RFC1533_VENDOR_IMG &&
  947. c<RFC1533_VENDOR_IMG+RFC1533_VENDOR_NUMOFIMG){
  948. imagelist[c - RFC1533_VENDOR_IMG] = p;
  949. useimagemenu++;
  950. }
  951. #endif
  952. #ifdef MOTD
  953. else if (c >= RFC1533_VENDOR_MOTD &&
  954. c < RFC1533_VENDOR_MOTD +
  955. RFC1533_VENDOR_NUMOFMOTD)
  956. motd[c - RFC1533_VENDOR_MOTD] = p;
  957. #endif
  958. else {
  959. #if 0
  960. unsigned char *q;
  961. printf("Unknown RFC1533-tag ");
  962. for(q=p;q<p+2+TAG_LEN(p);q++)
  963. printf("%x ",*q);
  964. putchar('\n');
  965. #endif
  966. }
  967. p += TAG_LEN(p) + 2;
  968. }
  969. extdata = extend = endp;
  970. if (block == 0 && extpath != NULL) {
  971. char fname[64];
  972. memcpy(fname, extpath+2, TAG_LEN(extpath));
  973. fname[(int)TAG_LEN(extpath)] = '\000';
  974. printf("Loading BOOTP-extension file: %s\n",fname);
  975. download(fname,decode_rfc1533);
  976. }
  977. }
  978. return(-1); /* proceed with next block */
  979. }
  980. /**************************************************************************
  981. IPCHKSUM - Checksum IP Header
  982. **************************************************************************/
  983. unsigned short ipchksum(ip, len)
  984. register unsigned short *ip;
  985. register int len;
  986. {
  987. unsigned long sum = 0;
  988. len >>= 1;
  989. while (len--) {
  990. sum += *(ip++);
  991. if (sum > 0xFFFF)
  992. sum -= 0xFFFF;
  993. }
  994. return((~sum) & 0x0000FFFF);
  995. }
  996. /**************************************************************************
  997. RFC951_SLEEP - sleep for expotentially longer times
  998. **************************************************************************/
  999. void rfc951_sleep(exp)
  1000. int exp;
  1001. {
  1002. static long seed = 0;
  1003. long q;
  1004. unsigned long tmo;
  1005. #ifdef BACKOFF_LIMIT
  1006. if (exp > BACKOFF_LIMIT)
  1007. exp = BACKOFF_LIMIT;
  1008. #endif
  1009. if (!seed) /* Initialize linear congruential generator */
  1010. seed = currticks() + *(long *)&arptable[ARP_CLIENT].node
  1011. + ((short *)arptable[ARP_CLIENT].node)[2];
  1012. /* simplified version of the LCG given in Bruce Scheier's
  1013. "Applied Cryptography" */
  1014. q = seed/53668;
  1015. if ((seed = 40014*(seed-53668*q) - 12211*q) < 0) seed += 2147483563l;
  1016. /* compute mask */
  1017. for (tmo = 63; tmo <= 60*TICKS_PER_SEC && --exp > 0; tmo = 2*tmo+1);
  1018. /* sleep */
  1019. printf("<sleep>\n");
  1020. for (tmo = (tmo&seed)+currticks(); currticks() < tmo; )
  1021. if (iskey() && (getchar() == ESC)) longjmp(jmp_bootmenu,1);
  1022. return;
  1023. }
  1024. /**************************************************************************
  1025. CLEANUP_NET - shut down networking
  1026. **************************************************************************/
  1027. void cleanup_net(void)
  1028. {
  1029. #ifdef DOWNLOAD_PROTO_NFS
  1030. nfs_umountall(ARP_SERVER);
  1031. #endif
  1032. eth_disable();
  1033. eth_reset();
  1034. }
  1035. /**************************************************************************
  1036. CLEANUP - shut down etherboot so that the OS may be called right away
  1037. **************************************************************************/
  1038. void cleanup(void)
  1039. {
  1040. #if defined(ANSIESC) && defined(CONSOLE_CRT)
  1041. ansi_reset();
  1042. #endif
  1043. }
  1044. /*
  1045. * Local variables:
  1046. * c-basic-offset: 8
  1047. * End:
  1048. */