Started work on memory map, added printf features

Printf now has long (64-bit), char, and % literal support. I haven't written
anything specific for shorts yet but if you cast it to an int on the way
in, it'll work anyway, so whatever.
This commit is contained in:
lordtet 2025-07-05 04:36:39 -04:00
parent 53198515c8
commit 472f91fe14
8 changed files with 95 additions and 25 deletions

View file

@ -19,8 +19,8 @@ extern char_writer_t* default_output;
int putc(char_writer_t*, char); int putc(char_writer_t*, char);
int print(char_writer_t*, const char*); int print(char_writer_t*, const char*);
int println(char_writer_t*, const char*); int println(char_writer_t*, const char*);
int printhex(char_writer_t*, uint32_t); int printhex(char_writer_t*, uint64_t);
int prindec(char_writer_t*, uint32_t out); int prindec(char_writer_t*, uint64_t out);
int printf(char_writer_t*, const char* fmt, ...); int printf(char_writer_t*, const char* fmt, ...);
#endif #endif

View file

@ -7,8 +7,15 @@
#define KMULTIBOOT_H #define KMULTIBOOT_H
#include <stdint.h> #include <stdint.h>
typedef struct multiboot_mmap_entry {
uint32_t entry_size; //size of this struct entry
uint64_t addr; //physical location of memory
uint64_t mem_size; //size of the memory block
uint32_t type;
} __attribute__((packed)) mb_mmap_entry_t;
typedef struct {
typedef struct mb_info_s {
uint32_t flags; uint32_t flags;
uint32_t mem_lower; uint32_t mem_lower;
uint32_t mem_upper; uint32_t mem_upper;
@ -16,13 +23,13 @@ typedef struct {
uint32_t cmdline; uint32_t cmdline;
uint32_t mods_count; uint32_t mods_count;
uint32_t mods_addr; uint32_t mods_addr;
uint32_t syms[4];
uint32_t mmap_length;
uint32_t mmap_addr;
} mb_info_t; } mb_info_t;
typedef struct multiboot_mmap_entry {
uint32_t ssize; //size of the entry extern uint8_t _kernel_start;
uint64_t addr; //physical location of memory extern uint8_t _kernel_end;
uint64_t msize;
uint32_t type;
} __attribute__((packed)) mb_mmap_entry_t;
#endif #endif

View file

@ -21,6 +21,6 @@
* @return No return value * @return No return value
* *
*/ */
void i_to_str(uint32_t num, char* buf, int size, int radix); void i_to_str(uint64_t num, char* buf, int size, int radix);
#endif #endif

View file

@ -6,8 +6,9 @@ SECTIONS
/*start me at 1Mb because below that is x86 essential stuff, which we dont want to be written on top of.*/ /*start me at 1Mb because below that is x86 essential stuff, which we dont want to be written on top of.*/
. = 1M; . = 1M;
/* we're going to maintain 4K alignment - apparently useful for paging, and i'm not complaining about the lost space anyway. */ _kernel_start = .;
/* we're going to maintain 4K alignment - apparently useful for paging, and i'm not complaining about the lost space anyway. */
/*our multiboot header from start.s - has to go at the beginning of the executable so the bootloader knows we're loadable.*/ /*our multiboot header from start.s - has to go at the beginning of the executable so the bootloader knows we're loadable.*/
/*executable section*/ /*executable section*/
.text BLOCK(4K) : ALIGN(4K) .text BLOCK(4K) : ALIGN(4K)
@ -37,4 +38,7 @@ SECTIONS
*(.bss) *(.bss)
*(.idt) *(.idt)
} }
_kernel_end = .;
} }

View file

@ -4,15 +4,21 @@
char_writer_t* default_output = 0; char_writer_t* default_output = 0;
int printhex(char_writer_t* writer, uint32_t out) { int printnum(char_writer_t* writer, int radix, uint64_t out) {
char buff[9]; char buff[65];
i_to_str(out, buff, 9, 0x10); i_to_str(out, buff, 65, radix);
return print(writer, buff); return print(writer, buff);
} }
int printdec(char_writer_t* writer, uint32_t out) { int printhex(char_writer_t* writer, uint64_t out) {
char buff[11]; char buff[17];
i_to_str(out, buff, 11, 10); i_to_str(out, buff, 17, 0x10);
return print(writer, buff);
}
int printdec(char_writer_t* writer, uint64_t out) {
char buff[21];
i_to_str(out, buff, 21, 10);
return print(writer, buff); return print(writer, buff);
} }
@ -48,23 +54,58 @@ int println(char_writer_t* writer, const char* out) {
*/ */
int printf(char_writer_t* writer, const char* fmt, ...) { int printf(char_writer_t* writer, const char* fmt, ...) {
//borrowed (stole) a lot of ideas for this from the linux implementation (thanks!)
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
int ret = 0; int ret = 0;
uint64_t num = 0;
int radix = 9;
char qualifier = '\0';
while(*fmt) { while(*fmt) {
if(*fmt == '%') { if(*fmt == '%') {
fmt++; fmt++;
if(*fmt == 'l') {
qualifier = *fmt;
fmt++;
}
switch(*fmt) { switch(*fmt) {
case '%':
ret = putc(writer, '%');
fmt++;
continue;
case 'c':
ret = putc(writer, va_arg(args, int));
fmt++;
continue;
case 's':
ret = print(writer, va_arg(args, char*));
fmt++;
continue;
//Integer definitions.
case 'X': case 'X':
ret = print(writer, "0x"); ret = print(writer, "0x");
case 'x': case 'x':
ret = printhex(writer, va_arg(args,uint32_t)); radix = 0x10;
break; break;
case 'd': case 'u':
ret = printdec(writer, va_arg(args,uint32_t)); radix = 10;
break;
case 'b':
radix = 0b10;
break; break;
} }
if(qualifier == 'l'){
num = va_arg(args, uint64_t);
qualifier = 0;
}
else {
num = va_arg(args, unsigned int);
}
ret = printnum(writer, radix, num);
} else { } else {
ret = putc(writer,*fmt); ret = putc(writer,*fmt);
} }

View file

@ -12,7 +12,7 @@
void i_to_str(uint32_t num, char* buf, int size, int radix) { void i_to_str(uint64_t num, char* buf, int size, int radix) {
//null terminate the string //null terminate the string
if(num == 0){ if(num == 0){
buf[0] = '0'; buf[0] = '0';

View file

@ -35,10 +35,9 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
serial_init(&serial_ctx); serial_init(&serial_ctx);
//AND OUR DEFAULT OUTPUT IS: //AND OUR DEFAULT OUTPUT IS:
default_output = default_vga; default_output = default_COM;
printf(default_output, "Entry eax:%X\n", multiboot_magic); printf(default_output, "Entry eax:%X\n", multiboot_magic);
if(multiboot_magic != 0x2BADB002) { if(multiboot_magic != 0x2BADB002) {
println(default_output, "Bootloader not multiboot1 compliant! Needed for mmap, etc. Can't work without it, kthxbye!"); println(default_output, "Bootloader not multiboot1 compliant! Needed for mmap, etc. Can't work without it, kthxbye!");
return; return;
@ -47,5 +46,24 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
} }
printf(default_output, "MEM_LOWER:%X\n", multiboot_info->mem_lower); printf(default_output, "MEM_LOWER:%X\n", multiboot_info->mem_lower);
printf(default_output, "MEM_UPPER:%X\n", multiboot_info->mem_upper); printf(default_output, "MEM_UPPER:%X\n", multiboot_info->mem_upper);
//Let's get out memory map.
if(!(multiboot_info->flags & (1<<6))){
printf(default_output, "No mmap supplied by multiboot flags!");
return;
}
printf(default_output, "lol:%X", multiboot_info->flags);
int mmap_end = (uint32_t)multiboot_info->mmap_addr + multiboot_info->mmap_length;
for(mb_mmap_entry_t* entry = (mb_mmap_entry_t*)multiboot_info->mmap_addr;
(int)entry < mmap_end;
entry = (mb_mmap_entry_t*)((int)entry + entry->entry_size + sizeof(entry->entry_size))) {
printf(default_output,"__MMAP_ENTRY__:\nSTART_ADDR:%X\nSIZE:%X\nTYPE:%u\n",(uint32_t)entry->addr, (uint32_t)entry->mem_size, entry->type);
}
} }