diff --git a/boredos.iso b/boredos.iso index ebfe321..06cd62a 100644 Binary files a/boredos.iso and b/boredos.iso differ diff --git a/build/cmd.o b/build/cmd.o index 82fb549..f37afaf 100644 Binary files a/build/cmd.o and b/build/cmd.o differ diff --git a/build/icmp.o b/build/icmp.o index 8886576..11a1a99 100644 Binary files a/build/icmp.o and b/build/icmp.o differ diff --git a/build/main.o b/build/main.o index cac14f0..a19f2f5 100644 Binary files a/build/main.o and b/build/main.o differ diff --git a/build/network.o b/build/network.o deleted file mode 100644 index 28dbce2..0000000 Binary files a/build/network.o and /dev/null differ diff --git a/build_error.log b/build_error.log deleted file mode 100644 index 8263bca..0000000 --- a/build_error.log +++ /dev/null @@ -1,33 +0,0 @@ -src/kernel/wm.c: In function 'wm_handle_click': -src/kernel/wm.c:1491:29: warning: this 'if' clause does not guard... [-Wmisleading-indentation] - 1491 | if (col < 0) col = 0; if (row < 0) row = 0; - | ^~ -src/kernel/wm.c:1491:51: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' - 1491 | if (col < 0) col = 0; if (row < 0) row = 0; - | ^~ -src/kernel/wm.c: In function 'wm_handle_mouse': -src/kernel/wm.c:1884:17: error: implicit declaration of function 'cli_cmd_shutdown' [-Wimplicit-function-declaration] - 1884 | cli_cmd_shutdown(NULL); - | ^~~~~~~~~~~~~~~~ -src/kernel/wm.c:1886:17: error: implicit declaration of function 'cli_cmd_reboot' [-Wimplicit-function-declaration] - 1886 | cli_cmd_reboot(NULL); - | ^~~~~~~~~~~~~~ -src/kernel/wm.c:2083:41: warning: this 'if' clause does not guard... [-Wmisleading-indentation] - 2083 | if (col < 0) col = 0; if (row < 0) row = 0; - | ^~ -src/kernel/wm.c:2083:63: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if' - 2083 | if (col < 0) col = 0; if (row < 0) row = 0; - | ^~ -src/kernel/wm.c: At top level: -src/kernel/wm.c:1057:13: warning: 'erase_cursor' defined but not used [-Wunused-function] - 1057 | static void erase_cursor(int x, int y) { - | ^~~~~~~~~~~~ -src/kernel/wm.c:976:13: warning: 'draw_dock_editor' defined but not used [-Wunused-function] - 976 | static void draw_dock_editor(int x, int y) { - | ^~~~~~~~~~~~~~~~ -src/kernel/wm.c:82:13: warning: 'cursor_visible' defined but not used [-Wunused-variable] - 82 | static bool cursor_visible = true; - | ^~~~~~~~~~~~~~ -src/kernel/wm.c:79:12: warning: 'desktop_refresh_timer' defined but not used [-Wunused-variable] - 79 | static int desktop_refresh_timer = 0; - | ^~~~~~~~~~~~~~~~~~~~~ diff --git a/src/kernel/icmp.c b/src/kernel/icmp.c index 368ad65..09fd52a 100644 --- a/src/kernel/icmp.c +++ b/src/kernel/icmp.c @@ -89,4 +89,62 @@ void cli_cmd_ping(char *args) { } } is_pinging = false; +} + +// Syscall version of ping for userland - returns success/failure +int cli_cmd_ping_syscall(ipv4_address_t *dest) { + if (!dest) return -1; + + // Check if network is initialized + if (!network_is_initialized()) { + return -2; // Network not initialized + } + + ipv4_address_t dest_ip = *dest; + + is_pinging = true; + const int payload_size = 8; + uint8_t packet[sizeof(icmp_header_t) + payload_size]; + icmp_header_t *icmp = (icmp_header_t *)packet; + int success_count = 0; + + for (int i = 0; i < 4; i++) { + current_ping_id = ++ping_id_counter; + icmp->type = 8; // Echo Request + icmp->code = 0; + icmp->id = htons(current_ping_id); + icmp->sequence = htons(i + 1); + icmp->checksum = 0; + + // Fill payload + for (int j = 0; j < payload_size; j++) { + packet[sizeof(icmp_header_t) + j] = (uint8_t)('a' + (j % 26)); + } + + icmp->checksum = net_checksum(packet, sizeof(packet)); + + ping_reply_received = false; + ip_send_packet(dest_ip, IP_PROTO_ICMP, packet, sizeof(packet)); + + uint32_t start_ticks = wm_get_ticks(); + while (!ping_reply_received && (wm_get_ticks() - start_ticks) < 180) { // 3 seconds timeout + network_process_frames(); + } + + if (ping_reply_received) { + success_count++; + } + + if (i < 3) { + // Wait a bit before next ping + uint32_t wait_start = wm_get_ticks(); + while ((wm_get_ticks() - wait_start) < 60) { + network_process_frames(); + } + } + } + is_pinging = false; + + // Return number of successful replies + return success_count; } \ No newline at end of file diff --git a/src/kernel/icmp.h b/src/kernel/icmp.h new file mode 100644 index 0000000..db49336 --- /dev/null +++ b/src/kernel/icmp.h @@ -0,0 +1,10 @@ +#ifndef ICMP_H +#define ICMP_H + +#include +#include "network.h" + +void icmp_handle_packet(ipv4_address_t src, void *data, uint16_t len); +int cli_cmd_ping_syscall(ipv4_address_t *dest); + +#endif diff --git a/src/kernel/main.c b/src/kernel/main.c index 613b9fe..362aa76 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -46,13 +46,6 @@ static volatile struct limine_request *const requests_start_marker[] = { NULL }; -__attribute__((used, section(".requests"))) -static volatile struct limine_stack_size_request stack_size_request = { - .id = LIMINE_STACK_SIZE_REQUEST, - .revision = 0, - .stack_size = 1024 * 1024 // 1MB stack -}; - __attribute__((used, section(".requests_end"))) static volatile struct limine_request *const requests_end_marker[] = { NULL diff --git a/src/kernel/man_entries.h b/src/kernel/man_entries.h index 8c359d8..0bfabb4 100644 --- a/src/kernel/man_entries.h +++ b/src/kernel/man_entries.h @@ -31,6 +31,8 @@ void create_man_entries(void) { fat32_mkdir("A:/Library"); fat32_mkdir("A:/Library/man"); + write_man_file("ping", "PING - Send ICMP echo requests\n\nUsage: ping \n\nSends ICMP echo requests to the specified IP address and displays the response times."); + write_man_file("net", "NET - Network utilities\n\nUsage: net init\nnet info\nnet ipset >ip<\nnet udpsend >ip< >port< >message< net ping >ip< net help\n\nA collection of network-related commands."); write_man_file("ls", "LS - List directory contents\n\nUsage: ls [path]\n\nLists files and directories in the current or specified directory."); write_man_file("cat", "CAT - Concatenate and display file contents\n\nUsage: cat \n\nDisplays the text content of the specified file."); write_man_file("man", "MAN - Display manual pages\n\nUsage: man \n\nDisplays help information for the specified command."); diff --git a/src/kernel/process.c b/src/kernel/process.c index b5cb47c..1a1b1af 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -51,8 +51,8 @@ void process_create(void* entry_point, bool is_user) { if (!new_proc->pml4_phys) return; // 2. Allocate aligned stack - void* stack = kmalloc_aligned(524288, 4096); // 512KB for kernel threads - void* kernel_stack = kmalloc_aligned(126976, 16384); // 128KB for ringswitch + void* stack = kmalloc_aligned(4096, 4096); + void* kernel_stack = kmalloc_aligned(16384, 16384); // Needed for when user interrupts to Ring 0 if (is_user) { // Map user stack to 0x800000 @@ -66,7 +66,7 @@ void process_create(void* entry_point, bool is_user) { // Build initial stack frame for iretq // Stack grows down, start at top - uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 126976); + uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 16384); *(--stack_ptr) = 0x1B; // SS (User Data) *(--stack_ptr) = 0x800000 + 4096; // RSP @@ -79,11 +79,11 @@ void process_create(void* entry_point, bool is_user) { // Push 15 zeros for general purpose registers (r15 -> rax) for (int i = 0; i < 15; i++) *(--stack_ptr) = 0; - new_proc->kernel_stack = (uint64_t)kernel_stack + 126976; + new_proc->kernel_stack = (uint64_t)kernel_stack + 16384; new_proc->rsp = (uint64_t)stack_ptr; } else { // Kernel thread - uint64_t* stack_ptr = (uint64_t*)((uint64_t)stack + 524288); + uint64_t* stack_ptr = (uint64_t*)((uint64_t)stack + 4096); *(--stack_ptr) = 0x10; // SS (Kernel Data) stack_ptr--; *stack_ptr = (uint64_t)stack_ptr; // RSP @@ -134,18 +134,17 @@ process_t* process_create_elf(const char* filepath, const char* args_str) { } // 3. Allocate generic User stack and Kernel stack for interrupts - void* stack = kmalloc_aligned(2097152, 4096); // 2MB for user apps - void* kernel_stack = kmalloc_aligned(126976, 16384); // 128KB for interrupts + void* stack = kmalloc_aligned(65536, 4096); + void* kernel_stack = kmalloc_aligned(16384, 16384); - // Map User stack to 0x800000 (starting from 0x600000 for 2MB) - for (uint64_t i = 0; i < 512; i++) { - paging_map_page(new_proc->pml4_phys, 0x800000 - 2097152 + (i * 4096), v2p((uint64_t)stack + (i * 4096)), PT_PRESENT | PT_RW | PT_USER); + // Map User stack to 0x800000 (starting from 0x7F0000 for 64KB) + for (uint64_t i = 0; i < 16; i++) { + paging_map_page(new_proc->pml4_phys, 0x800000 - 65536 + (i * 4096), v2p((uint64_t)stack + (i * 4096)), PT_PRESENT | PT_RW | PT_USER); } - // Parse arguments and push them to the user stack - // We'll place the strings at the very high end of the user stack + int argc = 1; - char *args_buf = (char *)stack + 2097152; + char *args_buf = (char *)stack + 65536; uint64_t user_args_buf = 0x800000; // Copy filepath as argv[0] @@ -197,7 +196,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str) { // Align stack to 8 bytes before pushing argv array uint64_t current_user_sp = user_args_buf; current_user_sp &= ~7ULL; - args_buf = (char *)((uint64_t)stack + (current_user_sp - (0x800000 - 2097152))); + args_buf = (char *)((uint64_t)stack + (current_user_sp - (0x800000 - 65536))); // Push argv array int argv_size = (argc + 1) * sizeof(uint64_t); @@ -215,7 +214,7 @@ process_t* process_create_elf(const char* filepath, const char* args_str) { current_user_sp &= ~15ULL; // 4. Build Stack Frame for context switch via IRETQ - uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 126976); + uint64_t* stack_ptr = (uint64_t*)((uint64_t)kernel_stack + 16384); *(--stack_ptr) = 0x1B; // SS (User Mode Data) *(--stack_ptr) = current_user_sp; // RSP (Updated user stack pointer) *(--stack_ptr) = 0x202; // RFLAGS (Interrupts Enabled) diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index b5ce626..382c416 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -10,6 +10,8 @@ #include "io.h" #include "pci.h" #include "kutils.h" +#include "network.h" +#include "icmp.h" // Read MSR static inline uint64_t rdmsr(uint32_t msr) { @@ -671,6 +673,54 @@ uint64_t syscall_handler_c(uint64_t syscall_num, uint64_t arg1, uint64_t arg2, u return 0; } return -1; + } else if (cmd == 18) { // SYSTEM_CMD_NETWORK_DHCP + return network_dhcp_acquire(); + } else if (cmd == 19) { // SYSTEM_CMD_NETWORK_GET_MAC + mac_address_t *mac = (mac_address_t *)arg2; + if (!mac) return -1; + return network_get_mac_address(mac); + } else if (cmd == 20) { // SYSTEM_CMD_NETWORK_GET_IP + ipv4_address_t *ip = (ipv4_address_t *)arg2; + if (!ip) return -1; + return network_get_ipv4_address(ip); + } else if (cmd == 21) { // SYSTEM_CMD_NETWORK_SET_IP + ipv4_address_t *ip = (ipv4_address_t *)arg2; + if (!ip) return -1; + return network_set_ipv4_address(ip); + } else if (cmd == 22) { // SYSTEM_CMD_UDP_SEND + ipv4_address_t *dest_ip = (ipv4_address_t *)arg2; + uint32_t ports = (uint32_t)arg3; // dest_port in lower 16, src_port in upper 16 + uint16_t dest_port = ports & 0xFFFF; + uint16_t src_port = (ports >> 16) & 0xFFFF; + const void *data = (const void *)arg4; + size_t data_len = (size_t)arg5; + if (!dest_ip || !data) return -1; + return udp_send_packet(dest_ip, dest_port, src_port, data, data_len); + } else if (cmd == 23) { // SYSTEM_CMD_NETWORK_GET_STATS + int stat_type = (int)arg2; + switch (stat_type) { + case 0: return network_get_frames_received(); + case 1: return network_get_udp_packets_received(); + case 2: return network_get_udp_callbacks_called(); + case 3: return network_get_e1000_receive_calls(); + case 4: return network_get_e1000_receive_empty(); + case 5: return network_get_process_calls(); + default: return -1; + } + } else if (cmd == 24) { // SYSTEM_CMD_NETWORK_GET_GATEWAY + ipv4_address_t *ip = (ipv4_address_t *)arg2; + if (!ip) return -1; + return network_get_gateway_ip(ip); + } else if (cmd == 25) { // SYSTEM_CMD_NETWORK_GET_DNS + ipv4_address_t *ip = (ipv4_address_t *)arg2; + if (!ip) return -1; + return network_get_dns_ip(ip); + } else if (cmd == 26) { // SYSTEM_CMD_ICMP_PING + ipv4_address_t *dest_ip = (ipv4_address_t *)arg2; + if (!dest_ip) return -1; + return cli_cmd_ping_syscall(dest_ip); + } else if (cmd == 27) { // SYSTEM_CMD_NETWORK_IS_INIT + return network_is_initialized() ? 1 : 0; } return -1; } diff --git a/src/kernel/userland/calculator.c b/src/kernel/userland/calculator.c index 661eb79..dc39d3f 100644 --- a/src/kernel/userland/calculator.c +++ b/src/kernel/userland/calculator.c @@ -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)) { diff --git a/src/kernel/userland/clear.c b/src/kernel/userland/clear.c index 3219fee..c42d28c 100644 --- a/src/kernel/userland/clear.c +++ b/src/kernel/userland/clear.c @@ -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; } diff --git a/src/kernel/userland/cowsay.c b/src/kernel/userland/cowsay.c index 9cffca3..5d138f3 100644 --- a/src/kernel/userland/cowsay.c +++ b/src/kernel/userland/cowsay.c @@ -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]; } diff --git a/src/kernel/userland/help.c b/src/kernel/userland/help.c index 3d19068..b901e7f 100644 --- a/src/kernel/userland/help.c +++ b/src/kernel/userland/help.c @@ -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 - Change current directory (built-in)\n"); @@ -27,6 +27,6 @@ int main(int argc, char **argv) { printf("man - 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; } diff --git a/src/kernel/userland/libc/syscall.c b/src/kernel/userland/libc/syscall.c index abba093..bc3cc01 100644 --- a/src/kernel/userland/libc/syscall.c +++ b/src/kernel/userland/libc/syscall.c @@ -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); +} + diff --git a/src/kernel/userland/libc/syscall.h b/src/kernel/userland/libc/syscall.h index dd9fc06..94798cf 100644 --- a/src/kernel/userland/libc/syscall.h +++ b/src/kernel/userland/libc/syscall.h @@ -2,6 +2,7 @@ #define SYSCALL_H #include +#include // 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 diff --git a/src/kernel/userland/mv.c b/src/kernel/userland/mv.c index f5346c3..9e8cdd1 100644 --- a/src/kernel/userland/mv.c +++ b/src/kernel/userland/mv.c @@ -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]); diff --git a/src/kernel/userland/net.c b/src/kernel/userland/net.c new file mode 100644 index 0000000..c99a036 --- /dev/null +++ b/src/kernel/userland/net.c @@ -0,0 +1,376 @@ +#include +#include + +// 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; +} diff --git a/src/kernel/userland/pci_list.c b/src/kernel/userland/pci_list.c index 564d56b..3e2e436 100644 --- a/src/kernel/userland/pci_list.c +++ b/src/kernel/userland/pci_list.c @@ -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; diff --git a/src/kernel/userland/ping.c b/src/kernel/userland/ping.c new file mode 100644 index 0000000..9eb2d3e --- /dev/null +++ b/src/kernel/userland/ping.c @@ -0,0 +1,73 @@ +#include +#include + +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; +}