feat: Add Process Manager, Limine Framebuffer GUI, RTL8139 Net stack, and extended UNIX commands

This commit is contained in:
RarDog
2026-09-02 20:10:02 +03:00
parent 521f7ed9ce
commit aa32cffd15
24 changed files with 1446 additions and 72 deletions
+2
View File
@@ -9,6 +9,8 @@ extern "C" {
int puts(const char *s);
int putchar(int c);
int printf(const char *format, ...);
int sprintf(char *str, const char *format, ...);
#ifdef __cplusplus
}
+1
View File
@@ -14,6 +14,7 @@ void *realloc(void *ptr, size_t size);
void abort(void);
void exit(int status);
int atoi(const char *nptr);
#ifdef __cplusplus
}
+2
View File
@@ -17,6 +17,8 @@ int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
char *strchr(const char *s, int c);
char *strstr(const char *haystack, const char *needle);
#ifdef __cplusplus
}
+182
View File
@@ -0,0 +1,182 @@
#include "abi/net.h"
#include "rtl8139.h"
#include "string.h"
#include "stdio.h"
// Default QEMU User Networking (SLIRP) Configuration
// Guest IP: 10.0.2.15 (0x0F02000A)
// Gateway: 10.0.2.2 (0x0202000A)
// Netmask: 255.255.255.0
net_config_t g_net_cfg = {
.ip = (10) | (0 << 8) | (2 << 16) | (15 << 24),
.gateway = (10) | (0 << 8) | (2 << 16) | (2 << 24),
.netmask = (255) | (255 << 8) | (255 << 16) | (0 << 24),
.mac = {0x52, 0x54, 0x00, 0x12, 0x34, 0x56}
};
static uint16_t htons(uint16_t v) {
return (uint16_t)(((v & 0xFF) << 8) | ((v >> 8) & 0xFF));
}
static __attribute__((unused)) uint32_t htonl(uint32_t v) {
return (((v & 0xFF) << 24) |
(((v >> 8) & 0xFF) << 16) |
(((v >> 16) & 0xFF) << 8) |
((v >> 24) & 0xFF));
}
uint16_t net_checksum(const void *buf, size_t len) {
const uint16_t *data = (const uint16_t *)buf;
uint32_t sum = 0;
while (len > 1) {
sum += *data++;
len -= 2;
}
if (len == 1) {
sum += *(const uint8_t *)data;
}
while (sum >> 16) {
sum = (sum & 0xFFFF) + (sum >> 16);
}
return (uint16_t)(~sum);
}
void net_init(void) {
rtl8139_init();
for (int i = 0; i < 6; i++) {
g_net_cfg.mac[i] = g_rtl8139.mac[i];
}
}
int net_send_arp_request(uint32_t target_ip) {
uint8_t packet[64] = {0};
eth_hdr_t *eth = (eth_hdr_t *)packet;
arp_hdr_t *arp = (arp_hdr_t *)(packet + sizeof(eth_hdr_t));
// Broadcast Ethernet Header
memset(eth->dest_mac, 0xFF, 6);
memcpy(eth->src_mac, g_net_cfg.mac, 6);
eth->ethertype = htons(ETHERTYPE_ARP);
// ARP Payload
arp->hw_type = htons(1); // Ethernet
arp->proto_type = htons(0x0800); // IPv4
arp->hw_len = 6;
arp->proto_len = 4;
arp->opcode = htons(1); // Request
memcpy(arp->sender_mac, g_net_cfg.mac, 6);
arp->sender_ip = g_net_cfg.ip;
memset(arp->target_mac, 0x00, 6);
arp->target_ip = target_ip;
return rtl8139_send_packet(packet, sizeof(eth_hdr_t) + sizeof(arp_hdr_t));
}
int net_send_icmp_ping(uint32_t target_ip, uint16_t seq) {
uint8_t packet[98] = {0};
eth_hdr_t *eth = (eth_hdr_t *)packet;
ipv4_hdr_t *ip = (ipv4_hdr_t *)(packet + sizeof(eth_hdr_t));
icmp_hdr_t *icmp = (icmp_hdr_t *)(packet + sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t));
uint8_t *payload = packet + sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(icmp_hdr_t);
// 1. Ethernet Header (Direct to Gateway or Broadcast MAC in QEMU SLIRP)
memset(eth->dest_mac, 0xFF, 6);
memcpy(eth->src_mac, g_net_cfg.mac, 6);
eth->ethertype = htons(ETHERTYPE_IPv4);
// 2. IPv4 Header
ip->version_ihl = 0x45; // Version 4, Header Length 5 (20 bytes)
ip->tos = 0;
ip->total_length = htons(20 + 8 + 32); // IP + ICMP + 32-byte payload = 60 bytes
ip->id = htons(seq);
ip->flags_fragment = htons(0x4000); // Don't Fragment
ip->ttl = 64;
ip->protocol = IP_PROTO_ICMP;
ip->src_ip = g_net_cfg.ip;
ip->dst_ip = target_ip;
ip->checksum = 0;
ip->checksum = net_checksum(ip, 20);
// 3. ICMP Echo Request Header
icmp->type = ICMP_ECHO_REQUEST;
icmp->code = 0;
icmp->id = htons(0x1234);
icmp->sequence = htons(seq);
// 32-byte payload pattern: 'a', 'b', 'c'...
for (int i = 0; i < 32; i++) {
payload[i] = (uint8_t)('a' + (i % 26));
}
icmp->checksum = 0;
icmp->checksum = net_checksum(icmp, 8 + 32);
size_t total_len = sizeof(eth_hdr_t) + 20 + 8 + 32;
return rtl8139_send_packet(packet, (uint16_t)total_len);
}
int net_poll_icmp_reply(uint32_t *from_ip, uint16_t *seq) {
uint8_t buffer[1600];
int len = rtl8139_poll_packet(buffer, sizeof(buffer));
if (len < (int)(sizeof(eth_hdr_t) + sizeof(ipv4_hdr_t) + sizeof(icmp_hdr_t))) {
return 0;
}
eth_hdr_t *eth = (eth_hdr_t *)buffer;
if (htons(eth->ethertype) != ETHERTYPE_IPv4) {
return 0;
}
ipv4_hdr_t *ip = (ipv4_hdr_t *)(buffer + sizeof(eth_hdr_t));
if (ip->protocol != IP_PROTO_ICMP) {
return 0;
}
int ip_hdr_len = (ip->version_ihl & 0x0F) * 4;
icmp_hdr_t *icmp = (icmp_hdr_t *)(buffer + sizeof(eth_hdr_t) + ip_hdr_len);
if (icmp->type == ICMP_ECHO_REPLY) {
if (from_ip) *from_ip = ip->src_ip;
if (seq) *seq = htons(icmp->sequence);
return 1; // Got Echo Reply!
}
return 0;
}
uint32_t parse_ip(const char *str) {
uint32_t parts[4] = {0};
int idx = 0;
while (*str && idx < 4) {
if (*str >= '0' && *str <= '9') {
parts[idx] = parts[idx] * 10 + (*str - '0');
} else if (*str == '.') {
idx++;
}
str++;
}
return (parts[0]) | (parts[1] << 8) | (parts[2] << 16) | (parts[3] << 24);
}
void format_ip(uint32_t ip, char *buf) {
uint8_t *b = (uint8_t *)&ip;
// Simple itoa formatting
int len = 0;
for (int i = 0; i < 4; i++) {
uint8_t val = b[i];
if (val >= 100) {
buf[len++] = '0' + (val / 100);
val %= 100;
buf[len++] = '0' + (val / 10);
val %= 10;
} else if (val >= 10) {
buf[len++] = '0' + (val / 10);
val %= 10;
}
buf[len++] = '0' + val;
if (i < 3) buf[len++] = '.';
}
buf[len] = '\0';
}
+19
View File
@@ -121,3 +121,22 @@ void abort(void) {
void exit(int status) {
sys_exit(status);
}
int atoi(const char *nptr) {
int res = 0;
int sign = 1;
while (*nptr == ' ' || *nptr == '\t' || *nptr == '\n' || *nptr == '\r') {
nptr++;
}
if (*nptr == '-') {
sign = -1;
nptr++;
} else if (*nptr == '+') {
nptr++;
}
while (*nptr >= '0' && *nptr <= '9') {
res = res * 10 + (*nptr - '0');
nptr++;
}
return sign * res;
}
+22
View File
@@ -90,3 +90,25 @@ char *strncpy(char *dest, const char *src, size_t n) {
}
return ret;
}
char *strchr(const char *s, int c) {
char ch = (char)c;
while (*s) {
if (*s == ch) return (char *)s;
s++;
}
if (ch == '\0') return (char *)s;
return NULL;
}
char *strstr(const char *haystack, const char *needle) {
if (!*needle) return (char *)haystack;
size_t needle_len = strlen(needle);
while (*haystack) {
if (strncmp(haystack, needle, needle_len) == 0) {
return (char *)haystack;
}
haystack++;
}
return NULL;
}
+106
View File
@@ -1,4 +1,5 @@
#include "stdio.h"
#include "string.h"
#include "abi/syscalls.h"
#include "abi/types.h"
@@ -15,3 +16,108 @@ int putchar(int c) {
sys_log_debug(&ch, 1);
return c;
}
static int format_uint(char *buf, unsigned long long val, int base, int width, char pad) {
char tmp[32];
int tpos = 0;
const char digits[] = "0123456789abcdef";
if (val == 0) {
tmp[tpos++] = '0';
} else {
while (val > 0) {
tmp[tpos++] = digits[val % base];
val /= base;
}
}
int written = 0;
while (tpos < width) {
buf[written++] = pad;
width--;
}
while (tpos > 0) {
buf[written++] = tmp[--tpos];
}
return written;
}
int vsnprintf(char *buf, size_t size, const char *fmt, __builtin_va_list args) {
if (size == 0) return 0;
size_t out = 0;
while (*fmt && out < size - 1) {
if (*fmt != '%') {
buf[out++] = *fmt++;
continue;
}
fmt++; // skip '%'
char pad = ' ';
int width = 0;
if (*fmt == '0') {
pad = '0';
fmt++;
}
while (*fmt >= '0' && *fmt <= '9') {
width = width * 10 + (*fmt - '0');
fmt++;
}
if (*fmt == 's') {
const char *str = __builtin_va_arg(args, const char *);
if (!str) str = "(null)";
while (*str && out < size - 1) {
buf[out++] = *str++;
}
} else if (*fmt == 'd' || *fmt == 'i') {
long long val = __builtin_va_arg(args, int);
if (val < 0) {
if (out < size - 1) buf[out++] = '-';
val = -val;
}
out += format_uint(buf + out, (unsigned long long)val, 10, width, pad);
} else if (*fmt == 'u') {
unsigned long long val = __builtin_va_arg(args, unsigned int);
out += format_uint(buf + out, val, 10, width, pad);
} else if (*fmt == 'x' || *fmt == 'X') {
unsigned long long val = __builtin_va_arg(args, unsigned int);
out += format_uint(buf + out, val, 16, width, pad);
} else if (*fmt == 'p') {
unsigned long long val = (unsigned long long)__builtin_va_arg(args, void *);
if (out < size - 2) {
buf[out++] = '0';
buf[out++] = 'x';
}
out += format_uint(buf + out, val, 16, 8, '0');
} else if (*fmt == 'c') {
char c = (char)__builtin_va_arg(args, int);
if (out < size - 1) buf[out++] = c;
} else if (*fmt == '%') {
if (out < size - 1) buf[out++] = '%';
}
fmt++;
}
buf[out] = '\0';
return (int)out;
}
int sprintf(char *buf, const char *fmt, ...) {
__builtin_va_list args;
__builtin_va_start(args, fmt);
int ret = vsnprintf(buf, 2048, fmt, args);
__builtin_va_end(args);
return ret;
}
int printf(const char *fmt, ...) {
char buf[1024];
__builtin_va_list args;
__builtin_va_start(args, fmt);
int len = vsnprintf(buf, sizeof(buf), fmt, args);
__builtin_va_end(args);
if (len > 0) {
sys_log_debug(buf, (size_t)len);
}
return len;
}