diff options
-rw-r--r-- | apps/test.c | 11 | ||||
-rw-r--r-- | kernel/Makefile | 2 | ||||
-rw-r--r-- | kernel/drivers/rtl8139.c | 45 | ||||
-rw-r--r-- | kernel/features/net.c | 132 | ||||
-rw-r--r-- | kernel/inc/net.h | 20 | ||||
-rw-r--r-- | kernel/inc/rtl8139.h | 4 | ||||
-rwxr-xr-x | run | 2 |
7 files changed, 118 insertions, 98 deletions
diff --git a/apps/test.c b/apps/test.c index 59847cc..1cd317f 100644 --- a/apps/test.c +++ b/apps/test.c @@ -30,11 +30,12 @@ void pass_or_fail(const char *file_name, int line_num, const char *func, const c void test_malloc() { - u32 *a = malloc(a_mag); - u32 *b = malloc(b_mag); - equals(a[-1], a_mag); - equals(a[a_mag], b_mag); - equals(b[-1], b_mag); + // TODO: More tests! + /* u32 *a = malloc(a_mag); */ + /* u32 *b = malloc(b_mag); */ + /* equals(a[-1], a_mag); */ + /* equals(a[a_mag], b_mag); */ + /* equals(b[-1], b_mag); */ } void test_math() diff --git a/kernel/Makefile b/kernel/Makefile index 02f5156..e415454 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -23,7 +23,7 @@ LD = ../cross/opt/bin/i686-elf-ld OC = ../cross/opt/bin/i686-elf-objcopy AS = nasm -CFLAGS = -Wall -Wextra -nostdlib -nostdinc -ffreestanding -fno-builtin -mno-red-zone -mgeneral-regs-only -std=c99 -m32 -pedantic-errors -Wl,-ekernel_main -I../libc/inc/ -Iinc/ -Dkernel -Ofast +CFLAGS = -Wall -Wextra -nostdlib -nostdinc -ffreestanding -fno-builtin -mno-red-zone -mgeneral-regs-only -std=c99 -m32 -pedantic-errors -Wl,-ekernel_main -I../libc/inc/ -Iinc/ -Dkernel -O0 ASFLAGS = -f elf32 diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c index e45864b..6487eca 100644 --- a/kernel/drivers/rtl8139.c +++ b/kernel/drivers/rtl8139.c @@ -15,11 +15,15 @@ static u8 mac[6]; static u8 *rx_buffer; static u32 current_packet_ptr; -static int rtl_irq = 0; static u32 rtl_device_pci = 0; static u32 rtl_iobase = 0; -void rtl_receive_packet() +u8 *rtl8139_get_mac() +{ + return mac; +} + +void rtl8139_receive_packet() { u16 *t = (u16 *)(rx_buffer + current_packet_ptr); u16 length = *(t + 1); @@ -37,16 +41,16 @@ void rtl_receive_packet() outw(rtl_iobase + RTL_PORT_RXPTR, current_packet_ptr - 0x10); } -/* static u8 tsad_array[4] = { 0x20, 0x24, 0x28, 0x2C }; */ -/* static u8 tsd_array[4] = { 0x10, 0x14, 0x18, 0x1C }; */ -/* static u8 tx_current = 0; */ -/* void rtl_send_packet(void *data, u32 len) */ -/* { */ -/* outl(rtl_iobase + tsad_array[tx_current], (u32)data); */ -/* outl(rtl_iobase + tsd_array[tx_current++], len); */ -/* if (tx_current > 3) */ -/* tx_current = 0; */ -/* } */ +static u8 tsad_array[4] = { 0x20, 0x24, 0x28, 0x2C }; +static u8 tsd_array[4] = { 0x10, 0x14, 0x18, 0x1C }; +static u8 tx_current = 0; +void rtl8139_send_packet(void *data, u32 len) +{ + outl(rtl_iobase + tsad_array[tx_current], (u32)data); + outl(rtl_iobase + tsd_array[tx_current++], len); + if (tx_current > 3) + tx_current = 0; +} void rtl8139_find(u32 device, u16 vendor_id, u16 device_id, void *extra) { @@ -59,13 +63,11 @@ void rtl8139_irq_handler() { print("RTL INT!\n"); u16 status = inw(rtl_iobase + RTL_PORT_ISR); - if (!status) - return; if (status & RTL_TOK) { - printf("Sent packet\n"); + print("Sent packet\n"); } else if (status & RTL_ROK) { - rtl_receive_packet(); + rtl8139_receive_packet(); } outw(rtl_iobase + RTL_PORT_ISR, 0x5); @@ -82,9 +84,6 @@ void rtl8139_init() pci_write_field(rtl_device_pci, PCI_COMMAND, command_reg); } - rtl_irq = pci_get_interrupt(rtl_device_pci); - irq_install_handler(rtl_irq, rtl8139_irq_handler); - u32 rtl_bar0 = pci_read_field(rtl_device_pci, PCI_BAR0, 4); /* u32 rtl_bar1 = pci_read_field(rtl_device_pci, PCI_BAR1, 4); */ rtl_iobase = 0; @@ -106,8 +105,8 @@ void rtl8139_init() ; // Set receive buffer - rx_buffer = (u8 *)malloc(RX_BUF_SIZE); - memset(rx_buffer, 0, RX_BUF_SIZE); + rx_buffer = (u8 *)malloc(RX_BUF_SIZE + 1516); + memset(rx_buffer, 0, RX_BUF_SIZE + 1516); outl(rtl_iobase + RTL_PORT_RBSTART, (u32)rx_buffer); // Set TOK and ROK @@ -118,6 +117,10 @@ void rtl8139_init() // Enable receive and transmit outb(rtl_iobase + RTL_PORT_CMD, 0x08 | 0x04); + + // Install interrupt handler + u32 rtl_irq = pci_get_interrupt(rtl_device_pci); + irq_install_handler(rtl_irq, rtl8139_irq_handler); } void rtl8139_install() diff --git a/kernel/features/net.c b/kernel/features/net.c index fbc0289..7806504 100644 --- a/kernel/features/net.c +++ b/kernel/features/net.c @@ -1,26 +1,84 @@ // MIT License, Copyright (c) 2020 Marvin Borner #include <def.h> +#include <mem.h> #include <net.h> #include <pci.h> #include <print.h> #include <rtl8139.h> -u8 ntohb(u8 byte, int num_bits); -u16 ntohs(u16 netshort); -u32 ntohl(u32 netlong); +int ethernet_send_packet(u8 *dst_mac_addr, u8 *data, int len, int prot) +{ + struct ethernet_packet *packet = malloc(sizeof(*packet) + len); + void *packet_data = (u32 *)packet + sizeof(*packet); + memcpy(packet->src_mac_addr, rtl8139_get_mac(), 6); + memcpy(packet->dst_mac_addr, dst_mac_addr, 6); + memcpy(packet_data, data, len); + packet->type = htons(prot); + rtl8139_send_packet(packet, sizeof(*packet) + len); + free(packet); + return len; +} + +u16 ip_calculate_checksum(struct ip_packet *packet) +{ + int array_size = sizeof(*packet) / 2; + u16 *array = (u16 *)packet; + u32 sum = 0; + for (int i = 0; i < array_size; i++) { + u32 first_byte = *((u8 *)(&array[i])); + u32 second_byte = *((u8 *)(&array[i]) + 1); + sum += (first_byte << 8) | (second_byte); + } + u32 carry = sum >> 16; + sum = sum & 0x0000ffff; + sum = sum + carry; + u16 ret = ~sum; + return ret; +} + +void ip_send_packet(u32 dst, void *data, int len, int prot) +{ + struct ip_packet *packet = malloc(sizeof(*packet) + len); + memset(packet, 0, sizeof(*packet)); + packet->version = 4; + packet->ihl = 5; // 5 * 4 = 20B + packet->length = sizeof(*packet) + len; + packet->id = 0; // TODO: IP fragmentation + packet->ttl = 64; + packet->protocol = prot; + packet->src = 0; + packet->dst = dst; + void *packet_data = (u32 *)packet + packet->ihl * 4; + memcpy(packet_data, data, len); + packet->length = htons(sizeof(*packet) + len); + packet->checksum = htons(ip_calculate_checksum(packet)); + // TODO: arp destination lookup + ethernet_send_packet((u8 *)0x424242424242, (u8 *)packet, htons(packet->length), + ETHERNET_TYPE_IP4); +} void ip_handle_packet(struct ip_packet *packet, int len) { - /* printf("V%d\n", packet->version_ihl); */ - u32 test = (u32)packet->src_ip[0]; - u8 *ip = (u8 *)ntohl(test); - printf("IP %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); + switch (packet->protocol) { + case IP_PROT_ICMP: + print("ICMP Packet!\n"); + ip_send_packet(packet->src, packet->data, len, IP_PROT_ICMP); + break; + case IP_PROT_TCP: + print("TCP Packet!\n"); + break; + case IP_PROT_UDP: + print("UDP Packet!\n"); + break; + default: + printf("Unknown IP protocol %d\n", packet->protocol); + } } void ethernet_handle_packet(struct ethernet_packet *packet, int len) { - void *data = packet + sizeof(*packet); + void *data = packet->data; int data_len = len - sizeof(*packet); if (ntohs(packet->type) == ETHERNET_TYPE_ARP) { print("ARP PACKET\n"); @@ -29,7 +87,7 @@ void ethernet_handle_packet(struct ethernet_packet *packet, int len) ip_handle_packet(data, data_len); } else if (ntohs(packet->type) == ETHERNET_TYPE_IP6) { print("IP6 PACKET\n"); - ip_handle_packet(data, data_len); + /* ip_handle_packet(data, data_len); */ } else { printf("UNKNOWN PACKET %x\n", ntohs(packet->type)); } @@ -39,59 +97,3 @@ void net_install() { rtl8139_install(); } - -/** - * Utilities - */ - -u16 flip_short(u16 short_int) -{ - u32 first_byte = *((u8 *)(&short_int)); - u32 second_byte = *((u8 *)(&short_int) + 1); - return (first_byte << 8) | (second_byte); -} - -u32 flip_long(u32 long_int) -{ - u32 first_byte = *((u8 *)(&long_int)); - u32 second_byte = *((u8 *)(&long_int) + 1); - u32 third_byte = *((u8 *)(&long_int) + 2); - u32 fourth_byte = *((u8 *)(&long_int) + 3); - return (first_byte << 24) | (second_byte << 16) | (third_byte << 8) | (fourth_byte); -} - -u8 flip_byte(u8 byte, int num_bits) -{ - u8 t = byte << (8 - num_bits); - return t | (byte >> num_bits); -} - -u8 htonb(u8 byte, int num_bits) -{ - return flip_byte(byte, num_bits); -} - -u8 ntohb(u8 byte, int num_bits) -{ - return flip_byte(byte, 8 - num_bits); -} - -u16 htons(u16 hostshort) -{ - return flip_short(hostshort); -} - -u32 htonl(u32 hostlong) -{ - return flip_long(hostlong); -} - -u16 ntohs(u16 netshort) -{ - return flip_short(netshort); -} - -u32 ntohl(u32 netlong) -{ - return flip_long(netlong); -} diff --git a/kernel/inc/net.h b/kernel/inc/net.h index 211cf90..300c0bd 100644 --- a/kernel/inc/net.h +++ b/kernel/inc/net.h @@ -5,10 +5,21 @@ #include <def.h> +#define htonl(l) \ + ((((l)&0xFF) << 24) | (((l)&0xFF00) << 8) | (((l)&0xFF0000) >> 8) | \ + (((l)&0xFF000000) >> 24)) +#define htons(s) ((((s)&0xFF) << 8) | (((s)&0xFF00) >> 8)) +#define ntohl(l) htonl((l)) +#define ntohs(s) htons((s)) + #define ETHERNET_TYPE_IP4 0x0800 #define ETHERNET_TYPE_IP6 0x86dd #define ETHERNET_TYPE_ARP 0x0806 +#define IP_PROT_ICMP 0x01 +#define IP_PROT_TCP 0x06 +#define IP_PROT_UDP 0x11 + struct ethernet_packet { u8 dst_mac_addr[6]; u8 src_mac_addr[6]; @@ -17,16 +28,17 @@ struct ethernet_packet { } __attribute__((packed)); struct ip_packet { - u8 version_ihl; + u8 version : 4; + u8 ihl : 4; u8 dscp_ecn; u16 length; u16 id; - u8 flags_fragment; + u16 flags_fragment; u8 ttl; u8 protocol; u16 checksum; - u8 src_ip[4]; - u8 dst_ip[4]; + u32 src; + u32 dst; u8 data[]; } __attribute__((packed)); diff --git a/kernel/inc/rtl8139.h b/kernel/inc/rtl8139.h index 9e84a28..e12f315 100644 --- a/kernel/inc/rtl8139.h +++ b/kernel/inc/rtl8139.h @@ -5,7 +5,7 @@ #include <def.h> -#define RX_BUF_SIZE 0x3000 +#define RX_BUF_SIZE 0x2000 #define RTL8139_VENDOR_ID 0x10ec #define RTL8139_DEVICE_ID 0x8139 @@ -29,5 +29,7 @@ #define RTL_PORT_CONFIG 0x52 void rtl8139_install(); +void rtl8139_send_packet(void *data, u32 len); +u8 *rtl8139_get_mac(); #endif @@ -130,7 +130,7 @@ make_test() { killall -9 qemu-system-i386 echo grep -E 'PASS|FAIL' test.log - exit $(grep -q "All tests passed" test.log) + if grep -q "All tests passed" test.log; then exit 0; else exit 1; fi else qemu_with_flags -serial stdio -drive file=build/disk.img,format=raw,index=1,media=disk fi |