forked from Bananymous/banan-os
				
			Fixes :)
This commit is contained in:
		
							parent
							
								
									35e21ca4ce
								
							
						
					
					
						commit
						123382eace
					
				|  | @ -31,7 +31,7 @@ KERNEL_OBJS=\ | ||||||
| $(KERNEL_ARCH_OBJS) \ | $(KERNEL_ARCH_OBJS) \ | ||||||
| kernel/kernel.o \ | kernel/kernel.o \ | ||||||
| kernel/panic.o \ | kernel/panic.o \ | ||||||
| kernel/ssp.o \ | kernel/SSP.o \ | ||||||
|   |   | ||||||
| OBJS=\
 | OBJS=\
 | ||||||
| $(ARCHDIR)/crti.o \ | $(ARCHDIR)/crti.o \ | ||||||
|  | @ -59,7 +59,7 @@ banan-os.kernel: $(OBJS) $(ARCHDIR)/linker.ld | ||||||
| 	grub-file --is-x86-multiboot banan-os.kernel | 	grub-file --is-x86-multiboot banan-os.kernel | ||||||
|   |   | ||||||
| $(ARCHDIR)/crtbegin.o $(ARCHDIR)/crtend.o: | $(ARCHDIR)/crtbegin.o $(ARCHDIR)/crtend.o: | ||||||
| 	OBJ=`$(CXX) $(CFLAGS) $(LDFLAGS) -print-file-name=$(@F)` && cp "$$OBJ" $@ | 	OBJ=`$(CXX) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -print-file-name=$(@F)` && cp "$$OBJ" $@ | ||||||
|   |   | ||||||
| .cpp.o: | .cpp.o: | ||||||
| 	$(CXX) -MD -c $< -o $@ $(CFLAGS) $(CPPFLAGS) | 	$(CXX) -MD -c $< -o $@ $(CFLAGS) $(CPPFLAGS) | ||||||
|  |  | ||||||
|  | @ -1,13 +1,16 @@ | ||||||
|  | #include <kernel/multiboot.h> | ||||||
|  | #include <kernel/panic.h> | ||||||
| #include <kernel/tty.h> | #include <kernel/tty.h> | ||||||
| 
 | 
 | ||||||
| #include "vga.h" | #include "vga.h" | ||||||
| 
 | 
 | ||||||
| #include <stddef.h> | #include <stddef.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  | #include <string.h> | ||||||
| 
 | 
 | ||||||
| static constexpr size_t VGA_WIDTH = 80; | static size_t VGA_WIDTH; | ||||||
| static constexpr size_t VGA_HEIGHT = 25; | static size_t VGA_HEIGHT; | ||||||
| static uint16_t* const VGA_MEMORY = (uint16_t*)0xB8000; | static uint16_t* VGA_MEMORY; | ||||||
| 
 | 
 | ||||||
| static size_t terminal_row; | static size_t terminal_row; | ||||||
| static size_t terminal_col; | static size_t terminal_col; | ||||||
|  | @ -29,11 +32,29 @@ void terminal_clear() | ||||||
| 
 | 
 | ||||||
| void terminal_initialize() | void terminal_initialize() | ||||||
| { | { | ||||||
|  | 	if (s_multiboot_info->flags & (1 << 12)) | ||||||
|  | 	{ | ||||||
|  | 		const framebuffer_info_t& fb = s_multiboot_info->framebuffer; | ||||||
|  | 		VGA_WIDTH	= fb.width; | ||||||
|  | 		VGA_HEIGHT 	= fb.height; | ||||||
|  | 		VGA_MEMORY	= (uint16_t*)fb.addr; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		VGA_WIDTH	= 80; | ||||||
|  | 		VGA_HEIGHT	= 25; | ||||||
|  | 		VGA_MEMORY	= (uint16_t*)0xB8000; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	terminal_row = 0; | 	terminal_row = 0; | ||||||
| 	terminal_col = 0; | 	terminal_col = 0; | ||||||
| 	terminal_color = vga_entry_color(VGA_COLOR_WHITE, VGA_COLOR_BLACK); | 	terminal_color = vga_entry_color(VGA_COLOR_WHITE, VGA_COLOR_BLACK); | ||||||
| 	terminal_buffer = VGA_MEMORY; | 	terminal_buffer = VGA_MEMORY; | ||||||
| 	terminal_clear(); | 	terminal_clear(); | ||||||
|  | 
 | ||||||
|  | 	if (s_multiboot_info->flags & (1 << 12)) | ||||||
|  | 		if (s_multiboot_info->framebuffer.type != 2) | ||||||
|  | 			Kernel::panic("Invalid framebuffer_type in multiboot info"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void terminal_setcolor(uint8_t color) | void terminal_setcolor(uint8_t color) | ||||||
|  | @ -118,8 +139,5 @@ void terminal_write(const char* data, size_t size) | ||||||
| 
 | 
 | ||||||
| void terminal_writestring(const char* data) | void terminal_writestring(const char* data) | ||||||
| { | { | ||||||
| 	size_t len = 0; | 	terminal_write(data, strlen(data)); | ||||||
| 	while (data[len]) |  | ||||||
| 		len++; |  | ||||||
| 	terminal_write(data, len); |  | ||||||
| } | } | ||||||
|  | @ -0,0 +1,150 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <kernel/tty.h> | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | template<typename T> | ||||||
|  | static void kprint_signed(T value) | ||||||
|  | { | ||||||
|  | 	if (value == 0) | ||||||
|  | 	{ | ||||||
|  | 		terminal_putchar('0'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	char  buffer[32]; | ||||||
|  | 	char* ptr = buffer + sizeof(buffer); | ||||||
|  | 	bool  sign = false; | ||||||
|  | 	 | ||||||
|  | 	if (value < 0) | ||||||
|  | 	{ | ||||||
|  | 		sign = true; | ||||||
|  | 		*(--ptr) = ((value % 10 + 10) % 10) + '0'; | ||||||
|  | 		value /= 10; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	while (value) | ||||||
|  | 	{ | ||||||
|  | 		*(--ptr) = (value % 10) + '0'; | ||||||
|  | 		value /= 10; | ||||||
|  | 	} | ||||||
|  | 	if (sign) | ||||||
|  | 		*(--ptr) = '-'; | ||||||
|  | 
 | ||||||
|  | 	terminal_write(ptr, sizeof(buffer) - (ptr - buffer)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template<typename T> | ||||||
|  | static void kprint_unsigned(T value) | ||||||
|  | { | ||||||
|  | 	if (value == 0) | ||||||
|  | 	{ | ||||||
|  | 		terminal_putchar('0'); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	char  buffer[32]; | ||||||
|  | 	char* ptr = buffer + sizeof(buffer); | ||||||
|  | 
 | ||||||
|  | 	while (value) | ||||||
|  | 	{ | ||||||
|  | 		*(--ptr) = (value % 10) + '0'; | ||||||
|  | 		value /= 10; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	terminal_write(ptr, sizeof(buffer) - (ptr - buffer)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | template<typename T> | ||||||
|  | static void kprint_val(T) | ||||||
|  | { | ||||||
|  | 	terminal_writestring("<unknown type>"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void kprint(const char* format) | ||||||
|  | { | ||||||
|  | 	terminal_writestring(format); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template<typename Arg, typename... Args> | ||||||
|  | static void kprint(const char* format, Arg arg, Args... args) | ||||||
|  | { | ||||||
|  | 	const char* next = strstr(format, "{}"); | ||||||
|  | 	if (next == NULL) | ||||||
|  | 	{ | ||||||
|  | 		terminal_writestring(format); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	terminal_write(format, next - format); | ||||||
|  | 	kprint_val<Arg>(arg); | ||||||
|  | 	kprint(next + 2, args...); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template<> void kprint_val(short     int value)				{ kprint_signed(value); } | ||||||
|  | template<> void kprint_val(          int value)				{ kprint_signed(value); } | ||||||
|  | template<> void kprint_val(long      int value)				{ kprint_signed(value); } | ||||||
|  | template<> void kprint_val(long long int value)				{ kprint_signed(value); } | ||||||
|  | 
 | ||||||
|  | template<> void kprint_val(unsigned short     int value)	{ kprint_unsigned(value); } | ||||||
|  | template<> void kprint_val(unsigned           int value)	{ kprint_unsigned(value); } | ||||||
|  | template<> void kprint_val(unsigned long      int value)	{ kprint_unsigned(value); } | ||||||
|  | template<> void kprint_val(unsigned long long int value)	{ kprint_unsigned(value); } | ||||||
|  | 
 | ||||||
|  | template<> void kprint_val(         char value)				{ terminal_putchar(value); } | ||||||
|  | template<> void kprint_val(signed   char value)				{ kprint_signed(value); } | ||||||
|  | template<> void kprint_val(unsigned char value)				{ kprint_unsigned(value); } | ||||||
|  | 
 | ||||||
|  | template<> void kprint_val(const char* value)				{ terminal_writestring(value); } | ||||||
|  | template<> void kprint_val(char*       value)				{ terminal_writestring(value); } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | static char bits_to_hex(uint8_t val) | ||||||
|  | { | ||||||
|  | 	val = val & 0xF; | ||||||
|  | 	if (val < 10) | ||||||
|  | 		return val + '0'; | ||||||
|  | 	return val + 'a' - 10; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template<> void kprint_val(void* value) | ||||||
|  | { | ||||||
|  | 	terminal_write("0x", 2); | ||||||
|  | 
 | ||||||
|  | 	if constexpr(sizeof(void*) == sizeof(uint32_t)) | ||||||
|  | 	{ | ||||||
|  | 		uint32_t addr = (uint32_t)value; | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 28)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 24)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 20)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 16)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 12)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >>  8)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >>  4)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >>  0)); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		uint64_t addr = (uint64_t)value; | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 60)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 56)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 52)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 48)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 44)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 40)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 36)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 32)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 28)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 24)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 20)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 16)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >> 12)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >>  8)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >>  4)); | ||||||
|  | 		terminal_putchar(bits_to_hex(addr >>  0)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -0,0 +1,51 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | 
 | ||||||
|  | struct framebuffer_info_t | ||||||
|  | { | ||||||
|  | 	uint64_t addr; | ||||||
|  | 	uint32_t pitch; | ||||||
|  | 	uint32_t width; | ||||||
|  | 	uint32_t height; | ||||||
|  | 	uint8_t  bpp; | ||||||
|  | 	uint8_t  type; | ||||||
|  | 	uint8_t  color_info[6]; | ||||||
|  | } __attribute__((packed)); | ||||||
|  | 
 | ||||||
|  | struct multiboot_memory_map_t | ||||||
|  | { | ||||||
|  | 	uint32_t size; | ||||||
|  | 	uint64_t base_addr; | ||||||
|  | 	uint64_t length; | ||||||
|  | 	uint32_t type; | ||||||
|  | } __attribute__((packed)); | ||||||
|  | 
 | ||||||
|  | // https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format
 | ||||||
|  | struct multiboot_info_t | ||||||
|  | { | ||||||
|  | 	uint32_t flags; | ||||||
|  | 	uint32_t mem_lower; | ||||||
|  | 	uint32_t mem_upper; | ||||||
|  | 	uint32_t boot_device; | ||||||
|  | 	uint32_t cmdline; | ||||||
|  | 	uint32_t mods_count; | ||||||
|  | 	uint32_t mods_addr; | ||||||
|  | 	uint32_t syms[4]; | ||||||
|  | 	uint32_t mmap_length; | ||||||
|  | 	uint32_t mmap_addr; | ||||||
|  | 	uint32_t drives_length; | ||||||
|  | 	uint32_t drives_addr; | ||||||
|  | 	uint32_t config_table; | ||||||
|  | 	uint32_t boot_loader_name; | ||||||
|  | 	uint32_t apm_table; | ||||||
|  | 	uint32_t vbe_control_info; | ||||||
|  | 	uint32_t vbe_mode_info; | ||||||
|  | 	uint16_t vbe_mode; | ||||||
|  | 	uint16_t vbe_interface_seg; | ||||||
|  | 	uint16_t vbe_interface_off; | ||||||
|  | 	uint16_t vbe_interface_len; | ||||||
|  | 	framebuffer_info_t framebuffer; | ||||||
|  | } __attribute__((packed)); | ||||||
|  | 
 | ||||||
|  | extern multiboot_info_t* s_multiboot_info; | ||||||
|  | @ -3,7 +3,6 @@ | ||||||
| #include <stddef.h> | #include <stddef.h> | ||||||
| #include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| void terminal_initialize(); | void terminal_initialize(); | ||||||
| void terminal_putchar(char c); | void terminal_putchar(char c); | ||||||
| void terminal_write(const char* data, size_t size); | void terminal_write(const char* data, size_t size); | ||||||
|  |  | ||||||
|  | @ -10,9 +10,13 @@ | ||||||
|   |   | ||||||
| uintptr_t __stack_chk_guard = STACK_CHK_GUARD; | uintptr_t __stack_chk_guard = STACK_CHK_GUARD; | ||||||
| 
 | 
 | ||||||
|  | __BEGIN_DECLS | ||||||
|  | 
 | ||||||
| __attribute__((noreturn)) | __attribute__((noreturn)) | ||||||
| void __stack_chk_fail(void) | void __stack_chk_fail(void) | ||||||
| { | { | ||||||
| 	printf("Stack smashing detected\n"); | 	printf("Stack smashing detected\n"); | ||||||
| 	abort(); | 	abort(); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | __END_DECLS | ||||||
|  | @ -1,60 +1,43 @@ | ||||||
| #include <kernel/GDT.h> | #include <kernel/GDT.h> | ||||||
| #include <kernel/kmalloc.h> | #include <kernel/kmalloc.h> | ||||||
|  | #include <kernel/multiboot.h> | ||||||
| #include <kernel/panic.h> | #include <kernel/panic.h> | ||||||
| #include <kernel/tty.h> | #include <kernel/tty.h> | ||||||
|  | #include <kernel/kprint.h> | ||||||
| 
 | 
 | ||||||
| #include <stdio.h> |  | ||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| 
 | 
 | ||||||
| #define DISABLE_INTERRUPTS() asm volatile("cli") | #define DISABLE_INTERRUPTS() asm volatile("cli") | ||||||
| #define ENABLE_INTERRUPTS() asm volatile("sti") | #define ENABLE_INTERRUPTS() asm volatile("sti") | ||||||
| 
 | 
 | ||||||
| // https://www.gnu.org/software/grub/manual/multiboot/multiboot.html#Boot-information-format
 | multiboot_info_t* s_multiboot_info; | ||||||
| struct multiboot_info_t |  | ||||||
| { |  | ||||||
| 	uint32_t flags; |  | ||||||
| 	uint32_t mem_lower; |  | ||||||
| 	uint32_t mem_upper; |  | ||||||
| 	uint32_t boot_device; |  | ||||||
| 	uint32_t cmdline; |  | ||||||
| 	uint32_t mods_count; |  | ||||||
| 	uint32_t mods_addr; |  | ||||||
| 	uint32_t syms[4]; |  | ||||||
| 	uint32_t mmap_length; |  | ||||||
| 	uint32_t mmap_addr; |  | ||||||
| 	uint32_t drives_length; |  | ||||||
| 	uint32_t drives_addr; |  | ||||||
| 	uint32_t config_table; |  | ||||||
| 	uint32_t boot_loader_name; |  | ||||||
| 	uint32_t apm_table; |  | ||||||
| 	uint32_t vbe_control_info; |  | ||||||
| 	uint32_t vbe_mode_info; |  | ||||||
| 	uint16_t vbe_mode; |  | ||||||
| 	uint16_t vbe_interface_seg; |  | ||||||
| 	uint16_t vbe_interface_off; |  | ||||||
| 	uint16_t vbe_interface_len; |  | ||||||
| 	uint8_t framebuffer[22]; |  | ||||||
| #if 1 |  | ||||||
| 	uint8_t  color_info[6]; |  | ||||||
| #endif |  | ||||||
| } __attribute__((packed)); |  | ||||||
| 
 | 
 | ||||||
| extern "C" | extern "C" | ||||||
| void kernel_main(multiboot_info_t* mbi, uint32_t magic) | void kernel_main(multiboot_info_t* mbi, uint32_t magic) | ||||||
| { | { | ||||||
| 	DISABLE_INTERRUPTS(); | 	DISABLE_INTERRUPTS(); | ||||||
| 
 | 
 | ||||||
|  | 	s_multiboot_info = mbi; | ||||||
|  | 
 | ||||||
| 	terminal_initialize(); | 	terminal_initialize(); | ||||||
| 
 | 
 | ||||||
| 	if (magic != 0x2BADB002) | 	if (magic != 0x2BADB002) | ||||||
| 		Kernel::panic("Invalid magic in multiboot"); | 		Kernel::panic("Invalid magic in multiboot"); | ||||||
| 	if (mbi->flags & 0b00100000) | 
 | ||||||
|  | 	if (!(mbi->flags & (1 << 6))) | ||||||
|  | 		Kernel::panic("Bootloader did not provide memory map"); | ||||||
|  | 
 | ||||||
|  | 	for (uint32_t i = 0; i < mbi->mmap_length;) | ||||||
| 	{ | 	{ | ||||||
| 		printf("mmap_length: %d\n", mbi->mmap_length); | 		multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)(mbi->mmap_addr + i); | ||||||
| 		printf("mmap_addr:   %p\n", mbi->mmap_addr); | 		if (mmmt->type == 1) | ||||||
|  | 			kprint("Size: {}, Addr: {}, Length: {}, Type: {}\n", mmmt->size, (void*)mmmt->base_addr, (void*)mmmt->length, mmmt->type); | ||||||
|  | 
 | ||||||
|  | 		i += mmmt->size + sizeof(uint32_t); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	printf("Hello from the kernel!\n"); | 	printf("Hello from the kernel!\n"); | ||||||
| 
 | 
 | ||||||
|  | 	kprint("Hello from the kernel!\n"); | ||||||
| } | } | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| #include <kernel/panic.h> | #include <kernel/panic.h> | ||||||
| #include <kernel/tty.h> | #include <kernel/kprint.h> | ||||||
| 
 | 
 | ||||||
| namespace Kernel | namespace Kernel | ||||||
| { | { | ||||||
|  | @ -7,8 +7,7 @@ namespace Kernel | ||||||
| 	__attribute__((__noreturn__)) | 	__attribute__((__noreturn__)) | ||||||
| 	void panic(const char* message) | 	void panic(const char* message) | ||||||
| 	{ | 	{ | ||||||
| 		terminal_writestring("Kernel panic: "); | 		kprint("Kernel panic: {}", message); | ||||||
| 		terminal_writestring(message); |  | ||||||
| 		asm volatile("hlt"); | 		asm volatile("hlt"); | ||||||
| 		__builtin_unreachable(); | 		__builtin_unreachable(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -40,6 +40,7 @@ string/memset.o \ | ||||||
| string/strcpy.o \ | string/strcpy.o \ | ||||||
| string/strlen.o \ | string/strlen.o \ | ||||||
| string/strncpy.o \ | string/strncpy.o \ | ||||||
|  | string/strstr.o \ | ||||||
|   |   | ||||||
| HOSTEDOBJS=\
 | HOSTEDOBJS=\
 | ||||||
| $(ARCH_HOSTEDOBJS) \ | $(ARCH_HOSTEDOBJS) \ | ||||||
|  |  | ||||||
|  | @ -14,4 +14,6 @@ size_t strlen(const char*); | ||||||
| char* strcpy(char* __restrict, const char* __restrict); | char* strcpy(char* __restrict, const char* __restrict); | ||||||
| char* strncpy(char* __restrict, const char* __restrict, size_t); | char* strncpy(char* __restrict, const char* __restrict, size_t); | ||||||
| 
 | 
 | ||||||
|  | char* strstr(const char*, const char*); | ||||||
|  | 
 | ||||||
| __END_DECLS | __END_DECLS | ||||||
|  | @ -33,6 +33,7 @@ static bool print_integer(T value, size_t& out_len) | ||||||
| 		buffer[len++] = (value % 10) + '0'; | 		buffer[len++] = (value % 10) + '0'; | ||||||
| 		value /= 10; | 		value /= 10; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	if (sign) | 	if (sign) | ||||||
| 		buffer[len++] = '-'; | 		buffer[len++] = '-'; | ||||||
| 	if (len == 0) | 	if (len == 0) | ||||||
|  | @ -52,34 +53,39 @@ static bool print_integer(T value, size_t& out_len) | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static char bits_to_hex(unsigned char bits) | static char bits_to_hex(int bits, bool upper_case) | ||||||
| { | { | ||||||
| 	if (bits < 10) | 	if (bits < 10) | ||||||
| 		return bits + '0'; | 		return bits + '0'; | ||||||
| 	return bits - 10 + 'a'; | 	return bits - 10 + (upper_case ? 'A' : 'a'); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool print_ptr(void* ptr, size_t& out_len) | template<typename T> | ||||||
|  | static bool print_hex(T value, bool upper_case, size_t& out_len) | ||||||
| { | { | ||||||
| 	ptrdiff_t addr = reinterpret_cast<ptrdiff_t>(ptr); | 	char buffer[16] {}; | ||||||
|  | 	int len = 0; | ||||||
| 
 | 
 | ||||||
| 	char buffer[2 + sizeof(ptrdiff_t) * 2]; | 	while (value) | ||||||
| 	buffer[0] = '0'; |  | ||||||
| 	buffer[1] = 'x'; |  | ||||||
| 
 |  | ||||||
| 	size_t bytes = sizeof(ptrdiff_t); |  | ||||||
| 
 |  | ||||||
| 	for (size_t i = 1; i <= bytes; i++) |  | ||||||
| 	{ | 	{ | ||||||
| 		unsigned char byte = (addr >> ((bytes - i) * 8)) & 0xff; | 		buffer[len++] = bits_to_hex(value & 0xF, upper_case); | ||||||
| 		buffer[i * 2 + 0] = bits_to_hex(byte >> 4); | 		value >>= 4; | ||||||
| 		buffer[i * 2 + 1] = bits_to_hex(byte & 0b1111); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!print(buffer, 2 + bytes * 2)) | 	if (len == 0) | ||||||
|  | 		buffer[len++] = '0'; | ||||||
|  | 
 | ||||||
|  | 	for (int i = 0; i < len / 2; i++) | ||||||
|  | 	{ | ||||||
|  | 		char temp = buffer[i]; | ||||||
|  | 		buffer[i] = buffer[len - i - 1]; | ||||||
|  | 		buffer[len - i - 1] = temp; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!print(buffer, len)) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	out_len = 2 + bytes * 2; | 	out_len = len; | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -149,12 +155,21 @@ int printf(const char* __restrict format, ...) | ||||||
| 				return -1; | 				return -1; | ||||||
| 			written += len; | 			written += len; | ||||||
| 		} | 		} | ||||||
|  | 		else if (*format == 'x' || *format == 'X') | ||||||
|  | 		{ | ||||||
|  | 			format++; | ||||||
|  | 			unsigned int value = va_arg(args, unsigned int); | ||||||
|  | 			size_t len; | ||||||
|  | 			if (!print_hex<unsigned int>(value, *(format - 1) == 'X', len)) | ||||||
|  | 				return -1; | ||||||
|  | 			written += len; | ||||||
|  | 		} | ||||||
| 		else if (*format == 'p') | 		else if (*format == 'p') | ||||||
| 		{ | 		{ | ||||||
| 			format++; | 			format++; | ||||||
| 			void* const ptr = va_arg(args, void*); | 			void* ptr = va_arg(args, void*); | ||||||
| 			size_t len; | 			size_t len; | ||||||
| 			if (!print_ptr(ptr, len)) | 			if (!print("0x", 2) || !print_hex<ptrdiff_t>((ptrdiff_t)ptr, false, len)) | ||||||
| 				return -1; | 				return -1; | ||||||
| 			written += len; | 			written += len; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| 
 | 
 | ||||||
| #if defined(__is_libk) | #if defined(__is_libk) | ||||||
| #include <kernel/tty.h> | #include <kernel/tty.h> | ||||||
|  | #include <kernel/panic.h> | ||||||
| #else | #else | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| #endif | #endif | ||||||
|  | @ -9,6 +10,7 @@ | ||||||
| int putchar(int c) | int putchar(int c) | ||||||
| { | { | ||||||
| #if defined(__is_libk) | #if defined(__is_libk) | ||||||
|  | 	Kernel::panic("Please use kprint() instead of stdio"); | ||||||
| 	char ch = (char)c; | 	char ch = (char)c; | ||||||
| 	terminal_write(&ch, sizeof(ch)); | 	terminal_write(&ch, sizeof(ch)); | ||||||
| #else | #else | ||||||
|  |  | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | #include <string.h> | ||||||
|  | 
 | ||||||
|  | char* strstr(const char* haystack, const char* needle) | ||||||
|  | { | ||||||
|  | 	for (size_t i = 0; haystack[i]; i++) | ||||||
|  | 		if (memcmp(haystack + i, needle, strlen(needle)) == 0) | ||||||
|  | 			return (char*)haystack + i; | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue