got multiboot info parsed!

This commit is contained in:
Benji Dial 2019-12-26 13:06:21 -05:00
parent 2c542b87ff
commit 336cfa313d
7 changed files with 159 additions and 77 deletions

View file

@ -5,13 +5,14 @@ cd: kernel fs
grub2-mkrescue out/fs -o out/cd.iso --product-name=portland --product-version=0.0.9
kernel: obj out
nasm src/kernel/serial.asm -o obj/kserial.o -f elf32
nasm src/kernel/stub.asm -o obj/kstub.o -f elf32
gcc -c src/kernel/files.c -o obj/kfiles.o -ffreestanding -nostdlib -m32
gcc -c src/kernel/main.c -o obj/kmain.o -ffreestanding -nostdlib -m32
gcc -c src/kernel/mem.c -o obj/kmem.o -ffreestanding -nostdlib -m32
gcc -c src/kernel/proc.c -o obj/kproc.o -ffreestanding -nostdlib -m32
gcc -c src/kernel/vga.c -o obj/kvga.o -ffreestanding -nostdlib -m32
ld obj/kstub.o obj/kfiles.o obj/kmain.o obj/kmem.o obj/kproc.o obj/kvga.o \
ld obj/kstub.o obj/kfiles.o obj/kmain.o obj/kmem.o obj/kproc.o obj/kserial.o obj/kvga.o \
-o out/kernel.elf -T src/kernel/link.ld -s --orphan-handling=discard -melf_i386

View file

@ -23,8 +23,6 @@ OF THIS SOFTWARE.
#include "proc.h"
#include <stdbool.h>
extern uint32_t info_pointer;
enum tag_type {
BOOT_COMMAND = 1,
LOADER_NAME = 2,
@ -52,7 +50,6 @@ enum tag_type {
struct tag_start {
uint32_t type;
uint32_t size;
uint8_t rest;
} __attribute__ ((__packed__));
struct boot_device_tag {
@ -79,52 +76,68 @@ bool have_boot_device = false;
bool have_mmap = false;
enum error_codes {
NO_BOOT_DEVICE = 000000000000,
NO_MMAP = 000000000001,
INSUFF_MEMORY = 000000000002
NO_BOOT_DEVICE = 0x00000000,
NO_MMAP = 0x00000001,
INSUFF_MEMORY = 0x00000002
};
struct tag_start *tag_pointer;
uint32_t main(void) {
for (uint32_t *i = (uint32_t *)VGA_BUFFER; i < (uint32_t *)0x000b8fa0; ++i)
*i = 0x70207020;
clear();
put_sz("Starting...\n");
uint32_t info_size = *(uint32_t *)info_pointer;
struct tag_start *tag_pointer = (struct tag_start *)(info_pointer + 2);
/*
uint32_t *debug_ptr = (uint32_t *)tag_pointer - 2;
uint32_t debug_size = *debug_ptr / 4;
for (uint32_t i = 0; i < debug_size; ++i) {
put_32_hex(debug_ptr[i]);
put_char(' ');
}
*/
put_sz("Multiboot info:\n");
while (tag_pointer->type) {
put_sz(" Tag type 0x");
put_32_hex(tag_pointer->type);
put_sz(" with size 0x");
put_32_hex(tag_pointer->size);
switch (tag_pointer->type) {
case BOOT_DEVICE:
boot_device = *(struct boot_device_tag *)&tag_pointer->rest;
boot_device = *(struct boot_device_tag *)(tag_pointer + 1);
have_boot_device = true;
put_sz("Boot device: 0x");
put_sz(": boot device\n BIOS code: ");
put_32_hex(boot_device.bios_device);
if (boot_device.partition != 0xffffffff) {
put_sz(", 0x");
put_sz("\n Partition number: ");
put_32_hex(boot_device.partition);
if (boot_device.subpartition != 0xffffffff) {
put_sz(", 0x");
put_sz("\n Subpartition number: ");
put_32_hex(boot_device.subpartition);
}
}
put_char('\n');
}
else
put_sz("\n No subpartition\n");
}
else
put_sz("\n No partition\n");
break;
case MEMORY_MAP:
{
struct mmap_tag_entry *tag = (struct mmap_tag_entry *)((uint32_t)&tag_pointer->rest + 8);
uint32_t size = *(uint32_t *)&tag_pointer->rest;
uint32_t size = *(uint32_t *)(tag_pointer + 1);
struct mmap_tag_entry *tag = (struct mmap_tag_entry *)(tag_pointer + 2);
struct mmap_tag_entry *end = (struct mmap_tag_entry *)((uint32_t)tag_pointer + tag_pointer->size);
struct mmap_entry *entry = (struct mmap_entry *)tag;
struct mmap_entry **last_next = &mmap_start;
uint32_t usable = 0;
while (tag) {
put_sz(": memory map\n Regions:\n");
while (tag != end) {
if (!(tag->base & 0xffffffff00000000)) {
entry->base = (uint32_t)tag->base;
entry->length = (tag->base + tag->length - 1) & 0xffffffff00000000 ?
1 + ~(uint32_t)tag->base : (uint32_t)tag->length;
put_sz("Memory: 0x");
put_sz(" 0x");
put_32_hex(entry->base);
put_sz(" - 0x");
put_32_hex(entry->base + entry->length - 1);
@ -147,7 +160,9 @@ uint32_t main(void) {
entry->whose = HARDWARE;
break;
default:
put_sz(": unrecognized type, assuming hardware use\n");
put_sz(": hardware use (0x");
put_32_hex(tag->type);
put_sz(")\n");
entry->whose = HARDWARE;
break;
}
@ -158,13 +173,13 @@ uint32_t main(void) {
tag = (struct mmap_tag_entry *)((uint32_t)tag + size);
}
put_sz("Total usable memory: 0x");
put_sz(" Total usable memory: ");
put_32_hex(usable);
put_char('\n');
bool clean;
bool dirty;
do {
clean = true;
dirty = false;
for (struct mmap_entry *current = mmap_start; current; current = current->next)
for (struct mmap_entry *against = mmap_start; against; against = against->next)
if ((current->base + current->length == against->base) &&
@ -177,27 +192,29 @@ uint32_t main(void) {
;
current->next = against->next;
}
clean = false;
dirty = true;
}
} while (clean);
} while (dirty);
have_mmap = true;
break;
}
default:
put_sz("Ignoring multiboot tag 0x");
put_32_hex(tag_pointer->type);
put_char('\n');
put_sz(": ignoring\n");
}
tag_pointer = (struct tag_start *)((uint32_t)tag_pointer + tag_pointer->size);
};
tag_pointer = (struct tag_start *)(((uint32_t)tag_pointer + tag_pointer->size - 1 & 0xfffffff8) + 8);
}
if (!have_boot_device)
return NO_BOOT_DEVICE;
if (!have_mmap)
return NO_MMAP;
put_sz("Halting.");
while (1)
;
if (!((proc_table = allocate_block(sizeof(struct proc_info) * 65536, KERNEL)) &&
(file_table = allocate_block(sizeof(struct file_info) * 65536, KERNEL))))
return INSUFF_MEMORY;
@ -206,3 +223,11 @@ uint32_t main(void) {
while (1)
put_sz("|\b/\b-\b\\\b");
}
void wrapped_main(void) {
uint32_t error = main();
set_color(0x47);
clear();
put_sz("Error: 0x");
put_32_hex(error);
}

29
src/kernel/serial.asm Normal file
View file

@ -0,0 +1,29 @@
;Copyright 2019 Benji Dial
;Permission to use, copy, modify, and/or distribute this
;software for any purpose with or without fee is hereby
;granted, provided that the above copyright notice and this
;permission notice appear in all copies.
;THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
;ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
;IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
;EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
;INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
;RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
;ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
;ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
;OF THIS SOFTWARE.
global send_byte
global read_byte
section .text
;COM1: COM2: COM3: COM4:
;0x03f8, 0x02f8, 0x03e8, 0x02e8
send_byte:;void send_byte(uint8_t value, uint8_t port)
;TODO
read_byte:;uint8_t read_byte(uint8_t port)
;TODO

38
src/kernel/serial.h Normal file
View file

@ -0,0 +1,38 @@
/*
Copyright 2019 Benji Dial
Permission to use, copy, modify, and/or distribute this
software for any purpose with or without fee is hereby
granted, provided that the above copyright notice and this
permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
OF THIS SOFTWARE.
*/
#include <stdint.h>
#ifndef SERIAL_H
#define SERIAL_H
enum serials {
COM1 = 0,
COM2 = 1,
COM3 = 2,
COM4 = 3
};
/*
Commenting out so I don't accidentally call garbage while these are unimplemented.
void send_byte(uint8_t value, uint8_t port);
uint8_t read_byte(uint8_t port);
*/
#endif

View file

@ -15,7 +15,9 @@
;ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
;OF THIS SOFTWARE.
extern main
global _start
extern wrapped_main
extern tag_pointer
section .mb_header
dd 0xe852_50d6;magic
@ -34,37 +36,12 @@ mb_end:
section .text
bits 32
global _start
_start:
mov dword [info_pointer], ebx
add ebx, 8
mov dword [tag_pointer], ebx
mov esp, stack
call main
mov edx, eax
mov eax, 0x4720_4720
mov ebx, 0x000b_8000
mov ecx, 0x000b_8fa0
clear_screen_loop:
mov dword [ebx], eax
add ebx, 4
test ebx, ecx
jne clear_screen_loop
mov dword [0x000b_8000], 0x4772_4745
mov dword [0x000b_8004], 0x476f_4772
mov dword [0x000b_8008], 0x4720_4772
mov ebx, 0x000b_8020
mov ecx, 0x000b_800a
error_number_loop:
mov al, dl
and al, 0x07
or al, 0x30
mov byte [ebx], al
sub ebx, 2
shr edx, 3
test ebx, ecx
jne error_number_loop
call wrapped_main
cli
halt:
@ -72,7 +49,6 @@ halt:
jmp halt
section .bss
global info_pointer
info_pointer resd 1
resb 0x1000 - $ + $$
stack:

View file

@ -18,6 +18,7 @@ OF THIS SOFTWARE.
*/
#include "vga.h"
#include "serial.h"
#include <stdbool.h>
uint16_t cursor_pos = 0;
@ -25,18 +26,24 @@ uint8_t color = 0x70;
#define cols 80
#define rows 25
void clear(void) {
uint32_t fill = 0x00200020 | (color << 24) | (color << 8);
for (uint32_t *i = (uint32_t *)VGA_BUFFER; i < (uint32_t *)(VGA_BUFFER + rows * cols * 2); ++i)
*i = fill;
cursor_pos = 0;
}
void scroll(void) {
cursor_pos -= cols * 2;
uint32_t *limit = (uint32_t *)(VGA_BUFFER + cols * (rows - 1));
for (uint32_t *i = (uint32_t *)VGA_BUFFER; i < limit; ++i)
for (uint32_t *i = (uint32_t *)VGA_BUFFER; i < (uint32_t *)(VGA_BUFFER + (rows - 1) * cols * 2); ++i)
*i = *(i + cols / 2);
limit += cols / 2;
uint32_t fill = (color * 0x0100 + (uint8_t)' ') * 0x00010001;
for (uint32_t *i = limit - cols / 2; i < limit; ++i)
uint32_t fill = (color << 8) | (color << 24) | 0x00200020;
for (uint32_t *i = (uint32_t *)(VGA_BUFFER + (rows - 1) * cols * 2); i < (uint32_t *)(VGA_BUFFER + rows * cols * 2); ++i)
*i = fill;
}
void put_char(uint8_t ch) {
//send_byte(ch, COM2);
switch (ch) {
case '\b':
if (cursor_pos)
@ -89,12 +96,12 @@ void put_16(uint16_t n) {
void put_32_hex(uint32_t n) {
for (uint8_t i = 0; i < 4; ++i) {
put_char(n / 0xf0000000 + (n < 0xa0000000 ? (uint8_t)'0' : (uint8_t)'a' - 1));
put_char("0123456789abcdef"[n >> 28]);
n <<= 4;
}
put_char('_');
put_char('.');
for (uint8_t i = 0; i < 4; ++i) {
put_char(n / 0xf0000000 + (n < 0xa0000000 ? (uint8_t)'0' : (uint8_t)'a' - 1));
put_char("0123456789abcdef"[n >> 28]);
n <<= 4;
}
}

View file

@ -22,7 +22,13 @@ OF THIS SOFTWARE.
#ifndef VGA_H
#define VGA_H
#define put_debug(name, value) \
put_sz(name ": 0x"); \
put_32_hex(value); \
put_char('\n');
#define VGA_BUFFER ((uint8_t *)0x000b8000)
void clear(void);
void put_char(uint8_t ch);
void put_sz(uint8_t *s);
void put_16(uint16_t n);