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 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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,10 @@ 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;
|
||||||
|
|
||||||
|
_kernel_start = .;
|
||||||
|
|
||||||
/* we're going to maintain 4K alignment - apparently useful for paging, and i'm not complaining about the lost space anyway. */
|
/* 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 = .;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
61
src/io.c
61
src/io.c
|
|
@ -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;
|
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 {
|
} else {
|
||||||
ret = putc(writer,*fmt);
|
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
|
//null terminate the string
|
||||||
if(num == 0){
|
if(num == 0){
|
||||||
buf[0] = '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);
|
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);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
;multiboot for GRUB to boot it. Ideally stage01_bootloader will be able to support the multiboot standard.
|
;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
|
;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_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.
|
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