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:
parent
53198515c8
commit
472f91fe14
8 changed files with 95 additions and 25 deletions
|
|
@ -19,8 +19,8 @@ extern char_writer_t* default_output;
|
|||
int putc(char_writer_t*, char);
|
||||
int print(char_writer_t*, const char*);
|
||||
int println(char_writer_t*, const char*);
|
||||
int printhex(char_writer_t*, uint32_t);
|
||||
int prindec(char_writer_t*, uint32_t out);
|
||||
int printhex(char_writer_t*, uint64_t);
|
||||
int prindec(char_writer_t*, uint64_t out);
|
||||
int printf(char_writer_t*, const char* fmt, ...);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,8 +7,15 @@
|
|||
#define KMULTIBOOT_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 mem_lower;
|
||||
uint32_t mem_upper;
|
||||
|
|
@ -16,13 +23,13 @@ typedef struct {
|
|||
uint32_t cmdline;
|
||||
uint32_t mods_count;
|
||||
uint32_t mods_addr;
|
||||
uint32_t syms[4];
|
||||
uint32_t mmap_length;
|
||||
uint32_t mmap_addr;
|
||||
} mb_info_t;
|
||||
|
||||
typedef struct multiboot_mmap_entry {
|
||||
uint32_t ssize; //size of the entry
|
||||
uint64_t addr; //physical location of memory
|
||||
uint64_t msize;
|
||||
uint32_t type;
|
||||
} __attribute__((packed)) mb_mmap_entry_t;
|
||||
|
||||
extern uint8_t _kernel_start;
|
||||
extern uint8_t _kernel_end;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -21,6 +21,6 @@
|
|||
* @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
|
||||
|
|
|
|||
|
|
@ -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.*/
|
||||
. = 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.*/
|
||||
/*executable section*/
|
||||
.text BLOCK(4K) : ALIGN(4K)
|
||||
|
|
@ -37,4 +38,7 @@ SECTIONS
|
|||
*(.bss)
|
||||
*(.idt)
|
||||
}
|
||||
|
||||
_kernel_end = .;
|
||||
|
||||
}
|
||||
|
|
|
|||
59
src/io.c
59
src/io.c
|
|
@ -4,15 +4,21 @@
|
|||
|
||||
char_writer_t* default_output = 0;
|
||||
|
||||
int printhex(char_writer_t* writer, uint32_t out) {
|
||||
char buff[9];
|
||||
i_to_str(out, buff, 9, 0x10);
|
||||
int printnum(char_writer_t* writer, int radix, uint64_t out) {
|
||||
char buff[65];
|
||||
i_to_str(out, buff, 65, radix);
|
||||
return print(writer, buff);
|
||||
}
|
||||
|
||||
int printdec(char_writer_t* writer, uint32_t out) {
|
||||
char buff[11];
|
||||
i_to_str(out, buff, 11, 10);
|
||||
int printhex(char_writer_t* writer, uint64_t out) {
|
||||
char buff[17];
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -48,23 +54,58 @@ int println(char_writer_t* writer, const char* out) {
|
|||
*/
|
||||
|
||||
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_start(args, fmt);
|
||||
int ret = 0;
|
||||
uint64_t num = 0;
|
||||
int radix = 9;
|
||||
char qualifier = '\0';
|
||||
while(*fmt) {
|
||||
if(*fmt == '%') {
|
||||
fmt++;
|
||||
if(*fmt == 'l') {
|
||||
qualifier = *fmt;
|
||||
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':
|
||||
ret = print(writer, "0x");
|
||||
case 'x':
|
||||
ret = printhex(writer, va_arg(args,uint32_t));
|
||||
radix = 0x10;
|
||||
break;
|
||||
case 'd':
|
||||
ret = printdec(writer, va_arg(args,uint32_t));
|
||||
case 'u':
|
||||
radix = 10;
|
||||
break;
|
||||
case 'b':
|
||||
radix = 0b10;
|
||||
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 {
|
||||
ret = putc(writer,*fmt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
if(num == 0){
|
||||
buf[0] = '0';
|
||||
|
|
|
|||
22
src/main.c
22
src/main.c
|
|
@ -35,10 +35,9 @@ void kern_main(uint32_t multiboot_magic, mb_info_t* multiboot_info)
|
|||
serial_init(&serial_ctx);
|
||||
|
||||
//AND OUR DEFAULT OUTPUT IS:
|
||||
default_output = default_vga;
|
||||
default_output = default_COM;
|
||||
|
||||
printf(default_output, "Entry eax:%X\n", multiboot_magic);
|
||||
|
||||
if(multiboot_magic != 0x2BADB002) {
|
||||
println(default_output, "Bootloader not multiboot1 compliant! Needed for mmap, etc. Can't work without it, kthxbye!");
|
||||
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_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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
;multiboot for GRUB to boot it. Ideally stage01_bootloader will be able to support the multiboot standard.
|
||||
;regardless of who's doing it, we have to set the required stuff
|
||||
MB_MAGIC equ 0x1BADB002 ; bytes that bootloader will use to find this place
|
||||
MB_FLAGS equ (1 << 0) | (1 << 1) ; flags request the following from the bootloader: maintain page boundaries + provide a memory map
|
||||
MB_FLAGS equ (1 << 0) | (1 << 1); flags request the following from the bootloader: maintain page boundaries + provide a memory map
|
||||
MB_CHECKSUM equ (0 - (MB_MAGIC + MB_FLAGS)) ; Fails if checksum doesn't pass. Kind of arbitrary, but required.
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue