Re-wrote boot code, moved to x86 folder
This commit is contained in:
203
src/x86/entry.S
203
src/x86/entry.S
@@ -143,181 +143,54 @@ memory_map:
|
||||
.global _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
# This platform reqires a Multiboot2 bootloader.
|
||||
cmp $0x36d76289, %eax
|
||||
jne _err
|
||||
jne .err
|
||||
|
||||
movb $64, 0xB8000
|
||||
# Initialize stack in physical address space
|
||||
mov $stackTop, %esp
|
||||
sub $BASE_DIFF, %esp
|
||||
|
||||
mov $system_info, %edi
|
||||
sub $BASE_DIFF, %edi
|
||||
add $8, %ebx
|
||||
|
||||
switch:
|
||||
mov (%ebx), %eax
|
||||
cmp $0, %eax
|
||||
je s_end
|
||||
cmp $1, %eax
|
||||
je tag_1
|
||||
cmp $3, %eax
|
||||
je tag_3
|
||||
cmp $4, %eax
|
||||
je tag_4
|
||||
cmp $6, %eax
|
||||
je tag_6
|
||||
cmp $21, %eax
|
||||
je tag_21
|
||||
jmp def
|
||||
|
||||
# Boot command line
|
||||
tag_1:
|
||||
mov 4(%ebx), %ecx
|
||||
sub $8, %ecx
|
||||
mov %ebx, %esi
|
||||
add $8, %esi
|
||||
mov $_bootCmdLine, %edi
|
||||
sub $BASE_DIFF, %edi
|
||||
rep movsb
|
||||
mov $system_info, %edi
|
||||
sub $BASE_DIFF, %edi
|
||||
jmp def
|
||||
|
||||
tag_3:
|
||||
mov 8(%ebx), %esi
|
||||
mov (%esi), %eax
|
||||
mov %al, (0xB8004)
|
||||
mov %ah, (0xB8006)
|
||||
shr $16, %eax
|
||||
mov %al, (0xB8008)
|
||||
mov %ah, (0xB800a)
|
||||
jmp def
|
||||
|
||||
# Basic memory info
|
||||
tag_4:
|
||||
mov 8(%ebx), %eax
|
||||
mov %eax, (%edi)
|
||||
mov 12(%ebx), %eax
|
||||
mov %eax, 4(%edi)
|
||||
jmp def
|
||||
|
||||
# Memory map
|
||||
tag_6:
|
||||
mov $memory_map, %esi
|
||||
sub $BASE_DIFF, %esi # set esi to point to the table in the kernel image
|
||||
mov 4(%ebx), %ecx
|
||||
sub $16, %ecx # set ecx to store the size of the table provided by the bootloader
|
||||
mov 8(%ebx), %edx # set edx to store the size of each table entry
|
||||
add $16, %ebx # move ebx up to the first entry
|
||||
1: mov (%ebx), %eax
|
||||
mov %eax, (%esi) # save the address of that region in memory
|
||||
mov 8(%ebx), %eax
|
||||
mov %eax, 4(%esi) # save the size of that region in memory
|
||||
mov 16(%ebx), %eax
|
||||
mov %eax, 8(%esi) # save the type of memory in that region
|
||||
add $12, %esi # move esi to the next entry in the kernel's array
|
||||
add %edx, %ebx # move ebx to the next entry in the bootloader's array
|
||||
sub %edx, %ecx # subtract the size of an entry from ecx.
|
||||
jnz 1b # loop if there are entries left
|
||||
mov $0, %eax
|
||||
mov %eax, (%esi)
|
||||
mov %eax, 4(%esi)
|
||||
mov %eax, 8(%esi)
|
||||
jmp switch
|
||||
|
||||
# Program image location
|
||||
tag_21:
|
||||
mov 8(%ebx), %eax
|
||||
mov %eax, 8(%edi)
|
||||
jmp def
|
||||
|
||||
def:
|
||||
mov 4(%ebx), %eax
|
||||
add $7, %eax
|
||||
and $0xFFFFFFF8, %eax
|
||||
add %eax, %ebx
|
||||
jmp switch
|
||||
s_end:
|
||||
|
||||
movb $64, 0xB8002
|
||||
|
||||
mov $0, %ecx
|
||||
1:
|
||||
# Generate a page table entry pointing to a page in the kernel binary
|
||||
mov %ecx, %eax
|
||||
mov $4096, %edx
|
||||
mul %edx
|
||||
or $3, %eax
|
||||
|
||||
# Load the address of the temporary page table and translate it to a physical address
|
||||
mov $_tempPgTable, %edi
|
||||
sub $BASE_DIFF, %edi
|
||||
|
||||
# Save the PTE into an entry in the temporary page table
|
||||
mov %eax, (%edi, %ecx, 4)
|
||||
|
||||
# Load the address of the identity map and translate it to a physical address
|
||||
mov $_tempIdentityMap, %edi
|
||||
sub $BASE_DIFF, %edi
|
||||
|
||||
# Save the PTE into an entry in the identity map
|
||||
mov %eax, (%edi, %ecx, 4)
|
||||
|
||||
# Increment count and loop
|
||||
inc %ecx
|
||||
mov $IMAGE_SIZE, %edx
|
||||
add $256, %edx
|
||||
cmp %edx, %ecx
|
||||
jne 1b
|
||||
|
||||
# Load the physical address of the identity map, and generate a PDE
|
||||
# Push physical address of identity map
|
||||
mov $_tempIdentityMap, %eax
|
||||
sub $BASE_DIFF, %eax
|
||||
or $3, %eax
|
||||
push %eax
|
||||
|
||||
# Load the physical address of the page directory
|
||||
mov $_tempPgDir, %edi
|
||||
sub $BASE_DIFF, %edi
|
||||
|
||||
# Save the PDE to the first element in the page directory
|
||||
mov %eax, (%edi)
|
||||
|
||||
# Load the physical address of the temporary page table, and generate a PDE
|
||||
# Push physical address of page table
|
||||
mov $_tempPgTable, %eax
|
||||
sub $BASE_DIFF, %eax
|
||||
or $3, %eax
|
||||
push %eax
|
||||
|
||||
# Save the PDE to the entry corresponding to 0xC0000000
|
||||
mov %eax, 4088(%edi)
|
||||
|
||||
# Set the last entry in the page directory to point to the page directory itself
|
||||
mov %edi, %eax
|
||||
or $3, %eax
|
||||
mov %eax, 4092(%edi)
|
||||
# Push physical address of page directory
|
||||
mov $_tempPgDir, %eax
|
||||
sub $BASE_DIFF, %eax
|
||||
push %eax
|
||||
|
||||
# Load the physical address of the page directory into CR3
|
||||
mov $_tempPgDir, %edi
|
||||
sub $BASE_DIFF, %edi
|
||||
mov %edi, %cr3
|
||||
|
||||
# Enable paging
|
||||
mov %cr0, %eax
|
||||
or $0x80010000, %eax
|
||||
mov %eax, %cr0
|
||||
# Load physical address of startPaging()
|
||||
mov $startPaging, %eax
|
||||
sub $BASE_DIFF, %eax
|
||||
|
||||
# Initialize paging
|
||||
call *%eax
|
||||
|
||||
# Jump into mapped kernel binary
|
||||
lea 2f, %eax
|
||||
lea 1f, %eax
|
||||
jmp *%eax
|
||||
2:
|
||||
1:
|
||||
# Delete PDE corresponding to identity map. We shouldn't need it anymore.
|
||||
movl $0, (_tempIdentityMap)
|
||||
|
||||
# Reload page tables
|
||||
# Flush TLB
|
||||
mov %cr3, %eax
|
||||
mov %eax, %cr3
|
||||
|
||||
# Initialize stack
|
||||
# Initialize stack in virtual memory
|
||||
mov $stackTop, %esp
|
||||
|
||||
# Load GPT
|
||||
lgdt gdt_info
|
||||
|
||||
# Load segment registers
|
||||
jmp $8, $.ldcs
|
||||
.ldcs:
|
||||
mov $16, %ax
|
||||
@@ -327,15 +200,27 @@ s_end:
|
||||
mov %ax, %fs
|
||||
mov %ax, %ss
|
||||
|
||||
mov $_bootCmdLine, %eax
|
||||
push %eax
|
||||
# Change EBX to point to the virtual address of the multiboot info
|
||||
# If the new pointer is out-of-bounds, error
|
||||
add $0xFF800000, %ebx
|
||||
cmp $0xFF800000, %ebx
|
||||
jl .err
|
||||
cmp $0xFFC00000, %ebx
|
||||
jge .err
|
||||
|
||||
# Call initialize(void* multibootInfo)
|
||||
push %ebx
|
||||
call initialize
|
||||
|
||||
# mov $_bootCmdLine, %eax
|
||||
# push %eax
|
||||
|
||||
# Call main function
|
||||
call main
|
||||
# call main
|
||||
|
||||
_err:
|
||||
.err:
|
||||
cli
|
||||
3: hlt
|
||||
jmp 3b
|
||||
2: hlt
|
||||
jmp 2b
|
||||
|
||||
.size _start, . - _start
|
||||
|
||||
77
src/x86/initialize.cpp
Normal file
77
src/x86/initialize.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include <stdint.h>
|
||||
#include "multiboot2.hpp"
|
||||
#include "tty.hpp"
|
||||
#include "../kernelstate.hpp"
|
||||
#include "../systeminfo.hpp"
|
||||
#include "../mmap.hpp"
|
||||
#include "../util.hpp"
|
||||
|
||||
using namespace kernel;
|
||||
|
||||
extern int _kernelEnd;
|
||||
|
||||
enum BootInfoType
|
||||
{
|
||||
Terminate = 0,
|
||||
CommandLine = 1,
|
||||
BootLoader = 2,
|
||||
Module = 3,
|
||||
MemoryInfo = 4,
|
||||
BootDevice = 5,
|
||||
MMap = 6,
|
||||
VBEInfo = 7,
|
||||
FramebufferInfo = 8,
|
||||
ELFSymbols = 9,
|
||||
APMTable = 10
|
||||
};
|
||||
|
||||
extern "C"
|
||||
int startPaging(uint32_t* directory, uint32_t* table, uint32_t* identityTable)
|
||||
{
|
||||
for(int i = 0; i < 1024; i++)
|
||||
{
|
||||
uint32_t pte = i * 4096 + 3;
|
||||
table[i] = pte;
|
||||
identityTable[i] = pte;
|
||||
}
|
||||
directory[0] = ((uint32_t) identityTable) + 3;
|
||||
directory[1022] = ((uint32_t) table) + 3;
|
||||
directory[1023] = ((uint32_t) directory) + 3;
|
||||
asm("mov %0, %%cr3"
|
||||
:
|
||||
: "r" (directory));
|
||||
asm("mov %%cr0, %%eax \n"
|
||||
"or $0x80010000, %%eax \n"
|
||||
"mov %%eax, %%cr0"
|
||||
:
|
||||
:
|
||||
: "eax");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int initialize(void* multibootInfo)
|
||||
{
|
||||
size_t heapSize = 0xFFC00000 - (size_t) &_kernelEnd;
|
||||
int log = 0;
|
||||
for(; heapSize > 1; log++)
|
||||
heapSize >>= 1;
|
||||
heapSize <<= log;
|
||||
new(&State::allocator) Allocator((void*) (0xFFC00000 - heapSize), heapSize, 64);
|
||||
Multiboot2Info bootInfo(multibootInfo);
|
||||
if(!bootInfo.isValid())
|
||||
return 1;
|
||||
bootInfo.getMemoryMap().insertEntry(0, 4 * 1024 * 1024, MemoryMap::UNAVAILABLE);
|
||||
new(&State::config) SystemInfo(bootInfo.getMemoryMap(), bootInfo.getCommandLine());
|
||||
TTY tty((char*) 0xFF8B8000);
|
||||
tty << "Type\t\tLocation\t\tSize\n";
|
||||
for(size_t i = 0; i < bootInfo.getMemoryMap().size() && bootInfo.getMemoryMap()[i].getSize() > 0; i++)
|
||||
{
|
||||
tty << (int) bootInfo.getMemoryMap()[i].getType() << "\t\t\t";
|
||||
tty << (void*) bootInfo.getMemoryMap()[i].getLocation() << "\t\t";
|
||||
tty << (int) bootInfo.getMemoryMap()[i].getSize() << "\n";
|
||||
}
|
||||
// TODO: Initialize page allocator
|
||||
// TODO: Initialize process queue, add entry for each module
|
||||
return 0;
|
||||
}
|
||||
@@ -2,7 +2,6 @@ ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
|
||||
. = 0xFF900000;
|
||||
VIRTUAL_BASE = .;
|
||||
PHYSICAL_BASE = 0x100000;
|
||||
|
||||
125
src/x86/tty.cpp
Normal file
125
src/x86/tty.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include <stdbool.h>
|
||||
#include "tty.hpp"
|
||||
|
||||
kernel::TTY::TTY(char* vga)
|
||||
{
|
||||
this->vga = vga;
|
||||
this->cursor = 0;
|
||||
this->width = 0;
|
||||
this->base = 10;
|
||||
}
|
||||
|
||||
kernel::TTY& kernel::TTY::operator<<(kernel::TTY::Format fmt)
|
||||
{
|
||||
switch(fmt)
|
||||
{
|
||||
case Binary:
|
||||
base = 2;
|
||||
break;
|
||||
case Decimal:
|
||||
base = 10;
|
||||
break;
|
||||
case Hex:
|
||||
base = 16;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
kernel::TTY& kernel::TTY::operator<<(const char* str)
|
||||
{
|
||||
return printString(str);
|
||||
}
|
||||
|
||||
kernel::TTY& kernel::TTY::operator<<(unsigned int n)
|
||||
{
|
||||
return printNumber(n, base, width);
|
||||
}
|
||||
|
||||
kernel::TTY& kernel::TTY::operator<<(int n)
|
||||
{
|
||||
return printNumber((unsigned int) n, base, width);
|
||||
}
|
||||
|
||||
kernel::TTY& kernel::TTY::operator<<(void* n)
|
||||
{
|
||||
return printNumber((unsigned int) n, 16, 8);
|
||||
}
|
||||
|
||||
kernel::TTY& kernel::TTY::operator<<(char c)
|
||||
{
|
||||
return putChar(c);
|
||||
}
|
||||
|
||||
void kernel::TTY::setWidth(size_t width)
|
||||
{
|
||||
this->width = width;
|
||||
}
|
||||
|
||||
size_t kernel::TTY::getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
void kernel::TTY::clear()
|
||||
{
|
||||
for(int i = 0; i < 80*25; i++)
|
||||
{
|
||||
vga[i * 2] = ' ';
|
||||
}
|
||||
cursor = 0;
|
||||
}
|
||||
|
||||
kernel::TTY& kernel::TTY::printNumber(unsigned int n, size_t base,
|
||||
size_t width)
|
||||
{
|
||||
const char* digits = "0123456789ABCDEF";
|
||||
char str[33];
|
||||
size_t i = 1;
|
||||
do
|
||||
{
|
||||
str[i] = digits[n % base];
|
||||
n /= base;
|
||||
i++;
|
||||
} while(n > 0);
|
||||
while(i <= width)
|
||||
{
|
||||
str[i] = '0';
|
||||
i++;
|
||||
}
|
||||
str[0] = '\0';
|
||||
for(char* s = str + (i - 1); *s; s--)
|
||||
{
|
||||
putChar(*s);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
kernel::TTY& kernel::TTY::printString(const char* str)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
putChar(*str);
|
||||
str++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
kernel::TTY& kernel::TTY::putChar(char c)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case '\n':
|
||||
cursor = (cursor + 80) - (cursor % 80);
|
||||
break;
|
||||
case '\t':
|
||||
cursor = (cursor + 4) - (cursor % 4);
|
||||
break;
|
||||
case '\r':
|
||||
cursor -= cursor % 160;
|
||||
break;
|
||||
default:
|
||||
vga[cursor * 2] = c;
|
||||
cursor++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
60
src/x86/tty.hpp
Normal file
60
src/x86/tty.hpp
Normal file
@@ -0,0 +1,60 @@
|
||||
#ifndef TTY_H_
|
||||
#define TTY_H_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace kernel
|
||||
{
|
||||
|
||||
class TTY
|
||||
{
|
||||
public:
|
||||
|
||||
enum Format
|
||||
{
|
||||
Binary,
|
||||
Decimal,
|
||||
Hex
|
||||
};
|
||||
|
||||
TTY(char* vga);
|
||||
|
||||
TTY& operator<<(Format fmt);
|
||||
|
||||
TTY& operator<<(const char* str);
|
||||
|
||||
TTY& operator<<(unsigned int n);
|
||||
|
||||
TTY& operator<<(int n);
|
||||
|
||||
TTY& operator<<(void* n);
|
||||
|
||||
TTY& operator<<(char c);
|
||||
|
||||
void setWidth(size_t width);
|
||||
|
||||
size_t getWidth();
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
|
||||
TTY& printNumber(unsigned int n, size_t base, size_t width);
|
||||
|
||||
TTY& printString(const char* str);
|
||||
|
||||
TTY& putChar(char c);
|
||||
|
||||
char* vga;
|
||||
|
||||
int cursor;
|
||||
|
||||
size_t width;
|
||||
|
||||
size_t base;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user