|
@@ -15,6 +15,8 @@ Literature dealing with the network protocols:
|
15
|
15
|
|
16
|
16
|
**************************************************************************/
|
17
|
17
|
#include "etherboot.h"
|
|
18
|
+#include "console.h"
|
|
19
|
+#include "dev.h"
|
18
|
20
|
#include "nic.h"
|
19
|
21
|
#include "elf.h" /* FOR EM_CURRENT */
|
20
|
22
|
|
|
@@ -221,52 +223,6 @@ int vci_etherboot;
|
221
|
223
|
#endif
|
222
|
224
|
#endif /* NO_DHCP_SUPPORT */
|
223
|
225
|
|
224
|
|
-static int dummy(void *unused __unused)
|
225
|
|
-{
|
226
|
|
- return (0);
|
227
|
|
-}
|
228
|
|
-
|
229
|
|
-/* Careful. We need an aligned buffer to avoid problems on machines
|
230
|
|
- * that care about alignment. To trivally align the ethernet data
|
231
|
|
- * (the ip hdr and arp requests) we offset the packet by 2 bytes.
|
232
|
|
- * leaving the ethernet data 16 byte aligned. Beyond this
|
233
|
|
- * we use memmove but this makes the common cast simple and fast.
|
234
|
|
- */
|
235
|
|
-static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
|
236
|
|
-
|
237
|
|
-struct nic nic =
|
238
|
|
-{
|
239
|
|
- {
|
240
|
|
- 0, /* dev.disable */
|
241
|
|
- {
|
242
|
|
- 0,
|
243
|
|
- 0,
|
244
|
|
- PCI_BUS_TYPE,
|
245
|
|
- }, /* dev.devid */
|
246
|
|
- 0, /* index */
|
247
|
|
- 0, /* type */
|
248
|
|
- PROBE_FIRST, /* how_pobe */
|
249
|
|
- PROBE_NONE, /* to_probe */
|
250
|
|
- 0, /* failsafe */
|
251
|
|
- 0, /* type_index */
|
252
|
|
- {}, /* state */
|
253
|
|
- },
|
254
|
|
- (int (*)(struct nic *, int))dummy, /* poll */
|
255
|
|
- (void (*)(struct nic *, const char *,
|
256
|
|
- unsigned int, unsigned int,
|
257
|
|
- const char *))dummy, /* transmit */
|
258
|
|
- (void (*)(struct nic *,
|
259
|
|
- irq_action_t))dummy, /* irq */
|
260
|
|
- 0, /* flags */
|
261
|
|
- &rom, /* rom_info */
|
262
|
|
- arptable[ARP_CLIENT].node, /* node_addr */
|
263
|
|
- packet + ETH_DATA_ALIGN, /* packet */
|
264
|
|
- 0, /* packetlen */
|
265
|
|
- 0, /* ioaddr */
|
266
|
|
- 0, /* irqno */
|
267
|
|
- 0, /* priv_data */
|
268
|
|
-};
|
269
|
|
-
|
270
|
226
|
#ifdef RARP_NOT_BOOTP
|
271
|
227
|
static int rarp(void);
|
272
|
228
|
#else
|
|
@@ -275,42 +231,12 @@ static int bootp(void);
|
275
|
231
|
static unsigned short tcpudpchksum(struct iphdr *ip);
|
276
|
232
|
|
277
|
233
|
|
278
|
|
-int eth_probe(struct dev *dev)
|
279
|
|
-{
|
280
|
|
- return probe(dev);
|
281
|
|
-}
|
282
|
|
-
|
283
|
|
-int eth_poll(int retrieve)
|
284
|
|
-{
|
285
|
|
- return ((*nic.poll)(&nic, retrieve));
|
286
|
|
-}
|
287
|
|
-
|
288
|
|
-void eth_transmit(const char *d, unsigned int t, unsigned int s, const void *p)
|
289
|
|
-{
|
290
|
|
- (*nic.transmit)(&nic, d, t, s, p);
|
291
|
|
- if (t == ETH_P_IP) twiddle();
|
292
|
|
-}
|
293
|
|
-
|
294
|
|
-void eth_disable(void)
|
295
|
|
-{
|
296
|
|
-#ifdef MULTICAST_LEVEL2
|
297
|
|
- int i;
|
298
|
|
- for(i = 0; i < MAX_IGMP; i++) {
|
299
|
|
- leave_group(i);
|
300
|
|
- }
|
301
|
|
-#endif
|
302
|
|
- disable(&nic.dev);
|
303
|
|
-}
|
304
|
|
-
|
305
|
|
-void eth_irq (irq_action_t action)
|
306
|
|
-{
|
307
|
|
- (*nic.irq)(&nic,action);
|
308
|
|
-}
|
|
234
|
+struct nic *nic = &dev.nic;
|
309
|
235
|
|
310
|
236
|
/*
|
311
|
237
|
* Find out what our boot parameters are
|
312
|
238
|
*/
|
313
|
|
-int eth_load_configuration(struct dev *dev __unused)
|
|
239
|
+static int nic_load_configuration(struct dev *dev __unused)
|
314
|
240
|
{
|
315
|
241
|
int server_found;
|
316
|
242
|
/* Find a server to get BOOTP reply from */
|
|
@@ -340,7 +266,7 @@ int eth_load_configuration(struct dev *dev __unused)
|
340
|
266
|
/**************************************************************************
|
341
|
267
|
LOAD - Try to get booted
|
342
|
268
|
**************************************************************************/
|
343
|
|
-int eth_load(struct dev *dev __unused)
|
|
269
|
+static int nic_load(struct dev *dev __unused)
|
344
|
270
|
{
|
345
|
271
|
const char *kernel;
|
346
|
272
|
printf("\nMe: %@", arptable[ARP_CLIENT].ipaddr.s_addr );
|
|
@@ -390,6 +316,56 @@ int eth_load(struct dev *dev __unused)
|
390
|
316
|
}
|
391
|
317
|
|
392
|
318
|
|
|
319
|
+static void nic_disable ( struct dev *dev ) {
|
|
320
|
+ struct nic *nic = &dev->nic;
|
|
321
|
+
|
|
322
|
+#ifdef MULTICAST_LEVEL2
|
|
323
|
+ int i;
|
|
324
|
+ for(i = 0; i < MAX_IGMP; i++) {
|
|
325
|
+ leave_group(i);
|
|
326
|
+ }
|
|
327
|
+#endif
|
|
328
|
+
|
|
329
|
+ nic->nic_op->disable ( nic );
|
|
330
|
+}
|
|
331
|
+
|
|
332
|
+/*
|
|
333
|
+ * Device operations tables
|
|
334
|
+ *
|
|
335
|
+ */
|
|
336
|
+static struct dev_operations nic_operations = {
|
|
337
|
+ .disable = nic_disable,
|
|
338
|
+ .load_configuration = nic_load_configuration,
|
|
339
|
+ .load = nic_load,
|
|
340
|
+};
|
|
341
|
+
|
|
342
|
+/* Careful. We need an aligned buffer to avoid problems on machines
|
|
343
|
+ * that care about alignment. To trivally align the ethernet data
|
|
344
|
+ * (the ip hdr and arp requests) we offset the packet by 2 bytes.
|
|
345
|
+ * leaving the ethernet data 16 byte aligned. Beyond this
|
|
346
|
+ * we use memmove but this makes the common cast simple and fast.
|
|
347
|
+ */
|
|
348
|
+static char packet[ETH_FRAME_LEN + ETH_DATA_ALIGN] __aligned;
|
|
349
|
+
|
|
350
|
+/*
|
|
351
|
+ * Set up a struct dev to operate as a NIC, return the struct nic *
|
|
352
|
+ *
|
|
353
|
+ */
|
|
354
|
+struct nic * nic_device ( struct dev *dev ) {
|
|
355
|
+ struct nic *nic = &dev->nic;
|
|
356
|
+
|
|
357
|
+ memset ( nic, 0, sizeof ( *nic ) );
|
|
358
|
+ nic->node_addr = arptable[ARP_CLIENT].node;
|
|
359
|
+ nic->packet = packet + ETH_DATA_ALIGN;
|
|
360
|
+ dev->dev_op = &nic_operations;
|
|
361
|
+ return nic;
|
|
362
|
+}
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
|
393
|
369
|
/**************************************************************************
|
394
|
370
|
DEFAULT_NETMASK - Return default netmask for IP address
|
395
|
371
|
**************************************************************************/
|
|
@@ -414,9 +390,9 @@ static int await_arp(int ival, void *ptr,
|
414
|
390
|
struct arprequest *arpreply;
|
415
|
391
|
if (ptype != ETH_P_ARP)
|
416
|
392
|
return 0;
|
417
|
|
- if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
|
|
393
|
+ if (nic->packetlen < ETH_HLEN + sizeof(struct arprequest))
|
418
|
394
|
return 0;
|
419
|
|
- arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
|
|
395
|
+ arpreply = (struct arprequest *)&nic->packet[ETH_HLEN];
|
420
|
396
|
|
421
|
397
|
if (arpreply->opcode != htons(ARP_REPLY))
|
422
|
398
|
return 0;
|
|
@@ -703,7 +679,7 @@ int tftp_block ( struct tftpreq_info_t *request, struct tftpblk_info_t *block )
|
703
|
679
|
continue; /* Back to waiting for packet */
|
704
|
680
|
}
|
705
|
681
|
/* Packet has been received */
|
706
|
|
- rcvd = (struct tftp_t *)&nic.packet[ETH_HLEN];
|
|
682
|
+ rcvd = (struct tftp_t *)&nic->packet[ETH_HLEN];
|
707
|
683
|
recvlen = ntohs(rcvd->udp.len) - sizeof(struct udphdr)
|
708
|
684
|
- sizeof(rcvd->opcode);
|
709
|
685
|
rport = ntohs(rcvd->udp.src);
|
|
@@ -783,9 +759,9 @@ static int await_rarp(int ival, void *ptr,
|
783
|
759
|
struct arprequest *arpreply;
|
784
|
760
|
if (ptype != ETH_P_RARP)
|
785
|
761
|
return 0;
|
786
|
|
- if (nic.packetlen < ETH_HLEN + sizeof(struct arprequest))
|
|
762
|
+ if (nic->packetlen < ETH_HLEN + sizeof(struct arprequest))
|
787
|
763
|
return 0;
|
788
|
|
- arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
|
|
764
|
+ arpreply = (struct arprequest *)&nic->packet[ETH_HLEN];
|
789
|
765
|
if (arpreply->opcode != htons(RARP_REPLY))
|
790
|
766
|
return 0;
|
791
|
767
|
if ((arpreply->opcode == htons(RARP_REPLY)) &&
|
|
@@ -847,9 +823,9 @@ static int await_bootp(int ival __unused, void *ptr __unused,
|
847
|
823
|
if (!udp) {
|
848
|
824
|
return 0;
|
849
|
825
|
}
|
850
|
|
- bootpreply = (struct bootp_t *)&nic.packet[ETH_HLEN +
|
|
826
|
+ bootpreply = (struct bootp_t *)&nic->packet[ETH_HLEN +
|
851
|
827
|
sizeof(struct iphdr) + sizeof(struct udphdr)];
|
852
|
|
- if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) +
|
|
828
|
+ if (nic->packetlen < ETH_HLEN + sizeof(struct iphdr) +
|
853
|
829
|
sizeof(struct udphdr) +
|
854
|
830
|
#ifdef NO_DHCP_SUPPORT
|
855
|
831
|
sizeof(struct bootp_t)
|
|
@@ -922,11 +898,11 @@ static int bootp(void)
|
922
|
898
|
unsigned char *bp_vend;
|
923
|
899
|
|
924
|
900
|
#ifndef NO_DHCP_SUPPORT
|
925
|
|
- dhcp_machine_info[4] = nic.dev.devid.bus_type;
|
926
|
|
- dhcp_machine_info[5] = nic.dev.devid.vendor_id & 0xff;
|
927
|
|
- dhcp_machine_info[6] = ((nic.dev.devid.vendor_id) >> 8) & 0xff;
|
928
|
|
- dhcp_machine_info[7] = nic.dev.devid.device_id & 0xff;
|
929
|
|
- dhcp_machine_info[8] = ((nic.dev.devid.device_id) >> 8) & 0xff;
|
|
901
|
+ dhcp_machine_info[4] = dev.devid.bus_type;
|
|
902
|
+ dhcp_machine_info[5] = dev.devid.vendor_id & 0xff;
|
|
903
|
+ dhcp_machine_info[6] = ((dev.devid.vendor_id) >> 8) & 0xff;
|
|
904
|
+ dhcp_machine_info[7] = dev.devid.device_id & 0xff;
|
|
905
|
+ dhcp_machine_info[8] = ((dev.devid.device_id) >> 8) & 0xff;
|
930
|
906
|
#endif /* NO_DHCP_SUPPORT */
|
931
|
907
|
memset(&ip, 0, sizeof(struct bootpip_t));
|
932
|
908
|
ip.bp.bp_op = BOOTP_REQUEST;
|
|
@@ -1092,11 +1068,11 @@ static void process_igmp(struct iphdr *ip, unsigned long now)
|
1092
|
1068
|
int i;
|
1093
|
1069
|
unsigned iplen;
|
1094
|
1070
|
if (!ip || (ip->protocol == IP_IGMP) ||
|
1095
|
|
- (nic.packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) {
|
|
1071
|
+ (nic->packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) {
|
1096
|
1072
|
return;
|
1097
|
1073
|
}
|
1098
|
1074
|
iplen = (ip->verhdrlen & 0xf)*4;
|
1099
|
|
- igmp = (struct igmp *)&nic.packet[sizeof(struct iphdr)];
|
|
1075
|
+ igmp = (struct igmp *)&nic->packet[sizeof(struct iphdr)];
|
1100
|
1076
|
if (ipchksum(igmp, ntohs(ip->len) - iplen) != 0)
|
1101
|
1077
|
return;
|
1102
|
1078
|
if ((igmp->type == IGMP_QUERY) &&
|
|
@@ -1303,7 +1279,7 @@ int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
|
1303
|
1279
|
syn_ack = state == CLOSED || state == SYN_RCVD;
|
1304
|
1280
|
consumed = ntohl(tcp->ack) - send_seq - syn_ack;
|
1305
|
1281
|
if (consumed < 0 || consumed > can_send) {
|
1306
|
|
- tcp_reset((struct iphdr *)&nic.packet[ETH_HLEN]);
|
|
1282
|
+ tcp_reset((struct iphdr *)&nic->packet[ETH_HLEN]);
|
1307
|
1283
|
goto recv_data;
|
1308
|
1284
|
}
|
1309
|
1285
|
|
|
@@ -1345,7 +1321,7 @@ int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
|
1345
|
1321
|
}
|
1346
|
1322
|
|
1347
|
1323
|
consume_data:
|
1348
|
|
- ip = (struct iphdr *)&nic.packet[ETH_HLEN];
|
|
1324
|
+ ip = (struct iphdr *)&nic->packet[ETH_HLEN];
|
1349
|
1325
|
header_size = sizeof(struct iphdr) + ((ntohs(tcp->ctrl)>>10)&0x3C);
|
1350
|
1326
|
payload = ntohs(ip->len) - header_size;
|
1351
|
1327
|
if (payload > 0 && state == ESTABLISHED) {
|
|
@@ -1354,7 +1330,7 @@ int tcp_transaction(unsigned long destip, unsigned int destsock, void *ptr,
|
1354
|
1330
|
recv_seq += payload - old_bytes;
|
1355
|
1331
|
if (state != FIN_WAIT_1 && state != FIN_WAIT_2 &&
|
1356
|
1332
|
!recv(payload - old_bytes,
|
1357
|
|
- &nic.packet[ETH_HLEN+header_size+old_bytes],
|
|
1333
|
+ &nic->packet[ETH_HLEN+header_size+old_bytes],
|
1358
|
1334
|
ptr)) {
|
1359
|
1335
|
goto close;
|
1360
|
1336
|
}
|
|
@@ -1466,15 +1442,15 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout)
|
1466
|
1442
|
/* We have something! */
|
1467
|
1443
|
|
1468
|
1444
|
/* Find the Ethernet packet type */
|
1469
|
|
- if (nic.packetlen >= ETH_HLEN) {
|
1470
|
|
- ptype = ((unsigned short) nic.packet[12]) << 8
|
1471
|
|
- | ((unsigned short) nic.packet[13]);
|
|
1445
|
+ if (nic->packetlen >= ETH_HLEN) {
|
|
1446
|
+ ptype = ((unsigned short) nic->packet[12]) << 8
|
|
1447
|
+ | ((unsigned short) nic->packet[13]);
|
1472
|
1448
|
} else continue; /* what else could we do with it? */
|
1473
|
1449
|
/* Verify an IP header */
|
1474
|
1450
|
ip = 0;
|
1475
|
|
- if ((ptype == ETH_P_IP) && (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
|
|
1451
|
+ if ((ptype == ETH_P_IP) && (nic->packetlen >= ETH_HLEN + sizeof(struct iphdr))) {
|
1476
|
1452
|
unsigned ipoptlen;
|
1477
|
|
- ip = (struct iphdr *)&nic.packet[ETH_HLEN];
|
|
1453
|
+ ip = (struct iphdr *)&nic->packet[ETH_HLEN];
|
1478
|
1454
|
if ((ip->verhdrlen < 0x45) || (ip->verhdrlen > 0x4F))
|
1479
|
1455
|
continue;
|
1480
|
1456
|
iplen = (ip->verhdrlen & 0xf) * 4;
|
|
@@ -1496,17 +1472,17 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout)
|
1496
|
1472
|
/* Delete the ip options, to guarantee
|
1497
|
1473
|
* good alignment, and make etherboot simpler.
|
1498
|
1474
|
*/
|
1499
|
|
- memmove(&nic.packet[ETH_HLEN + sizeof(struct iphdr)],
|
1500
|
|
- &nic.packet[ETH_HLEN + iplen],
|
1501
|
|
- nic.packetlen - ipoptlen);
|
1502
|
|
- nic.packetlen -= ipoptlen;
|
|
1475
|
+ memmove(&nic->packet[ETH_HLEN + sizeof(struct iphdr)],
|
|
1476
|
+ &nic->packet[ETH_HLEN + iplen],
|
|
1477
|
+ nic->packetlen - ipoptlen);
|
|
1478
|
+ nic->packetlen -= ipoptlen;
|
1503
|
1479
|
}
|
1504
|
1480
|
}
|
1505
|
1481
|
udp = 0;
|
1506
|
1482
|
if (ip && (ip->protocol == IP_UDP) &&
|
1507
|
|
- (nic.packetlen >=
|
|
1483
|
+ (nic->packetlen >=
|
1508
|
1484
|
ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr))) {
|
1509
|
|
- udp = (struct udphdr *)&nic.packet[ETH_HLEN + sizeof(struct iphdr)];
|
|
1485
|
+ udp = (struct udphdr *)&nic->packet[ETH_HLEN + sizeof(struct iphdr)];
|
1510
|
1486
|
|
1511
|
1487
|
/* Make certain we have a reasonable packet length */
|
1512
|
1488
|
if (ntohs(udp->len) > (ntohs(ip->len) - iplen))
|
|
@@ -1520,9 +1496,9 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout)
|
1520
|
1496
|
tcp = 0;
|
1521
|
1497
|
#ifdef DOWNLOAD_PROTO_HTTP
|
1522
|
1498
|
if (ip && (ip->protocol == IP_TCP) &&
|
1523
|
|
- (nic.packetlen >=
|
|
1499
|
+ (nic->packetlen >=
|
1524
|
1500
|
ETH_HLEN + sizeof(struct iphdr) + sizeof(struct tcphdr))){
|
1525
|
|
- tcp = (struct tcphdr *)&nic.packet[ETH_HLEN +
|
|
1501
|
+ tcp = (struct tcphdr *)&nic->packet[ETH_HLEN +
|
1526
|
1502
|
sizeof(struct iphdr)];
|
1527
|
1503
|
/* Make certain we have a reasonable packet length */
|
1528
|
1504
|
if (((ntohs(tcp->ctrl) >> 10) & 0x3C) >
|
|
@@ -1544,11 +1520,11 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout)
|
1544
|
1520
|
* action. This allows us reply to arp, igmp, and lacp queries.
|
1545
|
1521
|
*/
|
1546
|
1522
|
if ((ptype == ETH_P_ARP) &&
|
1547
|
|
- (nic.packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
|
|
1523
|
+ (nic->packetlen >= ETH_HLEN + sizeof(struct arprequest))) {
|
1548
|
1524
|
struct arprequest *arpreply;
|
1549
|
1525
|
unsigned long tmp;
|
1550
|
1526
|
|
1551
|
|
- arpreply = (struct arprequest *)&nic.packet[ETH_HLEN];
|
|
1527
|
+ arpreply = (struct arprequest *)&nic->packet[ETH_HLEN];
|
1552
|
1528
|
memcpy(&tmp, arpreply->tipaddr, sizeof(in_addr));
|
1553
|
1529
|
if ((arpreply->opcode == htons(ARP_REQUEST)) &&
|
1554
|
1530
|
(tmp == arptable[ARP_CLIENT].ipaddr.s_addr)) {
|