Backport sysfs and random

This commit is contained in:
Mark 2020-02-03 12:39:53 +02:00
parent 4269177c1a
commit 14805828b5
8 changed files with 356 additions and 44 deletions

View File

@ -56,6 +56,8 @@ OBJS+=$(O)/sys/debug.o \
$(O)/sys/time.o \
$(O)/sys/sys_file.o \
$(O)/sys/sys_sys.o \
$(O)/sys/snprintf.o \
$(O)/sys/random.o \
$(O)/sys/init.o
OBJS+=$(O)/sys/driver/pci/pci.o \

5
include/sys/random.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "sys/types.h"
void random_init(uint64_t seed);
uint64_t random_single(void);

6
include/sys/snprintf.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <stdarg.h>
#include "sys/types.h"
int snprintf(char *buf, size_t lim, const char *fmt, ...);
int vsnprintf(char *buf, size_t lim, const char *fmt, va_list args);

View File

@ -12,10 +12,12 @@
#include "sys/amd64/cpuid.h"
#include "sys/amd64/mm/mm.h"
#include "sys/block/ram.h"
#include "sys/fs/sysfs.h"
#include "sys/char/tty.h"
#include "sys/config.h"
#include "sys/fs/tar.h"
#include "sys/fs/vfs.h"
#include "sys/random.h"
#include "sys/sched.h"
#include "sys/debug.h"
#include "sys/panic.h"
@ -24,6 +26,10 @@
static multiboot_info_t *multiboot_info;
static void amd64_make_random_seed(void) {
random_init(15267 + system_time);
}
void kernel_main(struct amd64_loader_data *data) {
cpuid_init();
data = (struct amd64_loader_data *) MM_VIRTUALIZE(data);
@ -76,9 +82,12 @@ void kernel_main(struct amd64_loader_data *data) {
tarfs_init();
}
amd64_make_random_seed();
syscall_init();
sched_init();
sysfs_populate();
user_init_start();
sched_enter();

View File

@ -2,6 +2,7 @@
#include "sys/user/errno.h"
#include "sys/amd64/cpu.h"
#include "sys/fs/sysfs.h"
#include "sys/snprintf.h"
#include "sys/fs/ofile.h"
#include "sys/fs/node.h"
#include "sys/assert.h"
@ -150,52 +151,52 @@ int sysfs_add_config_endpoint(const char *name, size_t bufsz, void *ctx, cfg_rea
return 0;
}
//// TODO: move this to an appropriate place
//#define PROC_PROP_PID 1
//#define PROC_PROP_NAME 2
//
//static int proc_property_getter(void *ctx, char *buf, size_t lim) {
// uint64_t prop = (uint64_t) ctx;
// struct thread *thr = get_cpu()->thread;
// _assert(thr);
//
// switch (prop) {
// case PROC_PROP_PID:
// sysfs_buf_printf(buf, lim, "%d\n", (int) thr->pid);
// break;
// case PROC_PROP_NAME:
// sysfs_buf_puts(buf, lim, thr->name);
// sysfs_buf_puts(buf, lim, "\n");
// break;
// }
//
// return 0;
//}
//
//static int system_uptime_getter(void *ctx, char *buf, size_t lim) {
// char *p = buf;
// uint64_t t = system_time / 1000000000ULL;
// int days = (t / 86400),
// hours = (t / 3600) % 24,
// minutes = (t / 60) % 60,
// seconds = t % 60;
//
// sysfs_buf_printf(buf, lim, "%u day", days);
// if (days != 1) {
// sysfs_buf_puts(buf, lim, "s");
// }
// sysfs_buf_printf(buf, lim, ", %02u:%02u:%02u\n", hours, minutes, seconds);
//
// return 0;
//}
// TODO: move this to an appropriate place
#define PROC_PROP_PID 1
#define PROC_PROP_NAME 2
static int proc_property_getter(void *ctx, char *buf, size_t lim) {
uint64_t prop = (uint64_t) ctx;
struct thread *thr = get_cpu()->thread;
_assert(thr);
switch (prop) {
case PROC_PROP_PID:
sysfs_buf_printf(buf, lim, "%d\n", (int) thr->pid);
break;
case PROC_PROP_NAME:
sysfs_buf_puts(buf, lim, "TODO");
sysfs_buf_puts(buf, lim, "\n");
break;
}
return 0;
}
static int system_uptime_getter(void *ctx, char *buf, size_t lim) {
char *p = buf;
uint64_t t = system_time / 1000000000ULL;
int days = (t / 86400),
hours = (t / 3600) % 24,
minutes = (t / 60) % 60,
seconds = t % 60;
sysfs_buf_printf(buf, lim, "%u day", days);
if (days != 1) {
sysfs_buf_puts(buf, lim, "s");
}
sysfs_buf_printf(buf, lim, ", %02u:%02u:%02u\n", hours, minutes, seconds);
return 0;
}
void sysfs_populate(void) {
// sysfs_add_config_endpoint("version", sizeof(KERNEL_VERSION_STR) + 1, KERNEL_VERSION_STR, sysfs_config_getter, NULL);
//
// sysfs_add_config_endpoint("uptime", 32, NULL, system_uptime_getter, NULL);
//
// sysfs_add_config_endpoint("self.pid", 16, (void *) PROC_PROP_PID, proc_property_getter, NULL);
// sysfs_add_config_endpoint("self.name", 128, (void *) PROC_PROP_NAME, proc_property_getter, NULL);
sysfs_add_config_endpoint("version", sizeof(KERNEL_VERSION_STR) + 1, KERNEL_VERSION_STR, sysfs_config_getter, NULL);
sysfs_add_config_endpoint("uptime", 32, NULL, system_uptime_getter, NULL);
sysfs_add_config_endpoint("self.pid", 16, (void *) PROC_PROP_PID, proc_property_getter, NULL);
sysfs_add_config_endpoint("self.name", 128, (void *) PROC_PROP_NAME, proc_property_getter, NULL);
}
static void __init sysfs_class_init(void) {

25
sys/random.c Normal file
View File

@ -0,0 +1,25 @@
#include "sys/random.h"
#include "sys/panic.h"
#include "sys/debug.h"
static int random_ready = 0;
static uint64_t xs64_state;
void random_init(uint64_t s) {
if (random_ready) {
kinfo("Random is ready already\n");
}
random_ready = 1;
xs64_state = s;
}
uint64_t random_single(void) {
if (!random_ready) {
panic("Random was not ready\n");
}
uint64_t x = xs64_state;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
return xs64_state = x;
}

261
sys/snprintf.c Normal file
View File

@ -0,0 +1,261 @@
// TODO: merge snprintf and debug.c
#include "sys/snprintf.h"
#include "sys/string.h"
union printfv {
int value_int;
unsigned int value_uint;
long value_long;
uint32_t value_uint32;
uint64_t value_uint64;
uintptr_t value_ptr;
const char *value_str;
};
static const char *s_print_xs_set0 = "0123456789abcdef";
static const char *s_print_xs_set1 = "0123456789ABCDEF";
static int vsnprintf_ds(int64_t x, char *res, int s, int sz) {
if (!x) {
res[0] = '0';
res[1] = 0;
return 1;
}
int c;
uint64_t v;
if (sz) {
if (s && x < 0) {
v = (uint64_t) -x;
} else {
s = 0;
v = (uint64_t) x;
}
} else {
if (s && ((int32_t) x) < 0) {
v = (uint64_t) -((int32_t) x);
} else {
s = 0;
v = (uint64_t) x;
}
}
c = 0;
while (v) {
res[c++] = '0' + v % 10;
v /= 10;
}
if (s) {
res[c++] = '-';
}
res[c] = 0;
for (int i = 0, j = c - 1; i < j; ++i, --j) {
res[i] ^= res[j];
res[j] ^= res[i];
res[i] ^= res[j];
}
return c;
}
static int vsnprintf_xs(uint64_t v, char *res, const char *set) {
if (!v) {
res[0] = '0';
res[1] = 0;
return 1;
}
int c = 0;
while (v) {
res[c++] = set[v & 0xF];
v >>= 4;
}
res[c] = 0;
for (int i = 0, j = c - 1; i < j; ++i, --j) {
res[i] ^= res[j];
res[j] ^= res[i];
res[i] ^= res[j];
}
return c;
}
int snprintf(char *buf, size_t len, const char *fmt, ...) {
va_list args;
va_start(args, fmt);
int res = vsnprintf(buf, len, fmt, args);
va_end(args);
return res;
}
int vsnprintf(char *buf, size_t len, const char *fmt, va_list args) {
union printfv val;
char cbuf[64];
size_t p = 0;
// padn > 0:
// --------vvvvv
// padn < 0:
// vvvv----------
int padn;
char padc;
int pads;
int clen;
char c;
#define __putc(ch) \
if (p == len - 1) { \
goto __end; \
} else { \
buf[p++] = ch; \
}
#define __puts(s, l) \
if (padn >= 0) { \
if ((int) l < padn) { \
size_t padd = padn - l; \
if (p + padd < len + 1) { \
memset(buf + p, padc, padd); \
p += padd; \
} else { \
memset(buf + p, padc, len - 1 - p); \
p = len - 1; \
goto __end; \
} \
} \
if (p + l < len + 1) { \
strncpy(buf + p, s, l); \
p += l; \
} else { \
strncpy(buf + p, s, len - 1 - p); \
p = len - 1; \
goto __end; \
} \
} else { \
padn = -padn; \
if (p + l < len + 1) { \
strncpy(buf + p, s, l); \
p += l; \
} else { \
strncpy(buf + p, s, len - 1 - p); \
p = len - 1; \
goto __end; \
} \
if ((int) l < padn) { \
size_t padd = padn - l; \
if (p + padd < len + 1) { \
memset(buf + p, padc, padd); \
p += padd; \
} else { \
memset(buf + p, padc, len - 1 - p); \
p = len - 1; \
goto __end; \
} \
} \
}
while ((c = *fmt)) {
switch (c) {
case '%':
c = *++fmt;
padn = 0;
padc = ' ';
pads = 1;
if (c == '0') {
padc = c;
c = *++fmt;
}
if (c == '-') {
pads = -1;
c = *++fmt;
}
while (c >= '0' && c <= '9') {
padn *= 10;
padn += c - '0';
c = *++fmt;
}
padn *= pads;
switch (c) {
case 'l':
// Not supported
return -1;
case 's':
if ((val.value_str = va_arg(args, const char *))) {
__puts(val.value_str, strlen(val.value_str));
} else {
__puts("(null)", 6);
}
break;
case 'p':
val.value_ptr = va_arg(args, uintptr_t);
__putc('0');
__putc('x');
padn = sizeof(uintptr_t) * 2;
padc = '0';
clen = vsnprintf_xs(val.value_ptr, cbuf, s_print_xs_set0);
__puts(cbuf, clen);
break;
case 'i':
case 'd':
val.value_int = va_arg(args, int);
clen = vsnprintf_ds(val.value_int, cbuf, 1, 1);
__puts(cbuf, clen);
break;
case 'u':
val.value_uint = va_arg(args, unsigned int);
clen = vsnprintf_ds(val.value_uint, cbuf, 0, 1);
__puts(cbuf, clen);
break;
case 'x':
val.value_uint32 = va_arg(args, uint32_t);
clen = vsnprintf_xs(val.value_uint32, cbuf, s_print_xs_set0);
__puts(cbuf, clen);
break;
case 'X':
val.value_uint32 = va_arg(args, uint32_t);
clen = vsnprintf_xs(val.value_uint32, cbuf, s_print_xs_set1);
__puts(cbuf, clen);
break;
case 'c':
val.value_int = va_arg(args, int);
__putc(val.value_int);
break;
default:
__putc('%');
__putc(c);
break;
}
break;
default:
__putc(c);
break;
}
++fmt;
}
#undef __puts
#undef __putc
__end:
buf[p] = 0;
return p;
}

View File

@ -515,6 +515,9 @@ int sys_waitpid(pid_t pid, int *status) {
if (status) {
*status = chld->exit_status;
}
// TODO: Cleanup the child here
return 0;
}