Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions arch/x86_64/interrupts/Interrupts.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "Pic.h"
#include "StackTrace.h"
#include "PageFaultHandler.h"
#include "ethernet/Network.h"

volatile uint32_t PITTicks = 0;

Expand All @@ -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;

Expand Down
36 changes: 21 additions & 15 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
> assembler-0 @ voidframe-kernel - 18:57 - 13-09-2025
64 changes: 64 additions & 0 deletions drivers/ethernet/Network.c
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
30 changes: 30 additions & 0 deletions drivers/ethernet/Network.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef NETWORK_H
#define NETWORK_H

#include <stdint.h>

#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
29 changes: 29 additions & 0 deletions drivers/ethernet/intel/E1000.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#include "E1000.h"
#include "../interface/Arp.h"
#include "../interface/Ip.h"
#include "Console.h"
#include "Cpu.h"
#include "Io.h"
#include "KernelHeap.h"
#include "MemOps.h"
#include "PCI/PCI.h"
#include "PMem.h"
#include "ethernet/Packet.h"

static E1000Device g_e1000_device = {0};

Expand Down Expand Up @@ -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);
}
}
1 change: 1 addition & 0 deletions drivers/ethernet/intel/E1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
84 changes: 84 additions & 0 deletions drivers/ethernet/interface/Arp.c
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
}
28 changes: 28 additions & 0 deletions drivers/ethernet/interface/Arp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef ARP_H
#define ARP_H

#include <stdint.h>
#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
Loading