Split vnet driver to generic vnet part, tap and file interfaces

Fix most compilation issues of umka_shell on Windows(R)(TM), not all
of them.
This commit is contained in:
Ivan Baravy 2023-02-01 18:30:44 +00:00
parent 0fdfde2b5b
commit be21f83af2
31 changed files with 491 additions and 302 deletions

12
README
View File

@ -89,15 +89,15 @@ Testing
# Copy ACPI tables and PCI configs
$ sudo cp --parents /sys/firmware/acpi/tables/?SDT* /sys/bus/pci/devices/*/config .
# cp --parents /sys/firmware/acpi/tables/?SDT* /sys/bus/pci/devices/*/config .
# Manage tap device
$ sudo ip tuntap add dev tap0 mode tap
$ sudo ip link set tap0 address 00:11:00:00:00:00
$ sudo ip addr add 10.50.0.1/24 dev tap0
$ sudo ip link set up dev tap0
$ sudo ip tuntap del dev tap0 mode tap
# ip tuntap add dev tap0 mode tap
# ip link set tap0 address 00:11:00:00:00:00
# ip addr add 10.50.0.1/24 dev tap0
# ip link set up dev tap0
# ip tuntap del dev tap0 mode tap
Troubleshooting

View File

@ -10,7 +10,7 @@
#ifndef IO_ASYNC_H_INCLUDED
#define IO_ASYNC_H_INCLUDED
#include <unistd.h>
#include <stddef.h>
void *
io_async_init();

142
linux/vnet/tap.c Normal file
View File

@ -0,0 +1,142 @@
/*
SPDX-License-Identifier: GPL-2.0-or-later
UMKa - User-Mode KolibriOS developer tools
vnet - virtual network card, tap interface
Copyright (C) 2023 Ivan Baravy <dunkaist@gmail.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <net/if_arp.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "trace.h"
#include "vnet.h"
#define TAP_DEV "/dev/net/tun"
static STDCALL void
vnet_unload_tap() {
printf("vnet_unload\n");
COVERAGE_ON();
COVERAGE_OFF();
}
static STDCALL void
vnet_reset_tap() {
printf("vnet_reset\n");
COVERAGE_ON();
COVERAGE_OFF();
}
static void
dump_net_buff(net_buff_t *buf) {
for (size_t i = 0; i < buf->length; i++) {
printf("%2.2x ", buf->data[i]);
}
putchar('\n');
}
static STDCALL int
vnet_transmit_tap(net_buff_t *buf) {
struct vnet *net;
__asm__ __inline__ __volatile__ (
"nop"
: "=b"(net)
:
: "memory");
printf("vnet_transmit: %d bytes\n", buf->length);
dump_net_buff(buf);
write(net->fdout, buf->data, buf->length);
buf->length = 0;
COVERAGE_OFF();
COVERAGE_ON();
printf("vnet_transmit: done\n");
return 0;
}
struct vnet *
vnet_init_tap() {
struct ifreq ifr = {.ifr_name = UMKA_VNET_NAME,
.ifr_flags = IFF_TAP | IFF_NO_PI};
int fd, err;
if( (fd = open(TAP_DEV, O_RDWR | O_NONBLOCK)) < 0 ) {
perror("Opening /dev/net/tun");
return NULL;
}
if( (err = ioctl(fd, TUNSETIFF, &ifr)) < 0 ) {
perror("ioctl(TUNSETIFF)");
close(fd);
return NULL;
}
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
memcpy(ifr.ifr_hwaddr.sa_data, (char[]){0x00, 0x11, 0x00, 0x00, 0x00, 0x00}, 6);
if( (err = ioctl(fd, SIOCSIFHWADDR, &ifr)) < 0 ) {
perror("ioctl(SIOCSIFHWADDR)");
close(fd);
return NULL;
}
struct sockaddr_in sai;
sai.sin_family = AF_INET;
sai.sin_port = 0;
sai.sin_addr.s_addr = inet_addr("10.50.0.1");
memcpy(&ifr.ifr_addr, &sai, sizeof(struct sockaddr));
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if ( (err = ioctl(sockfd, SIOCSIFADDR, &ifr)) < 0 ) {
perror("ioctl(SIOCSIFADDR)");
close(fd);
return NULL;
}
sai.sin_addr.s_addr = inet_addr("255.255.255.0");
memcpy(&ifr.ifr_netmask, &sai, sizeof(struct sockaddr));
if ((err = ioctl(sockfd, SIOCSIFNETMASK, &ifr)) < 0) {
perror("ioctl(SIOCSIFNETMASK)");
close(fd);
return NULL;
}
if ((err = ioctl(sockfd, SIOCGIFFLAGS, &ifr)) < 0) {
perror("ioctl(SIOCGIFFLAGS)");
close(fd);
return NULL;
}
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
ifr.ifr_flags &= ~(IFF_BROADCAST | IFF_LOWER_UP);
if ((err = ioctl(sockfd, SIOCSIFFLAGS, &ifr)) < 0) {
perror("ioctl(SIOCSIFFLAGS)");
close(fd);
return NULL;
}
struct vnet *net = malloc(sizeof(struct vnet));
net->netdev.device_type = NET_TYPE_ETH;
net->netdev.mtu = 1514;
net->netdev.name = "UMK0770";
net->netdev.unload = vnet_unload_tap;
net->netdev.reset = vnet_reset_tap;
net->netdev.transmit = vnet_transmit_tap;
net->fdin = fd;
net->fdout = fd;
net->input_processed = 1;
return net;
}

View File

@ -30,15 +30,15 @@ CFLAGS_32=$(CFLAGS) -m32 -D_FILE_OFFSET_BITS=64 -D__USE_TIME_BITS64
LDFLAGS=-no-pie
LDFLAGS_32=$(LDFLAGS) -m32
ifeq ($(HOST),linux)
#ifeq ($(HOST),linux)
FASM_INCLUDE=$(KOLIBRIOS)/kernel/trunk;$(KOLIBRIOS)/programs/develop/libraries/libcrash/hash
FASM=INCLUDE="$(FASM_INCLUDE)" $(FASM_EXE) $(FASM_FLAGS)
else ifeq ($(HOST),windows)
FASM_INCLUDE=$(KOLIBRIOS)\kernel\trunk;$(KOLIBRIOS)\programs\develop\libraries\libcrash\hash
FASM=set "INCLUDE=$(FASM_INCLUDE)" && $(FASM_EXE) $(FASM_FLAGS)
else
$(error your OS is not supported)
endif
#else ifeq ($(HOST),windows)
# FASM_INCLUDE=$(KOLIBRIOS)\kernel\trunk;$(KOLIBRIOS)\programs\develop\libraries\libcrash\hash
# FASM=set "INCLUDE=$(FASM_INCLUDE)" && $(FASM_EXE) $(FASM_FLAGS)
#else
# $(error your OS is not supported)
#endif
ifeq ($(HOST),linux)
all: umka_shell umka_fuse umka_os umka_gen_devices_dat umka.sym umka.prp \
@ -56,20 +56,21 @@ test: umka_shell
@cd test && make clean all && cd ../
umka_shell: umka_shell.o umka.o shell.o trace.o trace_lbr.o vdisk.o \
vdisk/raw.o vdisk/qcow2.o vdisk/miniz/miniz.a vnet.o lodepng.o \
$(HOST)/pci.o $(HOST)/thread.o io.o $(HOST)/io_async.o umkart.o \
optparse32.o bestline32.o
vdisk/raw.o vdisk/qcow2.o vdisk/miniz/miniz.a vnet.o \
$(HOST)/vnet/tap.o vnet/file.o lodepng.o $(HOST)/pci.o \
$(HOST)/thread.o umkaio.o $(HOST)/io_async.o umkart.o optparse32.o \
bestline32.o
$(CC) $(LDFLAGS_32) $^ -o $@ -T umka.ld
umka_fuse: umka_fuse.o umka.o trace.o trace_lbr.o vdisk.o vdisk/raw.o \
vdisk/qcow2.o vdisk/miniz/miniz.a $(HOST)/pci.o $(HOST)/thread.o \
io.o $(HOST)/io_async.o
umkaio.o $(HOST)/io_async.o
$(CC) $(LDFLAGS_32) $^ -o $@ `pkg-config fuse3 --libs` -T umka.ld
umka_os: umka_os.o umka.o shell.o lodepng.o vdisk.o vdisk/raw.o vdisk/qcow2.o \
vdisk/miniz/miniz.a vnet.o trace.o trace_lbr.o $(HOST)/pci.o \
$(HOST)/thread.o io.o $(HOST)/io_async.o umkart.o bestline32.o \
optparse32.o
vdisk/miniz/miniz.a vnet.o $(HOST)/vnet/tap.o vnet/file.o trace.o \
trace_lbr.o $(HOST)/pci.o $(HOST)/thread.o umkaio.o \
$(HOST)/io_async.o umkart.o bestline32.o optparse32.o
$(CC) $(LDFLAGS_32) `sdl2-config --libs` $^ -o $@ -T umka.ld
umka_gen_devices_dat: umka_gen_devices_dat.o umka.o $(HOST)/pci.o \
@ -82,10 +83,10 @@ umka.o umka.fas: umka.asm
shell.o: shell.c lodepng.h
$(CC) $(CFLAGS_32) -c $<
io.o: io.c io.h
umkaio.o: umkaio.c umkaio.h
$(CC) $(CFLAGS_32) -D_DEFAULT_SOURCE -c $< -o $@
$(HOST)/io_async.o: $(HOST)/io_async.c $(HOST)/io_async.h
$(HOST)/io_async.o: $(HOST)/io_async.c io_async.h
$(CC) $(CFLAGS_32) -D_DEFAULT_SOURCE -c $< -o $@
$(HOST)/thread.o: $(HOST)/thread.c
@ -160,9 +161,15 @@ vdisk/miniz/miniz.o: vdisk/miniz/miniz.c vdisk/miniz/miniz.h
vdisk/miniz/miniz.a: vdisk/miniz/miniz.o vdisk/miniz/miniz_tinfl.o vdisk/miniz/miniz_tdef.o
$(AR) --target=elf32-i386 r $@ $^
vnet.o: vnet.c
vnet.o: vnet.c vnet.h
$(CC) $(CFLAGS_32) -c $<
$(HOST)/vnet/tap.o: $(HOST)/vnet/tap.c vnet/tap.h
$(CC) $(CFLAGS_32) -c $< -o $@
vnet/file.o: vnet/file.c vnet/file.h
$(CC) $(CFLAGS_32) -c $< -o $@
umka_shell.o: umka_shell.c umka.h trace.h
$(CC) $(CFLAGS_32) -c $<

64
shell.c
View File

@ -25,6 +25,9 @@
// TODO: Cleanup
#ifndef _WIN32
#include <arpa/inet.h>
#else
#include <winsock2.h>
#include <io.h>
#endif
#include "shell.h"
@ -78,13 +81,13 @@ umka_run_cmd_sync(struct shell_ctx *ctx) {
}
atomic_store_explicit(&cmd->status, UMKA_CMD_STATUS_DONE,
memory_order_release);
cnd_signal(&ctx->cmd_done);
pthread_cond_signal(&ctx->cmd_done);
}
static void
umka_run_cmd(struct shell_ctx *ctx) {
if (atomic_load_explicit(ctx->running, memory_order_acquire)) {
cnd_wait(&ctx->cmd_done, &ctx->cmd_mutex);
pthread_cond_wait(&ctx->cmd_done, &ctx->cmd_mutex);
} else {
umka_run_cmd_sync(ctx);
}
@ -109,20 +112,20 @@ const char *f70_status_name[] = {
static const char *
get_f70_status_name(int s) {
switch (s) {
case ERROR_SUCCESS:
case KOS_ERROR_SUCCESS:
// return "";
case ERROR_DISK_BASE:
case ERROR_UNSUPPORTED_FS:
case ERROR_UNKNOWN_FS:
case ERROR_PARTITION:
case ERROR_FILE_NOT_FOUND:
case ERROR_END_OF_FILE:
case ERROR_MEMORY_POINTER:
case ERROR_DISK_FULL:
case ERROR_FS_FAIL:
case ERROR_ACCESS_DENIED:
case ERROR_DEVICE:
case ERROR_OUT_OF_MEMORY:
case KOS_ERROR_DISK_BASE:
case KOS_ERROR_UNSUPPORTED_FS:
case KOS_ERROR_UNKNOWN_FS:
case KOS_ERROR_PARTITION:
case KOS_ERROR_FILE_NOT_FOUND:
case KOS_ERROR_END_OF_FILE:
case KOS_ERROR_MEMORY_POINTER:
case KOS_ERROR_DISK_FULL:
case KOS_ERROR_FS_FAIL:
case KOS_ERROR_ACCESS_DENIED:
case KOS_ERROR_DEVICE:
case KOS_ERROR_OUT_OF_MEMORY:
return f70_status_name[s];
default:
return "unknown";
@ -144,7 +147,7 @@ print_f70_status(struct shell_ctx *ctx, f7080ret_t *r, int use_ebx) {
fprintf(ctx->fout, "status = %d %s", r->status,
get_f70_status_name(r->status));
if (use_ebx
&& (r->status == ERROR_SUCCESS || r->status == ERROR_END_OF_FILE)) {
&& (r->status == KOS_ERROR_SUCCESS || r->status == KOS_ERROR_END_OF_FILE)) {
fprintf(ctx->fout, ", count = %d", r->count);
}
fprintf(ctx->fout, "\n");
@ -2326,8 +2329,8 @@ ls_range(struct shell_ctx *ctx, f7080s1arg_t *fX0, f70or80_t f70or80) {
f7080s1info_t *dir = fX0->buf;
int ok = (r.count <= fX0->size);
ok &= (dir->cnt == r.count);
ok &= (r.status == ERROR_SUCCESS && r.count == fX0->size)
|| (r.status == ERROR_END_OF_FILE && r.count < fX0->size);
ok &= (r.status == KOS_ERROR_SUCCESS && r.count == fX0->size)
|| (r.status == KOS_ERROR_END_OF_FILE && r.count < fX0->size);
assert(ok);
if (!ok)
break;
@ -2338,7 +2341,7 @@ ls_range(struct shell_ctx *ctx, f7080s1arg_t *fX0, f70or80_t f70or80) {
fprintf(ctx->fout, "%s %s\n", fattr, bdfe->name);
bdfe = (bdfe_t*)((uintptr_t)bdfe + bdfe_len);
}
if (r.status == ERROR_END_OF_FILE) {
if (r.status == KOS_ERROR_END_OF_FILE) {
break;
}
}
@ -2360,8 +2363,8 @@ ls_all(struct shell_ctx *ctx, f7080s1arg_t *fX0, f70or80_t f70or80) {
fX0->offset += dir->cnt;
int ok = (r.count <= fX0->size);
ok &= (dir->cnt == r.count);
ok &= (r.status == ERROR_SUCCESS && r.count == fX0->size)
|| (r.status == ERROR_END_OF_FILE && r.count < fX0->size);
ok &= (r.status == KOS_ERROR_SUCCESS && r.count == fX0->size)
|| (r.status == KOS_ERROR_END_OF_FILE && r.count < fX0->size);
assert(ok);
if (!ok)
break;
@ -2373,7 +2376,7 @@ ls_all(struct shell_ctx *ctx, f7080s1arg_t *fX0, f70or80_t f70or80) {
fprintf(ctx->fout, "%s %s\n", fattr, bdfe->name);
bdfe = (bdfe_t*)((uintptr_t)bdfe + bdfe_len);
}
if (r.status == ERROR_END_OF_FILE) {
if (r.status == KOS_ERROR_END_OF_FILE) {
break;
}
}
@ -2538,7 +2541,7 @@ cmd_stat(struct shell_ctx *ctx, int argc, char **argv, f70or80_t f70or80) {
umka_sys_lfn(&fX0, &r, f70or80);
COVERAGE_OFF();
print_f70_status(ctx, &r, 0);
if (r.status != ERROR_SUCCESS)
if (r.status != KOS_ERROR_SUCCESS)
return;
char fattr[KF_ATTR_CNT+1];
convert_f70_file_attr(file.attr, fattr);
@ -2648,7 +2651,7 @@ cmd_read(struct shell_ctx *ctx, int argc, char **argv, f70or80_t f70or80,
COVERAGE_OFF();
print_f70_status(ctx, &r, 1);
if (r.status == ERROR_SUCCESS || r.status == ERROR_END_OF_FILE) {
if (r.status == KOS_ERROR_SUCCESS || r.status == KOS_ERROR_END_OF_FILE) {
if (dump_bytes)
print_bytes(ctx, fX0.buf, r.count);
if (dump_hash)
@ -2889,9 +2892,9 @@ cmd_net_add_device(struct shell_ctx *ctx, int argc, char **argv) {
fputs(usage, ctx->fout);
return;
}
net_device_t *vnet = vnet_init(); // FIXME: list like block devices
struct vnet *net = vnet_init(VNET_TAP); // TODO: list like block devices
COVERAGE_ON();
int32_t dev_num = kos_net_add_device(vnet);
int32_t dev_num = kos_net_add_device(&net->netdev);
COVERAGE_OFF();
fprintf(ctx->fout, "device number: %" PRIi32 "\n", dev_num);
}
@ -3990,7 +3993,7 @@ cmd_help(struct shell_ctx *ctx, int argc, char **argv) {
void *
run_test(struct shell_ctx *ctx) {
mtx_lock(&ctx->cmd_mutex);
pthread_mutex_lock(&ctx->cmd_mutex);
int is_tty = isatty(fileno(ctx->fin));
char **argv = (char**)calloc(sizeof(char*), (MAX_COMMAND_ARGS + 1));
bestlineSetCompletionCallback(completion);
@ -4030,7 +4033,8 @@ run_test(struct shell_ctx *ctx) {
free(argv);
bestlineHistorySave(ctx->hist_file);
mtx_unlock(&ctx->cmd_mutex);
fclose(ctx->fin);
pthread_mutex_unlock(&ctx->cmd_mutex);
return NULL;
}
@ -4046,8 +4050,8 @@ shell_init(int reproducible, const char *hist_file, struct umka_ctx *umka,
ctx->fin = fin;
ctx->fout = fout;
ctx->running = running;
cnd_init(&ctx->cmd_done);
mtx_init(&ctx->cmd_mutex, mtx_plain);
pthread_cond_init(&ctx->cmd_done, NULL);
pthread_mutex_init(&ctx->cmd_mutex, NULL);
return ctx;
}

View File

@ -11,9 +11,9 @@
#define SHELL_H_INCLUDED
#include <stdio.h>
#include <threads.h>
#include <pthread.h>
#include "umka.h"
#include "io.h"
#include "umkaio.h"
enum shell_var_type {
SHELL_VAR_SINT,
@ -42,8 +42,8 @@ struct shell_ctx {
FILE *fin;
FILE *fout;
const int *running;
cnd_t cmd_done;
mtx_t cmd_mutex;
pthread_cond_t cmd_done;
pthread_mutex_t cmd_mutex;
};

View File

@ -3,7 +3,7 @@
UMKa - User-Mode KolibriOS developer tools
Copyright (C) 2019-2020,2022 Ivan Baravy <dunkaist@gmail.com>
Copyright (C) 2019-2020,2022-2023 Ivan Baravy <dunkaist@gmail.com>
Copyright (C) 2021 Magomed Kostoev <mkostoevr@yandex.ru>
*/
@ -36,6 +36,7 @@ uint64_t rdmsr(uint32_t reg)
exit(1);
}
#else
(void)reg;
printf("STUB: %s:%d", __FILE__, __LINE__);
#endif
@ -59,6 +60,8 @@ void wrmsr(uint32_t reg, uint64_t data)
close(fd);
#else
(void)reg;
(void)data;
printf("STUB: %s:%d", __FILE__, __LINE__);
#endif
}

View File

@ -1023,7 +1023,6 @@ acpi_root dd ?
acpi_dev_next dd ?
endg
;sys_msg_board equ __pex0
delay_ms equ __pex1
include fix pew
@ -1047,14 +1046,13 @@ include 'kernel.asm'
purge jmp
restore bios32_entry, tmp_page_tabs
purge org,delay_ms
;purge sys_msg_board
restore org,delay_ms
;restore sys_msg_board
coverage_end:
section '.bss.coverage' executable writable align 64
; cov for coverage; otherwide fasm complains with 'name too long' for MS COFF
section '.bss.cov' executable writable align 64
struct coverage_branch
to_cnt DQ ?
from_cnt DQ ?
@ -1066,7 +1064,8 @@ coverage_table rb COVERAGE_TABLE_SIZE * sizeof.coverage_branch
pubsym coverage_table
section '.data.boot' writeable align 0x1000
; bt for boot; otherwide fasm complains with 'name too long' for MS COFF
section '.data.bt' writeable align 0x1000
BOOT boot_data
virtual at BOOT
BOOT_LO boot_data

47
umka.h
View File

@ -41,6 +41,9 @@ struct umka_ctx {
#define KEYBOARD_MODE_ASCII 0
#define KEYBOARD_MODE_SCANCODES 1
#define UMKA_IRQ_MOUSE 14
#define UMKA_IRQ_NETWORK 15
enum kos_lang {
KOS_LANG_EN = 1,
KOS_LANG_FIRST = KOS_LANG_EN,
@ -195,19 +198,19 @@ typedef enum {
} f70or80_t;
enum {
ERROR_SUCCESS,
ERROR_DISK_BASE,
ERROR_UNSUPPORTED_FS,
ERROR_UNKNOWN_FS,
ERROR_PARTITION,
ERROR_FILE_NOT_FOUND,
ERROR_END_OF_FILE,
ERROR_MEMORY_POINTER,
ERROR_DISK_FULL,
ERROR_FS_FAIL,
ERROR_ACCESS_DENIED,
ERROR_DEVICE,
ERROR_OUT_OF_MEMORY,
KOS_ERROR_SUCCESS,
KOS_ERROR_DISK_BASE,
KOS_ERROR_UNSUPPORTED_FS,
KOS_ERROR_UNKNOWN_FS,
KOS_ERROR_PARTITION,
KOS_ERROR_FILE_NOT_FOUND,
KOS_ERROR_END_OF_FILE,
KOS_ERROR_MEMORY_POINTER,
KOS_ERROR_DISK_FULL,
KOS_ERROR_FS_FAIL,
KOS_ERROR_ACCESS_DENIED,
KOS_ERROR_DEVICE,
KOS_ERROR_OUT_OF_MEMORY,
};
typedef struct lhead lhead_t;
@ -501,7 +504,6 @@ struct net_device_t {
uint32_t hwacc; // bitmask stating enabled HW accelerations (offload
// engines)
uint8_t mac[6];
void *userdata; // not in kolibri, umka-specific
}; // NET_DEVICE
typedef struct {
@ -1085,13 +1087,6 @@ static_assert(sizeof(appdata_t) == 256, "must be 0x100 bytes long");
#define UMKA_OS 3
#define UMKA_GEN_DEVICES_DAT 4
#define MAX_PRIORITY 0 // highest, used for kernel tasks
#define USER_PRIORITY 1 // default
#define IDLE_PRIORITY 2 // lowest, only IDLE thread goes here
#define NR_SCHED_QUEUES 3 // MUST equal IDLE_PRIORYTY + 1
extern appdata_t *kos_scheduler_current[NR_SCHED_QUEUES];
extern uint8_t kos_redraw_background;
extern size_t kos_task_count;
extern wdata_t kos_window_data[];
@ -1130,14 +1125,16 @@ umka_scheduler_add_thread(appdata_t *thread, int32_t priority) {
: "memory", "cc");
}
#define MAX_PRIORITY 0
#define USER_PRIORITY 1
#define IDLE_PRIORITY 2
#define NR_SCHED_QUEUES 3
#define KOS_MAX_PRIORITY 0 // highest, used for kernel tasks
#define KOS_USER_PRIORITY 1 // default
#define KOS_IDLE_PRIORITY 2 // lowest, only IDLE thread goes here
#define KOS_NR_SCHED_QUEUES 3 // MUST equal IDLE_PRIORYTY + 1
#define SCHEDULE_ANY_PRIORITY 0
#define SCHEDULE_HIGHER_PRIORITY 1
extern appdata_t *kos_scheduler_current[KOS_NR_SCHED_QUEUES];
typedef struct {
appdata_t *appdata;
void *taskdata;

View File

@ -19,7 +19,7 @@ SECTIONS
{
.data.boot BLOCK(0x1000) :
{
*(.data.boot)
*(.data.bt)
}
}

View File

@ -22,7 +22,7 @@
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "io.h"
#include "umkaio.h"
#include "vdisk.h"
#define DIRENTS_TO_READ 100

View File

@ -112,7 +112,7 @@ thread_start(int is_kernel, void (*entry)(void), size_t stack_size) {
static void
dump_procs() {
for (int i = 0; i < NR_SCHED_QUEUES; i++) {
for (int i = 0; i < KOS_NR_SCHED_QUEUES; i++) {
fprintf(stderr, "sched queue #%i:", i);
appdata_t *p_begin = kos_scheduler_current[i];
appdata_t *p = p_begin;
@ -186,7 +186,7 @@ hw_int(int signo, siginfo_t *info, void *context) {
}
int
sdlthr(void *arg) {
umka_display(void *arg) {
(void)arg;
if(SDL_Init(SDL_INIT_VIDEO) < 0)
{
@ -194,7 +194,10 @@ sdlthr(void *arg) {
return -1;
}
SDL_Window *window = SDL_CreateWindow("LFB Viewer SDL2",
char title[64];
sprintf(title, "umka0 %ux%u %ubpp", kos_display.width, kos_display.height,
kos_display.bits_per_pixel);
SDL_Window *window = SDL_CreateWindow(title,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
kos_display.width,
@ -257,10 +260,8 @@ umka_thread_cmd_runner() {
static int
umka_monitor(void *arg) {
(void)arg;
os->shell->fin = stdin;
os->shell->fout = stdout;
run_test(os->shell);
return 0;
exit(0);
}
static void
@ -280,11 +281,13 @@ int
main(int argc, char *argv[]) {
(void)argc;
const char *usage = "umka_os [-i <infile>] [-o <outfile>]"
" [-b <boardlog>]\n";
" [-b <boardlog>] [\n";
if (coverage) {
trace_begin();
}
int show_display = 0;
umka_sti();
build_history_filename();
@ -292,9 +295,11 @@ main(int argc, char *argv[]) {
bestlineSetHintsCallback(hints);
bestlineHistoryLoad(history_filename);
const char *startupfile = NULL;
const char *infile = NULL;
const char *outfile = NULL;
const char *boardlogfile = NULL;
FILE *fstartup = NULL;
FILE *fin = stdin;
FILE *fout = stdout;
FILE *fboardlog;
@ -303,17 +308,23 @@ main(int argc, char *argv[]) {
int opt;
optparse_init(&options, argv);
while ((opt = optparse(&options, "b:i:o:s:")) != -1) {
while ((opt = optparse(&options, "b:di:o:s:")) != -1) {
switch (opt) {
case 'b':
boardlogfile = options.optarg;
break;
case 'd':
show_display = 1;
break;
case 'i':
infile = options.optarg;
break;
case 'o':
outfile = options.optarg;
break;
case 's':
startupfile = options.optarg;
break;
default:
fprintf(stderr, "bad option: %c\n", opt);
fputs(usage, stderr);
@ -379,8 +390,8 @@ main(int argc, char *argv[]) {
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGUSR2, &sa, NULL) == -1) {
fprintf(stderr, "Can't install SIGUSR2 handler!\n");
if (sigaction(SIGSYS, &sa, NULL) == -1) {
fprintf(stderr, "Can't install SIGSYS handler!\n");
return 1;
}
@ -397,14 +408,19 @@ main(int argc, char *argv[]) {
kos_boot.pitch = UMKA_DEFAULT_DISPLAY_WIDTH * UMKA_DEFAULT_DISPLAY_BPP / 8;
run_test(os->shell);
// umka_stack_init();
os->shell->fin = stdin;
umka_stack_init();
// load_app_host("../apps/board_cycle", app);
load_app_host("../apps/readdir", app);
// load_app("/rd/1/loader");
// net_device_t *vnet = vnet_init();
// kos_net_add_device(vnet);
struct vnet *net = vnet_init(VNET_TAP);
if (net) {
kos_net_add_device(&net->netdev);
} else {
fprintf(stderr, "[!] can't initialize vnet device\n");
}
char devname[64];
for (size_t i = 0; i < umka_sys_net_get_dev_count(); i++) {
@ -442,7 +458,7 @@ main(int argc, char *argv[]) {
}
*/
kos_attach_int_handler(14, hw_int_mouse, NULL);
kos_attach_int_handler(UMKA_IRQ_MOUSE, hw_int_mouse, NULL);
thread_start(1, umka_thread_board, THREAD_STACK_SIZE);
thread_start(1, umka_thread_cmd_runner, THREAD_STACK_SIZE);
@ -454,8 +470,10 @@ main(int argc, char *argv[]) {
thrd_t thrd_monitor;
thrd_create(&thrd_monitor, umka_monitor, NULL);
thrd_t thrd_screen;
thrd_create(&thrd_screen, sdlthr, NULL);
if (show_display) {
thrd_t thrd_display;
thrd_create(&thrd_display, umka_display, NULL);
}
setitimer(ITIMER_REAL, &timeout, NULL);

View File

@ -18,7 +18,7 @@
#include <unistd.h>
#include "optparse.h"
#include "shell.h"
#include "io.h"
#include "umkaio.h"
#include "trace.h"
#define HIST_FILE_BASENAME ".umka_shell.history"

View File

@ -12,7 +12,7 @@
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include "io.h"
#include "umkaio.h"
#include "io_async.h"
struct umka_io *

View File

@ -7,8 +7,8 @@
Copyright (C) 2023 Ivan Baravy <dunkaist@gmail.com>
*/
#ifndef IO_H_INCLUDED
#define IO_H_INCLUDED
#ifndef UMKAIO_H_INCLUDED
#define UMKAIO_H_INCLUDED
#include <unistd.h>
@ -29,4 +29,4 @@ io_read(int fd, void *buf, size_t count, struct umka_io *io);
ssize_t
io_write(int fd, const void *buf, size_t count, struct umka_io *io);
#endif // IO_H_INCLUDED
#endif // UMKAIO_H_INCLUDED

View File

@ -6,12 +6,13 @@
Copyright (C) 2021, 2023 Ivan Baravy <dunkaist@gmail.com>
*/
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>
#include <stdlib.h>
#include "umka.h"
#include "shell.h"
uint32_t umka_irq_number;
struct devices_dat_entry {
uint8_t fun:3;
uint8_t dev:5;

View File

@ -6,8 +6,8 @@
Copyright (C) 2021, 2023 Ivan Baravy <dunkaist@gmail.com>
*/
#ifndef UTIL_H_INCLUDED
#define UTIL_H_INCLUDED
#ifndef UMKART_H_INCLUDED
#define UMKART_H_INCLUDED
#include "umka.h"
#include "shell.h"
@ -20,4 +20,4 @@ dump_devices_dat(const char *filename);
void
copy_display_to_rgb888(void *to);
#endif // UTIL_H_INCLUDED
#endif // UMKART_H_INCLUDED

View File

@ -27,7 +27,7 @@ vdisk_querymedia(void *userdata, diskmediainfo_t *minfo) {
minfo->sector_size = disk->sect_size;
minfo->capacity = disk->sect_cnt;
COVERAGE_ON();
return ERROR_SUCCESS;
return KOS_ERROR_SUCCESS;
}
STDCALL size_t

View File

@ -14,7 +14,11 @@
#include "../trace.h"
#include "qcow2.h"
#include "miniz/miniz.h"
#include "io.h"
#include "umkaio.h"
#ifdef _WIN32
//#include <io.h>
//#define open _open
#endif
#define L1_MAX_LEN (32u*1024u*1024u)
#define L1_MAX_ENTRIES (L1_MAX_LEN / sizeof(uint64_t))
@ -179,7 +183,7 @@ vdisk_qcow2_read(void *userdata, void *buffer, off_t startsector,
buffer = (uint8_t*)buffer + d->vdisk.sect_size;
}
COVERAGE_ON();
return ERROR_SUCCESS;
return KOS_ERROR_SUCCESS;
}
STDCALL int
@ -193,7 +197,7 @@ vdisk_qcow2_write(void *userdata, void *buffer, off_t startsector,
(void)numsectors;
fprintf(stderr, "[vdisk.qcow2] writing is not implemented");
COVERAGE_ON();
return ERROR_UNSUPPORTED_FS;
return KOS_ERROR_UNSUPPORTED_FS;
}
struct vdisk*

View File

@ -12,7 +12,7 @@
#include <stdio.h>
#include "vdisk.h"
#include "io.h"
#include "umkaio.h"
#define QCOW2_SUFFIX ".qcow2"

View File

@ -12,7 +12,7 @@
#include <stdlib.h>
#include <unistd.h>
#include "../trace.h"
#include "io.h"
#include "umkaio.h"
#include "raw.h"
struct vdisk_raw {
@ -38,7 +38,7 @@ vdisk_raw_read(void *userdata, void *buffer, off_t startsector,
io_read(disk->fd, buffer, *numsectors * disk->vdisk.sect_size,
disk->vdisk.io);
COVERAGE_ON();
return ERROR_SUCCESS;
return KOS_ERROR_SUCCESS;
}
STDCALL int
@ -50,7 +50,7 @@ vdisk_raw_write(void *userdata, void *buffer, off_t startsector,
io_write(disk->fd, buffer, *numsectors * disk->vdisk.sect_size,
disk->vdisk.io);
COVERAGE_ON();
return ERROR_SUCCESS;
return KOS_ERROR_SUCCESS;
}
struct vdisk*

View File

@ -12,7 +12,7 @@
#include <stdio.h>
#include "vdisk.h"
#include "io.h"
#include "umkaio.h"
#define RAW_SUFFIX ".raw"

224
vnet.c
View File

@ -4,115 +4,42 @@
UMKa - User-Mode KolibriOS developer tools
vnet - virtual network card
Copyright (C) 2020-2022 Ivan Baravy <dunkaist@gmail.com>
Copyright (C) 2020-2023 Ivan Baravy <dunkaist@gmail.com>
Copyright (C) 2021 Magomed Kostoev <mkostoevr@yandex.ru>
*/
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <poll.h>
#include <stdbool.h>
#define _POSIX // to have SIGSYS on windows
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include "umka.h"
#include "trace.h"
#include "vnet.h"
#include "vnet/tap.h"
#include "vnet/file.h"
// TODO: Cleanup
#ifndef _WIN32
#include <arpa/inet.h>
#include <poll.h>
#include <unistd.h>
#else
#include <winsock2.h>
#include <pthread.h>
#endif
#define TAP_DEV "/dev/net/tun"
#define UMKA_TAP_NAME "umka%d"
#define STACK_SIZE 0x10000
typedef struct {
int tapfd;
bool input_processed;
} vnet_userdata_t;
static int
tap_alloc() {
struct ifreq ifr = {.ifr_name = UMKA_TAP_NAME,
.ifr_flags = IFF_TAP | IFF_NO_PI};
int fd, err;
if( (fd = open(TAP_DEV, O_RDWR | O_NONBLOCK)) < 0 ) {
perror("Opening /dev/net/tun");
return fd;
}
if( (err = ioctl(fd, TUNSETIFF, &ifr)) < 0 ) {
perror("ioctl(TUNSETIFF)");
close(fd);
return err;
}
ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
memcpy(ifr.ifr_hwaddr.sa_data, (char[]){0x00, 0x11, 0x00, 0x00, 0x00, 0x00}, 6);
if( (err = ioctl(fd, SIOCSIFHWADDR, &ifr)) < 0 ) {
perror("ioctl(SIOCSIFHWADDR)");
close(fd);
return err;
}
struct sockaddr_in sai;
sai.sin_family = AF_INET;
sai.sin_port = 0;
sai.sin_addr.s_addr = inet_addr("10.50.0.1");
memcpy(&ifr.ifr_addr, &sai, sizeof(struct sockaddr));
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if ( (err = ioctl(sockfd, SIOCSIFADDR, &ifr)) < 0 ) {
perror("ioctl(SIOCSIFADDR)");
close(fd);
return err;
}
sai.sin_addr.s_addr = inet_addr("255.255.255.0");
memcpy(&ifr.ifr_netmask, &sai, sizeof(struct sockaddr));
if ((err = ioctl(sockfd, SIOCSIFNETMASK, &ifr)) < 0) {
perror("ioctl(SIOCSIFNETMASK)");
close(fd);
return err;
}
if ((err = ioctl(sockfd, SIOCGIFFLAGS, &ifr)) < 0) {
perror("ioctl(SIOCGIFFLAGS)");
close(fd);
return err;
}
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
ifr.ifr_flags &= ~(IFF_BROADCAST | IFF_LOWER_UP);
if ((err = ioctl(sockfd, SIOCSIFFLAGS, &ifr)) < 0) {
perror("ioctl(SIOCSIFFLAGS)");
close(fd);
return err;
}
return fd;
}
static int
vnet_input(void *udata) {
umka_sti();
net_device_t *vnet = udata;
vnet_userdata_t *u = vnet->userdata;
int tapfd = u->tapfd;
struct vnet *net = udata;
int fd = net->fdin;
int plen = 0;
fprintf(stderr, "[vnet] input interrupt\n");
net_buff_t *buf = kos_net_buff_alloc(NET_BUFFER_SIZE);
@ -120,8 +47,8 @@ vnet_input(void *udata) {
fprintf(stderr, "[vnet] Can't allocate network buffer!\n");
return 1;
}
buf->device = vnet;
plen = read(tapfd, buf->data, NET_BUFFER_SIZE - offsetof(net_buff_t, data));
buf->device = &net->netdev;
plen = read(fd, buf->data, NET_BUFFER_SIZE - offsetof(net_buff_t, data));
if (plen == -1) {
plen = 0; // we have just allocated a buffer, so we have to submit it
}
@ -134,112 +61,63 @@ vnet_input(void *udata) {
buf->length = plen;
buf->offset = offsetof(net_buff_t, data);
kos_eth_input(buf);
u->input_processed = true;
net->input_processed = 1;
return 1; // acknowledge our interrupt
}
static void
vnet_input_monitor(net_device_t *vnet) {
vnet_input_monitor(struct vnet *net) {
umka_sti();
vnet_userdata_t *u = vnet->userdata;
int tapfd = u->tapfd;
struct pollfd pfd = {tapfd, POLLIN, 0};
while(true)
{
if (u->input_processed && poll(&pfd, 1, 0)) {
u->input_processed = false;
raise(SIGUSR1);
struct pollfd pfd = {net->fdin, POLLIN, 0};
while (1) {
if (net->input_processed && poll(&pfd, 1, 0)) {
net->input_processed = 0;
umka_irq_number = UMKA_IRQ_NETWORK;
raise(SIGSYS);
umka_sti();
}
}
}
static void
dump_net_buff(net_buff_t *buf) {
for (size_t i = 0; i < buf->length; i++) {
printf("%2.2x ", buf->data[i]);
}
putchar('\n');
}
static STDCALL void
vnet_unload() {
printf("vnet_unload\n");
COVERAGE_ON();
COVERAGE_OFF();
}
static STDCALL void
vnet_reset() {
printf("vnet_reset\n");
COVERAGE_ON();
COVERAGE_OFF();
}
static STDCALL int
vnet_transmit(net_buff_t *buf) {
// TODO: Separate implementations for win32 and linux
#ifdef _WIN32
assert(!"Function is not implemented for win32");
#else
net_device_t *vnet;
__asm__ __inline__ __volatile__ (
"nop"
: "=b"(vnet)
:
: "memory");
vnet_userdata_t *u = vnet->userdata;
printf("vnet_transmit: %d bytes\n", buf->length);
dump_net_buff(buf);
write(u->tapfd, buf->data, buf->length);
buf->length = 0;
COVERAGE_OFF();
COVERAGE_ON();
printf("vnet_transmit: done\n");
#endif
return 0;
}
net_device_t*
vnet_init() {
struct vnet *
vnet_init(enum vnet_type type) {
// printf("vnet_init\n");
int tapfd = tap_alloc();
vnet_userdata_t *u = (vnet_userdata_t*)malloc(sizeof(vnet_userdata_t));
u->tapfd = tapfd;
u->input_processed = true;
struct vnet *net;
switch (type) {
case VNET_FILE:
net = vnet_init_file();
break;
case VNET_TAP:
net = vnet_init_tap();
break;
default:
fprintf(stderr, "[vnet] bad vnet type: %d\n", type);
return NULL;
}
if (!net) {
fprintf(stderr, "[vnet] device initialization failed\n");
return NULL;
}
net_device_t *vnet = (net_device_t*)malloc(sizeof(net_device_t));
*vnet = (net_device_t){
.device_type = NET_TYPE_ETH,
.mtu = 1514,
.name = "UMK0770",
net->netdev.bytes_tx = 0;
net->netdev.bytes_rx = 0;
net->netdev.packets_tx = 0;
net->netdev.packets_rx = 0;
.unload = vnet_unload,
.reset = vnet_reset,
.transmit = vnet_transmit,
net->netdev.link_state = ETH_LINK_FD + ETH_LINK_10M;
net->netdev.hwacc = 0;
memcpy(net->netdev.mac, &(uint8_t[6]){0x80, 0x2b, 0xf9, 0x3b, 0x6c, 0xca},
sizeof(net->netdev.mac));
.bytes_tx = 0,
.bytes_rx = 0,
.packets_tx = 0,
.packets_rx = 0,
.link_state = ETH_LINK_FD + ETH_LINK_10M,
.hwacc = 0,
.mac = {0x80, 0x2b, 0xf9, 0x3b, 0x6c, 0xca},
.userdata = u,
};
kos_attach_int_handler(SIGUSR1, vnet_input, vnet);
kos_attach_int_handler(UMKA_IRQ_NETWORK, vnet_input, net);
fprintf(stderr, "[vnet] start input_monitor thread\n");
uint8_t *stack = malloc(STACK_SIZE);
size_t tid = umka_new_sys_threads(0, vnet_input_monitor, stack + STACK_SIZE);
appdata_t *t = kos_slot_base + tid;
*(void**)((uint8_t*)t->saved_esp0-12) = vnet; // param for monitor thread
*(void**)((uint8_t*)t->saved_esp0-12) = net; // param for monitor thread
// -12 here because in UMKa, unlike real hardware, we don't switch between
// kernel and userspace, i.e. stack structure is different
return vnet;
return net;
}

22
vnet.h
View File

@ -4,7 +4,7 @@
UMKa - User-Mode KolibriOS developer tools
vnet - virtual network card
Copyright (C) 2020-2022 Ivan Baravy <dunkaist@gmail.com>
Copyright (C) 2020-2023 Ivan Baravy <dunkaist@gmail.com>
*/
#ifndef VNET_H_INCLUDED
@ -12,7 +12,23 @@
#include "umka.h"
net_device_t*
vnet_init(void);
#define UMKA_VNET_NAME "umka%d"
extern uint32_t umka_irq_number;
enum vnet_type {
VNET_FILE,
VNET_TAP,
};
struct vnet {
net_device_t netdev;
int fdin;
int fdout;
int input_processed;
};
struct vnet *
vnet_init(enum vnet_type type);
#endif // VNET_H_INCLUDED

15
vnet/file.c Normal file
View File

@ -0,0 +1,15 @@
/*
SPDX-License-Identifier: GPL-2.0-or-later
UMKa - User-Mode KolibriOS developer tools
vnet - virtual network card, file interface
Copyright (C) 2023 Ivan Baravy <dunkaist@gmail.com>
*/
#include <stddef.h>
struct vnet *
vnet_init_file() {
return NULL;
}

16
vnet/file.h Normal file
View File

@ -0,0 +1,16 @@
/*
SPDX-License-Identifier: GPL-2.0-or-later
UMKa - User-Mode KolibriOS developer tools
vnet - virtual network card, file interface
Copyright (C) 2023 Ivan Baravy <dunkaist@gmail.com>
*/
#ifndef VNET_FILE_H_INCLUDED
#define VNET_FILE_H_INCLUDED
struct vnet *
vnet_init_file(void);
#endif // VNET_FILE_H_INCLUDED

16
vnet/tap.h Normal file
View File

@ -0,0 +1,16 @@
/*
SPDX-License-Identifier: GPL-2.0-or-later
UMKa - User-Mode KolibriOS developer tools
vnet - virtual network card, tap interface
Copyright (C) 2023 Ivan Baravy <dunkaist@gmail.com>
*/
#ifndef VNET_TAP_H_INCLUDED
#define VNET_TAP_H_INCLUDED
struct vnet *
vnet_init_tap(void);
#endif // VNET_TAP_H_INCLUDED

51
windows/io_async.c Normal file
View File

@ -0,0 +1,51 @@
/*
SPDX-License-Identifier: GPL-2.0-or-later
UMKa - User-Mode KolibriOS developer tools
io_async - input/output platform specific code
Copyright (C) 2023 Ivan Baravy <dunkaist@gmail.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <inttypes.h>
#include "umka.h"
#define QUEUE_DEPTH 1
#define read_barrier() __asm__ __volatile__("":::"memory")
#define write_barrier() __asm__ __volatile__("":::"memory")
#define MAX(x, y) ((x) >= (y) ? (x) : (y))
void *
io_async_init() {
fprintf(stderr, "[io_async] not implemented for windows\n");
return NULL;
}
void
io_async_close(void *arg) {
(void)arg;
}
ssize_t
io_async_read(int fd, void *buf, size_t count, void *arg) {
(void)fd;
(void)buf;
(void)count;
(void)arg;
return -1;
}
ssize_t
io_async_write(int fd, const void *buf, size_t count, void *arg) {
(void)fd;
(void)buf;
(void)count;
(void)arg;
return -1;
}

View File

@ -17,6 +17,11 @@ char pci_path[UMKA_PATH_MAX] = ".";
__attribute__((stdcall)) uint32_t pci_read(uint32_t bus, uint32_t dev,
uint32_t fun, uint32_t offset,
size_t len) {
(void)bus;
(void)dev;
(void)fun;
(void)offset;
(void)len;
printf("STUB: %s:%d", __FILE__, __LINE__);
return 0xffffffff;
}

View File

@ -13,6 +13,7 @@ void reset_procmask(void) {
}
int get_fake_if(void *ctx) {
(void)ctx;
printf("STUB: %s:%d", __FILE__, __LINE__);
return 0;
}

16
windows/vnet/tap.c Normal file
View File

@ -0,0 +1,16 @@
/*
SPDX-License-Identifier: GPL-2.0-or-later
UMKa - User-Mode KolibriOS developer tools
vnet - virtual network card, tap interface
Copyright (C) 2023 Ivan Baravy <dunkaist@gmail.com>
*/
#include <stdio.h>
struct vnet *
vnet_init_tap() {
fprintf(stderr, "[vnet] tap interface isn't implemented for windows\n");
return NULL;
}