mirror of
https://github.com/encounter/osdev.git
synced 2026-03-30 11:33:54 -07:00
ELF support; printf impl; replacing kprint with printf
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
qemu-system-i386 -kernel kernel.bin -device isa-debug-exit,iobase=0xf4,iosize=0x04
|
||||
# directly
|
||||
qemu-system-i386 -kernel kernel.bin
|
||||
|
||||
# via Grub:
|
||||
./mkiso.sh kernel.bin
|
||||
qemu-system-i386 -cdrom os.iso -device isa-debug-exit,iobase=0xf4,iosize=0x04
|
||||
qemu-system-i386 -cdrom os.iso
|
||||
|
||||
# support exit
|
||||
-device isa-debug-exit,iobase=0xf4,iosize=0x04
|
||||
|
||||
# remote gdb (port 1234):
|
||||
-s
|
||||
@@ -11,4 +15,4 @@ qemu-system-i386 -cdrom os.iso -device isa-debug-exit,iobase=0xf4,iosize=0x04
|
||||
-serial stdio
|
||||
|
||||
# IDE drive:
|
||||
-drive file=fat.img,if=ide
|
||||
-drive file=hd.img,if=ide
|
||||
@@ -32,6 +32,7 @@ set(SOURCE_FILES
|
||||
drivers/ata
|
||||
drivers/pci
|
||||
drivers/pci_registry
|
||||
# drivers/i825xx
|
||||
fatfs/diskio
|
||||
fatfs/ff
|
||||
fatfs/ffconf.h
|
||||
|
||||
+82
-26
@@ -2,6 +2,9 @@
|
||||
#include "drivers/vga.h"
|
||||
#include "drivers/serial.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static bool vga_enabled = false;
|
||||
static bool serial_enabled = false;
|
||||
|
||||
@@ -25,29 +28,30 @@ void console_set_serial_enabled(bool enabled) {
|
||||
* Print a message on the specified location
|
||||
* If col, row, are negative, we will use the current offset
|
||||
*/
|
||||
|
||||
void kprint(const char *message) {
|
||||
static void knprint(const char *str, size_t len, uint8_t vga_color) {
|
||||
if (vga_enabled) {
|
||||
int offset = vga_get_cursor_offset();
|
||||
int row = vga_get_offset_row(offset);
|
||||
int col = vga_get_offset_col(offset);
|
||||
|
||||
int i = 0;
|
||||
while (message[i] != 0) {
|
||||
offset = vga_print_char(message[i++], col, row, vga_entry_color(VGA_COLOR_WHITE, VGA_COLOR_BLACK));
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
offset = vga_print_char(str[i], col, row, vga_color);
|
||||
row = vga_get_offset_row(offset);
|
||||
col = vga_get_offset_col(offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (serial_enabled) {
|
||||
int i = 0;
|
||||
while (message[i] != 0) {
|
||||
serial_write(message[i++]);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
serial_write(str[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kprint(const char *message) {
|
||||
knprint(message, strlen(message), WHITE_ON_BLACK);
|
||||
}
|
||||
|
||||
void kprint_char(char c) {
|
||||
if (vga_enabled) {
|
||||
int offset = vga_get_cursor_offset();
|
||||
@@ -59,20 +63,6 @@ void kprint_char(char c) {
|
||||
}
|
||||
}
|
||||
|
||||
void kprint_backspace() {
|
||||
if (vga_enabled) {
|
||||
int offset = vga_get_cursor_offset() - 1;
|
||||
vga_print_char(' ', vga_get_offset_col(offset), vga_get_offset_row(offset), WHITE_ON_BLACK);
|
||||
vga_set_cursor_offset(offset);
|
||||
}
|
||||
|
||||
if (serial_enabled) {
|
||||
serial_write(0x8);
|
||||
serial_write(' ');
|
||||
serial_write(0x8);
|
||||
}
|
||||
}
|
||||
|
||||
void clear_screen() {
|
||||
if (vga_enabled) {
|
||||
vga_clear_screen();
|
||||
@@ -135,8 +125,13 @@ void kprint_uint8(uint8_t val) {
|
||||
}
|
||||
|
||||
_noreturn
|
||||
void panic(char *str) {
|
||||
if (str != NULL) kprint(str);
|
||||
void panic(char *str, ...) {
|
||||
va_list args;
|
||||
va_start(args, str);
|
||||
if (str != NULL) vfprintf(stderr, str, args);
|
||||
va_end(args);
|
||||
fflush(stderr);
|
||||
|
||||
__asm__("cli");
|
||||
while (1) __asm__("hlt");
|
||||
}
|
||||
@@ -148,9 +143,70 @@ void panic(char *str) {
|
||||
#endif
|
||||
|
||||
_unused
|
||||
uintptr_t __stack_chk_guard = STACK_CHK_GUARD;
|
||||
uintptr_t __stack_chk_guard = STACK_CHK_GUARD;
|
||||
|
||||
_noreturn _unused
|
||||
void __stack_chk_fail() {
|
||||
panic("Stack smashing detected");
|
||||
}
|
||||
}
|
||||
|
||||
// --- stdio
|
||||
|
||||
int errno;
|
||||
|
||||
size_t __stdout_write(FILE *f, const char *str, size_t len) {
|
||||
size_t rem = f->wpos - f->wbase;
|
||||
if (rem) knprint(f->wbase, rem, WHITE_ON_BLACK);
|
||||
if (len) knprint(str, len, WHITE_ON_BLACK);
|
||||
|
||||
f->wend = f->buf + f->buf_size;
|
||||
f->wpos = f->wbase = f->buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t __stderr_write(FILE *f, const char *str, size_t len) {
|
||||
size_t rem = f->wpos - f->wbase;
|
||||
if (rem) knprint(f->wbase, rem, RED_ON_WHITE);
|
||||
if (len) knprint(str, len, RED_ON_WHITE);
|
||||
|
||||
f->wend = f->buf + f->buf_size;
|
||||
f->wpos = f->wbase = f->buf;
|
||||
return len;
|
||||
}
|
||||
|
||||
off_t __stdio_seek(FILE *file, const off_t offset, int origin) {
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
int __stdio_close(FILE *file) {
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
#define BUFSIZ 1024
|
||||
#define UNGET 8
|
||||
|
||||
static char __stdout_buf[BUFSIZ + UNGET];
|
||||
FILE *stdout = &(FILE) {
|
||||
.buf = __stdout_buf + UNGET,
|
||||
.buf_size = BUFSIZ,
|
||||
.fd = 1,
|
||||
.flags = F_PERM | F_NORD,
|
||||
.lbf = '\n',
|
||||
.write = __stdout_write,
|
||||
.seek = __stdio_seek,
|
||||
.close = __stdio_close,
|
||||
.lock = -1,
|
||||
};
|
||||
|
||||
static char __stderr_buf[BUFSIZ + UNGET];
|
||||
FILE *stderr = &(FILE) {
|
||||
.buf = __stderr_buf + UNGET,
|
||||
.buf_size = BUFSIZ,
|
||||
.fd = 1,
|
||||
.flags = F_PERM | F_NORD,
|
||||
.lbf = '\n',
|
||||
.write = __stderr_write,
|
||||
.seek = __stdio_seek,
|
||||
.close = __stdio_close,
|
||||
.lock = -1,
|
||||
};
|
||||
+7
-8
@@ -10,13 +10,12 @@ void console_set_serial_enabled(bool enabled);
|
||||
|
||||
void clear_screen();
|
||||
|
||||
void kprint(const char *message);
|
||||
void kprint_char(char c);
|
||||
void kprint_uint64(uint64_t val);
|
||||
void kprint_uint32(uint32_t val);
|
||||
void kprint_uint16(uint16_t val);
|
||||
void kprint_uint8(uint8_t val);
|
||||
void kprint_backspace();
|
||||
//void kprint(const char *message);
|
||||
//void kprint_char(char c);
|
||||
//void kprint_uint64(uint64_t val);
|
||||
//void kprint_uint32(uint32_t val);
|
||||
//void kprint_uint16(uint16_t val);
|
||||
//void kprint_uint8(uint8_t val);
|
||||
|
||||
_noreturn
|
||||
void panic(char *str);
|
||||
void panic(char *str, ...);
|
||||
+55
-2
@@ -1,5 +1,7 @@
|
||||
#include <malloc.h>
|
||||
#include <byteswap.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "dwarf.h"
|
||||
#include "../elf.h"
|
||||
#include "../console.h"
|
||||
@@ -7,12 +9,18 @@
|
||||
|
||||
#define KERNEL_BASE 0xC0100000
|
||||
|
||||
void dwarf_find_file(uintptr_t address) {
|
||||
FILE *file;
|
||||
}
|
||||
|
||||
void *dwarf_find_debug_info(FATFS *fs) {
|
||||
FRESULT ret;
|
||||
FILINFO f_info;
|
||||
FIL file;
|
||||
void *header_ptr = NULL;
|
||||
void *sh_table_ptr = NULL;
|
||||
void *sh_table_str_ptr = NULL;
|
||||
void *debug_line_ptr = NULL;
|
||||
uint32_t read = 0;
|
||||
|
||||
ret = f_stat("kernel.bin", &f_info);
|
||||
@@ -23,6 +31,8 @@ void *dwarf_find_debug_info(FATFS *fs) {
|
||||
|
||||
size_t header_size = sizeof(elf_header_t);
|
||||
header_ptr = malloc(header_size);
|
||||
if (header_ptr == NULL) goto fail;
|
||||
|
||||
ret = f_read(&file, header_ptr, header_size, &read);
|
||||
if (ret != FR_OK || read != header_size) goto fail;
|
||||
|
||||
@@ -36,11 +46,52 @@ void *dwarf_find_debug_info(FATFS *fs) {
|
||||
header->section_header_num_entries;
|
||||
kprint("sh_table_size = "); kprint_uint16(sh_table_size); kprint_char('\n');
|
||||
sh_table_ptr = malloc(sh_table_size);
|
||||
if (sh_table_ptr == NULL) goto fail;
|
||||
|
||||
ret = f_read(&file, sh_table_ptr, sh_table_size, &read);
|
||||
if (ret != FR_OK || read != sh_table_size) goto fail;
|
||||
|
||||
elf_section_header_t *section = elf_find_section(header, sh_table_ptr, ELF_SHT_STRTAB);
|
||||
kprint_uint32((uintptr_t) section);
|
||||
elf_section_header_t *sh_table_str_section = elf_get_section(header, sh_table_ptr, header->section_header_section_names_idx);
|
||||
if (sh_table_str_section == NULL || sh_table_str_section->size > UINT16_MAX) goto fail;
|
||||
|
||||
ret = f_lseek(&file, sh_table_str_section->offset);
|
||||
if (ret != FR_OK) goto fail;
|
||||
|
||||
uint16_t sh_table_str_size = (uint16_t) sh_table_str_section->size;
|
||||
kprint("sh_table_str_size = "); kprint_uint16(sh_table_str_size); kprint_char('\n');
|
||||
sh_table_str_ptr = malloc(sh_table_str_size);
|
||||
if (sh_table_str_ptr == NULL) goto fail;
|
||||
|
||||
ret = f_read(&file, sh_table_str_ptr, sh_table_str_size, &read);
|
||||
if (ret != FR_OK || read != sh_table_str_size) goto fail;
|
||||
|
||||
// elf_print_sections(header, sh_table_ptr, sh_table_str_ptr);
|
||||
|
||||
elf_section_header_t *debug_line_section = NULL;
|
||||
for (uint16_t i = 0; i < header->section_header_num_entries; ++i) {
|
||||
elf_section_header_t *section_header = sh_table_ptr + header->section_header_entry_size * i;
|
||||
char *name = sh_table_str_ptr + section_header->name;
|
||||
if (strcmp(name, ".debug_line") == 0) {
|
||||
debug_line_section = section_header;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (debug_line_section == NULL || debug_line_section->size > UINT16_MAX) goto fail;
|
||||
|
||||
ret = f_lseek(&file, debug_line_section->offset);
|
||||
if (ret != FR_OK) goto fail;
|
||||
|
||||
uint16_t debug_line_section_size = (uint16_t) debug_line_section->size;
|
||||
kprint("debug_line_section_size = "); kprint_uint16(debug_line_section_size); kprint_char('\n');
|
||||
debug_line_ptr = malloc(debug_line_section_size);
|
||||
if (debug_line_ptr == NULL) goto fail;
|
||||
|
||||
ret = f_read(&file, debug_line_ptr, debug_line_section_size, &read);
|
||||
if (ret != FR_OK || read != debug_line_section_size) goto fail;
|
||||
|
||||
dwarf_debug_line_header_t *debug_line_header = debug_line_ptr;
|
||||
kprint_uint32(debug_line_header->length);
|
||||
kprint_char('\n');
|
||||
|
||||
goto end;
|
||||
|
||||
@@ -55,5 +106,7 @@ void *dwarf_find_debug_info(FATFS *fs) {
|
||||
f_close(&file);
|
||||
free(header_ptr);
|
||||
free(sh_table_ptr);
|
||||
free(sh_table_str_ptr);
|
||||
free(debug_line_ptr);
|
||||
return NULL;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <common.h>
|
||||
|
||||
typedef struct _packed {
|
||||
struct _packed dwarf_debug_line_header {
|
||||
uint32_t length;
|
||||
uint16_t version;
|
||||
uint32_t header_length;
|
||||
@@ -12,4 +12,5 @@ typedef struct _packed {
|
||||
uint8_t line_range;
|
||||
uint8_t opcode_base;
|
||||
uint8_t std_opcode_lengths[12];
|
||||
} dwarf_debug_line_header;
|
||||
};
|
||||
typedef struct dwarf_debug_line_header dwarf_debug_line_header_t;
|
||||
@@ -30,7 +30,9 @@ int vga_print_char(char c, int col, int row, char attr) {
|
||||
if (col >= 0 && row >= 0) offset = vga_get_offset(col, row);
|
||||
else offset = vga_get_cursor_offset();
|
||||
|
||||
if (c == '\n') {
|
||||
if (c == '\b') {
|
||||
offset--;
|
||||
} else if (c == '\n') {
|
||||
row = vga_get_offset_row(offset);
|
||||
offset = vga_get_offset(0, row + 1);
|
||||
} else {
|
||||
|
||||
+43
-4
@@ -1,7 +1,8 @@
|
||||
#include "elf.h"
|
||||
#include "console.h"
|
||||
|
||||
#include <byteswap.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define ELF_DEBUG
|
||||
|
||||
@@ -68,12 +69,50 @@ elf_section_header_t *elf_find_section(elf_header_t *header,
|
||||
elf_section_header_t *sht_start,
|
||||
elf_section_header_type_t type) {
|
||||
uint16_t num_entries = header->section_header_num_entries;
|
||||
kprint("starting scan @ "); kprint_uint32((uintptr_t) sht_start); kprint_char('\n');
|
||||
for (uint16_t i = 0; i < num_entries; ++i) {
|
||||
elf_section_header_t *section_header = (void *) sht_start + header->section_header_entry_size * i;
|
||||
kprint("scanning sect @ "); kprint_uint32((uintptr_t) section_header);
|
||||
kprint(", type "); kprint_uint32(section_header->type); kprint_char('\n');
|
||||
if (section_header->type == type) return section_header;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
elf_section_header_t *elf_get_section(elf_header_t *header,
|
||||
elf_section_header_t *sht_start,
|
||||
uint16_t index) {
|
||||
uint16_t num_entries = header->section_header_num_entries;
|
||||
if (index > num_entries - 1) return NULL;
|
||||
return (void *) sht_start + header->section_header_entry_size * index;
|
||||
}
|
||||
|
||||
static const char* elf_section_type(elf_section_header_type_t type) {
|
||||
switch (type) {
|
||||
case ELF_SHT_NULL: return "SHT_NULL";
|
||||
case ELF_SHT_PROGBITS: return "SHT_PROGBITS";
|
||||
case ELF_SHT_SYMTAB: return "SHT_SYMTAB";
|
||||
case ELF_SHT_STRTAB: return "SHT_STRTAB";
|
||||
case ELF_SHT_RELA: return "SHT_RELA";
|
||||
case ELF_SHT_HASH: return "SHT_HASH";
|
||||
case ELF_SHT_DYNAMIC: return "SHT_DYNAMIC";
|
||||
case ELF_SHT_NOTE: return "SHT_NOTE";
|
||||
case ELF_SHT_NOBITS: return "SHT_NOBITS";
|
||||
case ELF_SHT_REL: return "SHT_REL";
|
||||
case ELF_SHT_SHLIB: return "SHT_SHLIB";
|
||||
case ELF_SHT_DYNSYM: return "SHT_DYNSYM";
|
||||
case ELF_SHT_LOPROC: return "SHT_LOPROC";
|
||||
case ELF_SHT_HIPROC: return "SHT_HIPROC";
|
||||
case ELF_SHT_LOUSER: return "SHT_LOUSER";
|
||||
case ELF_SHT_HIUSER: return "SHT_HIUSER";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void elf_print_sections(elf_header_t *header, elf_section_header_t *sht_start, void *shstrtab_ptr) {
|
||||
uint16_t num_entries = header->section_header_num_entries;
|
||||
for (uint16_t i = 0; i < num_entries; ++i) {
|
||||
elf_section_header_t *section_header = (void *) sht_start + header->section_header_entry_size * i;
|
||||
if (section_header->type == ELF_SHT_NULL) continue; // Skip null header
|
||||
printf("Section %d %s: offset "PRIx32", size "PRIx32", type %s\n",
|
||||
i, (char *) shstrtab_ptr + section_header->name, section_header->offset,
|
||||
section_header->size, elf_section_type(section_header->type));
|
||||
}
|
||||
}
|
||||
+31
-2
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <common.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define ELF_HEADER_MAGIC_LE ((uint32_t) 0x7F | 'E' << 8 | 'L' << 16 | 'F' << 24)
|
||||
|
||||
@@ -42,14 +43,29 @@ typedef enum elf_machine_type elf_machine_type_t;
|
||||
_Static_assert(sizeof(elf_machine_type_t) == sizeof(uint16_t),
|
||||
"elf_machine_type incorrect size");
|
||||
|
||||
enum elf_obj_type {
|
||||
ELF_ET_NONE = 0,
|
||||
ELF_ET_REL = 1,
|
||||
ELF_ET_EXEC = 2,
|
||||
ELF_ET_DYN = 3,
|
||||
ELF_ET_CORE = 4,
|
||||
ELF_ET_LOPROC = 0xFF00,
|
||||
ELF_ET_HIPROC = 0xFFFF
|
||||
};
|
||||
typedef enum elf_obj_type elf_obj_type_t;
|
||||
|
||||
_Static_assert(sizeof(elf_obj_type_t) == sizeof(uint16_t),
|
||||
"elf_obj_type incorrect size");
|
||||
|
||||
struct _packed elf_header {
|
||||
uint32_t magic;
|
||||
elf_header_arch_bits_t arch_bits;
|
||||
elf_header_endianness_t endianness;
|
||||
uint8_t elf_version;
|
||||
uint8_t __padding[9];
|
||||
uint16_t elf_type; // 1 = relocatable, 2 = executable, 3 = shared, 4 = core
|
||||
elf_obj_type_t obj_type;
|
||||
elf_machine_type_t machine_type;
|
||||
uint32_t version; // ?????
|
||||
uint32_t program_entry_offset;
|
||||
uint32_t program_header_offset;
|
||||
uint32_t section_header_offset;
|
||||
@@ -63,7 +79,7 @@ struct _packed elf_header {
|
||||
};
|
||||
typedef struct elf_header elf_header_t;
|
||||
|
||||
_Static_assert(sizeof(elf_header_t) == 48,
|
||||
_Static_assert(sizeof(elf_header_t) == 52,
|
||||
"elf_header incorrect size");
|
||||
|
||||
enum elf_section_header_type {
|
||||
@@ -103,6 +119,13 @@ struct _packed elf_section_header {
|
||||
};
|
||||
typedef struct elf_section_header elf_section_header_t;
|
||||
|
||||
struct elf_file {
|
||||
FILE fd;
|
||||
elf_header_t *header;
|
||||
elf_section_header_t *sht_start;
|
||||
};
|
||||
typedef struct elf_file elf_file_t;
|
||||
|
||||
//_Static_assert(sizeof(elf_section_header_t) == 32,
|
||||
// "elf_section_header incorrect size");
|
||||
|
||||
@@ -113,3 +136,9 @@ elf_header_t *read_elf_header(void *ptr);
|
||||
elf_section_header_t *elf_find_section(elf_header_t *header,
|
||||
elf_section_header_t *sht_start,
|
||||
elf_section_header_type_t type);
|
||||
|
||||
elf_section_header_t *elf_get_section(elf_header_t *header,
|
||||
elf_section_header_t *sht_start,
|
||||
uint16_t index);
|
||||
|
||||
void elf_print_sections(elf_header_t *header, elf_section_header_t *sht_start, void *shstrtab_ptr);
|
||||
+10
-8
@@ -5,6 +5,8 @@
|
||||
#ifndef FF_INTEGER
|
||||
#define FF_INTEGER
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _WIN32 /* FatFs development platform */
|
||||
|
||||
#include <windows.h>
|
||||
@@ -13,20 +15,20 @@ typedef unsigned __int64 QWORD;
|
||||
#else /* Embedded platform */
|
||||
|
||||
/* These types MUST be 16-bit or 32-bit */
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef int32_t INT;
|
||||
typedef uint32_t UINT;
|
||||
|
||||
/* This type MUST be 8-bit */
|
||||
typedef unsigned char BYTE;
|
||||
typedef uint8_t BYTE;
|
||||
|
||||
/* These types MUST be 16-bit */
|
||||
typedef short SHORT;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned short WCHAR;
|
||||
typedef int16_t SHORT;
|
||||
typedef uint16_t WORD;
|
||||
typedef uint16_t WCHAR;
|
||||
|
||||
/* These types MUST be 32-bit */
|
||||
typedef long LONG;
|
||||
typedef unsigned long DWORD;
|
||||
typedef int32_t LONG;
|
||||
typedef uint32_t DWORD;
|
||||
|
||||
/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
|
||||
typedef unsigned long long QWORD;
|
||||
|
||||
+2
-8
@@ -1,3 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include "isr.h"
|
||||
#include "console.h"
|
||||
#include "drivers/ports.h"
|
||||
@@ -10,14 +11,7 @@ void register_interrupt_handler(uint8_t n, isr_t handler) {
|
||||
|
||||
_unused
|
||||
void isr_handler(registers_t regs) {
|
||||
kprint("Received interrupt: ");
|
||||
kprint_uint32(regs.int_no);
|
||||
kprint(" (err: ");
|
||||
kprint_uint32(regs.err_code);
|
||||
kprint(") @ ");
|
||||
kprint_uint32(regs.eip);
|
||||
kprint_char('\n');
|
||||
panic(NULL);
|
||||
panic("Received interrupt: %lu (err: %lu) @ %p\n", regs.int_no, regs.err_code, (void *) regs.eip);
|
||||
}
|
||||
|
||||
_unused
|
||||
|
||||
+7
-7
@@ -10,7 +10,7 @@
|
||||
#include "fatfs/ff.h"
|
||||
|
||||
#include <common.h>
|
||||
#include <lzma.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// #define KDEBUG
|
||||
|
||||
@@ -25,16 +25,16 @@ void kernel_main(uint32_t multiboot_magic, void *multiboot_info) {
|
||||
pci_init();
|
||||
ata_init();
|
||||
|
||||
uint32_t i = UINT32_MAX / 2;
|
||||
uint32_t i = UINT32_MAX / 16;
|
||||
while(i--); // stall
|
||||
|
||||
kprint("Mounting drive 0... ");
|
||||
printf("Mounting drive 0... ");
|
||||
FATFS fs;
|
||||
FRESULT ret = f_mount(&fs, "", 1);
|
||||
if (ret == FR_OK) {
|
||||
kprint("OK\n");
|
||||
printf("OK\n");
|
||||
} else {
|
||||
kprint("fail\n");
|
||||
printf("fail %d\n", ret);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DWARF
|
||||
@@ -42,7 +42,7 @@ void kernel_main(uint32_t multiboot_magic, void *multiboot_info) {
|
||||
dwarf_find_debug_info(&fs);
|
||||
#endif
|
||||
|
||||
clear_screen();
|
||||
// clear_screen();
|
||||
|
||||
#ifdef KDEBUG
|
||||
kprint("Initializing timer...\n");
|
||||
@@ -70,4 +70,4 @@ void kernel_main(uint32_t multiboot_magic, void *multiboot_info) {
|
||||
shell_read();
|
||||
key_buffer_print();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-67
@@ -1,3 +1,4 @@
|
||||
#include <stdio.h>
|
||||
#include "multiboot.h"
|
||||
#include "console.h"
|
||||
|
||||
@@ -7,94 +8,56 @@
|
||||
extern void *malloc_memory_start;
|
||||
extern void *malloc_memory_end;
|
||||
|
||||
struct multiboot_color
|
||||
{
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
};
|
||||
|
||||
void multiboot_init(uint32_t magic, void *info_ptr) {
|
||||
if (magic != MULTIBOOT_MAGIC) {
|
||||
panic("multiboot_magic: Invalid magic.\n");
|
||||
panic("multiboot_magic: Invalid magic "PRIX32"\n", magic);
|
||||
}
|
||||
|
||||
struct multiboot_info *info = (struct multiboot_info *) (info_ptr + PAGE_OFFSET);
|
||||
kprint("multiboot_info = "); kprint_uint32((uintptr_t) info);
|
||||
kprint("\nflags = "); kprint_uint32(info->flags); kprint_char('\n');
|
||||
printf("multiboot_info = "PRIXPTR", flags = "PRIx32"\n", info, info->flags);
|
||||
|
||||
if (CHECK_FLAG(info->flags, MULTIBOOT_INFO_MEMORY)) {
|
||||
malloc_memory_start = (void *) 0x100000 + PAGE_OFFSET + KERNEL_OFFSET;
|
||||
// 1 MiB + (info->mem_upper * 1 KiB)
|
||||
malloc_memory_end = malloc_memory_start + (info->mem_upper * 0x400) - KERNEL_OFFSET;
|
||||
kprint("upper_memory_end = "); kprint_uint32((uintptr_t) malloc_memory_end);
|
||||
kprint_char('\n');
|
||||
printf("upper_memory_end = "PRIXPTR"\n", malloc_memory_end);
|
||||
} else {
|
||||
panic("multiboot: Memory information required");
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(info->flags, MULTIBOOT_INFO_BOOTDEV)) {
|
||||
kprint("boot_device = "); kprint_uint32(info->boot_device);
|
||||
kprint_char('\n');
|
||||
printf("boot_device = "PRIx32"h\n", info->boot_device);
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(info->flags, MULTIBOOT_INFO_CMDLINE)) {
|
||||
kprint("cmdline = "); kprint((char *) (info->cmdline + PAGE_OFFSET));
|
||||
kprint_char('\n');
|
||||
printf("cmdline = %s\n", (char *) (info->cmdline + PAGE_OFFSET));
|
||||
}
|
||||
|
||||
if (CHECK_FLAG(info->flags, MULTIBOOT_INFO_MODS)) {
|
||||
struct multiboot_mod_list *mod;
|
||||
int i;
|
||||
|
||||
kprint("mods_count = "); kprint_uint32(info->mods_count);
|
||||
kprint(", mods_addr = "); kprint_uint32(info->mods_addr);
|
||||
kprint_char('\n');
|
||||
printf("mods_count = "PRIu32", mods_addr = "PRIXUPTR"\n", info->mods_count, info->mods_addr);
|
||||
for (i = 0, mod = (struct multiboot_mod_list *) (info->mods_addr + PAGE_OFFSET);
|
||||
i < info->mods_count;
|
||||
i++, mod++) {
|
||||
kprint(" mod_start = "); kprint_uint32(mod->mod_start);
|
||||
kprint(", mod_end = "); kprint_uint32(mod->mod_end);
|
||||
kprint(", cmdline = "); kprint((char *) (mod->cmdline + PAGE_OFFSET));
|
||||
kprint_char('\n');
|
||||
printf(" mod_start = "PRIXUPTR", mod_end = "PRIXUPTR", cmdline = %s\n",
|
||||
mod->mod_start, mod->mod_end, (char *) (mod->cmdline + PAGE_OFFSET));
|
||||
}
|
||||
}
|
||||
|
||||
/* Bits 4 and 5 are mutually exclusive! */
|
||||
if (CHECK_FLAG(info->flags, MULTIBOOT_INFO_AOUT_SYMS) &&
|
||||
CHECK_FLAG(info->flags, MULTIBOOT_INFO_ELF_SHDR)) {
|
||||
panic("multiboot_info->flags: Both bits 4 and 5 are set.\n");
|
||||
}
|
||||
|
||||
/* Is the symbol table of a.out valid? */
|
||||
if (CHECK_FLAG(info->flags, MULTIBOOT_INFO_AOUT_SYMS)) {
|
||||
struct multiboot_aout_symbol_table *aout_sym = &info->u.aout_sym;
|
||||
|
||||
kprint("multiboot_aout_symbol_table: tabsize = "); kprint_uint32(aout_sym->tabsize);
|
||||
kprint(", strsize = "); kprint_uint32(aout_sym->strsize);
|
||||
kprint(", addr = "); kprint_uint32(aout_sym->addr);
|
||||
kprint_char('\n');
|
||||
}
|
||||
|
||||
/* Is the section header table of ELF valid? */
|
||||
if (CHECK_FLAG(info->flags, MULTIBOOT_INFO_ELF_SHDR)) {
|
||||
struct multiboot_elf_section_header_table *elf_sec = &info->u.elf_sec;
|
||||
|
||||
kprint("multiboot_elf_sec: num = "); kprint_uint32(elf_sec->num);
|
||||
kprint(", size = "); kprint_uint32(elf_sec->size);
|
||||
kprint(", addr = "); kprint_uint32(elf_sec->addr);
|
||||
kprint(", shndx = "); kprint_uint32(elf_sec->shndx);
|
||||
kprint_char('\n');
|
||||
printf("multiboot_elf_sec: num = "PRIu32", size = "PRIu32", addr = "PRIXUPTR", shndx = "PRIu32"\n",
|
||||
elf_sec->num, elf_sec->size, elf_sec->addr, elf_sec->shndx);
|
||||
}
|
||||
|
||||
/* Are mmap_* valid? */
|
||||
if (CHECK_FLAG(info->flags, MULTIBOOT_INFO_MEM_MAP)) {
|
||||
printf("mmap_addr = "PRIXUPTR", mmap_length = "PRIx32"\n", info->mmap_addr, info->mmap_length);
|
||||
|
||||
struct multiboot_mmap_entry *mmap;
|
||||
|
||||
kprint("mmap_addr = "); kprint_uint32(info->mmap_addr);
|
||||
kprint(", mmap_length = "); kprint_uint32(info->mmap_length);
|
||||
kprint_char('\n');
|
||||
|
||||
struct multiboot_mmap_entry *largest_available_entry = NULL;
|
||||
for (mmap = (struct multiboot_mmap_entry *) (info->mmap_addr + PAGE_OFFSET);
|
||||
(unsigned long) mmap < info->mmap_addr + PAGE_OFFSET + info->mmap_length;
|
||||
@@ -105,28 +68,21 @@ void multiboot_init(uint32_t magic, void *info_ptr) {
|
||||
largest_available_entry = mmap;
|
||||
}
|
||||
|
||||
kprint(" size = "); kprint_uint32(mmap->size);
|
||||
kprint(", base_addr = "); kprint_uint64(mmap->addr);
|
||||
kprint(", length = "); kprint_uint64(mmap->len);
|
||||
kprint(", type = "); kprint_uint32(mmap->type);
|
||||
kprint_char('\n');
|
||||
printf(" size = "PRIx32", base_addr = "PRIXUPTR64S", length = "PRIX64S", type = "PRIu32"\n",
|
||||
mmap->size, mmap->addr, mmap->len, mmap->type);
|
||||
}
|
||||
|
||||
if (largest_available_entry != NULL) {
|
||||
// malloc_memory_start = (void *) (uint32_t) largest_available_entry->addr + PAGE_OFFSET + KERNEL_OFFSET;
|
||||
// malloc_memory_end = malloc_memory_start + largest_available_entry->len - KERNEL_OFFSET;
|
||||
kprint("malloc_memory_start = "); kprint_uint32((uintptr_t) malloc_memory_start);
|
||||
kprint(", end = "); kprint_uint32((uintptr_t) malloc_memory_end);
|
||||
kprint_char('\n');
|
||||
malloc_memory_start = (void *) (uint32_t) largest_available_entry->addr + PAGE_OFFSET + KERNEL_OFFSET;
|
||||
malloc_memory_end = malloc_memory_start + largest_available_entry->len - KERNEL_OFFSET;
|
||||
printf("malloc_memory_start = "PRIXPTR", end = "PRIXPTR"\n", malloc_memory_start, malloc_memory_end);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check VGA framebuffer. */
|
||||
if (CHECK_FLAG (info->flags, MULTIBOOT_INFO_FRAMEBUFFER_INFO)) {
|
||||
kprint("framebuffer addr = "); kprint_uint64(info->framebuffer_addr);
|
||||
kprint(", type = "); kprint_uint8(info->framebuffer_type);
|
||||
kprint(", bpp = "); kprint_uint8(info->framebuffer_bpp);
|
||||
kprint_char('\n');
|
||||
printf("framebuffer_addr = "PRIXUPTR64", type = %d, bpp = %d\n",
|
||||
info->framebuffer_addr, info->framebuffer_type, info->framebuffer_bpp);
|
||||
|
||||
switch (info->framebuffer_type) {
|
||||
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
|
||||
@@ -134,11 +90,11 @@ void multiboot_init(uint32_t magic, void *info_ptr) {
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
console_set_vga_enabled(true); // FIXME
|
||||
}
|
||||
|
||||
kprint("Multiboot info loaded.\n");
|
||||
printf("Multiboot info loaded.\n");
|
||||
}
|
||||
+33
-79
@@ -13,6 +13,7 @@
|
||||
#include <malloc.h>
|
||||
#include <vector.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define KEY_BUFFER_INITIAL_SIZE 0x100
|
||||
static char *key_buffer;
|
||||
@@ -28,80 +29,34 @@ void command_lspci() {
|
||||
for (pci_device_t *device = vc_vector_begin(pci_devices);
|
||||
device != vc_vector_end(pci_devices);
|
||||
device = vc_vector_next(pci_devices, device)) {
|
||||
kprint_uint8(device->loc.bus);
|
||||
kprint_char(':');
|
||||
kprint_uint8(device->loc.device);
|
||||
kprint_char('.');
|
||||
kprint_uint8(device->loc.function);
|
||||
kprint_char(' ');
|
||||
kprint_uint16(device->class);
|
||||
kprint_char('.');
|
||||
kprint_uint8(device->prog_if);
|
||||
kprint(": ");
|
||||
kprint_uint16(device->vendor_id);
|
||||
kprint_char(':');
|
||||
kprint_uint16(device->device_id);
|
||||
kprint_char(' ');
|
||||
kprint(pci_class_name(device->class, device->revision_id));
|
||||
if (device->revision_id) {
|
||||
kprint(" (rev ");
|
||||
kprint_uint8(device->revision_id);
|
||||
kprint_char(')');
|
||||
}
|
||||
kprint_char('\n');
|
||||
printf("%d:%d.%d %04X.%02X: %04X:%04X | %s",
|
||||
device->loc.bus, device->loc.device, device->loc.function,
|
||||
device->class, device->prog_if, device->vendor_id, device->device_id,
|
||||
pci_class_name(device->class, device->revision_id));
|
||||
if (device->revision_id) printf(" (rev %d)\n", device->revision_id);
|
||||
else printf("\n");
|
||||
|
||||
if (device->bar0) {
|
||||
kprint(" BAR0 = ");
|
||||
kprint_uint32(device->bar0);
|
||||
kprint_char('\n');
|
||||
}
|
||||
if (device->bar1) {
|
||||
kprint(" BAR1 = ");
|
||||
kprint_uint32(device->bar1);
|
||||
kprint_char('\n');
|
||||
}
|
||||
if (device->bar2) {
|
||||
kprint(" BAR2 = ");
|
||||
kprint_uint32(device->bar2);
|
||||
kprint_char('\n');
|
||||
}
|
||||
if (device->bar3) {
|
||||
kprint(" BAR3 = ");
|
||||
kprint_uint32(device->bar3);
|
||||
kprint_char('\n');
|
||||
}
|
||||
if (device->bar4) {
|
||||
kprint(" BAR4 = ");
|
||||
kprint_uint32(device->bar4);
|
||||
kprint_char('\n');
|
||||
}
|
||||
if (device->bar5) {
|
||||
kprint(" BAR5 = ");
|
||||
kprint_uint32(device->bar5);
|
||||
kprint_char('\n');
|
||||
}
|
||||
if (device->bar0) printf(" BAR0 = "PRIXUPTR"\n", device->bar0);
|
||||
if (device->bar1) printf(" BAR1 = "PRIXUPTR"\n", device->bar1);
|
||||
if (device->bar2) printf(" BAR2 = "PRIXUPTR"\n", device->bar2);
|
||||
if (device->bar3) printf(" BAR3 = "PRIXUPTR"\n", device->bar3);
|
||||
if (device->bar4) printf(" BAR4 = "PRIXUPTR"\n", device->bar4);
|
||||
if (device->bar5) printf(" BAR5 = "PRIXUPTR"\n", device->bar5);
|
||||
}
|
||||
kprint_char('\n');
|
||||
}
|
||||
|
||||
void command_lsata() {
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
if (ide_devices[i].reserved == 1) {
|
||||
kprint_uint8(i);
|
||||
kprint(": ");
|
||||
kprint((const char *[]) {"ATA", "ATAPI"}[ide_devices[i].type]);
|
||||
kprint(" Drive ");
|
||||
kprint_uint32(ide_devices[i].size / 1024 / 1024 / 2);
|
||||
kprint("GB - ");
|
||||
kprint(ide_devices[i].model);
|
||||
kprint_char('\n');
|
||||
const char *type_str = ((const char *[]) {"ATA ", "ATAPI"}[ide_devices[i].type]);
|
||||
printf("%d: %s | %016lu sectors | %s\n", i, type_str, ide_devices[i].size, ide_devices[i].model);
|
||||
}
|
||||
}
|
||||
kprint_char('\n');
|
||||
}
|
||||
|
||||
static void shell_callback(char *input) {
|
||||
kprint_char('\n');
|
||||
printf("\n");
|
||||
|
||||
unsigned char ret = 1;
|
||||
bool save = true;
|
||||
if (strcmp(input, "exit") == 0 ||
|
||||
@@ -112,11 +67,10 @@ static void shell_callback(char *input) {
|
||||
reboot();
|
||||
} else if (strcmp(input, "clear") == 0) {
|
||||
clear_screen();
|
||||
kprint("# ");
|
||||
printf("# ");
|
||||
return;
|
||||
} else if (strncmp(input, "echo ", 5) == 0) {
|
||||
kprint(input + 5);
|
||||
kprint_char('\n');
|
||||
printf("%s\n", input + 5);
|
||||
ret = 0;
|
||||
} else if (strcmp(input, "memdbg") == 0) {
|
||||
print_chunk_debug(NULL, true);
|
||||
@@ -132,8 +86,7 @@ static void shell_callback(char *input) {
|
||||
for (char **i = vc_vector_begin(shell_history);
|
||||
i != vc_vector_end(shell_history);
|
||||
i = vc_vector_next(shell_history, i)) {
|
||||
kprint(*i);
|
||||
kprint_char('\n');
|
||||
printf("%s\n", *i);
|
||||
}
|
||||
ret = 0;
|
||||
} else if (strcmp(input, "test vector") == 0) {
|
||||
@@ -142,9 +95,7 @@ static void shell_callback(char *input) {
|
||||
ret = (unsigned char) !fatfs_test();
|
||||
} else if (strcmp(input, "test") == 0 ||
|
||||
strncmp(input, "test ", 5) == 0) {
|
||||
kprint("Available tests:\n");
|
||||
kprint(" vector\n");
|
||||
kprint(" fatfs\n");
|
||||
printf("Available tests:\n vector\n fatfs\n");
|
||||
} else if (strcmp(input, "lspci") == 0) {
|
||||
command_lspci();
|
||||
ret = 0;
|
||||
@@ -152,9 +103,8 @@ static void shell_callback(char *input) {
|
||||
command_lsata();
|
||||
ret = 0;
|
||||
}
|
||||
(void) (ret);
|
||||
// kprint_uint32(ret);
|
||||
kprint("# ");
|
||||
printf("%d # ", ret);
|
||||
fflush(stdout);
|
||||
|
||||
if (save && input[0] != '\0') {
|
||||
char *value = strdup(input);
|
||||
@@ -169,7 +119,8 @@ static void shell_history_free_func(void *data) {
|
||||
void shell_init() {
|
||||
shell_history = vc_vector_create(0x100, sizeof(char *), shell_history_free_func);
|
||||
init_keyboard();
|
||||
kprint("# ");
|
||||
printf("# ");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void shell_read() {
|
||||
@@ -241,23 +192,26 @@ void key_buffer_clear() {
|
||||
|
||||
void key_buffer_set(char *input) {
|
||||
while (key_buffer_used--) {
|
||||
kprint_backspace();
|
||||
printf("\b \b");
|
||||
}
|
||||
key_buffer_used = strlen(input);
|
||||
key_buffer = realloc(key_buffer, max(key_buffer_used + 1, KEY_BUFFER_INITIAL_SIZE));
|
||||
key_buffer = realloc(key_buffer, MAX(key_buffer_used + 1, KEY_BUFFER_INITIAL_SIZE));
|
||||
if (key_buffer == NULL) return; // return error of some sort?
|
||||
strncpy(key_buffer, input, key_buffer_used + 1);
|
||||
key_buffer_printed = 0;
|
||||
key_buffer_print();
|
||||
}
|
||||
|
||||
void key_buffer_print() {
|
||||
while (key_buffer_printed < key_buffer_used) {
|
||||
kprint_char(key_buffer[key_buffer_printed++]);
|
||||
if (key_buffer_printed < key_buffer_used) {
|
||||
fwrite(key_buffer + key_buffer_printed, key_buffer_used - key_buffer_printed, 1, stdout);
|
||||
key_buffer_printed = key_buffer_used;
|
||||
}
|
||||
while (key_buffer_printed > key_buffer_used) {
|
||||
kprint_backspace();
|
||||
printf("\b \b");
|
||||
key_buffer_printed--;
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void key_buffer_return() {
|
||||
|
||||
@@ -46,7 +46,7 @@ bool fatfs_test() {
|
||||
kprint_char('\n');
|
||||
|
||||
end:
|
||||
if (buff != NULL) free(buff);
|
||||
free(buff);
|
||||
f_close(&file);
|
||||
f_unmount("");
|
||||
return ret == FR_OK;
|
||||
|
||||
+2
-1
@@ -11,4 +11,5 @@ if (CMAKE_HOST_APPLE)
|
||||
endif ()
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/libc)
|
||||
add_library(c STATIC string malloc math vector byteswap)
|
||||
add_library(c STATIC string malloc math vector byteswap ctype.h errno wchar stdio.c stdio.h
|
||||
stdio/printf stdio/fprintf stdio/snprintf stdio/vfprintf stdio/vsnprintf)
|
||||
+3
-1
@@ -9,4 +9,6 @@
|
||||
#ifdef __GNUC__
|
||||
#define _unused __attribute__((unused))
|
||||
#define _packed __attribute__((packed))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define off_t uint64_t
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
int isalnum(int);
|
||||
int isalpha(int);
|
||||
int isblank(int);
|
||||
int iscntrl(int);
|
||||
int isdigit(int);
|
||||
int isgraph(int);
|
||||
int islower(int);
|
||||
int isprint(int);
|
||||
int ispunct(int);
|
||||
int isspace(int);
|
||||
int isupper(int);
|
||||
int isxdigit(int);
|
||||
int tolower(int);
|
||||
int toupper(int);
|
||||
|
||||
static __inline int __isspace(int _c)
|
||||
{
|
||||
return _c == ' ' || (unsigned)_c-'\t' < 5;
|
||||
}
|
||||
|
||||
#define isalpha(a) (0 ? isalpha(a) : (((unsigned)(a)|32)-'a') < 26)
|
||||
#define isdigit(a) (0 ? isdigit(a) : ((unsigned)(a)-'0') < 10)
|
||||
#define islower(a) (0 ? islower(a) : ((unsigned)(a)-'a') < 26)
|
||||
#define isupper(a) (0 ? isupper(a) : ((unsigned)(a)-'A') < 26)
|
||||
#define isprint(a) (0 ? isprint(a) : ((unsigned)(a)-0x20) < 0x5f)
|
||||
#define isgraph(a) (0 ? isgraph(a) : ((unsigned)(a)-0x21) < 0x5e)
|
||||
#define isspace(a) __isspace(a)
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "errno.h"
|
||||
|
||||
char *strerror(int errno) {
|
||||
return "ERROR"; // FIXME
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#define EINVAL 22
|
||||
#define EOVERFLOW 75
|
||||
#define EILSEQ 84
|
||||
|
||||
extern int errno; // FIXME for threading
|
||||
|
||||
char *strerror(int errno);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user