From 5cf65a757b7f7806ef30c58e2fa7d50cb0b47acf Mon Sep 17 00:00:00 2001 From: Leonmmcoset Date: Sat, 25 Apr 2026 10:08:05 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=96=E7=BD=91=E9=80=9A=E8=AE=AF+TTY?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 52 ++-- Makefile | 3 + cleonos/CMakeLists.txt | 2 +- cleonos/c/apps/help_main.c | 8 +- cleonos/c/apps/ifconfig_main.c | 101 ++++++++ cleonos/c/apps/nslookup_main.c | 353 ++++++++++++++++++++++++++++ cleonos/c/include/cleonos_syscall.h | 24 +- cleonos/c/src/syscall.c | 26 +- clks | 2 +- docs/syscall.md | 28 ++- 10 files changed, 552 insertions(+), 47 deletions(-) create mode 100644 cleonos/c/apps/ifconfig_main.c create mode 100644 cleonos/c/apps/nslookup_main.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 35a1464..390121b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,17 @@ set(OBJCOPY_FOR_TARGET "llvm-objcopy" CACHE STRING "objcopy tool for limine conf set(OBJDUMP_FOR_TARGET "llvm-objdump" CACHE STRING "objdump tool for limine configure") set(READELF_FOR_TARGET "llvm-readelf" CACHE STRING "readelf tool for limine configure") -set(QEMU_X86_64 "qemu-system-x86_64" CACHE STRING "QEMU executable") +set(QEMU_X86_64 "qemu-system-x86_64" CACHE STRING "QEMU executable") +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + set(_cleonos_qemu_kvm_default ON) +else() + set(_cleonos_qemu_kvm_default OFF) +endif() +set(CLEONOS_QEMU_ENABLE_KVM ${_cleonos_qemu_kvm_default} CACHE BOOL "Enable QEMU KVM acceleration for run/debug targets") +set(CLEONOS_QEMU_ACCEL_ARGS "") +if(CLEONOS_QEMU_ENABLE_KVM) + list(APPEND CLEONOS_QEMU_ACCEL_ARGS -enable-kvm -cpu host) +endif() set(CLEONOS_SOURCE_DIR "${CMAKE_SOURCE_DIR}/cleonos") if(EXISTS "${CLEONOS_SOURCE_DIR}/CMakeLists.txt") @@ -348,27 +358,27 @@ if(CLEONOS_ENABLE) add_custom_target(iso ALL DEPENDS "${ISO_IMAGE}") add_dependencies(iso setup-tools setup-limine kernel ramdisk) - add_custom_target(run - COMMAND ${CMAKE_COMMAND} - "-DNO_COLOR=${NO_COLOR}" - "-DLOG_LEVEL=STEP" - "-DLOG_TEXT=launching qemu run" - -P "${CL_LOG_EMIT_SCRIPT}" - COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio - DEPENDS iso disk-image - USES_TERMINAL - ) + add_custom_target(run + COMMAND ${CMAKE_COMMAND} + "-DNO_COLOR=${NO_COLOR}" + "-DLOG_LEVEL=STEP" + "-DLOG_TEXT=launching qemu run" + -P "${CL_LOG_EMIT_SCRIPT}" + COMMAND ${QEMU_X86_64} ${CLEONOS_QEMU_ACCEL_ARGS} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio + DEPENDS iso disk-image + USES_TERMINAL + ) - add_custom_target(debug - COMMAND ${CMAKE_COMMAND} - "-DNO_COLOR=${NO_COLOR}" - "-DLOG_LEVEL=STEP" - "-DLOG_TEXT=launching qemu debug (-s -S)" - -P "${CL_LOG_EMIT_SCRIPT}" - COMMAND ${QEMU_X86_64} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio -s -S - DEPENDS iso disk-image - USES_TERMINAL - ) + add_custom_target(debug + COMMAND ${CMAKE_COMMAND} + "-DNO_COLOR=${NO_COLOR}" + "-DLOG_LEVEL=STEP" + "-DLOG_TEXT=launching qemu debug (-s -S)" + -P "${CL_LOG_EMIT_SCRIPT}" + COMMAND ${QEMU_X86_64} ${CLEONOS_QEMU_ACCEL_ARGS} -M pc -m 1024M -boot order=d -cdrom "${ISO_IMAGE}" -drive "file=${DISK_IMAGE},format=raw,if=none,id=clksdisk,media=disk" -device "ide-hd,drive=clksdisk,bus=ide.0" -netdev "user,id=clksnet0" -device "e1000,netdev=clksnet0" -serial stdio -s -S + DEPENDS iso disk-image + USES_TERMINAL + ) else() add_custom_target(clks-default ALL DEPENDS kernel) endif() diff --git a/Makefile b/Makefile index fe617e5..45f48c6 100644 --- a/Makefile +++ b/Makefile @@ -236,6 +236,9 @@ help: > $(Q)echo " make run V=1" > $(Q)echo " make run SHOW_COMMANDS=1" > $(Q)echo " (includes CMake build internals: compiler/linker command lines)" +> $(Q)echo "QEMU KVM toggle:" +> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_KVM=ON' # force on" +> $(Q)echo " make run CMAKE_EXTRA_ARGS='-DCLEONOS_QEMU_ENABLE_KVM=OFF' # force off" > $(Q)echo "" > $(Q)echo "Pass custom CMake cache args via:" > $(Q)echo " make configure CMAKE_EXTRA_ARGS='-DLIMINE_SKIP_CONFIGURE=1 -DOBJCOPY_FOR_TARGET=objcopy'" diff --git a/cleonos/CMakeLists.txt b/cleonos/CMakeLists.txt index dbc40c3..4485429 100644 --- a/cleonos/CMakeLists.txt +++ b/cleonos/CMakeLists.txt @@ -128,7 +128,7 @@ list(SORT DOOMGENERIC_DEP_SOURCES_ABS) set(USER_SHELL_COMMAND_APPS help args ls cat grep head tail wc cut uniq sort pwd cd exec pid spawn wait sleep yield - ping + ping ifconfig nslookup bg fg jobs kill ps top procstat sysstat diskinfo mkfsfat32 mount partctl diff --git a/cleonos/c/apps/help_main.c b/cleonos/c/apps/help_main.c index 33221b7..9b41b66 100644 --- a/cleonos/c/apps/help_main.c +++ b/cleonos/c/apps/help_main.c @@ -32,9 +32,11 @@ static int ush_cmd_help(void) { ush_writeln(" diskinfo"); ush_writeln(" mkfsfat32 [label]"); ush_writeln(" mount [path] (default suggested: /temp/disk)"); - ush_writeln(" partctl (mbr partition control: list/init-mbr/create/delete/set-boot)"); - ush_writeln(" ping [count]"); - ush_writeln(" pid"); + ush_writeln(" partctl (mbr partition control: list/init-mbr/create/delete/set-boot)"); + ush_writeln(" ping [count]"); + ush_writeln(" ifconfig"); + ush_writeln(" nslookup "); + ush_writeln(" pid"); ush_writeln(" spawn [args...] / bg [args...]"); ush_writeln(" wait / fg [pid]"); ush_writeln(" kill [signal]"); diff --git a/cleonos/c/apps/ifconfig_main.c b/cleonos/c/apps/ifconfig_main.c new file mode 100644 index 0000000..dac2bc8 --- /dev/null +++ b/cleonos/c/apps/ifconfig_main.c @@ -0,0 +1,101 @@ +#include "cmd_runtime.h" +#include + +static void ush_ifconfig_print_ipv4(u64 ipv4_be) { + unsigned int a = (unsigned int)((ipv4_be >> 24ULL) & 0xFFULL); + unsigned int b = (unsigned int)((ipv4_be >> 16ULL) & 0xFFULL); + unsigned int c = (unsigned int)((ipv4_be >> 8ULL) & 0xFFULL); + unsigned int d = (unsigned int)(ipv4_be & 0xFFULL); + + (void)printf("%u.%u.%u.%u", a, b, c, d); +} + +static int ush_cmd_ifconfig(const char *arg) { + u64 available; + u64 ip; + u64 netmask; + u64 gateway; + u64 dns; + + if (arg != (const char *)0 && arg[0] != '\0') { + if (ush_streq(arg, "--help") != 0 || ush_streq(arg, "-h") != 0) { + (void)puts("usage: ifconfig"); + return 1; + } + (void)puts("ifconfig: usage ifconfig"); + return 0; + } + + available = cleonos_sys_net_available(); + if (available == 0ULL) { + (void)puts("ifconfig: network unavailable"); + return 0; + } + + ip = cleonos_sys_net_ipv4_addr(); + netmask = cleonos_sys_net_netmask(); + gateway = cleonos_sys_net_gateway(); + dns = cleonos_sys_net_dns_server(); + + (void)fputs("inet: ", 1); + ush_ifconfig_print_ipv4(ip); + (void)putchar('\n'); + + (void)fputs("netmask: ", 1); + ush_ifconfig_print_ipv4(netmask); + (void)putchar('\n'); + + (void)fputs("gateway: ", 1); + ush_ifconfig_print_ipv4(gateway); + (void)putchar('\n'); + + (void)fputs("dns: ", 1); + ush_ifconfig_print_ipv4(dns); + (void)putchar('\n'); + + return 1; +} + +int cleonos_app_main(void) { + ush_cmd_ctx ctx; + ush_cmd_ret ret; + ush_state sh; + char initial_cwd[USH_PATH_MAX]; + int has_context = 0; + int success = 0; + const char *arg = ""; + + ush_zero(&ctx, (u64)sizeof(ctx)); + ush_zero(&ret, (u64)sizeof(ret)); + ush_init_state(&sh); + ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd); + + if (ush_command_ctx_read(&ctx) != 0) { + if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "ifconfig") != 0) { + has_context = 1; + arg = ctx.arg; + if (ctx.cwd[0] == '/') { + ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd); + ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd); + } + } + } + + success = ush_cmd_ifconfig(arg); + + if (has_context != 0) { + if (ush_streq(sh.cwd, initial_cwd) == 0) { + ret.flags |= USH_CMD_RET_FLAG_CWD; + ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd); + } + + if (sh.exit_requested != 0) { + ret.flags |= USH_CMD_RET_FLAG_EXIT; + ret.exit_code = sh.exit_code; + } + + (void)ush_command_ret_write(&ret); + } + + return (success != 0) ? 0 : 1; +} diff --git a/cleonos/c/apps/nslookup_main.c b/cleonos/c/apps/nslookup_main.c new file mode 100644 index 0000000..9b779e1 --- /dev/null +++ b/cleonos/c/apps/nslookup_main.c @@ -0,0 +1,353 @@ +#include "cmd_runtime.h" +#include + +#define USH_DNS_QUERY_MAX 512U + +typedef unsigned char u8; +typedef unsigned short u16; + +static u16 ush_dns_read_be16(const u8 *ptr) { + return (u16)(((u16)ptr[0] << 8U) | (u16)ptr[1]); +} + +static void ush_dns_write_be16(u8 *ptr, u16 value) { + ptr[0] = (u8)((value >> 8U) & 0xFFU); + ptr[1] = (u8)(value & 0xFFU); +} + +static void ush_dns_print_ipv4_be(u64 ipv4_be) { + unsigned int a = (unsigned int)((ipv4_be >> 24ULL) & 0xFFULL); + unsigned int b = (unsigned int)((ipv4_be >> 16ULL) & 0xFFULL); + unsigned int c = (unsigned int)((ipv4_be >> 8ULL) & 0xFFULL); + unsigned int d = (unsigned int)(ipv4_be & 0xFFULL); + (void)printf("%u.%u.%u.%u", a, b, c, d); +} + +static int ush_dns_encode_qname(const char *host, u8 *out, u64 out_cap, u64 *out_len) { + const char *p; + u64 at = 0ULL; + + if (host == (const char *)0 || out == (u8 *)0 || out_len == (u64 *)0 || out_cap < 2ULL || host[0] == '\0') { + return 0; + } + + p = host; + while (*p != '\0') { + const char *dot = p; + u64 label_len; + u64 i; + + while (*dot != '\0' && *dot != '.') { + dot++; + } + + label_len = (u64)(dot - p); + if (label_len == 0ULL || label_len > 63ULL) { + return 0; + } + + if (at + 1ULL + label_len + 1ULL > out_cap) { + return 0; + } + + out[at++] = (u8)label_len; + for (i = 0ULL; i < label_len; i++) { + out[at++] = (u8)p[i]; + } + + if (*dot == '.') { + p = dot + 1; + } else { + p = dot; + } + } + + out[at++] = 0U; + *out_len = at; + return 1; +} + +static int ush_dns_skip_name(const u8 *msg, u64 msg_len, u64 *io_off) { + u64 pos; + u64 depth = 0ULL; + int jumped = 0; + + if (msg == (const u8 *)0 || io_off == (u64 *)0 || *io_off >= msg_len) { + return 0; + } + + pos = *io_off; + while (depth < 32ULL) { + u8 len; + + if (pos >= msg_len) { + return 0; + } + + len = msg[pos]; + if (len == 0U) { + if (jumped == 0) { + *io_off = pos + 1ULL; + } + return 1; + } + + if ((len & 0xC0U) == 0xC0U) { + u16 ptr; + + if (pos + 1ULL >= msg_len) { + return 0; + } + ptr = (u16)(((u16)(len & 0x3FU) << 8U) | (u16)msg[pos + 1ULL]); + if ((u64)ptr >= msg_len) { + return 0; + } + + if (jumped == 0) { + *io_off = pos + 2ULL; + jumped = 1; + } + + pos = (u64)ptr; + depth++; + continue; + } + + if ((len & 0xC0U) != 0U) { + return 0; + } + + if (pos + 1ULL + (u64)len > msg_len) { + return 0; + } + + pos += 1ULL + (u64)len; + if (jumped == 0) { + *io_off = pos; + } + depth++; + } + + return 0; +} + +static int ush_dns_parse_response(const u8 *resp, u64 resp_len, u16 expected_id) { + u16 id; + u16 flags; + u16 qdcount; + u16 ancount; + u16 i; + u64 off = 12ULL; + int found = 0; + + if (resp == (const u8 *)0 || resp_len < 12ULL) { + return 0; + } + + id = ush_dns_read_be16(&resp[0]); + if (id != expected_id) { + return 0; + } + + flags = ush_dns_read_be16(&resp[2]); + qdcount = ush_dns_read_be16(&resp[4]); + ancount = ush_dns_read_be16(&resp[6]); + + if ((flags & 0x8000U) == 0U) { + return 0; + } + + if ((flags & 0x000FU) != 0U) { + (void)printf("nslookup: server error rcode=%u\n", (unsigned int)(flags & 0x000FU)); + return 0; + } + + for (i = 0U; i < qdcount; i++) { + if (ush_dns_skip_name(resp, resp_len, &off) == 0) { + return 0; + } + if (off + 4ULL > resp_len) { + return 0; + } + off += 4ULL; + } + + for (i = 0U; i < ancount; i++) { + u16 type; + u16 klass; + u16 rdlen; + + if (ush_dns_skip_name(resp, resp_len, &off) == 0) { + return found; + } + if (off + 10ULL > resp_len) { + return found; + } + + type = ush_dns_read_be16(&resp[off + 0ULL]); + klass = ush_dns_read_be16(&resp[off + 2ULL]); + rdlen = ush_dns_read_be16(&resp[off + 8ULL]); + off += 10ULL; + + if (off + (u64)rdlen > resp_len) { + return found; + } + + if (type == 1U && klass == 1U && rdlen == 4U) { + u64 ip = ((u64)resp[off] << 24ULL) | ((u64)resp[off + 1ULL] << 16ULL) | + ((u64)resp[off + 2ULL] << 8ULL) | (u64)resp[off + 3ULL]; + ush_dns_print_ipv4_be(ip); + (void)putchar('\n'); + found++; + } + + off += (u64)rdlen; + } + + return found; +} + +static int ush_cmd_nslookup(const char *arg) { + u64 dns_server; + u8 query[USH_DNS_QUERY_MAX]; + u8 answer[USH_DNS_QUERY_MAX]; + u64 qname_len = 0ULL; + u64 query_len; + u16 txid; + u16 src_port; + cleonos_net_udp_send_req send_req; + int loops; + + if (arg == (const char *)0 || arg[0] == '\0') { + (void)puts("nslookup: usage nslookup "); + return 0; + } + + if (cleonos_sys_net_available() == 0ULL) { + (void)puts("nslookup: network unavailable"); + return 0; + } + + dns_server = cleonos_sys_net_dns_server(); + if (dns_server == 0ULL) { + (void)puts("nslookup: dns server unavailable"); + return 0; + } + + txid = (u16)((cleonos_sys_timer_ticks() ^ 0xA5C3ULL) & 0xFFFFULL); + src_port = (u16)(40000U + (txid % 20000U)); + + (void)memset(query, 0, sizeof(query)); + if (ush_dns_encode_qname(arg, query + 12ULL, (u64)sizeof(query) - 12ULL, &qname_len) == 0) { + (void)puts("nslookup: invalid domain"); + return 0; + } + ush_dns_write_be16(&query[0], txid); + ush_dns_write_be16(&query[2], 0x0100U); + ush_dns_write_be16(&query[4], 1U); + ush_dns_write_be16(&query[6], 0U); + ush_dns_write_be16(&query[8], 0U); + ush_dns_write_be16(&query[10], 0U); + + query_len = 12ULL + qname_len; + if (query_len + 4ULL > (u64)sizeof(query)) { + (void)puts("nslookup: query too large"); + return 0; + } + ush_dns_write_be16(&query[query_len], 1U); + ush_dns_write_be16(&query[query_len + 2ULL], 1U); + query_len += 4ULL; + + send_req.dst_ipv4_be = dns_server; + send_req.dst_port = 53ULL; + send_req.src_port = (u64)src_port; + send_req.payload_ptr = (u64)(usize)query; + send_req.payload_len = query_len; + + if (cleonos_sys_net_udp_send(&send_req) != query_len) { + (void)puts("nslookup: send failed"); + return 0; + } + + (void)fputs("Server: ", 1); + ush_dns_print_ipv4_be(dns_server); + (void)putchar('\n'); + (void)fputs("Query: ", 1); + (void)puts(arg); + (void)puts("Answer:"); + + for (loops = 0; loops < 600; loops++) { + cleonos_net_udp_recv_req recv_req; + u64 got; + u64 src_ip = 0ULL; + u64 src_p = 0ULL; + u64 dst_p = 0ULL; + + recv_req.out_payload_ptr = (u64)(usize)answer; + recv_req.payload_capacity = (u64)sizeof(answer); + recv_req.out_src_ipv4_ptr = (u64)(usize)&src_ip; + recv_req.out_src_port_ptr = (u64)(usize)&src_p; + recv_req.out_dst_port_ptr = (u64)(usize)&dst_p; + + got = cleonos_sys_net_udp_recv(&recv_req); + if (got == 0ULL) { + (void)cleonos_sys_sleep_ticks(2ULL); + continue; + } + + if (src_p != 53ULL || src_ip != dns_server) { + continue; + } + + if (ush_dns_parse_response(answer, got, txid) > 0) { + return 1; + } + } + + (void)puts("nslookup: timeout"); + return 0; +} + +int cleonos_app_main(void) { + ush_cmd_ctx ctx; + ush_cmd_ret ret; + ush_state sh; + char initial_cwd[USH_PATH_MAX]; + int has_context = 0; + int success = 0; + const char *arg = ""; + + ush_zero(&ctx, (u64)sizeof(ctx)); + ush_zero(&ret, (u64)sizeof(ret)); + ush_init_state(&sh); + ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd); + + if (ush_command_ctx_read(&ctx) != 0) { + if (ctx.cmd[0] != '\0' && ush_streq(ctx.cmd, "nslookup") != 0) { + has_context = 1; + arg = ctx.arg; + if (ctx.cwd[0] == '/') { + ush_copy(sh.cwd, (u64)sizeof(sh.cwd), ctx.cwd); + ush_copy(initial_cwd, (u64)sizeof(initial_cwd), sh.cwd); + } + } + } + + success = ush_cmd_nslookup(arg); + + if (has_context != 0) { + if (ush_streq(sh.cwd, initial_cwd) == 0) { + ret.flags |= USH_CMD_RET_FLAG_CWD; + ush_copy(ret.cwd, (u64)sizeof(ret.cwd), sh.cwd); + } + + if (sh.exit_requested != 0) { + ret.flags |= USH_CMD_RET_FLAG_EXIT; + ret.exit_code = sh.exit_code; + } + + (void)ush_command_ret_write(&ret); + } + + return (success != 0) ? 0 : 1; +} diff --git a/cleonos/c/include/cleonos_syscall.h b/cleonos/c/include/cleonos_syscall.h index fc08eb7..bc170ab 100644 --- a/cleonos/c/include/cleonos_syscall.h +++ b/cleonos/c/include/cleonos_syscall.h @@ -172,10 +172,13 @@ typedef struct cleonos_net_udp_recv_req { #define CLEONOS_SYSCALL_DISK_READ_SECTOR 93ULL #define CLEONOS_SYSCALL_DISK_WRITE_SECTOR 94ULL #define CLEONOS_SYSCALL_NET_AVAILABLE 95ULL -#define CLEONOS_SYSCALL_NET_IPV4_ADDR 96ULL -#define CLEONOS_SYSCALL_NET_PING 97ULL -#define CLEONOS_SYSCALL_NET_UDP_SEND 98ULL -#define CLEONOS_SYSCALL_NET_UDP_RECV 99ULL +#define CLEONOS_SYSCALL_NET_IPV4_ADDR 96ULL +#define CLEONOS_SYSCALL_NET_PING 97ULL +#define CLEONOS_SYSCALL_NET_UDP_SEND 98ULL +#define CLEONOS_SYSCALL_NET_UDP_RECV 99ULL +#define CLEONOS_SYSCALL_NET_NETMASK 100ULL +#define CLEONOS_SYSCALL_NET_GATEWAY 101ULL +#define CLEONOS_SYSCALL_NET_DNS_SERVER 102ULL u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); u64 cleonos_sys_log_write(const char *message, u64 length); @@ -273,10 +276,13 @@ u64 cleonos_sys_disk_mounted(void); u64 cleonos_sys_disk_mount_path(char *out_path, u64 out_size); u64 cleonos_sys_disk_read_sector(u64 lba, void *out_sector); u64 cleonos_sys_disk_write_sector(u64 lba, const void *sector_data); -u64 cleonos_sys_net_available(void); -u64 cleonos_sys_net_ipv4_addr(void); -u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget); -u64 cleonos_sys_net_udp_send(const cleonos_net_udp_send_req *req); -u64 cleonos_sys_net_udp_recv(cleonos_net_udp_recv_req *req); +u64 cleonos_sys_net_available(void); +u64 cleonos_sys_net_ipv4_addr(void); +u64 cleonos_sys_net_netmask(void); +u64 cleonos_sys_net_gateway(void); +u64 cleonos_sys_net_dns_server(void); +u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget); +u64 cleonos_sys_net_udp_send(const cleonos_net_udp_send_req *req); +u64 cleonos_sys_net_udp_recv(cleonos_net_udp_recv_req *req); #endif diff --git a/cleonos/c/src/syscall.c b/cleonos/c/src/syscall.c index 8217151..f030a79 100644 --- a/cleonos/c/src/syscall.c +++ b/cleonos/c/src/syscall.c @@ -416,13 +416,25 @@ u64 cleonos_sys_net_available(void) { return cleonos_syscall(CLEONOS_SYSCALL_NET_AVAILABLE, 0ULL, 0ULL, 0ULL); } -u64 cleonos_sys_net_ipv4_addr(void) { - return cleonos_syscall(CLEONOS_SYSCALL_NET_IPV4_ADDR, 0ULL, 0ULL, 0ULL); -} - -u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget) { - return cleonos_syscall(CLEONOS_SYSCALL_NET_PING, dst_ipv4_be, poll_budget, 0ULL); -} +u64 cleonos_sys_net_ipv4_addr(void) { + return cleonos_syscall(CLEONOS_SYSCALL_NET_IPV4_ADDR, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_net_netmask(void) { + return cleonos_syscall(CLEONOS_SYSCALL_NET_NETMASK, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_net_gateway(void) { + return cleonos_syscall(CLEONOS_SYSCALL_NET_GATEWAY, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_net_dns_server(void) { + return cleonos_syscall(CLEONOS_SYSCALL_NET_DNS_SERVER, 0ULL, 0ULL, 0ULL); +} + +u64 cleonos_sys_net_ping(u64 dst_ipv4_be, u64 poll_budget) { + return cleonos_syscall(CLEONOS_SYSCALL_NET_PING, dst_ipv4_be, poll_budget, 0ULL); +} u64 cleonos_sys_net_udp_send(const cleonos_net_udp_send_req *req) { return cleonos_syscall(CLEONOS_SYSCALL_NET_UDP_SEND, (u64)req, 0ULL, 0ULL); diff --git a/clks b/clks index f7c89a3..9c23c27 160000 --- a/clks +++ b/clks @@ -1 +1 @@ -Subproject commit f7c89a3420dd7afcacb4f24c7b049963e801d990 +Subproject commit 9c23c272d092dcfd3b7dfed812f8a358bda7a80e diff --git a/docs/syscall.md b/docs/syscall.md index ae9b6e0..63d9082 100644 --- a/docs/syscall.md +++ b/docs/syscall.md @@ -83,7 +83,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); - `/proc/`:指定 PID 快照文本 - `/proc` 为只读;写入类 syscall 不支持。 -## 4. Syscall 列表(0~99) +## 4. Syscall 列表(0~102) ### 0 `CLEONOS_SYSCALL_LOG_WRITE` @@ -740,7 +740,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); - 参数:无 - 返回:当前 IPv4 地址(`u32`,以网络字节序放在返回值低 32 位)。 -- 说明:当前默认静态地址为 `10.0.2.15`(QEMU usernet 常见配置)。 +- 说明:优先使用 DHCP 自动获取地址;若 DHCP 失败回退到 `10.0.2.15`(QEMU usernet 常见默认值)。 ### 97 `CLEONOS_SYSCALL_NET_PING` @@ -762,6 +762,24 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); - `arg0`: `struct { u64 out_payload_ptr; u64 payload_capacity; u64 out_src_ipv4_ptr; u64 out_src_port_ptr; u64 out_dst_port_ptr; } *req` - 返回:实际拷贝到 `out_payload_ptr` 的字节数;无数据/失败返回 `0`。 - 说明:`out_src_*`/`out_dst_*` 指针可为 `0`(表示不关心该字段)。 + +### 100 `CLEONOS_SYSCALL_NET_NETMASK` + +- 参数:无 +- 返回:当前 IPv4 子网掩码(`u32`,网络字节序,位于返回值低 32 位)。 +- 说明:优先使用 DHCP 下发值;若 DHCP 未提供则按回退策略填充。 + +### 101 `CLEONOS_SYSCALL_NET_GATEWAY` + +- 参数:无 +- 返回:当前 IPv4 默认网关(`u32`,网络字节序,位于返回值低 32 位)。 +- 说明:优先使用 DHCP 下发值;若 DHCP 未提供则按回退策略填充。 + +### 102 `CLEONOS_SYSCALL_NET_DNS_SERVER` + +- 参数:无 +- 返回:当前 DNS 服务器 IPv4(`u32`,网络字节序,位于返回值低 32 位)。 +- 说明:优先使用 DHCP 下发值;若 DHCP 未提供则按回退策略填充。 ## 5. 用户态封装函数 @@ -795,7 +813,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); - `cleonos_sys_disk_present()` / `cleonos_sys_disk_size_bytes()` / `cleonos_sys_disk_sector_count()` - `cleonos_sys_disk_formatted()` / `cleonos_sys_disk_format_fat32()` / `cleonos_sys_disk_mount()` / `cleonos_sys_disk_mounted()` / `cleonos_sys_disk_mount_path()` - `cleonos_sys_disk_read_sector()` / `cleonos_sys_disk_write_sector()` -- `cleonos_sys_net_available()` / `cleonos_sys_net_ipv4_addr()` / `cleonos_sys_net_ping()` +- `cleonos_sys_net_available()` / `cleonos_sys_net_ipv4_addr()` / `cleonos_sys_net_netmask()` / `cleonos_sys_net_gateway()` / `cleonos_sys_net_dns_server()` / `cleonos_sys_net_ping()` - `cleonos_sys_net_udp_send()` / `cleonos_sys_net_udp_recv()` ## 6. 开发注意事项 @@ -807,7 +825,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); ## 7. Wine 兼容说明 -- `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..99`(含 `DL_*`、`FB_*`、`KERNEL_VERSION`、`DISK_*`、`NET_*`)。 +- `wine/cleonos_wine_lib/runner.py` 当前已覆盖到 `0..102`(含 `DL_*`、`FB_*`、`KERNEL_VERSION`、`DISK_*`、`NET_*`)。 - `DL_*`(`77..79`)在 Wine 中为“可运行兼容”实现: - `DL_OPEN`:加载 guest ELF 到当前 Unicorn 地址空间,返回稳定 `handle`,并做引用计数。 - `DL_SYM`:解析 ELF `SYMTAB/DYNSYM` 并返回 guest 可调用地址。 @@ -824,7 +842,7 @@ u64 cleonos_syscall(u64 id, u64 arg0, u64 arg1, u64 arg2); - `DISK_FORMAT_FAT32` 会初始化/重置 Wine rootfs 下的虚拟磁盘目录。 - `DISK_MOUNT`/`DISK_MOUNT_PATH` 支持挂载点管理,并与 `FS_MKDIR/WRITE/APPEND/REMOVE` 的路径规则联动。 - `DISK_READ_SECTOR`/`DISK_WRITE_SECTOR`(`93..94`)在 Wine 中已实现为 512B 原始扇区读写(host 文件后端)。 -- 网络 syscall(`95..99`)在 Wine 当前为兼容占位实现(统一返回 `0`);即 Wine 运行模式下不会提供真实网络收发。 +- 网络 syscall(`95..102`)在 Wine 当前为兼容占位实现(统一返回 `0`);即 Wine 运行模式下不会提供真实网络收发。 - Wine 在运行时崩溃场景下会生成与内核一致格式的“信号编码退出状态”,可通过 `WAITPID` 读取。 - Wine 当前音频 syscall 为占位实现:`AUDIO_AVAILABLE=0`,`AUDIO_PLAY_TONE=0`,`AUDIO_STOP=1`。 - Wine 版本号策略固定为 `85.0.0-wine`(历史兼容号;不会随 syscall 扩展继续增长)。