From be9f52c2e8bd3f6eb4371433861740ca68b621c5 Mon Sep 17 00:00:00 2001 From: Atheria Date: Sat, 13 Sep 2025 18:58:37 +0700 Subject: [PATCH] Network interfaces --- README.md | 4 ++ arch/x86_64/interrupts/Interrupts.c | 2 + docs/ARCHITECTURE.md | 36 ++++++----- drivers/ethernet/Network.c | 64 +++++++++++++++++++ drivers/ethernet/Network.h | 30 +++++++++ drivers/ethernet/intel/E1000.c | 29 +++++++++ drivers/ethernet/intel/E1000.h | 1 + drivers/ethernet/interface/Arp.c | 84 ++++++++++++++++++++++++ drivers/ethernet/interface/Arp.h | 28 ++++++++ drivers/ethernet/interface/Icmp.c | 79 +++++++++++++++++++++++ drivers/ethernet/interface/Icmp.h | 21 ++++++ drivers/ethernet/interface/Ip.c | 96 ++++++++++++++++++++++++++++ drivers/ethernet/interface/Ip.h | 33 ++++++++++ drivers/ethernet/realtek/RTL8139.c | 27 ++++++++ drivers/ethernet/realtek/RTL8139.h | 2 + kernel/core/Kernel.c | 14 ++-- kernel/etc/Shell.c | 34 +++++++++- kernel/etc/StringOps.c | 49 +++++++++++++- kernel/etc/StringOps.h | 23 +++---- kernel/etc/objects/panic.o | Bin 1920592 -> 1920592 bytes kernel/etc/objects/splash1.o | Bin 1920600 -> 1920600 bytes meson.build | 5 ++ 22 files changed, 621 insertions(+), 40 deletions(-) create mode 100644 drivers/ethernet/Network.c create mode 100644 drivers/ethernet/Network.h create mode 100644 drivers/ethernet/interface/Arp.c create mode 100644 drivers/ethernet/interface/Arp.h create mode 100644 drivers/ethernet/interface/Icmp.c create mode 100644 drivers/ethernet/interface/Icmp.h create mode 100644 drivers/ethernet/interface/Ip.c create mode 100644 drivers/ethernet/interface/Ip.h diff --git a/README.md b/README.md index c7fd5bb..cf9cc70 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,10 @@ ninja runmin - Network - [x] RTL8139 (PCI) - [x] E1000 (PCI) +- Network Interface + - [x] IP + - [x] ARP + - [x] ICMP - Sound - [x] SB16 (PCI) - [x] Generic PC speaker diff --git a/arch/x86_64/interrupts/Interrupts.c b/arch/x86_64/interrupts/Interrupts.c index 5eb12df..ad833d6 100644 --- a/arch/x86_64/interrupts/Interrupts.c +++ b/arch/x86_64/interrupts/Interrupts.c @@ -9,6 +9,7 @@ #include "Pic.h" #include "StackTrace.h" #include "PageFaultHandler.h" +#include "ethernet/Network.h" volatile uint32_t PITTicks = 0; @@ -21,6 +22,7 @@ asmlinkage void InterruptHandler(Registers* regs) { case 32: // Timer interrupt (IRQ 0) MLFQSchedule(regs); AtomicInc(&PITTicks); + Net_Poll(); PICSendEOI(regs->interrupt_number); return; diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 5eaf760..6515d65 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -167,30 +167,30 @@ The `ProcessControlBlock` is the fundamental data structure that represents a pr ```c typedef struct { + char name[64]; uint32_t pid; ProcessState state; void* stack; uint8_t priority; - uint8_t base_priority; - uint8_t is_user_mode; + uint8_t base_priority; uint8_t privilege_level; - uint32_t cpu_burst_history[CPU_BURST_HISTORY]; - uint32_t io_operations; - uint32_t preemption_count; + uint32_t cpu_burst_history[CPU_BURST_HISTORY]; + uint32_t io_operations; + uint32_t preemption_count; uint64_t cpu_time_accumulated; uint64_t last_scheduled_tick; - uint64_t wait_time; + uint64_t wait_time; TerminationReason term_reason; uint32_t exit_code; uint64_t termination_time; uint32_t parent_pid; - SecurityToken token; + MLFQSecurityToken token; MessageQueue ipc_queue; ProcessContext context; - SchedulerNode* scheduler_node; + MLFQSchedulerNode* scheduler_node; uint64_t creation_time; - char* ProcINFOPath; -} ProcessControlBlock; + char ProcessRuntimePath[256]; +} MLFQProcessControlBlock; ``` #### Key PCB Fields @@ -418,24 +418,30 @@ The following functions and commands provide interfaces to the process managemen '-DVF_CONFIG_ENABLE_PCI', '-DVF_CONFIG_ENABLE_PS2', '-DVF_CONFIG_ENABLE_IDE', + '-DVF_CONFIG_ENABLE_VFCOMPOSITOR', + '-DVF_CONFIG_ENABLE_AHCI', + '-DVF_CONFIG_ENABLE_GENERIC_SOUND', + #'-DVF_CONFIG_ENABLE_VMWARE_SVGA_II', '-DVF_CONFIG_RTC_CENTURY', '-DVF_CONFIG_ENFORCE_MEMORY_PROTECTION', '-DVF_CONFIG_VM_HOST', + '-DVF_CONFIG_SNOOZE_ON_BOOT', '-DVF_CONFIG_PROCINFO_CREATE_DEFAULT', '-DVF_CONFIG_USE_VFSHELL', '-DVF_CONFIG_USE_DYNAMOX', '-DVF_CONFIG_USE_ASTRA', '-DVF_CONFIG_USE_CERBERUS', - '-DVF_CONFIG_CERBERUS_VFS_LOGGING', - '-DVF_CONFIG_CERBERUS_THREAT_REPORTING', - #'-DVF_CONFIG_CERBERUS_STACK_PROTECTION', + #'-DVF_CONFIG_CERBERUS_VFS_LOGGING', + '-DVF_CONFIG_CERBERUS_THREAT_REPORTING', + '-DVF_CONFIG_CERBERUS_STACK_PROTECTION', '-DVF_CONFIG_SCHED_MLFQ', - '-DVF_CONFIG_PROCINFO_AUTO_CLEANUP', + #'-DVF_CONFIG_PROCINFO_AUTO_CLEANUP', #'-DVF_CONFIG_PANIC_OVERRIDE', ] ``` - Setup options: ```jetbrainsmeson option('exclude_extra_objects', type : 'boolean', value : false, description : 'Exclude extra objects from the build') # MASSIVE effect!, smaller size & smoother + option('automatic_post', type : 'boolean', value : false, description : 'Perform automatic power on self-test after kernel initialization') ``` -> assembler-0 @ voidframe-kernel - 14:40 02/09/2025 \ No newline at end of file +> assembler-0 @ voidframe-kernel - 18:57 - 13-09-2025 \ No newline at end of file diff --git a/drivers/ethernet/Network.c b/drivers/ethernet/Network.c new file mode 100644 index 0000000..37a651b --- /dev/null +++ b/drivers/ethernet/Network.c @@ -0,0 +1,64 @@ +#include "Network.h" +#include "Console.h" +#include "intel/E1000.h" +#include "interface/Arp.h" +#include "realtek/RTL8139.h" + +static NetworkDevice g_network_devices[MAX_NETWORK_DEVICES]; +static int g_device_count = 0; + +void Net_Initialize(void) { + PrintKernel("Initializing network devices...\n"); + g_device_count = 0; + ArpInit(); + + + // Try to initialize E1000 + if (E1000_Init() == 0) { + Net_RegisterDevice("E1000", (send_packet_t)E1000_SendPacket, (get_mac_t)E1000_GetDevice, E1000_HandleReceive); + } + + // Try to initialize RTL8139 + Rtl8139_Init(); + const Rtl8139Device* rtl_dev = GetRtl8139Device(); + if (rtl_dev && rtl_dev->io_base) { // Check if init was successful + Net_RegisterDevice("RTL8139", (send_packet_t)Rtl8139_SendPacket, (get_mac_t)GetRtl8139Device, Rtl8139_HandleReceive); + } +} + +void Net_RegisterDevice(const char* name, send_packet_t sender, get_mac_t mac_getter, poll_receive_t poller) { + if (g_device_count < MAX_NETWORK_DEVICES) { + NetworkDevice* dev = &g_network_devices[g_device_count++]; + // Simple string copy + int i = 0; + while(name[i] != '\0' && i < 31) { + dev->name[i] = name[i]; + i++; + } + dev->name[i] = '\0'; + + dev->send_packet = sender; + dev->get_mac_address = mac_getter; + dev->poll_receive = poller; + PrintKernel("Registered network device: "); + PrintKernel(name); + PrintKernel("\n"); + } else { + PrintKernel("Cannot register more network devices.\n"); + } +} + +NetworkDevice* Net_GetDevice(int index) { + if (index < g_device_count) { + return &g_network_devices[index]; + } + return NULL; +} + +void Net_Poll(void) { + for (int i = 0; i < g_device_count; i++) { + if (g_network_devices[i].poll_receive) { + g_network_devices[i].poll_receive(); + } + } +} diff --git a/drivers/ethernet/Network.h b/drivers/ethernet/Network.h new file mode 100644 index 0000000..a3b5cd7 --- /dev/null +++ b/drivers/ethernet/Network.h @@ -0,0 +1,30 @@ +#ifndef NETWORK_H +#define NETWORK_H + +#include + +#define MAX_NETWORK_DEVICES 4 + +// Forward declaration +struct NetworkDevice; + +// Function pointer types +typedef int (*send_packet_t)(const void* data, uint16_t len); +typedef const uint8_t* (*get_mac_t)(void); +typedef void (*poll_receive_t)(void); + +// Represents a generic network device +typedef struct NetworkDevice { + char name[32]; + send_packet_t send_packet; + get_mac_t get_mac_address; + poll_receive_t poll_receive; +} NetworkDevice; + +// Public functions +void Net_Initialize(void); +void Net_RegisterDevice(const char* name, send_packet_t sender, get_mac_t mac_getter, poll_receive_t poller); +NetworkDevice* Net_GetDevice(int index); +void Net_Poll(void); + +#endif // NETWORK_H diff --git a/drivers/ethernet/intel/E1000.c b/drivers/ethernet/intel/E1000.c index 539d867..b3ed100 100644 --- a/drivers/ethernet/intel/E1000.c +++ b/drivers/ethernet/intel/E1000.c @@ -1,4 +1,6 @@ #include "E1000.h" +#include "../interface/Arp.h" +#include "../interface/Ip.h" #include "Console.h" #include "Cpu.h" #include "Io.h" @@ -6,6 +8,7 @@ #include "MemOps.h" #include "PCI/PCI.h" #include "PMem.h" +#include "ethernet/Packet.h" static E1000Device g_e1000_device = {0}; @@ -185,4 +188,30 @@ int E1000_SendPacket(const void* data, uint16_t length) { const E1000Device* E1000_GetDevice(void) { return g_e1000_device.initialized ? &g_e1000_device : NULL; +} + +void E1000_HandleReceive(void) { + if (!g_e1000_device.initialized) { + return; + } + + uint16_t old_cur; + while (g_e1000_device.rx_descs[g_e1000_device.rx_cur].status & 1) { + uint8_t* received_data = g_e1000_device.rx_buffers[g_e1000_device.rx_cur]; + uint16_t received_length = g_e1000_device.rx_descs[g_e1000_device.rx_cur].length; + + EthernetHeader* eth_header = (EthernetHeader*)received_data; + + if (eth_header->ethertype == HTONS(0x0800)) { // IPv4 + IpHandlePacket((IpHeader*)(received_data + sizeof(EthernetHeader)), received_length - sizeof(EthernetHeader)); + } else if (eth_header->ethertype == HTONS(0x0806)) { // ARP + ArpHandlePacket(eth_header, received_length); + } + + // Reset descriptor + g_e1000_device.rx_descs[g_e1000_device.rx_cur].status = 0; + old_cur = g_e1000_device.rx_cur; + g_e1000_device.rx_cur = (g_e1000_device.rx_cur + 1) % E1000_NUM_RX_DESC; + E1000_WriteReg(E1000_RDT, old_cur); + } } \ No newline at end of file diff --git a/drivers/ethernet/intel/E1000.h b/drivers/ethernet/intel/E1000.h index 50e5d98..1c0a787 100644 --- a/drivers/ethernet/intel/E1000.h +++ b/drivers/ethernet/intel/E1000.h @@ -86,5 +86,6 @@ typedef struct { int E1000_Init(void); int E1000_SendPacket(const void* data, uint16_t length); const E1000Device* E1000_GetDevice(void); +void E1000_HandleReceive(void); #endif // VOIDFRAME_E1000_H \ No newline at end of file diff --git a/drivers/ethernet/interface/Arp.c b/drivers/ethernet/interface/Arp.c new file mode 100644 index 0000000..0c586a4 --- /dev/null +++ b/drivers/ethernet/interface/Arp.c @@ -0,0 +1,84 @@ +#include "Arp.h" +#include "../Network.h" +#include "Console.h" +#include "Ip.h" +#include "MemOps.h" +#include "stdbool.h" + +static ArpCacheEntry g_arp_cache[ARP_CACHE_SIZE]; + +void ArpInit(void) { + for (int i = 0; i < ARP_CACHE_SIZE; i++) { + g_arp_cache[i].state = ARP_STATE_EMPTY; + } + PrintKernel("ARP cache initialized.\n"); +} + +static void ArpSendRequest(uint8_t ip[4]) { + NetworkDevice* net_dev = Net_GetDevice(0); + if (!net_dev) return; + + FullArpPacket packet; + + // Ethernet Header + memset(packet.eth.dest_mac, 0xFF, 6); // Broadcast + const uint8_t* src_mac = net_dev->get_mac_address(); + FastMemcpy(packet.eth.src_mac, src_mac, 6); + packet.eth.ethertype = HTONS(0x0806); // ARP + + // ARP Packet + packet.arp.hardware_type = HTONS(1); // Ethernet + packet.arp.protocol_type = HTONS(0x0800); // IPv4 + packet.arp.hardware_addr_len = 6; + packet.arp.protocol_addr_len = 4; + packet.arp.opcode = HTONS(1); // Request + + FastMemcpy(packet.arp.sender_mac, src_mac, 6); + // Hardcoded IP for now + packet.arp.sender_ip[0] = 10; + packet.arp.sender_ip[1] = 0; + packet.arp.sender_ip[2] = 2; + packet.arp.sender_ip[3] = 15; + + memset(packet.arp.target_mac, 0, 6); + FastMemcpy(packet.arp.target_ip, ip, 4); + + net_dev->send_packet(&packet, sizeof(FullArpPacket)); + PrintKernel("ARP request sent for IP: "); + // Print IP + PrintKernel("\n"); +} + +bool ArpResolve(uint8_t ip[4], uint8_t out_mac[6]) { + for (int i = 0; i < ARP_CACHE_SIZE; i++) { + if (g_arp_cache[i].state == ARP_STATE_RESOLVED && FastMemcmp(g_arp_cache[i].ip, ip, 4) == 0) { + FastMemcpy(out_mac, g_arp_cache[i].mac, 6); + return true; + } + } + + // Not in cache, send a request + ArpSendRequest(ip); + return false; +} + +void ArpHandlePacket(const EthernetHeader* eth_header, uint16_t len) { + if (len < sizeof(EthernetHeader) + sizeof(ArpPacket)) { + return; + } + + const ArpPacket* arp_packet = (const ArpPacket*)((uint8_t*)eth_header + sizeof(EthernetHeader)); + + if (arp_packet->opcode == HTONS(2)) { // Reply + // Add to cache + for (int i = 0; i < ARP_CACHE_SIZE; i++) { + if (g_arp_cache[i].state == ARP_STATE_EMPTY) { + g_arp_cache[i].state = ARP_STATE_RESOLVED; + FastMemcpy(g_arp_cache[i].ip, arp_packet->sender_ip, 4); + FastMemcpy(g_arp_cache[i].mac, arp_packet->sender_mac, 6); + PrintKernel("ARP reply received, added to cache.\n"); + return; + } + } + } +} diff --git a/drivers/ethernet/interface/Arp.h b/drivers/ethernet/interface/Arp.h new file mode 100644 index 0000000..96874fc --- /dev/null +++ b/drivers/ethernet/interface/Arp.h @@ -0,0 +1,28 @@ +#ifndef ARP_H +#define ARP_H + +#include +#include "../Packet.h" +#include "stdbool.h" + +#define ARP_CACHE_SIZE 16 + +typedef enum { + ARP_STATE_EMPTY, + ARP_STATE_RESOLVING, + ARP_STATE_RESOLVED +} ArpCacheEntryState; + +typedef struct { + uint8_t ip[4]; + uint8_t mac[6]; + ArpCacheEntryState state; +} ArpCacheEntry; + +void ArpInit(void); +void ArpHandlePacket(const EthernetHeader* eth_header, uint16_t len); +// Returns true if the MAC is known, false if an ARP request was sent. +// The caller should then wait and retry. +bool ArpResolve(uint8_t ip[4], uint8_t out_mac[6]); + +#endif // ARP_H diff --git a/drivers/ethernet/interface/Icmp.c b/drivers/ethernet/interface/Icmp.c new file mode 100644 index 0000000..9e3e303 --- /dev/null +++ b/drivers/ethernet/interface/Icmp.c @@ -0,0 +1,79 @@ +#include "Icmp.h" +#include "Ip.h" +#include "Console.h" +#include "KernelHeap.h" +#include "MemOps.h" + +static uint16_t IcmpChecksum(const void* data, size_t length) { + const uint16_t* buf = data; + uint32_t sum = 0; + while (length > 1) { + sum += *buf++; + length -= 2; + } + if (length > 0) { + sum += *(const uint8_t*)buf; + } + while (sum >> 16) { + sum = (sum & 0xFFFF) + (sum >> 16); + } + return (uint16_t)~sum; +} + +void IcmpHandlePacket(const IpHeader* ip_header, const IcmpHeader* icmp_header, uint16_t len) { + if (len < sizeof(IcmpHeader)) { + return; + } + + if (icmp_header->type == ICMP_TYPE_ECHO_REQUEST) { + PrintKernel("ICMP: Echo request received.\n"); + + // Create a reply + uint8_t* reply_packet = KernelMemoryAlloc(len); + IcmpHeader* reply_header = (IcmpHeader*)reply_packet; + + reply_header->type = ICMP_TYPE_ECHO_REPLY; + reply_header->code = 0; + reply_header->identifier = icmp_header->identifier; + reply_header->sequence_number = icmp_header->sequence_number; + + // Copy data from original packet + FastMemcpy(reply_packet + sizeof(IcmpHeader), (uint8_t*)icmp_header + sizeof(IcmpHeader), len - sizeof(IcmpHeader)); + + // Calculate checksum + reply_header->checksum = 0; + reply_header->checksum = IcmpChecksum(reply_packet, len); + + // Send the reply + IpSend(ip_header->src_ip, IP_PROTOCOL_ICMP, reply_packet, len); + + KernelFree(reply_packet); + } else if (icmp_header->type == ICMP_TYPE_ECHO_REPLY) { + PrintKernel("ICMP: Echo reply received!\n"); + } +} + +void IcmpSendEchoRequest(uint8_t dest_ip[4]) { + uint16_t packet_size = sizeof(IcmpHeader) + 32; // 32 bytes of data + uint8_t* packet = KernelMemoryAlloc(packet_size); + IcmpHeader* icmp_header = (IcmpHeader*)packet; + + icmp_header->type = ICMP_TYPE_ECHO_REQUEST; + icmp_header->code = 0; + icmp_header->identifier = HTONS(1234); // Arbitrary identifier + icmp_header->sequence_number = HTONS(1); // Simple sequence number + + // Fill data with some pattern + for (int i = 0; i < 32; i++) { + packet[sizeof(IcmpHeader) + i] = i; + } + + // Calculate checksum + icmp_header->checksum = 0; + icmp_header->checksum = IcmpChecksum(packet, packet_size); + + PrintKernel("Sending ICMP Echo Request...\n"); + IpSend(dest_ip, IP_PROTOCOL_ICMP, packet, packet_size); + + KernelFree(packet); +} diff --git a/drivers/ethernet/interface/Icmp.h b/drivers/ethernet/interface/Icmp.h new file mode 100644 index 0000000..5bc1534 --- /dev/null +++ b/drivers/ethernet/interface/Icmp.h @@ -0,0 +1,21 @@ +#ifndef ICMP_H +#define ICMP_H + +#include +#include "Ip.h" + +#define ICMP_TYPE_ECHO_REPLY 0 +#define ICMP_TYPE_ECHO_REQUEST 8 + +typedef struct { + uint8_t type; + uint8_t code; + uint16_t checksum; + uint16_t identifier; + uint16_t sequence_number; +} __attribute__((packed)) IcmpHeader; + +void IcmpHandlePacket(const IpHeader* ip_header, const IcmpHeader* icmp_header, uint16_t len); +void IcmpSendEchoRequest(uint8_t dest_ip[4]); + +#endif // ICMP_H diff --git a/drivers/ethernet/interface/Ip.c b/drivers/ethernet/interface/Ip.c new file mode 100644 index 0000000..f4f0787 --- /dev/null +++ b/drivers/ethernet/interface/Ip.c @@ -0,0 +1,96 @@ +#include "Ip.h" +#include "../Network.h" +#include "Arp.h" +#include "Console.h" +#include "KernelHeap.h" +#include "MemOps.h" +#include "ethernet/interface/Icmp.h" + + +static uint16_t IpChecksum(const void* data, size_t length) { + const uint16_t* buf = data; + uint32_t sum = 0; + while (length > 1) { + sum += *buf++; + length -= 2; + } + if (length > 0) { + sum += *(const uint8_t*)buf; + } + while (sum >> 16) { + sum = (sum & 0xFFFF) + (sum >> 16); + } + return (uint16_t)~sum; +} + +void IpSend(uint8_t dest_ip[4], uint8_t protocol, const void* data, uint16_t len) { + NetworkDevice* net_dev = Net_GetDevice(0); + if (!net_dev) { + PrintKernel("IP: No network device found.\n"); + return; + } + + uint8_t dest_mac[6]; + if (!ArpResolve(dest_ip, dest_mac)) { + PrintKernel("IP: Destination MAC not in ARP cache, sending ARP request.\n"); + // For now, we don't handle queuing the packet. The packet is dropped. + return; + } + + uint16_t total_len = sizeof(IpHeader) + len; + uint8_t* packet = KernelMemoryAlloc(total_len); + IpHeader* ip_header = (IpHeader*)packet; + + // Fill IP header + ip_header->version_ihl = (4 << 4) | 5; // IPv4, 5 * 32-bit words + ip_header->dscp_ecn = 0; + ip_header->total_length = HTONS(total_len); + ip_header->identification = HTONS(1); // Simple static ID + ip_header->flags_fragment = 0; + ip_header->ttl = 64; + ip_header->protocol = protocol; + // Get our IP address (hardcoded for now) + ip_header->src_ip[0] = 10; + ip_header->src_ip[1] = 0; + ip_header->src_ip[2] = 2; + ip_header->src_ip[3] = 15; + FastMemcpy(ip_header->dest_ip, dest_ip, 4); + + // Calculate checksum + ip_header->header_checksum = 0; + ip_header->header_checksum = IpChecksum(ip_header, sizeof(IpHeader)); + + // Copy data + FastMemcpy(packet + sizeof(IpHeader), data, len); + + // Now, wrap it in an Ethernet frame + uint16_t eth_total_len = sizeof(EthernetHeader) + total_len; + uint8_t* eth_frame = KernelMemoryAlloc(eth_total_len); + EthernetHeader* eth_header = (EthernetHeader*)eth_frame; + + FastMemcpy(eth_header->dest_mac, dest_mac, 6); + const uint8_t* src_mac = net_dev->get_mac_address(); + FastMemcpy(eth_header->src_mac, src_mac, 6); + eth_header->ethertype = HTONS(0x0800); // IPv4 + + FastMemcpy(eth_frame + sizeof(EthernetHeader), packet, total_len); + + // Send it! + net_dev->send_packet(eth_frame, eth_total_len); + + KernelFree(packet); + KernelFree(eth_frame); + + PrintKernel("IP: Sent packet!\n"); +} + +void IpHandlePacket(const IpHeader* ip_header, uint16_t len) { + if (ip_header->protocol == IP_PROTOCOL_ICMP) { + IcmpHandlePacket(ip_header, (const IcmpHeader*)((uint8_t*)ip_header + sizeof(IpHeader)), len - sizeof(IpHeader)); + } else { + // For now, just print information about the received packet + PrintKernel("IP: Received packet! Protocol: "); + PrintKernelInt(ip_header->protocol); + PrintKernel("\n"); + } +} \ No newline at end of file diff --git a/drivers/ethernet/interface/Ip.h b/drivers/ethernet/interface/Ip.h new file mode 100644 index 0000000..86012dd --- /dev/null +++ b/drivers/ethernet/interface/Ip.h @@ -0,0 +1,33 @@ +#ifndef IP_H +#define IP_H + +#include +#include "ethernet/Packet.h" + +#define IP_PROTOCOL_ICMP 1 +#define IP_PROTOCOL_TCP 6 +#define IP_PROTOCOL_UDP 17 + +// IPv4 Header +typedef struct { + uint8_t version_ihl; // Version (4 bits) + IHL (4 bits) + uint8_t dscp_ecn; // Differentiated Services Code Point (6 bits) + Explicit Congestion Notification (2 bits) + uint16_t total_length; // Total length of the packet + uint16_t identification; // Identification field + uint16_t flags_fragment; // Flags (3 bits) + Fragment offset (13 bits) + uint8_t ttl; // Time to Live + uint8_t protocol; // Protocol (e.g., TCP, UDP, ICMP) + uint16_t header_checksum; // Header checksum + uint8_t src_ip[4]; + uint8_t dest_ip[4]; +} __attribute__((packed)) IpHeader; + +_Static_assert(sizeof(IpHeader) == 20, "IpHeader must be 20 bytes"); + +// Function to send an IP packet +void IpSend(uint8_t dest_ip[4], uint8_t protocol, const void* data, uint16_t len); + +// Function to handle a received IP packet +void IpHandlePacket(const IpHeader* ip_header, uint16_t len); + +#endif // IP_H diff --git a/drivers/ethernet/realtek/RTL8139.c b/drivers/ethernet/realtek/RTL8139.c index 8af4ce3..f4a6f0e 100644 --- a/drivers/ethernet/realtek/RTL8139.c +++ b/drivers/ethernet/realtek/RTL8139.c @@ -2,8 +2,11 @@ #include "../../../mm/KernelHeap.h" #include "../../../mm/MemOps.h" #include "../../../mm/VMem.h" +#include "../interface/Arp.h" +#include "../interface/Ip.h" #include "Console.h" #include "Io.h" +#include "ethernet/Packet.h" // Global device object static Rtl8139Device rtl_device; @@ -118,3 +121,27 @@ const Rtl8139Device* GetRtl8139Device() { return &rtl_device; } +void Rtl8139_HandleReceive() { + uint16_t status = inw(rtl_device.io_base + REG_ISR); + + if (status & ISR_RX_OK) { + uint8_t* received_data = rtl_device.rx_buffer + rtl_device.current_rx_offset; + uint16_t packet_len = *(uint16_t*)(received_data + 2); + + EthernetHeader* eth_header = (EthernetHeader*)received_data; + if (eth_header->ethertype == HTONS(0x0800)) { // IPv4 + IpHandlePacket((IpHeader*)(received_data + sizeof(EthernetHeader)), packet_len - sizeof(EthernetHeader)); + } else if (eth_header->ethertype == HTONS(0x0806)) { // ARP + ArpHandlePacket(eth_header, packet_len); + } + + rtl_device.current_rx_offset = (rtl_device.current_rx_offset + packet_len + 4 + 3) & ~3; + if (rtl_device.current_rx_offset > RX_BUFFER_SIZE) { + rtl_device.current_rx_offset -= RX_BUFFER_SIZE; + } + + outw(rtl_device.io_base + REG_CAPR, rtl_device.current_rx_offset - 0x10); + outw(rtl_device.io_base + REG_ISR, ISR_RX_OK); + } +} + diff --git a/drivers/ethernet/realtek/RTL8139.h b/drivers/ethernet/realtek/RTL8139.h index 8265caa..c6aa2e5 100644 --- a/drivers/ethernet/realtek/RTL8139.h +++ b/drivers/ethernet/realtek/RTL8139.h @@ -50,11 +50,13 @@ typedef struct { uint8_t* rx_buffer; uint8_t* tx_buffers[TX_BUFFER_COUNT]; int current_tx_buffer; + uint16_t current_rx_offset; } Rtl8139Device; // Function Prototypes void Rtl8139_Init(); void Rtl8139_SendPacket(void* data, uint32_t len); const Rtl8139Device* GetRtl8139Device(); +void Rtl8139_HandleReceive(); #endif // RTL8139_H \ No newline at end of file diff --git a/kernel/core/Kernel.c b/kernel/core/Kernel.c index 078e6dc..4cbe93a 100644 --- a/kernel/core/Kernel.c +++ b/kernel/core/Kernel.c @@ -1,6 +1,6 @@ // VoidFrame Kernel Entry File #include "Kernel.h" -#include "realtek/RTL8139.h" + #include "Compositor.h" #include "Console.h" #include "EXT/Ext2.h" @@ -30,7 +30,7 @@ #include "VFS.h" #include "VMem.h" #include "Vesa.h" -#include "ethernet/intel/E1000.h" +#include "ethernet/Network.h" #include "sound/Generic.h" #include "storage/AHCI.h" #include "stdbool.h" @@ -725,13 +725,9 @@ static InitResultT PXS2(void) { PciInit(); PrintKernelSuccess("System: PCI devices scanned\n"); - PrintKernel("Info: Initializing RTL8139 Driver...\n"); - Rtl8139_Init(); - PrintKernelSuccess("System: RTL8139 Driver initialized\n"); - - PrintKernel("Info: Initializing E1000 Driver...\n"); - E1000_Init(); - PrintKernelSuccess("System: E1000 Driver initialized\n"); + PrintKernel("Info: Initializing Network Stack...\n"); + Net_Initialize(); + PrintKernelSuccess("System: Network Stack initialized\n"); #endif #ifdef VF_CONFIG_ENABLE_GENERIC_SOUND diff --git a/kernel/etc/Shell.c b/kernel/etc/Shell.c index 2cc0a34..010f13f 100644 --- a/kernel/etc/Shell.c +++ b/kernel/etc/Shell.c @@ -1,9 +1,10 @@ #include "Shell.h" +#include "../../drivers/ethernet/interface/Icmp.h" #include "6502/6502.h" -#include "realtek/RTL8139.h" #include "Cerberus.h" #include "Console.h" #include "Editor.h" +#include "ExecLoader.h" #include "Format.h" #include "FsUtils.h" #include "ISA.h" @@ -14,6 +15,7 @@ #include "MemOps.h" #include "PCI/PCI.h" #include "PMem.h" +#include "POST.h" #include "PS2.h" #include "Packet.h" #include "Panic.h" @@ -26,11 +28,10 @@ #include "VFS.h" #include "VMem.h" #include "intel/E1000.h" +#include "realtek/RTL8139.h" #include "sound/Generic.h" #include "stdlib.h" #include "xHCI/xHCI.h" -#include "ExecLoader.h" -#include "POST.h" #define DATE __DATE__ #define TIME __TIME__ @@ -1155,7 +1156,33 @@ static void RegDumpHandler(const char * args) { PrintKernelSuccess("Registers dumped.\n"); } +static void PingHandler(const char* args) { + char* ip_str = GetArg(args, 1); + if (!ip_str) { + PrintKernel("Usage: ping \n"); + return; + } + + uint8_t ip[4]; + int i = 0; + char* octet = strtok(ip_str, '.'); + while (octet != NULL && i < 4) { + ip[i++] = atoi(octet); + octet = strtok(NULL, '.'); + } + + if (i != 4) { + PrintKernel("Invalid IP address format.\n"); + KernelFree(ip_str); + return; + } + + IcmpSendEchoRequest(ip); + KernelFree(ip_str); +} + static const ShellCommand commands[] = { + {"help", HelpHandler}, {"ps", PSHandler}, {"sched", SchedHandler}, @@ -1204,6 +1231,7 @@ static const ShellCommand commands[] = { {"6502", Entry6502}, {"regdump", RegDumpHandler}, {"post", POSTHandler}, + {"ping", PingHandler}, }; void ExecuteCommand(const char* cmd) { diff --git a/kernel/etc/StringOps.c b/kernel/etc/StringOps.c index 4de7670..3d8894f 100644 --- a/kernel/etc/StringOps.c +++ b/kernel/etc/StringOps.c @@ -1,4 +1,5 @@ -#include "StringOps.h" +// #include "StringOps.h" +#include "KernelHeap.h" int StringLength(const char* str) { // simpler than FasStrlen, if (!str) return 0; @@ -165,4 +166,48 @@ void itoa(uint64_t n, char* buffer) { *--p = '0' + n; strcpy(buffer, p); -} \ No newline at end of file +} + +char* strtok(char* s, char d) { + // Stores the state of string + static char* input = NULL; + + // Initialize the input string + if (s != NULL) + input = s; + + // Case for final token + if (input == NULL) + return NULL; + + // Stores the extracted string + char* result = KernelMemoryAlloc(StringLength(input) + 1); + int i = 0; + + // Start extracting string and + // store it in array + for (; input[i] != '\0'; i++) { + + // If delimiter is not reached + // then add the current character + // to result[i] + if (input[i] != d) + result[i] = input[i]; + + // Else store the string formed + else { + result[i] = '\0'; + input = input + i + 1; + return result; + } + } + + // Case when loop ends + result[i] = '\0'; + input = NULL; + + // Return the resultant pointer + // to the string + return result; +} + diff --git a/kernel/etc/StringOps.h b/kernel/etc/StringOps.h index 1548575..d0a373c 100644 --- a/kernel/etc/StringOps.h +++ b/kernel/etc/StringOps.h @@ -2,17 +2,18 @@ #define VOIDFRAME_STRINGOPS_H #include "stdint.h" -int FastStrCmp(const char* str1, const char* str2); -size_t FastStrlen(const char* s, size_t max); -void FastStrCopy(char* dst, const char* src, size_t max_len); -const char* FastStrChr(const char* str, int c); -int StringLength(const char* str); -int FastStrnCmp(const char* str1, const char* str2, size_t n); +extern int FastStrCmp(const char* str1, const char* str2); +extern size_t FastStrlen(const char* s, size_t max); +extern void FastStrCopy(char* dst, const char* src, size_t max_len); +extern const char* FastStrChr(const char* str, int c); +extern int StringLength(const char* str); +extern int FastStrnCmp(const char* str1, const char* str2, size_t n); +extern char* strtok(char* s, char d); -void strncpy(char* dest, const char* src, size_t max_len); -void strcpy(char* dest, const char* src); -void strcat(char* dest, const char* src); -void htoa(uint64_t n, char* buffer); -void itoa(uint64_t n, char* buffer); +extern void strncpy(char* dest, const char* src, size_t max_len); +extern void strcpy(char* dest, const char* src); +extern void strcat(char* dest, const char* src); +extern void htoa(uint64_t n, char* buffer); +extern void itoa(uint64_t n, char* buffer); #endif // VOIDFRAME_STRINGOPS_H diff --git a/kernel/etc/objects/panic.o b/kernel/etc/objects/panic.o index 3c5199b020c43365a3c04e2750f575f8da38d35e..d1055f1ea735489c6a229cbccf3b86b3f1d6d46a 100644 GIT binary patch delta 2613 zcmaJ@NlX-382+Uj8oIHYt%t2T!64f~VIpS0Xs`!V6cCLpQO7N6Fdp17(O{~@m!N?l z9Rj5hWRXPC5Nrin0|Z3$f{7jmGl%gox0%CaGKq&d&ij6NH6-mCd3kxpUyn4O z4o*x=4DWvI*fH{Yy{53V-~5h>ilV)H_tMFeC*eqwzJ2?4ayp%K;J^Voa^wiXHwwUu zi;JV9M~@Pm;BYwL2)20t{{7guT*>m=Vx38c61Uq;hYlU0g9i_i%jIHTad9!de*Kyn z8yl&jq9QDh{)clP93;Yv z>G$v7r$8V;n>TN!*49>9TwFw?`JX#??$DVtXP9^Q?p>;>sUc0%XmD`Q)R~f!LVbOG ze1h@uah5@>o;`a;YuB!2IpuP=bb5N4PrY^PRtkkeI*!Rg6B82zV|MM@MU|D6^!Dvr zQ$aW!CK$70#|}Du`ZT?K`I3f)hWKB^7r27|Ga5XlW9QDD9IKg`8M4_{+t`EB5~`}I zGCVOJZ&>=}7w0}W7>)-Z-VYx>O)iO6Xr#|@&-ByTXq3m6gSZx7+Q62g;s5f6k&PQbYuR!bN!@nUT0kJ~K0u z3mP&i5+_ca&^d!a1Vl$in@kAh=jSgmmoHx?zu(V$!5(W#fQZ7e!phW#-O@fI z`Ms8@6DSxbo1s-^SOTgI*Y>FEiEnFYDPvzn5OGG zr;1e`Ed-#vFJ*KtDyA+k=*a-Qt@(w>Am;!|0V8rj4J0KcDU@JzZf@>3jb75>Gymc0 zFDfcx!m{_n>F>3_oeiktYuB!s+d~8az<5xwd-ra-b?X+Ra$N8m{=qC#(B9roC_8|X zK~mvZvUSQ{q@#l(eyR~7-k&~w;t-%wqHUmC18g?i7abkNE9V_mS64G1Awxwrw zE)86H5HgsE%b?SS4I9i7htTok#}$+3&ZSG27*`4u^J^jameDJ91OizBQXxRkK@1gG z92N5a=B!^>Sl|Y#_;_Ptq9veG`sGkSqXoQs_l`Y^8HLk6dGdtitP>eB@-ARx{;uWe z<>lpk2|!0j!$W^j(*Ti2xr2sm-?C*3Z-NCw^y9~mW^_SAWx*&I1YK!qX&{>+!1wv{ z=V^3wlyyqubn{jM7hSn>g&sV3K*PhsgzY38=pP=Q>E|os(%5dQAHX6 delta 1132 zcma)5%}X0W6n}~NsM%(BlWf{-GC?s7wSrVMm(qwXrcf}2U=LLYR#YrP4-)X81k7Q) z3A&(6wL%aSQwZ8sL;Ps8sXY|zhiA{FQt(jFKcG7UZmm%3gSY$U?eER}_V?Z#&JQ2X z4`;9mn{frUU@Nv^JHCM{u>*7XCU#;T3s}T1?8Y7}VK2UgZ(|>pu^$IEQ0=6eIN>}V z4>UG5g2UlZ75VR_m-GAm5Q#*z{<)BjE;`N?(QxbOYz>O zOG$`Eqj1rtr>7yC&BDmY2o#G&=8PhkPvvAy{8uH|m^DC+zR< zgUMtva#vu;^BnTptyU{7QWbBgp`if+fdF)Lbbu_&Y!CX+`r*u7E>|)82K{vCVvwm4 zZy~V)k{K_;)R0^`as;UZdxtvbnZaSTYy}do??d=6o6xkl- zav9p&+ZnCZ)m1Q?&E$9k-P00zj(jX5sU?+4K|CHePNTv2_&78-HygPtFl15^yiHWe za5&5g1VI3w&&QmqNon=>_ZyonE-pfKb+tYPWT=e9;=2#%kf{>;ilnj5&Q2H{95m20 zSXfwqnwlCTcO47`^E?llrUC8Expj4Q!NkM_bDPb^*eQx~{@DWC+uLNUkC(~G7bF#< z-x#@H5B`%*;SrTN{i2huPZN zf`fwtIzfihiMnjGhZh;@0!T17HwVkh%aG6KK~+`IuMj!@L1*hTSD_=w{ZkYqQ+>SU i&uZut)v5`Rye0Y#xO0YLS|a_7Og#x&iphBJ%=8=X(GyJo diff --git a/kernel/etc/objects/splash1.o b/kernel/etc/objects/splash1.o index 51ca091436d32428a9562a821d74249d4a204a09..0a1d104b88df019ce09aff8b6daf5b052f74f665 100644 GIT binary patch delta 2610 zcmaJ@Sxi((6ur_98X9_G>0$A827(GqRG5evB^qcKWEDtQRH9(ipnixOCK61yT8R>j z(lJsPKyXPA9pkht4FQ7U@}r4g7=Mg2$$ZRwOmq@I=5y*)TW_9Z^d?=e>fYP;-MZ&4 z?`?nE+x|8`Tf!okg=s93MKLRjW--jhVp$xsGY4}r7mH^JERiKKH~WqyvlN!f(%8~5 zJ^Ko;e(%sMt5>h)O|6bp{&B{xSyruD#Xq#W+=1$7ez#lCx7O9wk;mf+cq=W(j~@?s zgCW8G$0oIZ>g(&Ho}L~$ckUcbPft^Fax$4IF)@)QCnxFr`SWz`+BLd)^Cm?^MDXMR zeJgh@acY*lygXsLr`X{SRHs`T8XCyybcU7==zrN7%gV~k#way4m4ts(Utdq{?d^sv zKR=%a1_q2XHt?#TpupgrIB|mZ?AfEvd~ihnF>CYY&2;eKL22~TrAs87Q3|wW%NA;B zX`!5)9RA_1?(snq6B8rfzIX3la=YDz^32SPv5$(1qMDi-I&k0sWn^R+{Nmzbve|63 zYu7GnYHA|HMiFE#my4R4n+Y+nTCIqK^mymaop^7F(v?q>cLpCu91aKV-o2X|8yhJ$ zHde~kuU}73pFX9wwl*p+FAs^U|7qhzkxs2#T+aA=cXu~sWo6OO&=94kryG21o;`c^ z#resTCtsWeGTisk?%{b8y3X@T9h%SY_tSp+Rixw6ZjM(<}_R^6fN2Kif_3Kny zTT8mG)2&;#43jA-DKt1ZC~q)6J}z~D)uTs`XxXx5Qcr~(A)TF_mA5V`DxzR8h+9gy zXkuc5Zrr#*$fSyj3VQM4g<&8R3K5*ywrv|7K75#_rl#o5ojdq50biUI{h!m2DI2Aw zr4p;TxjC{}EFyj}>C%(R%1ZuynZq3tfq84=zZ|t|RY*+`03RM6mV4YRE-p^))iOUn zueS0D<7SGCjKs|YUN`@FUU&JBkcb=-YsHEc5=gWD*w~mvVfpgq^5UAN5q_{UIyx#< zQJ_ErgrY@hA(4@^N7ql$)Cy7Kjx!jEI6DGgk=^ zTf26xlwm{(jEx<||)|=y!B<5PC>!YbzBN781^8LV2OTK=%CkbGmr( zqVYR>_N-Jzv@cw^AluA?2M;9A=kv)dG3%p!fK>E_j!zbpn>v>RZk$P}oc_cvR^%a<=@^Hg#?F)h&&P%cAa9-zsBUcGuH zBZ~Qi+upx_U+S5sF?7Ut0MGnG&+(O%l*kVNbaV7N^cOW{fjr6`JY@UEjT_}luwa0` zdGp3V7d%uJoPtBJm6nzUwgCb5$BrGNhYuf0o5DGt@kN3Voj!e*#aIlb6M7y@?~0_6SU$B*Sp@p&Uc6B!%+-V#3W!cV%#3TNf25WH@=CBUyu>qgKXK^();u>tiJQlEs&G;O)U@Nxa^Y{X`V+mixjx}_3QVxG5 z&+I%`)!5ib>WInt$4ny82Le~+^ZCfn0sbC&GKqY-@S2gltQ9z6X=w?@#>SvnEP~(f zC#hP&cH^%gRF0{sDM+PKFgiL4g+c*(dV1u*Ew&^1{2Vpq!m~>0ArnV-Gst=eAq1 zWbiI;yGf;VyWK275CpK>?aZj0lvZC~pIU5TVFBvv>*at%hRR4Ryn2m3Qdwp$@f>M; zkHn{uNCf)(`_&BU%+Jq5LqmfaI}L_{d7g({E(f$h$D^yO3nnHenCbO;#xM{F94~XQ zxw%Qc&6*@~R8l&1^iE;v|G-!tkv9iOe5kY&wzs#zU@)*Or_%{rTU*RmBxe89V5n9r zD=TDhK(xu>8rH&=mKK&zKk;}Ry1Tp8IX#7tWWT!ef+ z4=$IBWlT>`Lu+d*^Z$q0*w}!*y**Iw(y@_2kMR3eRZ^lyP9~F(PNyN8&4Mh;pu8S( p_=(=Cw?-08Dw=t}BQ%pxoXS}fiFyQ%T>gQAxp1sA9SJ$LzW|c