update
This commit is contained in:
parent
4856134d39
commit
b91de2f374
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "kernel/vendor/flanterm"]
|
||||||
|
path = kernel/vendor/flanterm
|
||||||
|
url = https://github.com/mintsuki/flanterm
|
|
@ -1,7 +1,7 @@
|
||||||
# Nuke built-in rules and variables.
|
# Nuke built-in rules and variables.
|
||||||
override MAKEFLAGS += -rR
|
override MAKEFLAGS += -rR
|
||||||
|
|
||||||
override IMAGE_NAME := template
|
override IMAGE_NAME := radix
|
||||||
|
|
||||||
# Convenience macro to reliably declare user overridable variables.
|
# Convenience macro to reliably declare user overridable variables.
|
||||||
define DEFAULT_VAR =
|
define DEFAULT_VAR =
|
||||||
|
@ -33,7 +33,7 @@ all-hdd: $(IMAGE_NAME).hdd
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: $(IMAGE_NAME).iso
|
run: $(IMAGE_NAME).iso
|
||||||
qemu-system-x86_64 -M q35 -m 2G -cdrom $(IMAGE_NAME).iso -boot d
|
qemu-system-x86_64 -m 1G -cdrom $(IMAGE_NAME).iso -enable-kvm -cpu host -boot d
|
||||||
|
|
||||||
.PHONY: run-uefi
|
.PHONY: run-uefi
|
||||||
run-uefi: ovmf $(IMAGE_NAME).iso
|
run-uefi: ovmf $(IMAGE_NAME).iso
|
|
@ -44,6 +44,7 @@ $(eval $(call DEFAULT_VAR,LDFLAGS,$(DEFAULT_LDFLAGS)))
|
||||||
# Internal C flags that should not be changed by the user.
|
# Internal C flags that should not be changed by the user.
|
||||||
override CFLAGS += \
|
override CFLAGS += \
|
||||||
-Wall \
|
-Wall \
|
||||||
|
-Werror \
|
||||||
-Wextra \
|
-Wextra \
|
||||||
-std=gnu11 \
|
-std=gnu11 \
|
||||||
-ffreestanding \
|
-ffreestanding \
|
||||||
|
@ -62,6 +63,7 @@ override CFLAGS += \
|
||||||
# Internal C preprocessor flags that should not be changed by the user.
|
# Internal C preprocessor flags that should not be changed by the user.
|
||||||
override CPPFLAGS := \
|
override CPPFLAGS := \
|
||||||
-I src \
|
-I src \
|
||||||
|
-I vendor \
|
||||||
$(CPPFLAGS) \
|
$(CPPFLAGS) \
|
||||||
-MMD \
|
-MMD \
|
||||||
-MP
|
-MP
|
||||||
|
@ -84,7 +86,7 @@ override NASMFLAGS += \
|
||||||
|
|
||||||
# Use "find" to glob all *.c, *.S, and *.asm files in the tree and obtain the
|
# Use "find" to glob all *.c, *.S, and *.asm files in the tree and obtain the
|
||||||
# object and header dependency file names.
|
# object and header dependency file names.
|
||||||
override CFILES := $(shell cd src && find -L * -type f -name '*.c')
|
override CFILES := $(shell cd src && find -L * -type f -name '*.c') $(shell cd vendor && find -L * -type f -name '*.c')
|
||||||
override ASFILES := $(shell cd src && find -L * -type f -name '*.S')
|
override ASFILES := $(shell cd src && find -L * -type f -name '*.S')
|
||||||
override NASMFILES := $(shell cd src && find -L * -type f -name '*.asm')
|
override NASMFILES := $(shell cd src && find -L * -type f -name '*.asm')
|
||||||
override OBJ := $(addprefix obj/,$(CFILES:.c=.c.o) $(ASFILES:.S=.S.o) $(NASMFILES:.asm=.asm.o))
|
override OBJ := $(addprefix obj/,$(CFILES:.c=.c.o) $(ASFILES:.S=.S.o) $(NASMFILES:.asm=.asm.o))
|
||||||
|
@ -98,7 +100,7 @@ src/limine.h:
|
||||||
curl -Lo $@ https://github.com/limine-bootloader/limine/raw/trunk/limine.h
|
curl -Lo $@ https://github.com/limine-bootloader/limine/raw/trunk/limine.h
|
||||||
|
|
||||||
# Link rules for the final kernel executable.
|
# Link rules for the final kernel executable.
|
||||||
bin/$(KERNEL): GNUmakefile linker.ld $(OBJ)
|
bin/$(KERNEL): Makefile linker.ld $(OBJ)
|
||||||
mkdir -p "$$(dirname $@)"
|
mkdir -p "$$(dirname $@)"
|
||||||
$(LD) $(OBJ) $(LDFLAGS) -o $@
|
$(LD) $(OBJ) $(LDFLAGS) -o $@
|
||||||
|
|
||||||
|
@ -106,17 +108,21 @@ bin/$(KERNEL): GNUmakefile linker.ld $(OBJ)
|
||||||
-include $(HEADER_DEPS)
|
-include $(HEADER_DEPS)
|
||||||
|
|
||||||
# Compilation rules for *.c files.
|
# Compilation rules for *.c files.
|
||||||
obj/%.c.o: src/%.c GNUmakefile src/limine.h
|
obj/%.c.o: src/%.c Makefile src/limine.h
|
||||||
|
mkdir -p "$$(dirname $@)"
|
||||||
|
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
obj/%.c.o: vendor/%.c Makefile src/limine.h
|
||||||
mkdir -p "$$(dirname $@)"
|
mkdir -p "$$(dirname $@)"
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
# Compilation rules for *.S files.
|
# Compilation rules for *.S files.
|
||||||
obj/%.S.o: src/%.S GNUmakefile
|
obj/%.S.o: src/%.S Makefile
|
||||||
mkdir -p "$$(dirname $@)"
|
mkdir -p "$$(dirname $@)"
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
||||||
|
|
||||||
# Compilation rules for *.asm (nasm) files.
|
# Compilation rules for *.asm (nasm) files.
|
||||||
obj/%.asm.o: src/%.asm GNUmakefile
|
obj/%.asm.o: src/%.asm Makefile
|
||||||
mkdir -p "$$(dirname $@)"
|
mkdir -p "$$(dirname $@)"
|
||||||
nasm $(NASMFLAGS) $< -o $@
|
nasm $(NASMFLAGS) $< -o $@
|
||||||
|
|
5
kernel/src/ctype.c
Normal file
5
kernel/src/ctype.c
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
int isdigit(char c) {
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
6
kernel/src/ctype.h
Normal file
6
kernel/src/ctype.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef __CTYPE_H__
|
||||||
|
#define __CTYPE_H__
|
||||||
|
|
||||||
|
int isdigit(char c);
|
||||||
|
|
||||||
|
#endif
|
18
kernel/src/framebuffer.c
Normal file
18
kernel/src/framebuffer.c
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include <framebuffer.h>
|
||||||
|
#include <hcf.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct limine_framebuffer_request framebuffer_request = {
|
||||||
|
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
struct limine_framebuffer* framebuffer = { 0 };
|
||||||
|
|
||||||
|
void fb_init() {
|
||||||
|
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
|
||||||
|
hcf();
|
||||||
|
}
|
||||||
|
|
||||||
|
framebuffer = framebuffer_request.response->framebuffers[0];
|
||||||
|
}
|
9
kernel/src/framebuffer.h
Normal file
9
kernel/src/framebuffer.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef __FRAMEBUFFER_H__
|
||||||
|
#define __FRAMEBUFFER_H__
|
||||||
|
|
||||||
|
#include <limine.h>
|
||||||
|
|
||||||
|
extern struct limine_framebuffer* framebuffer;
|
||||||
|
void fb_init();
|
||||||
|
|
||||||
|
#endif
|
7
kernel/src/hcf.asm
Normal file
7
kernel/src/hcf.asm
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
global hcf
|
||||||
|
|
||||||
|
hcf:
|
||||||
|
cli
|
||||||
|
loop:
|
||||||
|
hlt
|
||||||
|
jmp loop
|
6
kernel/src/hcf.h
Normal file
6
kernel/src/hcf.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef __HCF_H__
|
||||||
|
#define __HCF_H__
|
||||||
|
|
||||||
|
extern void hcf();
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,112 +1,108 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <framebuffer.h>
|
||||||
|
#include <terminal.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
#include <hcf.h>
|
||||||
// Set the base revision to 1, this is recommended as this is the latest
|
#include <memory.h>
|
||||||
// base revision described by the Limine boot protocol specification.
|
|
||||||
// See specification for further info.
|
|
||||||
|
|
||||||
LIMINE_BASE_REVISION(1)
|
LIMINE_BASE_REVISION(1)
|
||||||
|
|
||||||
// The Limine requests can be placed anywhere, but it is important that
|
struct limine_memmap_request memmap_request = {
|
||||||
// the compiler does not optimise them away, so, in C, they should
|
.id = LIMINE_MEMMAP_REQUEST,
|
||||||
// NOT be made "static".
|
.revision = 0
|
||||||
|
|
||||||
struct limine_framebuffer_request framebuffer_request = {
|
|
||||||
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
|
||||||
.revision = 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// GCC and Clang reserve the right to generate calls to the following
|
void* memcpy(void* dest, const void* src, size_t n) {
|
||||||
// 4 functions even if they are not directly called.
|
uint8_t* pdest = (uint8_t*)dest;
|
||||||
// Implement them as the C specification mandates.
|
const uint8_t* psrc = (const uint8_t*)src;
|
||||||
// DO NOT remove or rename these functions, or stuff will eventually break!
|
|
||||||
// They CAN be moved to a different .c file.
|
|
||||||
|
|
||||||
void *memcpy(void *dest, const void *src, size_t n) {
|
for(size_t i = 0; i < n; i++) {
|
||||||
uint8_t *pdest = (uint8_t *)dest;
|
pdest[i] = psrc[i];
|
||||||
const uint8_t *psrc = (const uint8_t *)src;
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
return dest;
|
||||||
pdest[i] = psrc[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memset(void *s, int c, size_t n) {
|
void* memset(void* s, int c, size_t n) {
|
||||||
uint8_t *p = (uint8_t *)s;
|
uint8_t* p = (uint8_t*)s;
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
for(size_t i = 0; i < n; i++) {
|
||||||
p[i] = (uint8_t)c;
|
p[i] = (uint8_t)c;
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *memmove(void *dest, const void *src, size_t n) {
|
void* memmove(void* dest, const void* src, size_t n) {
|
||||||
uint8_t *pdest = (uint8_t *)dest;
|
uint8_t* pdest = (uint8_t*)dest;
|
||||||
const uint8_t *psrc = (const uint8_t *)src;
|
const uint8_t* psrc = (const uint8_t*)src;
|
||||||
|
|
||||||
if (src > dest) {
|
if(src > dest) {
|
||||||
for (size_t i = 0; i < n; i++) {
|
for(size_t i = 0; i < n; i++) {
|
||||||
pdest[i] = psrc[i];
|
pdest[i] = psrc[i];
|
||||||
}
|
}
|
||||||
} else if (src < dest) {
|
} else if(src < dest) {
|
||||||
for (size_t i = n; i > 0; i--) {
|
for(size_t i = n; i > 0; i--) {
|
||||||
pdest[i-1] = psrc[i-1];
|
pdest[i-1] = psrc[i-1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
int memcmp(const void* s1, const void* s2, size_t n) {
|
||||||
const uint8_t *p1 = (const uint8_t *)s1;
|
const uint8_t* p1 = (const uint8_t*)s1;
|
||||||
const uint8_t *p2 = (const uint8_t *)s2;
|
const uint8_t* p2 = (const uint8_t*)s2;
|
||||||
|
|
||||||
for (size_t i = 0; i < n; i++) {
|
for(size_t i = 0; i < n; i++) {
|
||||||
if (p1[i] != p2[i]) {
|
if(p1[i] != p2[i]) {
|
||||||
return p1[i] < p2[i] ? -1 : 1;
|
return p1[i] < p2[i] ? -1 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Halt and catch fire function.
|
const char* types[] = {
|
||||||
static void hcf(void) {
|
"USABLE",
|
||||||
asm ("cli");
|
"RESERVED",
|
||||||
for (;;) {
|
"ACPI_RECLAIMABLE",
|
||||||
asm ("hlt");
|
"ACPI_NVS",
|
||||||
}
|
"BAD_MEMORY",
|
||||||
}
|
"BOOTLOADER_RECLAIMABLE",
|
||||||
|
"KERNEL_AND_MODULES",
|
||||||
|
"FRAMEBUFFER"
|
||||||
|
};
|
||||||
|
|
||||||
// The following will be our kernel's entry point.
|
|
||||||
// If renaming _start() to something else, make sure to change the
|
|
||||||
// linker script accordingly.
|
|
||||||
void _start(void) {
|
void _start(void) {
|
||||||
// Ensure the bootloader actually understands our base revision (see spec).
|
if(LIMINE_BASE_REVISION_SUPPORTED == false) {
|
||||||
if (LIMINE_BASE_REVISION_SUPPORTED == false) {
|
hcf();
|
||||||
hcf();
|
}
|
||||||
}
|
|
||||||
|
fb_init();
|
||||||
|
term_init();
|
||||||
|
mem_init();
|
||||||
|
|
||||||
// Ensure we got a framebuffer.
|
printf("running at %dx%d\n", framebuffer->width, framebuffer->height);
|
||||||
if (framebuffer_request.response == NULL
|
|
||||||
|| framebuffer_request.response->framebuffer_count < 1) {
|
|
||||||
hcf();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch the first framebuffer.
|
struct limine_memmap_response* memmap = memmap_request.response;
|
||||||
struct limine_framebuffer *framebuffer = framebuffer_request.response->framebuffers[0];
|
|
||||||
|
|
||||||
// Note: we assume the framebuffer model is RGB with 32-bit pixels.
|
printf("%d memmap entries present.\n", memmap->entry_count);
|
||||||
for (size_t i = 0; i < 100; i++) {
|
|
||||||
volatile uint32_t *fb_ptr = framebuffer->address;
|
|
||||||
fb_ptr[i * (framebuffer->pitch / 4) + i] = 0xffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We're done, just hang...
|
for(uint64_t i = 0; i < memmap->entry_count; i++) {
|
||||||
hcf();
|
struct limine_memmap_entry* entry = memmap->entries[i];
|
||||||
|
if(entry->type == LIMINE_MEMMAP_USABLE)
|
||||||
|
mem_add(entry->base, entry->length);
|
||||||
|
|
||||||
|
printf("0x%010x - 0x%010x (type: % 22s, size: % 10u)\n",
|
||||||
|
entry->base, entry->base + entry->length, types[entry->type], entry->length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* a = mem_alloc(10);
|
||||||
|
printf("memory allocated at %x", a);
|
||||||
|
|
||||||
|
hcf();
|
||||||
}
|
}
|
||||||
|
|
35
kernel/src/memory.c
Normal file
35
kernel/src/memory.c
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
void* mem_start;
|
||||||
|
void* mem_ptr;
|
||||||
|
int blocks = 0;
|
||||||
|
|
||||||
|
struct limine_kernel_address_request kernel_address_request = {
|
||||||
|
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
struct limine_kernel_address_response* kernel_address = { 0 };
|
||||||
|
|
||||||
|
void mem_init() {
|
||||||
|
kernel_address = kernel_address_request.response;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mem_add(uint64_t base, uint64_t len) {
|
||||||
|
if(!mem_start) {
|
||||||
|
mem_start = mem_ptr = (void*)kernel_address->virtual_base + base;
|
||||||
|
*((struct mem_desc*)mem_start) = (struct mem_desc) {
|
||||||
|
.base = base,
|
||||||
|
.len = len
|
||||||
|
};
|
||||||
|
mem_ptr += sizeof(struct mem_desc);
|
||||||
|
blocks++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* mem_alloc(size_t sz) {
|
||||||
|
void* start = mem_ptr;
|
||||||
|
*((size_t*)start) = sz;
|
||||||
|
mem_ptr += sz + sizeof(size_t);
|
||||||
|
return start + sizeof(size_t);
|
||||||
|
}
|
18
kernel/src/memory.h
Normal file
18
kernel/src/memory.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef __MEMORY_H__
|
||||||
|
#define __MEMORY_H__
|
||||||
|
|
||||||
|
#include <limine.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void mem_init();
|
||||||
|
void mem_add(uint64_t base, uint64_t len);
|
||||||
|
void* mem_alloc(size_t sz);
|
||||||
|
|
||||||
|
struct mem_desc {
|
||||||
|
uint64_t base;
|
||||||
|
uint64_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct limine_kernel_address_response* kernel_address;
|
||||||
|
|
||||||
|
#endif
|
73
kernel/src/stdio.c
Normal file
73
kernel/src/stdio.c
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#include <printf.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <terminal.h>
|
||||||
|
#include <flanterm/flanterm.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
void putc(char ch) {
|
||||||
|
flanterm_write(ft_ctx, &ch, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void puts(const char* str) {
|
||||||
|
flanterm_write(ft_ctx, str, strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
void printf(const char *str, ...) {
|
||||||
|
va_list list;
|
||||||
|
va_start(list, str);
|
||||||
|
|
||||||
|
char buf[128];
|
||||||
|
|
||||||
|
for(int i = 0; str[i] != '\0'; i++)
|
||||||
|
{
|
||||||
|
switch(str[i])
|
||||||
|
{
|
||||||
|
case '%':
|
||||||
|
i++;
|
||||||
|
|
||||||
|
size_t width = 0;
|
||||||
|
char padding_char = str[i];
|
||||||
|
if(isdigit(str[i]) || str[i] == ' ') {
|
||||||
|
i++;
|
||||||
|
int pos = 0;
|
||||||
|
while(isdigit(str[i])) {
|
||||||
|
buf[pos++] = str[i++];
|
||||||
|
}
|
||||||
|
buf[pos] = '\0';
|
||||||
|
width = atoi(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* out = 0;
|
||||||
|
|
||||||
|
if(str[i] == 's')
|
||||||
|
out = va_arg(list, const char*);
|
||||||
|
if(str[i] == 'd')
|
||||||
|
out = itoa(va_arg(list, int), buf, 10);
|
||||||
|
if(str[i] == 'u')
|
||||||
|
out = ultoa(va_arg(list, uint64_t), buf, 10);
|
||||||
|
if(str[i] == 'x')
|
||||||
|
out = ultoa(va_arg(list, uint64_t), buf, 16);
|
||||||
|
if(str[i] == 'c')
|
||||||
|
putc(va_arg(list, int));
|
||||||
|
|
||||||
|
size_t len = strlen(out);
|
||||||
|
if(width > len) {
|
||||||
|
char padding[256];
|
||||||
|
size_t j = 0;
|
||||||
|
for(; j < width - len; j++)
|
||||||
|
padding[j] = padding_char;
|
||||||
|
padding[j] = '\0';
|
||||||
|
puts(padding);
|
||||||
|
}
|
||||||
|
|
||||||
|
puts(out);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
putc(str[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(list);
|
||||||
|
}
|
8
kernel/src/stdio.h
Normal file
8
kernel/src/stdio.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef __STDIO_H__
|
||||||
|
#define __STDIO_H__
|
||||||
|
|
||||||
|
void putc(char ch);
|
||||||
|
void puts(const char* str);
|
||||||
|
void printf(const char *str, ...);
|
||||||
|
|
||||||
|
#endif
|
77
kernel/src/stdlib.c
Normal file
77
kernel/src/stdlib.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
const char* itoa(int value, char* str, int base)
|
||||||
|
{
|
||||||
|
char* rc;
|
||||||
|
char* ptr;
|
||||||
|
char* low;
|
||||||
|
|
||||||
|
if (base < 2 || base > 36)
|
||||||
|
{
|
||||||
|
*str = '\0';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
rc = ptr = str;
|
||||||
|
if (value < 0 && base == 10)
|
||||||
|
{
|
||||||
|
*ptr++ = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
low = ptr;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + value % base];
|
||||||
|
value /= base;
|
||||||
|
} while (value);
|
||||||
|
|
||||||
|
*ptr-- = '\0';
|
||||||
|
while (low < ptr)
|
||||||
|
{
|
||||||
|
char tmp = *low;
|
||||||
|
*low++ = *ptr;
|
||||||
|
*ptr-- = tmp;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* ultoa(uint64_t value, char* str, int base)
|
||||||
|
{
|
||||||
|
char* rc;
|
||||||
|
char* ptr;
|
||||||
|
char* low;
|
||||||
|
|
||||||
|
if (base < 2 || base > 36)
|
||||||
|
{
|
||||||
|
*str = '\0';
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
rc = ptr = str;
|
||||||
|
|
||||||
|
low = ptr;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + value % base];
|
||||||
|
value /= base;
|
||||||
|
} while (value);
|
||||||
|
|
||||||
|
*ptr-- = '\0';
|
||||||
|
while (low < ptr)
|
||||||
|
{
|
||||||
|
char tmp = *low;
|
||||||
|
*low++ = *ptr;
|
||||||
|
*ptr-- = tmp;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int atoi(const char* str) {
|
||||||
|
int value = 0;
|
||||||
|
while(isdigit(*str)) {
|
||||||
|
value *= 10;
|
||||||
|
value += (*str)-'0';
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
9
kernel/src/stdlib.h
Normal file
9
kernel/src/stdlib.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#ifndef __STDLIB_H__
|
||||||
|
#define __STDLIB_H__
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
const char* itoa(int value, char* str, int base);
|
||||||
|
const char* ultoa(uint64_t value, char* str, int base);
|
||||||
|
int atoi(const char* str);
|
||||||
|
|
||||||
|
#endif
|
8
kernel/src/string.c
Normal file
8
kernel/src/string.c
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
size_t strlen(const char* str) {
|
||||||
|
size_t len = 0;
|
||||||
|
while (str[len])
|
||||||
|
len++;
|
||||||
|
return len;
|
||||||
|
}
|
8
kernel/src/string.h
Normal file
8
kernel/src/string.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef __STRING_H__
|
||||||
|
#define __STRING_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
size_t strlen(const char* str);
|
||||||
|
|
||||||
|
#endif
|
11
kernel/src/terminal.c
Normal file
11
kernel/src/terminal.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
#include <terminal.h>
|
||||||
|
#include <flanterm/backends/fb.h>
|
||||||
|
#include <framebuffer.h>
|
||||||
|
|
||||||
|
struct flanterm_context* ft_ctx = { 0 };
|
||||||
|
|
||||||
|
void term_init() {
|
||||||
|
ft_ctx = flanterm_fb_simple_init(
|
||||||
|
framebuffer->address, framebuffer->width, framebuffer->height, framebuffer->pitch
|
||||||
|
);
|
||||||
|
}
|
7
kernel/src/terminal.h
Normal file
7
kernel/src/terminal.h
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef __TERMINAL_H__
|
||||||
|
#define __TERMINAL_H__
|
||||||
|
|
||||||
|
void term_init();
|
||||||
|
extern struct flanterm_context* ft_ctx;
|
||||||
|
|
||||||
|
#endif
|
1
kernel/vendor/flanterm
vendored
Submodule
1
kernel/vendor/flanterm
vendored
Submodule
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 545ab1faa8ba7493ae7a43064d520e402ad308b5
|
10
limine.cfg
10
limine.cfg
|
@ -1,16 +1,16 @@
|
||||||
# Timeout in seconds that Limine will use before automatically booting.
|
# Timeout in seconds that Limine will use before automatically booting.
|
||||||
TIMEOUT=3
|
TIMEOUT=0
|
||||||
|
|
||||||
# The entry name that will be displayed in the boot menu.
|
# The entry name that will be displayed in the boot menu.
|
||||||
:Limine Template (KASLR on)
|
#:Limine Template (KASLR on)
|
||||||
# We use the Limine boot protocol.
|
# We use the Limine boot protocol.
|
||||||
PROTOCOL=limine
|
# PROTOCOL=limine
|
||||||
|
|
||||||
# Path to the kernel to boot. boot:/// represents the partition on which limine.cfg is located.
|
# Path to the kernel to boot. boot:/// represents the partition on which limine.cfg is located.
|
||||||
KERNEL_PATH=boot:///kernel
|
# KERNEL_PATH=boot:///kernel
|
||||||
|
|
||||||
# Same thing, but without KASLR.
|
# Same thing, but without KASLR.
|
||||||
:Limine Template (KASLR off)
|
:radix
|
||||||
PROTOCOL=limine
|
PROTOCOL=limine
|
||||||
|
|
||||||
# Disable KASLR (it is enabled by default for relocatable kernels)
|
# Disable KASLR (it is enabled by default for relocatable kernels)
|
||||||
|
|
Loading…
Reference in a new issue