Network commands port to userspace

This commit is contained in:
boreddevnl
2026-02-27 23:24:43 +01:00
parent 304c2e1383
commit 8a6928b5c9
22 changed files with 680 additions and 69 deletions

View File

@@ -191,17 +191,13 @@ static void calculator_click(int x, int y) {
if (calc_decimal_divisor > 10) {
calc_decimal_divisor /= 10;
long long unit = SCALE / calc_decimal_divisor;
// This removes the last decimal digit
calc_curr = (calc_curr / (unit * 10)) * (unit * 10);
} else {
// Backspace on the dot itself or first decimal
calc_decimal_mode = false;
calc_decimal_divisor = 10;
// Ensure the fractional part is cleared
calc_curr = (calc_curr / SCALE) * SCALE;
}
} else {
// Integer backspace: remove last digit of integer part
calc_curr = (calc_curr / SCALE / 10) * SCALE;
}
}
@@ -240,11 +236,9 @@ int main(void) {
calc_new_entry = true;
update_display();
// First paint
calculator_paint();
ui_mark_dirty(win_calculator, 0, 0, 180, 230);
// Check events from Kernel User Interface queue
gui_event_t ev;
while (1) {
if (ui_get_event(win_calculator, &ev)) {

View File

@@ -3,6 +3,6 @@
int main(int argc, char **argv) {
(void)argc; (void)argv;
sys_system(10, 0, 0, 0, 0); // SYSTEM_CMD_CLEAR_SCREEN
sys_system(10, 0, 0, 0, 0);
return 0;
}

View File

@@ -4,8 +4,6 @@
int main(int argc, char **argv) {
char *msg = (char*)"Bored!";
if (argc > 1) {
// Simple concatenation of args for now
// For simplicity in this demo, just use the first arg
msg = argv[1];
}

View File

@@ -3,7 +3,7 @@
int main(int argc, char **argv) {
(void)argc; (void)argv;
printf("BoredOS CLI Help (Userspace)\n");
printf("BoredOS CLI Help\n");
printf("---------------------------\n");
printf("ls [path] - List directory contents\n");
printf("cd <path> - Change current directory (built-in)\n");
@@ -27,6 +27,6 @@ int main(int argc, char **argv) {
printf("man <cmd> - Show manual page\n");
printf("clear - Clear the screen\n");
printf("exit - Exit the terminal\n");
printf("\nHint: Use Ctrl+C to force quit any running .elf app.\n");
printf("\nHint: Use Ctrl+C to force quit any running application.\n");
return 0;
}

View File

@@ -105,7 +105,7 @@ uint32_t sys_size(int fd) {
return (uint32_t)syscall2(SYS_FS, FS_CMD_SIZE, (uint64_t)fd);
}
int sys_list(const char *path, struct FAT32_FileInfo *entries, int max_entries) {
int sys_list(const char *path, FAT32_FileInfo *entries, int max_entries) {
return (int)syscall4(SYS_FS, FS_CMD_LIST, (uint64_t)path, (uint64_t)entries, (uint64_t)max_entries);
}
@@ -133,3 +133,49 @@ void sys_kill(int pid) {
syscall1(SYS_KILL, (uint64_t)pid);
}
// Network API implementations
int sys_network_init(void) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_INIT, 0);
}
int sys_network_dhcp_acquire(void) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_DHCP, 0);
}
int sys_network_get_mac(net_mac_address_t *mac) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_MAC, (uint64_t)mac);
}
int sys_network_get_ip(net_ipv4_address_t *ip) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_IP, (uint64_t)ip);
}
int sys_network_set_ip(const net_ipv4_address_t *ip) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_SET_IP, (uint64_t)ip);
}
int sys_network_get_stat(int stat_type) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_STATS, (uint64_t)stat_type);
}
int sys_network_get_gateway(net_ipv4_address_t *ip) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_GATEWAY, (uint64_t)ip);
}
int sys_network_get_dns(net_ipv4_address_t *ip) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_GET_DNS, (uint64_t)ip);
}
int sys_udp_send(const net_ipv4_address_t *dest_ip, uint16_t dest_port, uint16_t src_port, const void *data, size_t data_len) {
uint32_t ports = (dest_port & 0xFFFF) | ((src_port & 0xFFFF) << 16);
return (int)syscall5(SYS_SYSTEM, SYSTEM_CMD_UDP_SEND, (uint64_t)dest_ip, (uint64_t)ports, (uint64_t)data, (uint64_t)data_len);
}
int sys_icmp_ping(const net_ipv4_address_t *dest_ip) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_ICMP_PING, (uint64_t)dest_ip);
}
int sys_network_is_initialized(void) {
return (int)syscall2(SYS_SYSTEM, SYSTEM_CMD_NETWORK_IS_INIT, 0);
}

View File

@@ -2,6 +2,7 @@
#define SYSCALL_H
#include <stdint.h>
#include <stddef.h>
// Standard syscalls available from Kernel mode
#define SYS_EXIT 0
@@ -27,6 +28,35 @@
#define FS_CMD_GETCWD 12
#define FS_CMD_CHDIR 13
// System Commands (via SYS_SYSTEM)
#define SYSTEM_CMD_SET_BG_COLOR 1
#define SYSTEM_CMD_SET_BG_PATTERN 2
#define SYSTEM_CMD_SET_WALLPAPER 3
#define SYSTEM_CMD_SET_DESKTOP_PROP 4
#define SYSTEM_CMD_SET_MOUSE_SPEED 5
#define SYSTEM_CMD_NETWORK_INIT 6
#define SYSTEM_CMD_GET_DESKTOP_PROP 7
#define SYSTEM_CMD_GET_MOUSE_SPEED 8
#define SYSTEM_CMD_GET_WALLPAPER_THUMB 9
#define SYSTEM_CMD_CLEAR_SCREEN 10
#define SYSTEM_CMD_RTC_GET 11
#define SYSTEM_CMD_REBOOT 12
#define SYSTEM_CMD_SHUTDOWN 13
#define SYSTEM_CMD_BEEP 14
#define SYSTEM_CMD_MEMINFO 15
#define SYSTEM_CMD_UPTIME 16
#define SYSTEM_CMD_PCI_LIST 17
#define SYSTEM_CMD_NETWORK_DHCP 18
#define SYSTEM_CMD_NETWORK_GET_MAC 19
#define SYSTEM_CMD_NETWORK_GET_IP 20
#define SYSTEM_CMD_NETWORK_SET_IP 21
#define SYSTEM_CMD_UDP_SEND 22
#define SYSTEM_CMD_NETWORK_GET_STATS 23
#define SYSTEM_CMD_NETWORK_GET_GATEWAY 24
#define SYSTEM_CMD_NETWORK_GET_DNS 25
#define SYSTEM_CMD_ICMP_PING 26
#define SYSTEM_CMD_NETWORK_IS_INIT 27
// Internal assembly entry into Ring 0
extern uint64_t syscall0(uint64_t sys_num);
extern uint64_t syscall1(uint64_t sys_num, uint64_t arg1);
@@ -67,4 +97,20 @@ typedef struct {
int sys_list(const char *path, FAT32_FileInfo *entries, int max_entries);
// Network API
typedef struct { uint8_t bytes[6]; } net_mac_address_t;
typedef struct { uint8_t bytes[4]; } net_ipv4_address_t;
int sys_network_init(void);
int sys_network_dhcp_acquire(void);
int sys_network_get_mac(net_mac_address_t *mac);
int sys_network_get_ip(net_ipv4_address_t *ip);
int sys_network_set_ip(const net_ipv4_address_t *ip);
int sys_network_get_stat(int stat_type);
int sys_network_get_gateway(net_ipv4_address_t *ip);
int sys_network_get_dns(net_ipv4_address_t *ip);
int sys_udp_send(const net_ipv4_address_t *dest_ip, uint16_t dest_port, uint16_t src_port, const void *data, size_t data_len);
int sys_icmp_ping(const net_ipv4_address_t *dest_ip);
int sys_network_is_initialized(void);
#endif

View File

@@ -7,7 +7,6 @@ int main(int argc, char **argv) {
return 1;
}
// Simplification: use cp then rm
int fd_in = sys_open(argv[1], "r");
if (fd_in < 0) {
printf("Error: Cannot open source %s\n", argv[1]);

376
src/kernel/userland/net.c Normal file
View File

@@ -0,0 +1,376 @@
#include <stdlib.h>
#include <syscall.h>
// Helper function to print a MAC address
static void print_mac(const net_mac_address_t* mac) {
char buf[64];
int p = 0;
for (int i = 0; i < 6; i++) {
int v = mac->bytes[i];
int hi = (v >> 4) & 0xF;
int lo = v & 0xF;
buf[p++] = (hi < 10) ? ('0' + hi) : ('A' + (hi - 10));
buf[p++] = (lo < 10) ? ('0' + lo) : ('A' + (lo - 10));
if (i < 5) buf[p++] = ':';
}
buf[p] = 0;
printf("%s", buf);
}
// Helper to parse integer from string
static int string_to_int(const char *str) {
int result = 0;
int sign = 1;
if (*str == '-') {
sign = -1;
str++;
}
while (*str >= '0' && *str <= '9') {
result = result * 10 + (*str - '0');
str++;
}
return result * sign;
}
// Helper to get string length
static int string_length(const char *str) {
int len = 0;
while (str[len]) len++;
return len;
}
// Command: netinit - Initialize network and acquire DHCP
static void cmd_netinit(void) {
int r = sys_network_init();
if (r == 0) {
printf("Network initialized\n");
int d = sys_network_dhcp_acquire();
if (d == 0) {
printf("DHCP acquired\n");
} else {
printf("DHCP failed\n");
}
} else {
printf("Network init failed\n");
}
}
// Command: netinfo - Display network information
static void cmd_netinfo(void) {
if (!sys_network_is_initialized()) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return;
}
net_mac_address_t mac;
net_ipv4_address_t ip;
if (sys_network_get_mac(&mac) == 0) {
printf("MAC: ");
print_mac(&mac);
printf("\n");
}
if (sys_network_get_ip(&ip) == 0) {
printf("IP: ");
for (int i = 0; i < 4; i++) {
printf("%d", ip.bytes[i]);
if (i < 3) printf(".");
}
printf("\n");
}
printf("Frames: %d\n", sys_network_get_stat(0));
printf("UDP packets: %d\n", sys_network_get_stat(1));
printf("UDP callbacks: %d\n", sys_network_get_stat(2));
printf("E1000 receive calls: %d\n", sys_network_get_stat(3));
printf("E1000 receive empty: %d\n", sys_network_get_stat(4));
printf("Process calls: %d\n", sys_network_get_stat(5));
}
// Command: ipset - Set IP address manually
static void cmd_ipset(const char *args) {
if (!sys_network_is_initialized()) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return;
}
if (!args || !*args) {
printf("Usage: NET IPSET a.b.c.d\n");
return;
}
net_ipv4_address_t ip = {{0, 0, 0, 0}};
int part = 0;
int val = 0;
int i = 0;
while (args[i]) {
char ch = args[i++];
if (ch >= '0' && ch <= '9') {
val = val * 10 + (ch - '0');
if (val > 255) {
printf("Invalid IP\n");
return;
}
} else if (ch == '.') {
if (part > 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[part++] = (uint8_t)val;
val = 0;
} else {
printf("Invalid IP\n");
return;
}
}
if (part != 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[3] = (uint8_t)val;
if (sys_network_set_ip(&ip) == 0) {
printf("IP set\n");
} else {
printf("IP set failed\n");
}
}
// Command: udpsend - Send UDP packet
static void cmd_udpsend(const char *args) {
if (!sys_network_is_initialized()) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return;
}
if (!args || !*args) {
printf("Usage: NET UDPSEND ip port data\n");
return;
}
// Parse IP address
char ipstr[32];
int pos = 0;
while (args[pos] && args[pos] != ' ') {
ipstr[pos] = args[pos];
pos++;
}
ipstr[pos] = 0;
while (args[pos] == ' ') pos++;
// Parse port
char portstr[16];
int p = 0;
while (args[pos] && args[pos] != ' ') {
portstr[p++] = args[pos++];
}
portstr[p] = 0;
while (args[pos] == ' ') pos++;
// Get data
const char *datastr = args + pos;
// Parse IP
net_ipv4_address_t ip = {{0, 0, 0, 0}};
int idx = 0;
int val = 0;
int j = 0;
while (ipstr[j]) {
char ch = ipstr[j++];
if (ch >= '0' && ch <= '9') {
val = val * 10 + (ch - '0');
if (val > 255) {
printf("Invalid IP\n");
return;
}
} else if (ch == '.') {
if (idx > 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[idx++] = (uint8_t)val;
val = 0;
} else {
printf("Invalid IP\n");
return;
}
}
if (idx != 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[3] = (uint8_t)val;
// Parse port
int port = 0;
int k = 0;
while (portstr[k]) {
char ch = portstr[k++];
if (ch < '0' || ch > '9') {
printf("Invalid port\n");
return;
}
port = port * 10 + (ch - '0');
}
if (port <= 0 || port > 65535) {
printf("Invalid port\n");
return;
}
int len = string_length(datastr);
if (len <= 0) {
printf("No data\n");
return;
}
int r = sys_udp_send(&ip, (uint16_t)port, 12345, datastr, (size_t)len);
if (r == 0) {
printf("Sent\n");
} else {
printf("Send failed\n");
}
}
// Command: ping - Send ICMP ping request
static void cmd_ping(const char *args) {
if (!sys_network_is_initialized()) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return;
}
if (!args || !*args) {
printf("Usage: NET PING a.b.c.d\n");
return;
}
net_ipv4_address_t ip = {{0, 0, 0, 0}};
int idx = 0;
int val = 0;
int j = 0;
while (args[j]) {
char ch = args[j++];
if (ch >= '0' && ch <= '9') {
val = val * 10 + (ch - '0');
if (val > 255) {
printf("Invalid IP\n");
return;
}
} else if (ch == '.') {
if (idx > 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[idx++] = (uint8_t)val;
val = 0;
} else if (ch == ' ' || ch == '\t') {
// Skip whitespace
while (args[j] == ' ' || args[j] == '\t') j++;
j--;
} else {
printf("Invalid IP\n");
return;
}
}
if (idx != 3) {
printf("Invalid IP\n");
return;
}
ip.bytes[3] = (uint8_t)val;
printf("Pinging ");
for (int i = 0; i < 4; i++) {
printf("%d", ip.bytes[i]);
if (i < 3) printf(".");
}
printf("...\n");
int result = sys_icmp_ping(&ip);
if (result == -2) {
printf("Error: Network not initialized. Run 'net init' first.\n");
} else if (result < 0) {
printf("Error: Failed to send ping request.\n");
} else {
printf("Ping complete: %d/%d replies received\n", result, 4);
}
}
// Command: help
static void cmd_help(void) {
printf("Network Commands:\n");
printf(" NET INIT - Initialize network and acquire DHCP\n");
printf(" NET INFO - Display network information\n");
printf(" NET IPSET a.b.c.d - Set IP address\n");
printf(" NET UDPSEND ip port data - Send UDP packet\n");
printf(" NET PING a.b.c.d - Send ICMP ping request\n");
printf(" NET HELP - Show this help\n");
}
int main(int argc, char **argv) {
if (argc < 2) {
cmd_help();
return 1;
}
const char *cmd = argv[1];
// Convert command to uppercase for easier comparison
char cmd_upper[32];
int i = 0;
while (cmd[i] && i < 31) {
char c = cmd[i];
cmd_upper[i] = (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c;
i++;
}
cmd_upper[i] = 0;
// Parse arguments if provided
const char *args = "";
if (argc > 2) {
args = argv[2];
}
if ((string_length(cmd_upper) == 4 &&
cmd_upper[0] == 'I' && cmd_upper[1] == 'N' && cmd_upper[2] == 'I' && cmd_upper[3] == 'T') ||
(string_length(cmd_upper) == 7 &&
cmd_upper[0] == 'N' && cmd_upper[1] == 'E' && cmd_upper[2] == 'T' &&
cmd_upper[3] == 'I' && cmd_upper[4] == 'N' && cmd_upper[5] == 'I' && cmd_upper[6] == 'T')) {
cmd_netinit();
} else if ((string_length(cmd_upper) == 4 &&
cmd_upper[0] == 'I' && cmd_upper[1] == 'N' && cmd_upper[2] == 'F' && cmd_upper[3] == 'O') ||
(string_length(cmd_upper) == 7 &&
cmd_upper[0] == 'N' && cmd_upper[1] == 'E' && cmd_upper[2] == 'T' &&
cmd_upper[3] == 'I' && cmd_upper[4] == 'N' && cmd_upper[5] == 'F' && cmd_upper[6] == 'O')) {
cmd_netinfo();
} else if (string_length(cmd_upper) == 5 &&
cmd_upper[0] == 'I' && cmd_upper[1] == 'P' && cmd_upper[2] == 'S' &&
cmd_upper[3] == 'E' && cmd_upper[4] == 'T') {
cmd_ipset(args);
} else if (string_length(cmd_upper) == 7 &&
cmd_upper[0] == 'U' && cmd_upper[1] == 'D' && cmd_upper[2] == 'P' &&
cmd_upper[3] == 'S' && cmd_upper[4] == 'E' && cmd_upper[5] == 'N' && cmd_upper[6] == 'D') {
cmd_udpsend(args);
} else if (string_length(cmd_upper) == 4 &&
cmd_upper[0] == 'P' && cmd_upper[1] == 'I' && cmd_upper[2] == 'N' && cmd_upper[3] == 'G') {
cmd_ping(args);
} else if (string_length(cmd_upper) == 4 &&
cmd_upper[0] == 'H' && cmd_upper[1] == 'E' && cmd_upper[2] == 'L' && cmd_upper[3] == 'P') {
cmd_help();
} else {
printf("Unknown command: %s\n", cmd);
cmd_help();
return 1;
}
return 0;
}

View File

@@ -10,7 +10,7 @@ typedef struct {
int main(int argc, char **argv) {
(void)argc; (void)argv;
int count = sys_system(17, 0, 0, 0, 0); // Get count
int count = sys_system(17, 0, 0, 0, 0);
if (count < 0) {
printf("Error: Could not retrieve PCI device count.\n");
return 1;

View File

@@ -0,0 +1,73 @@
#include <stdlib.h>
#include <syscall.h>
int main(int argc, char **argv) {
if (argc < 2) {
printf("Usage: ping a.b.c.d\n");
return 1;
}
if (!sys_network_is_initialized()) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return 1;
}
const char *args = argv[1];
net_ipv4_address_t ip = {{0, 0, 0, 0}};
int idx = 0;
int val = 0;
int j = 0;
while (args[j]) {
char ch = args[j++];
if (ch >= '0' && ch <= '9') {
val = val * 10 + (ch - '0');
if (val > 255) {
printf("Invalid IP\n");
return 1;
}
} else if (ch == '.') {
if (idx > 3) {
printf("Invalid IP\n");
return 1;
}
ip.bytes[idx++] = (uint8_t)val;
val = 0;
} else if (ch == ' ' || ch == '\t') {
// Skip whitespace
while (args[j] == ' ' || args[j] == '\t') j++;
j--;
} else {
printf("Invalid IP\n");
return 1;
}
}
if (idx != 3) {
printf("Invalid IP\n");
return 1;
}
ip.bytes[3] = (uint8_t)val;
printf("Pinging ");
for (int i = 0; i < 4; i++) {
printf("%d", ip.bytes[i]);
if (i < 3) printf(".");
}
printf("...\n");
int result = sys_icmp_ping(&ip);
if (result == -2) {
printf("Error: Network not initialized. Run 'net init' first.\n");
return 1;
} else if (result < 0) {
printf("Error: Failed to send ping request.\n");
return 1;
}
printf("Ping complete: %d/%d replies received\n", result, 4);
return 0;
}