[amd64] basic init
This commit is contained in:
@@ -16,7 +16,7 @@ export O?=$(abspath build)
|
||||
include conf/make/none.mk
|
||||
include conf/make/$(ARCH).mk
|
||||
|
||||
all: mkdirs _doc $(TARGETS)
|
||||
all: mkdirs $(TARGETS)
|
||||
|
||||
clean:
|
||||
@rm -rf $(O)
|
||||
|
||||
+22
-6
@@ -1,15 +1,31 @@
|
||||
all:
|
||||
### Kernel build
|
||||
OBJS+=$(O)/arch/amd64/entry.o
|
||||
DEFINES+=-DARCH_AMD64
|
||||
OBJS+=$(O)/arch/amd64/kernel.o \
|
||||
$(O)/arch/amd64/mm/pool.o \
|
||||
$(O)/arch/amd64/mm/mm.o \
|
||||
$(O)/arch/amd64/hw/rs232.o \
|
||||
$(O)/arch/amd64/hw/gdt.o \
|
||||
$(O)/arch/amd64/hw/gdt_s.o
|
||||
kernel_OBJS=$(O)/arch/amd64/entry.o \
|
||||
$(OBJS)
|
||||
kernel_LINKER=$(S)/arch/amd64/link.ld
|
||||
kernel_LDFLAGS=-nostdlib -T$(kernel_LINKER)
|
||||
kernel_CFLAGS=-ffreestanding -I$(S)
|
||||
kernel_CFLAGS=-ffreestanding -I$(S) $(DEFINES) $(CFLAGS)
|
||||
DIRS+=$(O)/arch/amd64/mm \
|
||||
$(O)/arch/amd64/hw
|
||||
|
||||
$(O)/kernel.elf: $(OBJS) $(kernel_LINKER)
|
||||
$(CROSSLD) $(kernel_LDFLAGS) -o $@ $(OBJS)
|
||||
$(O)/kernel.elf: $(kernel_OBJS) $(kernel_LINKER)
|
||||
@printf " LD\t%s\n" $@
|
||||
@$(CROSSLD) $(kernel_LDFLAGS) -o $@ $(kernel_OBJS)
|
||||
|
||||
$(O)/arch/amd64/%.o: $(S)/arch/amd64/%.S
|
||||
$(CROSSCC) $(kernel_CFLAGS) -c -o $@ $<
|
||||
$(O)/%.o: $(S)/%.S
|
||||
@printf " AS\t%s\n" $@
|
||||
@$(CROSSCC) $(kernel_CFLAGS) -c -o $@ $<
|
||||
|
||||
$(O)/%.o: $(S)/%.c
|
||||
@printf " CC\t%s\n" $@
|
||||
@$(CROSSCC) $(kernel_CFLAGS) -c -o $@ $<
|
||||
|
||||
### Kernel loader build
|
||||
TARGETS+=$(O)/loader.elf $(O)/kernel.elf
|
||||
|
||||
+9
-1
@@ -1,3 +1,11 @@
|
||||
HEADERS=$(shell find $(S) -name "*.h")
|
||||
|
||||
OBJS+=
|
||||
CFLAGS+=-Wall \
|
||||
-Wextra \
|
||||
-Werror \
|
||||
-Wno-unused-parameter
|
||||
|
||||
DIRS+=$(O)/sys
|
||||
OBJS+=$(O)/sys/mem.o \
|
||||
$(O)/sys/string.o \
|
||||
$(O)/sys/debug.o
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
.section .text
|
||||
.global _start
|
||||
_start:
|
||||
cli
|
||||
movabsq $kernel_stack_top, %rsp
|
||||
|
||||
call kernel_main
|
||||
|
||||
1:
|
||||
cli
|
||||
hlt
|
||||
jmp 1b
|
||||
|
||||
.section .bss
|
||||
kernel_stack_bottom:
|
||||
.skip 65536
|
||||
kernel_stack_top:
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#include "gdt.h"
|
||||
|
||||
extern void amd64_reload_segs(void);
|
||||
|
||||
#define AMD64_GDT_SIZE 3
|
||||
|
||||
#define GDT_ACC_AC (1 << 0)
|
||||
#define GDT_ACC_RW (1 << 1)
|
||||
#define GDT_ACC_DC (1 << 2)
|
||||
#define GDT_ACC_EX (1 << 3)
|
||||
#define GDT_ACC_S (1 << 4)
|
||||
#define GDT_ACC_R0 (0 << 5)
|
||||
#define GDT_ACC_R1 (1 << 5)
|
||||
#define GDT_ACC_R2 (2 << 5)
|
||||
#define GDT_ACC_R3 (3 << 5)
|
||||
#define GDT_ACC_PR (1 << 7)
|
||||
|
||||
#define GDT_FLG_LONG (1 << 5)
|
||||
#define GDT_FLG_SZ (1 << 6)
|
||||
#define GDT_FLG_GR (1 << 7)
|
||||
|
||||
static amd64_gdt_entry_t gdt[AMD64_GDT_SIZE];
|
||||
static amd64_gdt_ptr_t gdtr;
|
||||
|
||||
static void amd64_gdt_set(int idx, uint32_t base, uint32_t limit, uint8_t flags, uint8_t access) {
|
||||
gdt[idx].base_lo = base & 0xFFFF;
|
||||
gdt[idx].base_mi = (base >> 16) & 0xFF;
|
||||
gdt[idx].base_hi = (base >> 24) & 0xFF;
|
||||
gdt[idx].access = access;
|
||||
gdt[idx].flags = (flags & 0xF0) | ((limit >> 16) & 0xF);
|
||||
gdt[idx].limit_lo = limit & 0xFFFF;
|
||||
}
|
||||
|
||||
void amd64_gdt_init(void) {
|
||||
gdtr.size = sizeof(gdt) - 1;
|
||||
gdtr.offset = (uintptr_t) gdt;
|
||||
|
||||
amd64_gdt_set(0, 0, 0, 0, 0);
|
||||
amd64_gdt_set(1, 0, 0, GDT_FLG_LONG, GDT_ACC_PR | GDT_ACC_R0 | GDT_ACC_EX | GDT_ACC_S | GDT_ACC_RW);
|
||||
amd64_gdt_set(2, 0, 0, 0, GDT_ACC_PR | GDT_ACC_R0 | GDT_ACC_S | GDT_ACC_RW);
|
||||
|
||||
asm volatile ("lea gdtr(%rip), %rax; lgdt (%rax)");
|
||||
amd64_reload_segs();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef struct {
|
||||
uint16_t limit_lo;
|
||||
uint16_t base_lo;
|
||||
uint8_t base_mi;
|
||||
uint8_t access;
|
||||
uint8_t flags;
|
||||
uint8_t base_hi;
|
||||
} amd64_gdt_entry_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t size;
|
||||
uintptr_t offset;
|
||||
} __attribute__((packed)) amd64_gdt_ptr_t;
|
||||
|
||||
void amd64_gdt_init(void);
|
||||
@@ -0,0 +1,21 @@
|
||||
.section .text
|
||||
.global amd64_reload_segs
|
||||
amd64_reload_segs:
|
||||
cli
|
||||
|
||||
movabsq $.jmpbuf, %rax
|
||||
rex.w ljmp *(%rax)
|
||||
|
||||
.reload_data:
|
||||
mov $0x10, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %fs
|
||||
mov %ax, %gs
|
||||
mov %ax, %ss
|
||||
|
||||
ret
|
||||
|
||||
.jmpbuf:
|
||||
.quad .reload_data
|
||||
.word 0x08
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
static inline void outb(uint16_t addr, uint8_t v) {
|
||||
asm volatile("outb %0, %1"::"a"(v), "Nd"(addr));
|
||||
}
|
||||
|
||||
static inline uint8_t inb(uint16_t addr) {
|
||||
uint8_t v;
|
||||
asm volatile("inb %1, %0":"=a"(v):"Nd"(addr));
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void outl(uint16_t addr, uint32_t v) {
|
||||
asm volatile("outl %0, %1"::"a"(v), "Nd"(addr));
|
||||
}
|
||||
|
||||
static inline uint32_t inl(uint16_t addr) {
|
||||
uint32_t v;
|
||||
asm volatile("inl %1, %0":"=a"(v):"Nd"(addr));
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline void io_wait(void) {
|
||||
asm volatile("jmp 1f\n\t"
|
||||
"1:jmp 2f\n\t"
|
||||
"2:" );
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "rs232.h"
|
||||
#include "io.h"
|
||||
|
||||
void rs232_init(uint16_t port) {
|
||||
// Do nothing yet
|
||||
}
|
||||
|
||||
void rs232_send(uint16_t port, char v) {
|
||||
while (!(inb(port + 5) & 0x20)) {}
|
||||
outb(port, v);
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#define RS232_COM0 0x3F8
|
||||
|
||||
void rs232_init(uint16_t port);
|
||||
void rs232_send(uint16_t port, char c);
|
||||
char rs232_recv(uint16_t port);
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "sys/mm.h"
|
||||
#include "sys/debug.h"
|
||||
#include "arch/amd64/hw/gdt.h"
|
||||
|
||||
void kernel_main(void) {
|
||||
kdebug("Booting\n");
|
||||
|
||||
// Memory management
|
||||
amd64_mm_init();
|
||||
amd64_gdt_init();
|
||||
}
|
||||
@@ -25,6 +25,7 @@ SECTIONS {
|
||||
.data ALIGN(4K) : AT(ADDR(.data) - _kernel_base)
|
||||
{
|
||||
*(.data)
|
||||
*(.data.rel.local)
|
||||
}
|
||||
|
||||
.bss ALIGN(4K) : AT(ADDR(.bss) - _kernel_base)
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
/// The place where the kernel pages are virtually mapped to
|
||||
#define KERNEL_VIRT_BASE 0xFFFFFF0000000000
|
||||
|
||||
/// amd64 standard states that addresses' upper bits are copies of the 47th bit, so these need to be
|
||||
/// stripped down to only 48 bits
|
||||
#define AMD64_MM_MASK(a) ((uintptr_t) (a) & 0xFFFFFFFFFFFF)
|
||||
|
||||
/// Page map level 4
|
||||
typedef uint64_t *mm_pml4_t;
|
||||
/// Page directory pointer table
|
||||
@@ -14,3 +18,5 @@ typedef uint64_t *mm_pagetab_t;
|
||||
|
||||
/// Virtual memory space
|
||||
typedef mm_pml4_t mm_space_t;
|
||||
|
||||
void amd64_mm_init(void);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "sys/mem.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/mm.h"
|
||||
|
||||
mm_space_t mm_kernel;
|
||||
|
||||
void amd64_mm_init(void) {
|
||||
kdebug("Memory manager init\n");
|
||||
|
||||
// Physical memory at this point:
|
||||
// 0x000000 - 0x400000 - Used by kernel and info passed from the loader
|
||||
// Virtual memory:
|
||||
// Lower 1GiB mapped to itself for loader access
|
||||
// 0xFFFFFF0000000000 (1GiB) is mapped to 0 for kernel access
|
||||
|
||||
// XXX: assuming nothing important is there
|
||||
uint64_t *pml4 = (uint64_t *) (0x200000 - 0x1000);
|
||||
uint64_t *pdpt = (uint64_t *) (0x200000 - 0x2000);
|
||||
|
||||
memset((void *) (0x200000 - 2 * 0x1000), 0, 0x1000 * 2);
|
||||
|
||||
// 0xFFFFFF0000000000 -> 0 (1GiB) mapping
|
||||
pml4[AMD64_MM_MASK(KERNEL_VIRT_BASE) >> 39] = (uint64_t) pdpt | 1 | 2;
|
||||
pdpt[(AMD64_MM_MASK(KERNEL_VIRT_BASE) >> 30) & 0x1FF] = 1 | 2 | (1 << 7);
|
||||
|
||||
// Load the new table
|
||||
asm volatile ("mov %0, %%cr3"::"a"(pml4):"memory");
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "pool.h"
|
||||
#include "sys/mem.h"
|
||||
|
||||
static struct {
|
||||
uint64_t track[512];
|
||||
uintptr_t start;
|
||||
size_t size;
|
||||
} amd64_mm_pool;
|
||||
|
||||
void amd64_mm_pool_init(uintptr_t begin, size_t size) {
|
||||
amd64_mm_pool.start = begin;
|
||||
amd64_mm_pool.size = size;
|
||||
memset(amd64_mm_pool.track, 0, 512 * sizeof(uint64_t));
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/// Initialize the paging structure allocation pool
|
||||
void amd64_mm_pool_init(uintptr_t base, size_t size);
|
||||
|
||||
/// Allocate a paging structure
|
||||
uint64_t *amd64_mm_pool_alloc(void);
|
||||
|
||||
/// Free a paging structure
|
||||
void amd64_mm_pool_free(uint64_t *obj);
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define __weak __attribute__((weak))
|
||||
+254
@@ -0,0 +1,254 @@
|
||||
#include "debug.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
#include "sys/attr.h"
|
||||
|
||||
#if defined(ARCH_AMD64)
|
||||
#include "arch/amd64/hw/rs232.h"
|
||||
#endif
|
||||
|
||||
static const char *s_debug_xs_set0 = "0123456789abcdef";
|
||||
static const char *s_debug_xs_set1 = "0123456789ABCDEF";
|
||||
|
||||
// TODO: make debugc a __weak function of a character
|
||||
void debugc(int level, char c) {
|
||||
#if defined(ARCH_AMD64)
|
||||
rs232_send(RS232_COM0, c);
|
||||
#endif
|
||||
}
|
||||
|
||||
void debugs(int level, const char *s) {
|
||||
char c;
|
||||
while ((c = *(s++))) {
|
||||
debugc(level, c);
|
||||
}
|
||||
}
|
||||
|
||||
static void debugspl(int level, const char *s, char p, size_t c) {
|
||||
size_t l = strlen(s);
|
||||
for (size_t i = l; i < c; ++i) {
|
||||
debugc(level, p);
|
||||
}
|
||||
debugs(level, s);
|
||||
}
|
||||
|
||||
static void debugspr(int level, const char *s, char p, size_t c) {
|
||||
size_t l = strlen(s);
|
||||
debugs(level, s);
|
||||
for (size_t i = l; i < c; ++i) {
|
||||
debugc(level, p);
|
||||
}
|
||||
}
|
||||
|
||||
static void debugsp(int level, const char *s, char padc, int padl) {
|
||||
if (padl > 0) {
|
||||
debugspl(level, s, padc, padl);
|
||||
} else {
|
||||
debugspr(level, s, padc, -padl);
|
||||
}
|
||||
}
|
||||
|
||||
void debug_ds(int64_t x, char *res, int s, int sz) {
|
||||
if (!x) {
|
||||
res[0] = '0';
|
||||
res[1] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
void debug_xs(uint64_t v, char *res, const char *set) {
|
||||
if (!v) {
|
||||
res[0] = '0';
|
||||
res[1] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
void debugf(int level, const char *f, ...) {
|
||||
va_list args;
|
||||
va_start(args, f);
|
||||
debugfv(level, f, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void debugfv(int level, const char *fmt, va_list args) {
|
||||
char c;
|
||||
union {
|
||||
const char *v_string;
|
||||
char v_char;
|
||||
int32_t v_int32;
|
||||
uint32_t v_uint32;
|
||||
int64_t v_int64;
|
||||
uint64_t v_uint64;
|
||||
uintptr_t v_ptr;
|
||||
} value;
|
||||
char buf[64];
|
||||
char padc;
|
||||
int padn;
|
||||
int padd;
|
||||
|
||||
while ((c = *fmt)) {
|
||||
switch (c) {
|
||||
case '%':
|
||||
c = *(++fmt);
|
||||
|
||||
padc = ' ';
|
||||
padd = 1;
|
||||
padn = 0;
|
||||
if (c == '0') {
|
||||
padc = c;
|
||||
}
|
||||
|
||||
if (c == '-') {
|
||||
padd = -1;
|
||||
c = *(++fmt);
|
||||
}
|
||||
|
||||
while (c >= '0' && c <= '9') {
|
||||
padn *= 10;
|
||||
padn += padd * (int) (c - '0');
|
||||
c = *(++fmt);
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'l':
|
||||
c = *(++fmt);
|
||||
switch (c) {
|
||||
case 'd':
|
||||
value.v_int64 = va_arg(args, int64_t);
|
||||
debug_ds(value.v_int64, buf, 1, 1);
|
||||
debugsp(level, buf, padc, padn);
|
||||
break;
|
||||
case 'u':
|
||||
value.v_uint64 = va_arg(args, uint64_t);
|
||||
debug_ds(value.v_uint64, buf, 0, 1);
|
||||
debugsp(level, buf, padc, padn);
|
||||
break;
|
||||
case 'x':
|
||||
value.v_uint64 = va_arg(args, uint64_t);
|
||||
debug_xs(value.v_uint64, buf, s_debug_xs_set0);
|
||||
debugsp(level, buf, padc, padn);
|
||||
break;
|
||||
case 'X':
|
||||
value.v_uint64 = va_arg(args, uint64_t);
|
||||
debug_xs(value.v_uint64, buf, s_debug_xs_set1);
|
||||
debugsp(level, buf, padc, padn);
|
||||
break;
|
||||
case 'p':
|
||||
value.v_uint64 = va_arg(args, uint64_t);
|
||||
debugc(level, '0');
|
||||
debugc(level, 'x');
|
||||
debug_xs(value.v_uint64, buf, s_debug_xs_set0);
|
||||
debugspl(level, buf, '0', sizeof(uint64_t) * 2);
|
||||
break;
|
||||
default:
|
||||
debugc(level, '%');
|
||||
debugc(level, 'l');
|
||||
debugc(level, c);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
// char is promoted to int
|
||||
value.v_char = va_arg(args, int);
|
||||
debugc(level, value.v_char);
|
||||
break;
|
||||
case 'd':
|
||||
value.v_int64 = va_arg(args, int32_t);
|
||||
debug_ds(value.v_int64 & 0xFFFFFFFF, buf, 1, 0);
|
||||
debugsp(level, buf, padc, padn);
|
||||
break;
|
||||
case 'u':
|
||||
value.v_uint64 = va_arg(args, uint32_t);
|
||||
debug_ds(value.v_uint64 & 0xFFFFFFFF, buf, 0, 0);
|
||||
debugsp(level, buf, padc, padn);
|
||||
break;
|
||||
case 'x':
|
||||
value.v_uint64 = va_arg(args, uint32_t);
|
||||
debug_xs(value.v_uint64 & 0xFFFFFFFF, buf, s_debug_xs_set0);
|
||||
debugsp(level, buf, padc, padn);
|
||||
break;
|
||||
case 'X':
|
||||
value.v_uint64 = va_arg(args, uint32_t);
|
||||
debug_xs(value.v_uint64 & 0xFFFFFFFF, buf, s_debug_xs_set1);
|
||||
debugsp(level, buf, padc, padn);
|
||||
break;
|
||||
case 'p':
|
||||
value.v_ptr = va_arg(args, uintptr_t);
|
||||
debugc(level, '0');
|
||||
debugc(level, 'x');
|
||||
debug_xs(value.v_ptr, buf, s_debug_xs_set0);
|
||||
debugspl(level, buf, '0', sizeof(uintptr_t) * 2);
|
||||
break;
|
||||
case 's':
|
||||
value.v_string = va_arg(args, const char *);
|
||||
debugsp(level, value.v_string ? value.v_string : "(null)", padc, padn);
|
||||
break;
|
||||
default:
|
||||
debugc(level, '%');
|
||||
debugc(level, c);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
debugc(level, c);
|
||||
break;
|
||||
}
|
||||
|
||||
++fmt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define DEBUG_DEFAULT 0
|
||||
#define DEBUG_INFO 1
|
||||
#define DEBUG_WARN 2
|
||||
#define DEBUG_ERROR 3
|
||||
#define DEBUG_FATAL 4
|
||||
|
||||
#define DEBUG_OUT_SERIAL 0
|
||||
#define DEBUG_OUT_DISP 1
|
||||
|
||||
#define kdebug(f, ...) debugf(DEBUG_DEFAULT, "[%s] " f, __func__, ##__VA_ARGS__)
|
||||
#define kinfo(f, ...) debugf(DEBUG_INFO, "[%s] " f, __func__, ##__VA_ARGS__)
|
||||
#define kwarn(f, ...) debugf(DEBUG_WARN, "[%s] " f, __func__, ##__VA_ARGS__)
|
||||
#define kerror(f, ...) debugf(DEBUG_ERROR, "[%s] " f, __func__, ##__VA_ARGS__)
|
||||
#define kfatal(f, ...) debugf(DEBUG_FATAL, "[%s] " f, __func__, ##__VA_ARGS__)
|
||||
#define kprint(l, f, ...) debugf(l, "[%s] " f, __func__, ##__VA_ARGS__)
|
||||
|
||||
void debugc(int level, char c);
|
||||
void debugs(int level, const char *s);
|
||||
|
||||
void debug_xs(uint64_t v, char *res, const char *set);
|
||||
void debug_ds(int64_t x, char *res, int s, int sz);
|
||||
void debug_init(void);
|
||||
void debugf(int level, const char *fmt, ...);
|
||||
void debugfv(int level, const char *fmt, va_list args);
|
||||
|
||||
void debug_dump(int level, const void *block, size_t count);
|
||||
@@ -0,0 +1,8 @@
|
||||
#include "mem.h"
|
||||
|
||||
void *memset(void *blk, int v, size_t sz) {
|
||||
for (size_t i = 0; i < sz; ++i) {
|
||||
((char *) blk)[i] = v;
|
||||
}
|
||||
return blk;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void *memset(void *blk, int v, size_t sz);
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "string.h"
|
||||
|
||||
size_t strlen(const char *a) {
|
||||
size_t s = 0;
|
||||
while (*a++) {
|
||||
++s;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
|
||||
size_t strlen(const char *s);
|
||||
Reference in New Issue
Block a user