summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--README.md3
-rw-r--r--driver/e1000.c25
-rw-r--r--driver/e1000.h3
-rw-r--r--driver/keyboard.c28
-rw-r--r--net/arp.c126
-rw-r--r--net/arp.h28
-rw-r--r--net/eth.c1
-rw-r--r--net/eth.h16
-rw-r--r--net/inet.h20
-rw-r--r--net/netdev.c16
-rw-r--r--net/netdev.h15
12 files changed, 249 insertions, 34 deletions
diff --git a/Makefile b/Makefile
index 7b7e233..b0b095a 100644
--- a/Makefile
+++ b/Makefile
@@ -32,6 +32,7 @@ CFLAGS+=-I./asm
CFLAGS+=-I./kernel
CFLAGS+=-I./driver
CFLAGS+=-I./fs
+CFLAGS+=-I./net
CFLAGS+=-gstabs
#CFLAGS+=-fstack-protector-all
@@ -81,6 +82,7 @@ SOURCES+=$(wildcard ./driver/*.c)
SOURCES+=$(wildcard ./terminal/*.c)
SOURCES+=$(wildcard ./lib/*/*.c)
SOURCES+=$(wildcard ./testing/*.c)
+SOURCES+=$(wildcard ./net/*.c)
#derive kernel object files
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
diff --git a/README.md b/README.md
index f461a32..ad813fd 100644
--- a/README.md
+++ b/README.md
@@ -86,6 +86,8 @@ FoolOS is tested/developed on the following emulators/machines
Todos
-----
+* ethernet drivers: vbox E1000 /virtio / NS2000 / ipxe network drivers?
+* tcp/ip stack
* threads! semaphores
* return value / argv / env
@@ -100,7 +102,6 @@ Todos
* GCC optimizations (break kernel?) / volatile??
-* Ethernet driver E1000 / NS2000 & Networking stack (ipxe network drivers?)
* Unit Testing
diff --git a/driver/e1000.c b/driver/e1000.c
index 35e106e..4c6b8de 100644
--- a/driver/e1000.c
+++ b/driver/e1000.c
@@ -5,9 +5,14 @@
//registers etc. verified from pdf at https://pdos.csail.mit.edu/6.828/2006/readings/hardware/8254x_GBe_SDM.pdf
#include <stdint.h>
+
#include "log.h"
#include "e1000.h"
#include "kmalloc.h"
+#include "netdev.h"
+#include "arp.h"
+
+#include "lib/string/string.h"
#define REG_CTRL 0x0000 // device control R/W
#define REG_CTRL_LRST 1<<3 // Link Reset / transition to 0 to initiates auto-negotiation
@@ -130,6 +135,10 @@
#define E1000_NUM_RX_DESC 32
#define E1000_NUM_TX_DESC 8
+// TODO: move all global stuff to some struct so we can run multiple e1000 cards!
+//
+struct netdev dev; ///TODO not global!
+
struct e1000_rx_desc {
volatile uint32_t addr_lo; // 4
volatile uint32_t addr_hi; // 4
@@ -413,6 +422,7 @@ void e1000_handleReceive()
uint16_t len = rx_descs[rx_cur]->length;
// Here you should inject the received packet into your network stack
+ arp_incoming(&dev,buf);
rx_descs[rx_cur]->status = 0;
old_cur = rx_cur;
@@ -472,8 +482,11 @@ void e1000_linkdown()
}
-bool e1000_init(uint32_t base)
+struct netdev e1000_init(uint32_t base)
{
+ dev.ip=0;
+ dev.hwaddr[0]=dev.hwaddr[1]=dev.hwaddr[2]=dev.hwaddr[3]=dev.hwaddr[4]=dev.hwaddr[5]=0;
+
klog("init E1000");
klog("interrupt mask: 0x%08X",readCommand(REG_IMS));
klog("device status: 0x%08X",readCommand(REG_STATUS));
@@ -485,10 +498,14 @@ bool e1000_init(uint32_t base)
if(base!=0){ mem_base=base;}
detectEEProm();
- if (! readMACAddress()) return false;
+ if (! readMACAddress()) return dev;
klog("mac : %02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],mac[6]);
+ memcpy(dev.hwaddr,mac,6); // use mac obtained from device
+ dev.ip=(192<<0)+(168<<8)+(0<<16)+(20<<24); // 192.168.0.20 // TODO: not hardcode!
+ dev.transmit=e1000_sendPacket;
+
// clear multicast table
for(int i = 0; i < 0x80; i++)writeCommand(REG_MTA + i*4, 0);
@@ -498,10 +515,10 @@ bool e1000_init(uint32_t base)
txinit();
rxinit();
-
+
klog("E1000 initialized");
- return true;
+ return dev;
}
void e1000_irq (int irq)
{
diff --git a/driver/e1000.h b/driver/e1000.h
index ba7db7d..27a052e 100644
--- a/driver/e1000.h
+++ b/driver/e1000.h
@@ -1,5 +1,6 @@
#include <stdint.h>
-bool e1000_init(uint32_t base);
+#include "netdev.h"
+struct netdev e1000_init(uint32_t base);
int e1000_sendPacket(const void * p_data, uint16_t p_len);
void e1000_irq (int irq);
void e1000_linkup();
diff --git a/driver/keyboard.c b/driver/keyboard.c
index d6ce465..d201882 100644
--- a/driver/keyboard.c
+++ b/driver/keyboard.c
@@ -23,34 +23,6 @@ int hex_to_dec(char c)
}
static void put(uint8_t c)
{
- /*
-0000 8a b1 aa 7e 4d 00 52 54 00 12 34 56 08 00 45 00
-0010 00 54 1e c0 00 00 40 01 da 1f c0 a8 00 14 c0 a8
-0020 00 65 00 00 ce 07 1f 02 03 b0 bf 79 a9 5b 00 00
-0030 00 00 df 9d 08 00 00 00 00 00 10 11 12 13 14 15
-0040 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25
-0050 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35
-0060 36 37
-*/
-
- static char data_raw[]="8ab1aa7e4d005254001234560800450000541ec000004001da1fc0a80014c0a800650000ce071f0203b0bf79a95b00000000df9d080000000000101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637";
- static uint8_t data[256];//=kballoc(1);
- int i=0;
-
- while(data_raw[i]!=0)
- {
- uint8_t val=hex_to_dec(data_raw[i])*16+hex_to_dec(data_raw[i+1]);
- data[i/2]=val;
- i+=2;
- }
-
-
- if(c=='p')e1000_sendPacket(data,i/2); // packet
-// if(c=='s')e1000_init(0); // start
- // if(c=='i')e1000_irq(11); // interrupt
- // if(c=='u')e1000_linkup(); // up
- //if(c=='d')e1000_linkdown(); // down
-
syscall_generic(SYSCALL_WRITE,kb_stream, (char *)&c , 1, 0);
}
diff --git a/net/arp.c b/net/arp.c
new file mode 100644
index 0000000..501186f
--- /dev/null
+++ b/net/arp.c
@@ -0,0 +1,126 @@
+// https://github.com/saminiir/level-ip/blob/e9ceb08f01a5499b85f03e2d615309c655b97e8f/src/arp.c#L53
+// https://github.com/chobits/tapip
+// https://tools.ietf.org/html/rfc826
+
+#include "inet.h"
+#include "eth.h"
+#include "arp.h"
+#include "netdev.h"
+#include "log.h"
+
+#include "lib/string/string.h"
+
+/*
+ */
+/*
+static struct arp_cache_entry arp_cache[ARP_CACHE_LEN];
+
+static int insert_arp_translation_table(struct arp_hdr *hdr, struct arp_ipv4 *data)
+{
+ struct arp_cache_entry *entry;
+ for (int i = 0; i<ARP_CACHE_LEN; i++) {
+ entry = &arp_cache[i];
+
+ if (entry->state == ARP_FREE) {
+ entry->state = ARP_RESOLVED;
+
+ entry->hwtype = hdr->hwtype;
+ entry->sip = data->sip;
+ memcpy(entry->smac, data->smac, sizeof(entry->smac));
+
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int update_arp_translation_table(struct arp_hdr *hdr, struct arp_ipv4 *data)
+{
+ struct arp_cache_entry *entry;
+
+ for (int i = 0; i<ARP_CACHE_LEN; i++) {
+ entry = &arp_cache[i];
+
+ if (entry->state == ARP_FREE) continue;
+
+ if (entry->hwtype == hdr->hwtype && entry->sip == data->sip) {
+ memcpy(entry->smac, data->smac, 6);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+void arp_init()
+{
+ memset(arp_cache, 0, ARP_CACHE_LEN * sizeof(struct arp_cache_entry));
+}
+*/
+
+void arp_reply(struct netdev *netdev, struct eth_hdr *hdr, struct arp_hdr *arphdr)
+{
+ struct arp_ipv4 *arpdata;
+ int len;
+
+ arpdata = (struct arp_ipv4 *) arphdr->data;
+
+ memcpy(arpdata->dmac, arpdata->smac, 6);
+ arpdata->dip = arpdata->sip;
+ memcpy(arpdata->smac, netdev->hwaddr, 6);
+ arpdata->sip = netdev->ip;
+
+ arphdr->opcode = ARP_REPLY;
+
+ arphdr->opcode = htons(arphdr->opcode);
+ arphdr->hwtype = htons(arphdr->hwtype);
+ arphdr->protype = htons(arphdr->protype);
+
+ len = sizeof(struct arp_hdr) + sizeof(struct arp_ipv4);
+ netdev_transmit(netdev, hdr, ETH_P_ARP, len, arpdata->dmac);
+}
+
+void arp_incoming(struct netdev *netdev, struct eth_hdr *hdr)
+{
+ struct arp_hdr *arphdr;
+ struct arp_ipv4 *arpdata;
+ int merge = 0;
+
+ arphdr = (struct arp_hdr *) hdr->payload;
+
+ arphdr->hwtype = ntohs(arphdr->hwtype);
+ arphdr->protype = ntohs(arphdr->protype);
+ arphdr->opcode = ntohs(arphdr->opcode);
+
+ if (arphdr->hwtype != ARP_ETHERNET) {
+ klog("Unsupported HW type\n");
+ return;
+ }
+
+ if (arphdr->protype != ARP_IPV4) {
+ klog("Unsupported protocol\n");
+ return;
+ }
+
+ arpdata = (struct arp_ipv4 *) arphdr->data;
+
+// merge = update_arp_translation_table(arphdr, arpdata);
+
+ if (netdev->ip != arpdata->dip) {
+ klog("ARP was not for us\n");
+ }
+
+// if (!merge && insert_arp_translation_table(arphdr, arpdata) != 0) {
+ // klog("ERR: No free space in ARP translation table\n");
+ // }
+
+ switch (arphdr->opcode) {
+ case ARP_REQUEST:
+ arp_reply(netdev, hdr, arphdr);
+ break;
+ default:
+ klog("Opcode not supported\n");
+ break;
+ }
+}
diff --git a/net/arp.h b/net/arp.h
new file mode 100644
index 0000000..a690ac0
--- /dev/null
+++ b/net/arp.h
@@ -0,0 +1,28 @@
+// http://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/
+//
+
+#include <stdint.h>
+
+#include "netdev.h"
+
+struct arp_hdr
+{
+ uint16_t hwtype; // link layer type (1 - ethernet)
+ uint16_t protype; // protocol (0x800 - ipv4)
+ unsigned char hwsize; // hardware field size (6 bytes mac)
+ unsigned char prosize; // protocol field size (4 byte ip)
+ uint16_t opcode; // arp message type (1- arp request, 2- arp reply, 3- rarp request, 4- rarp reply)
+ unsigned char data[]; // payload
+} __attribute__((packed));
+
+// arp ipv4 payload
+struct arp_ipv4
+{
+ unsigned char smac[6]; // sender mac
+ uint32_t sip; // sender ip
+ unsigned char dmac[6]; // receiver mac
+ uint32_t dip; // receiver ip
+} __attribute__((packed));
+
+void arp_incoming(struct netdev *netdev, struct eth_hdr *hdr);
+void arp_reply(struct netdev *netdev, struct eth_hdr *hdr, struct arp_hdr *arphdr);
diff --git a/net/eth.c b/net/eth.c
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/net/eth.c
@@ -0,0 +1 @@
+
diff --git a/net/eth.h b/net/eth.h
new file mode 100644
index 0000000..f90e615
--- /dev/null
+++ b/net/eth.h
@@ -0,0 +1,16 @@
+//http://www.saminiir.com/lets-code-tcp-ip-stack-1-ethernet-arp/
+//https://tools.ietf.org/html/rfc7414
+#ifndef FOOLOS_ETH_H
+#define FOOLOS_ETH_H
+
+#include <stdint.h>
+
+struct eth_hdr
+{
+ unsigned char dmac[6]; // destination mac
+ unsigned char smac[6]; // source mac
+ uint16_t ethertype; // length or type
+ unsigned char payload[]; // payload
+} __attribute__((packed));
+
+#endif
diff --git a/net/inet.h b/net/inet.h
new file mode 100644
index 0000000..a2e8dd8
--- /dev/null
+++ b/net/inet.h
@@ -0,0 +1,20 @@
+/*
+ * @file
+ * https://en.wikipedia.org/wiki/OSI_model
+ */
+#include <stdint.h>
+
+#define ARP_ETHERNET 1
+#define ARP_IPV4 0x800
+#define ARP_REPLY 2
+#define ARP_REQUEST 1
+#define ETH_P_ARP 0x0806
+
+static uint16_t ntohs(uint16_t val)
+{
+ return val<<8|val>>8;
+}
+static uint16_t htons(uint16_t val)
+{
+ return val<<8|val>>8;
+}
diff --git a/net/netdev.c b/net/netdev.c
new file mode 100644
index 0000000..3acd7a4
--- /dev/null
+++ b/net/netdev.c
@@ -0,0 +1,16 @@
+#include <stdint.h>
+#include "inet.h"
+#include "eth.h"
+#include "netdev.h"
+#include "lib/string/string.h"
+
+void netdev_transmit(struct netdev *dev, struct eth_hdr *hdr, uint16_t ethertype, int len, unsigned char *dst)
+{
+ hdr->ethertype = htons(ethertype);
+ memcpy(hdr->smac, dev->hwaddr, 6);
+ memcpy(hdr->dmac, dst, 6);
+
+ len += sizeof(struct eth_hdr);
+
+ dev->transmit(hdr,len);
+}
diff --git a/net/netdev.h b/net/netdev.h
new file mode 100644
index 0000000..c6c02dd
--- /dev/null
+++ b/net/netdev.h
@@ -0,0 +1,15 @@
+#ifndef FOOLOS_NETDEV_H
+#define FOOLOS_NETDEV_H
+
+#include "eth.h"
+
+struct netdev
+{
+ unsigned char hwaddr[6]; // device hardware address
+ uint32_t ip; // device ip
+ int (*transmit)(const void *data, uint16_t p_len);
+};
+
+void netdev_transmit(struct netdev *dev, struct eth_hdr *hdr, uint16_t ethertype, int len, unsigned char *dst);
+
+#endif