Reorganized source tree
This commit is contained in:
248
src/x86/entry.S
Executable file
248
src/x86/entry.S
Executable file
@@ -0,0 +1,248 @@
|
||||
.section .multiboot
|
||||
.include "x86/multiboot2header.S"
|
||||
|
||||
.section .rodata
|
||||
|
||||
gdt:
|
||||
.long 0, 0
|
||||
.short 0xFFFF
|
||||
.short 0x0000
|
||||
.short 0x9A00
|
||||
.short 0x00CF
|
||||
.short 0xFFFF
|
||||
.short 0x0000
|
||||
.short 0x9200
|
||||
.short 0x00CF
|
||||
|
||||
gdt_info:
|
||||
.short 23
|
||||
.long gdt
|
||||
|
||||
.section .bss
|
||||
|
||||
.align 16
|
||||
stackBottom:
|
||||
.skip 8192
|
||||
stackTop:
|
||||
|
||||
.align 4096
|
||||
_tempPgDir:
|
||||
.skip 4096
|
||||
_tempIdentityMap:
|
||||
.skip 4096
|
||||
_tempPgTable:
|
||||
.skip 8192
|
||||
|
||||
_bootCmdLine:
|
||||
.skip 64
|
||||
|
||||
.align 64
|
||||
.global system_info
|
||||
system_info:
|
||||
.skip 16
|
||||
|
||||
.align 64
|
||||
.global memory_map
|
||||
memory_map:
|
||||
.skip 16 * 16
|
||||
|
||||
.section .text
|
||||
.global _start
|
||||
.type _start, @function
|
||||
_start:
|
||||
cmp $0x36d76289, %eax
|
||||
jne _err
|
||||
|
||||
movb $64, 0xB8000
|
||||
|
||||
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
|
||||
mov $_tempIdentityMap, %eax
|
||||
sub $BASE_DIFF, %eax
|
||||
or $3, %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
|
||||
mov $_tempPgTable, %eax
|
||||
sub $BASE_DIFF, %eax
|
||||
or $3, %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)
|
||||
|
||||
# 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
|
||||
|
||||
# Jump into mapped kernel binary
|
||||
lea 2f, %eax
|
||||
jmp *%eax
|
||||
2:
|
||||
# Delete PDE corresponding to identity map. We shouldn't need it anymore.
|
||||
movl $0, (_tempIdentityMap)
|
||||
|
||||
# Reload page tables
|
||||
mov %cr3, %eax
|
||||
mov %eax, %cr3
|
||||
|
||||
# Initialize stack
|
||||
mov $stackTop, %esp
|
||||
lgdt gdt_info
|
||||
|
||||
jmp $8, $.ldcs
|
||||
.ldcs:
|
||||
mov $16, %ax
|
||||
mov %ax, %ds
|
||||
mov %ax, %es
|
||||
mov %ax, %gs
|
||||
mov %ax, %fs
|
||||
mov %ax, %ss
|
||||
|
||||
mov $_bootCmdLine, %eax
|
||||
push %eax
|
||||
|
||||
# Call main function
|
||||
call main
|
||||
|
||||
_err:
|
||||
cli
|
||||
3: hlt
|
||||
jmp 3b
|
||||
|
||||
.size _start, . - _start
|
||||
21
src/x86/idt.S
Normal file
21
src/x86/idt.S
Normal file
@@ -0,0 +1,21 @@
|
||||
.section .bss
|
||||
|
||||
.align 8
|
||||
.global idt
|
||||
idt:
|
||||
.skip 8 * 256
|
||||
idt_end:
|
||||
|
||||
.section .rodata
|
||||
|
||||
.idt_info:
|
||||
.short idt_end - idt - 1
|
||||
.long idt
|
||||
|
||||
.section .text
|
||||
|
||||
.global _lidt
|
||||
.type _lidt, @function
|
||||
_lidt:
|
||||
|
||||
ret
|
||||
10
src/x86/idt.hpp
Normal file
10
src/x86/idt.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef IDT_H
|
||||
#define IDT_H
|
||||
|
||||
#include "interruptdescriptor.hpp"
|
||||
|
||||
extern kernel::InterruptDescriptor idt[256];
|
||||
|
||||
extern "C" void _lidt();
|
||||
|
||||
#endif
|
||||
63
src/x86/interruptdescriptor.cpp
Normal file
63
src/x86/interruptdescriptor.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "interruptdescriptor.hpp"
|
||||
|
||||
kernel::InterruptDescriptor::InterruptDescriptor()
|
||||
{
|
||||
this->m_offset1 = 0;
|
||||
this->m_selector = 0;
|
||||
this->m_zero = 0;
|
||||
this->m_type = 0;
|
||||
this->m_storage = 0;
|
||||
this->m_dpl = 0;
|
||||
this->m_present = 0;
|
||||
this->m_offset2 = 0;
|
||||
}
|
||||
|
||||
kernel::InterruptDescriptor::InterruptDescriptor(void* handler, Type type, unsigned int dpl)
|
||||
{
|
||||
uint32_t offset = (uint32_t) handler;
|
||||
this->m_offset1 = (uint16_t) offset;
|
||||
this->m_selector = 8;
|
||||
this->m_zero = 0;
|
||||
this->m_type = (uint16_t) type;
|
||||
this->m_storage = 0;
|
||||
this->m_dpl = dpl;
|
||||
this->m_present = 1;
|
||||
this->m_offset2 = offset >> 16;
|
||||
}
|
||||
|
||||
bool kernel::InterruptDescriptor::present()
|
||||
{
|
||||
return m_present == 1;
|
||||
}
|
||||
void kernel::InterruptDescriptor::present(bool present)
|
||||
{
|
||||
m_present = present ? 1 : 0;
|
||||
}
|
||||
|
||||
kernel::InterruptDescriptor::Type kernel::InterruptDescriptor::type()
|
||||
{
|
||||
return (Type) m_type;
|
||||
}
|
||||
|
||||
void kernel::InterruptDescriptor::type(kernel::InterruptDescriptor::Type type)
|
||||
{
|
||||
m_type = (unsigned int) type;
|
||||
}
|
||||
|
||||
unsigned int kernel::InterruptDescriptor::dpl()
|
||||
{
|
||||
return m_dpl;
|
||||
}
|
||||
|
||||
void kernel::InterruptDescriptor::dpl(unsigned int dpl)
|
||||
{
|
||||
m_dpl = dpl;
|
||||
}
|
||||
|
||||
void* kernel::InterruptDescriptor::operator=(void* rhs)
|
||||
{
|
||||
uint32_t offset = (uint32_t) rhs;
|
||||
m_offset1 = (uint16_t) offset;
|
||||
m_offset2 = (offset >> 16);
|
||||
return rhs;
|
||||
}
|
||||
55
src/x86/interruptdescriptor.hpp
Normal file
55
src/x86/interruptdescriptor.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef INTERRUPTDESCRIPTOR_H
|
||||
#define INTERRUPTDESCRIPTOR_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace kernel
|
||||
{
|
||||
|
||||
class InterruptDescriptor
|
||||
{
|
||||
public:
|
||||
|
||||
enum Type
|
||||
{
|
||||
TASK32 = 5,
|
||||
TRAP32 = 15,
|
||||
INT32 = 14,
|
||||
TRAP16 = 7,
|
||||
INT16 = 6
|
||||
};
|
||||
|
||||
InterruptDescriptor();
|
||||
|
||||
InterruptDescriptor(void* handler, Type type, unsigned int dpl);
|
||||
|
||||
bool present();
|
||||
|
||||
void present(bool present);
|
||||
|
||||
Type type();
|
||||
|
||||
void type(Type type);
|
||||
|
||||
unsigned int dpl();
|
||||
|
||||
void dpl(unsigned int dpl);
|
||||
|
||||
void* operator=(void* rhs);
|
||||
|
||||
private:
|
||||
|
||||
uint16_t m_offset1;
|
||||
uint16_t m_selector;
|
||||
uint16_t m_zero : 8;
|
||||
uint16_t m_type : 4;
|
||||
uint16_t m_storage : 1;
|
||||
uint16_t m_dpl : 2;
|
||||
uint16_t m_present : 1;
|
||||
uint16_t m_offset2;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
23
src/x86/interrupts.cpp
Normal file
23
src/x86/interrupts.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "../interrupts.hpp"
|
||||
#include "idt.hpp"
|
||||
#include "inthandlers.hpp"
|
||||
|
||||
kernel::Interrupts::Interrupts()
|
||||
{
|
||||
idt[0] = InterruptDescriptor((void*) &divisionByZero, InterruptDescriptor::INT32, 0);
|
||||
idt[8] = InterruptDescriptor((void*) &doubleFaultHandler, InterruptDescriptor::INT32, 0);
|
||||
idt[0x80] = InterruptDescriptor((void*) &syscallHandler, InterruptDescriptor::INT32, 0);
|
||||
// Load interrupt handlers
|
||||
// Configure PIC
|
||||
_lidt();
|
||||
}
|
||||
|
||||
inline void kernel::Interrupts::enable()
|
||||
{
|
||||
asm("sti");
|
||||
}
|
||||
|
||||
inline void kernel::Interrupts::disable()
|
||||
{
|
||||
asm("cli");
|
||||
}
|
||||
39
src/x86/inthandlers.cpp
Normal file
39
src/x86/inthandlers.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "inthandlers.hpp"
|
||||
|
||||
char* display = (char*) 0xC00B8000;
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void divisionByZero(void* frame)
|
||||
{
|
||||
*display = 'z';
|
||||
display += 2;
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void gpFaultHandler(void* frame, unsigned int error)
|
||||
{
|
||||
*display = 'a';
|
||||
display += 2;
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void pageFaultHandler(void* frame, unsigned int error)
|
||||
{
|
||||
*display = '0';
|
||||
display += 2;
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void doubleFaultHandler(void* frame, unsigned int error)
|
||||
{
|
||||
*display = '#';
|
||||
asm("hlt");
|
||||
}
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void syscallHandler(void* frame)
|
||||
{
|
||||
*display = 'z';
|
||||
display += 2;
|
||||
}
|
||||
|
||||
19
src/x86/inthandlers.hpp
Normal file
19
src/x86/inthandlers.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef INTHANDLERS_H
|
||||
#define INTHANDLERS_H
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void divisionByZero(void* frame);
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void gpFaultHandler(void* frame, unsigned int error);
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void pageFaultHandler(void* frame, unsigned int error);
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void doubleFaultHandler(void* frame, unsigned int error);
|
||||
|
||||
__attribute__ ((interrupt))
|
||||
void syscallHandler(void* frame);
|
||||
|
||||
#endif
|
||||
36
src/x86/linker.ld
Executable file
36
src/x86/linker.ld
Executable file
@@ -0,0 +1,36 @@
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0xFF900000;
|
||||
VIRTUAL_BASE = .;
|
||||
PHYSICAL_BASE = 0x100000;
|
||||
BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE;
|
||||
|
||||
.text BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.text)
|
||||
}
|
||||
|
||||
.rodata BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.rodata)
|
||||
}
|
||||
|
||||
.data BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
|
||||
.bss BLOCK(4K) : ALIGN(4K)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
}
|
||||
|
||||
LOAD_START = ADDR(.text) - (VIRTUAL_BASE - PHYSICAL_BASE);
|
||||
LOAD_END = ADDR(.data) + SIZEOF(.data) - (VIRTUAL_BASE - PHYSICAL_BASE);
|
||||
BSS_END = ADDR(.bss) + SIZEOF(.bss) - (VIRTUAL_BASE - PHYSICAL_BASE);
|
||||
IMAGE_SIZE = ((BSS_END - LOAD_START) + (4096 - ((BSS_END - LOAD_START) % 4096))) / 4096;
|
||||
}
|
||||
100
src/x86/mmap.cpp
Normal file
100
src/x86/mmap.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "../mmap.hpp"
|
||||
#include "pagetableentry.hpp"
|
||||
|
||||
int kernel::mmap(MemoryAllocator& allocator, void* start, size_t length, int flags)
|
||||
{
|
||||
if((size_t) start % 4096 != 0)
|
||||
return -1;
|
||||
PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000;
|
||||
PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000;
|
||||
size_t tableIndex = (size_t) start / 4096;
|
||||
for(int i = (int) length; i > 0; i -= 4096)
|
||||
{
|
||||
size_t directoryIndex = tableIndex / 1024;
|
||||
if(!pageDirectory[directoryIndex].getPresent())
|
||||
{
|
||||
physaddr_t newPT = allocator.allocate(4096);
|
||||
if(newPT == 0)
|
||||
return -1;
|
||||
pageDirectory[directoryIndex] = newPT;
|
||||
pageDirectory[directoryIndex].setPresent(true);
|
||||
pageDirectory[directoryIndex].setUsermode(false);
|
||||
pageDirectory[directoryIndex].setRw(true);
|
||||
}
|
||||
if(!pageTables[tableIndex].getPresent())
|
||||
{
|
||||
physaddr_t page = allocator.allocate(4096);
|
||||
pageTables[tableIndex] = page;
|
||||
pageTables[tableIndex].setPresent(true);
|
||||
pageTables[tableIndex].setUsermode(false);
|
||||
if(flags & MMAP_RW)
|
||||
pageTables[tableIndex].setRw(true);
|
||||
|
||||
}
|
||||
tableIndex++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kernel::munmap(MemoryAllocator& allocator, void* start, size_t length)
|
||||
{
|
||||
if((size_t) start % 4096 != 0)
|
||||
return -1;
|
||||
PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000;
|
||||
PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000;
|
||||
size_t tableIndex = (size_t) start / 4096;
|
||||
for(int i = (int) length; i > 0; i -= 4096)
|
||||
{
|
||||
size_t directoryIndex = tableIndex / 1024;
|
||||
if(pageDirectory[directoryIndex].getPresent())
|
||||
{
|
||||
pageTables[tableIndex] = 0;
|
||||
pageTables[tableIndex].setPresent(false);
|
||||
pageTables[tableIndex].setUsermode(false);
|
||||
pageTables[tableIndex].setRw(false);
|
||||
}
|
||||
tableIndex++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool kernel::isMapped(void* addr)
|
||||
{
|
||||
PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000;
|
||||
size_t tableIndex = (size_t) addr / 4096;
|
||||
size_t directoryIndex = tableIndex / 1024;
|
||||
if(pageDirectory[directoryIndex].getPresent())
|
||||
{
|
||||
PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000;
|
||||
return pageTables[tableIndex].getPresent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
physaddr_t kernel::getPhysicalAddress(void* addr)
|
||||
{
|
||||
PageTableEntry* pageTables = (PageTableEntry*) 0xFFC00000;
|
||||
size_t tableIndex = (size_t) addr / 4096;
|
||||
return pageTables[tableIndex].getPhysicalAddress() + ((size_t) addr & 0xFFF);
|
||||
}
|
||||
|
||||
int kernel::createAddressSpace(void* table)
|
||||
{
|
||||
if(((size_t) table & 0xFFF) != 0)
|
||||
return -1;
|
||||
PageTableEntry* pageDirectory = (PageTableEntry*) 0xFFFFF000;
|
||||
PageTableEntry* newDirectory = (PageTableEntry*) table;
|
||||
newDirectory[1022] = pageDirectory[1022];
|
||||
newDirectory[1023] = pageDirectory[1023];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kernel::loadAddressSpace(physaddr_t table)
|
||||
{
|
||||
if((table & 0xFFF) != 0)
|
||||
return -1;
|
||||
asm("mov %0, %%cr3"
|
||||
:
|
||||
: "r" (table));
|
||||
return 0;
|
||||
}
|
||||
94
src/x86/multiboot2header.S
Executable file
94
src/x86/multiboot2header.S
Executable file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Define constants for the multiboot header. See Multuboot 2 Specifications for details.
|
||||
*/
|
||||
.set align, 1<<0
|
||||
.set meminfo, 1<<1
|
||||
.set magic, 0xE85250D6
|
||||
.set arch, 0
|
||||
.set headerLength, _multibootHeaderEnd - _multibootHeaderStart
|
||||
.set checksum, -(magic + arch + headerLength)
|
||||
|
||||
.set tagNotOptional, 0
|
||||
|
||||
.set tagInfoRequestType, 1
|
||||
.set tagInfoRequestSize, _multibootInfoTagEnd - _multibootInfoTagStart
|
||||
.set requestBootCommand, 1
|
||||
.set requestBootLoaderName, 2
|
||||
.set requestBootModules, 3
|
||||
.set requestMemoryInfo, 4
|
||||
.set requestBootDevice, 5
|
||||
.set requestMemoryMap, 6
|
||||
|
||||
.set tagAddressType, 2
|
||||
.set tagAddressSize, 24
|
||||
.set tagAddressHeaderLocation, LOAD_START
|
||||
.set tagAddressLoadStart, LOAD_START
|
||||
.set tagAddressLoadEnd, LOAD_END
|
||||
.set tagAddressBSSEnd, BSS_END
|
||||
|
||||
.set tagEntryType, 3
|
||||
.set tagEntrySize, 12
|
||||
.set tagEntryAddress, _start - (0xFF900000 - 0x100000)
|
||||
|
||||
.set tagModuleAlignType, 6
|
||||
.set tagModuleAlignSize, 8
|
||||
|
||||
/*
|
||||
* Each multiboot tag must be 8-byte aligned, or GRUB will not be able to read the header.
|
||||
*/
|
||||
.align 8
|
||||
_multibootHeaderStart:
|
||||
|
||||
.long magic
|
||||
.long arch
|
||||
.long headerLength
|
||||
.long checksum
|
||||
|
||||
.align 8
|
||||
|
||||
_multibootInfoTagStart:
|
||||
.short tagInfoRequestType
|
||||
.short tagNotOptional
|
||||
.long tagInfoRequestSize
|
||||
.long requestBootCommand
|
||||
.long requestBootLoaderName
|
||||
.long requestBootModules
|
||||
.long requestMemoryInfo
|
||||
.long requestBootDevice
|
||||
.long requestMemoryMap
|
||||
_multibootInfoTagEnd:
|
||||
|
||||
.align 8
|
||||
|
||||
.short tagAddressType
|
||||
.short tagNotOptional
|
||||
.long tagAddressSize
|
||||
.long tagAddressHeaderLocation
|
||||
.long tagAddressLoadStart
|
||||
.long tagAddressLoadEnd
|
||||
.long tagAddressBSSEnd
|
||||
|
||||
.align 8
|
||||
|
||||
.short tagEntryType
|
||||
.short tagNotOptional
|
||||
.long tagEntrySize
|
||||
.long tagEntryAddress
|
||||
|
||||
.align 8
|
||||
|
||||
.short tagModuleAlignType
|
||||
.short tagNotOptional
|
||||
.long tagModuleAlignSize
|
||||
|
||||
.align 8
|
||||
|
||||
/*
|
||||
* Terminate list of multiboot header tags.
|
||||
* Ending tag has type = 0, flags = 0, size = 8
|
||||
*/
|
||||
.long 0
|
||||
.long 8
|
||||
|
||||
_multibootHeaderEnd:
|
||||
|
||||
141
src/x86/pagetableentry.cpp
Executable file
141
src/x86/pagetableentry.cpp
Executable file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* PageTableEntry.cpp
|
||||
*
|
||||
* Created on: May 22, 2019
|
||||
* Author: nathan
|
||||
*/
|
||||
|
||||
#include "pagetableentry.hpp"
|
||||
|
||||
namespace kernel {
|
||||
|
||||
static_assert(sizeof(PageTableEntry) == 4, "PTE structure is the wrong size!");
|
||||
|
||||
PageTableEntry::PageTableEntry() {
|
||||
this->present = 0;
|
||||
this->rw = 0;
|
||||
this->usermode = 0;
|
||||
this->writeThrough = 0;
|
||||
this->cacheDisable = 0;
|
||||
this->accessed = 0;
|
||||
this->dirty = 0;
|
||||
this->pat = 0;
|
||||
this->global = 0;
|
||||
this->shared = 0;
|
||||
this->ignored = 0;
|
||||
this->physicalAddress = 0;
|
||||
}
|
||||
|
||||
bool PageTableEntry::getAccessed() const {
|
||||
return accessed == 1;
|
||||
}
|
||||
|
||||
bool PageTableEntry::getCacheDisable() const
|
||||
{
|
||||
return cacheDisable == 1;
|
||||
}
|
||||
|
||||
void PageTableEntry::setCacheDisable(bool cacheDisable)
|
||||
{
|
||||
this->cacheDisable = cacheDisable ? 1 : 0;
|
||||
}
|
||||
|
||||
bool PageTableEntry::getDirty() const
|
||||
{
|
||||
return dirty == 1;
|
||||
}
|
||||
|
||||
bool PageTableEntry::getGlobal() const
|
||||
{
|
||||
return global == 1;
|
||||
}
|
||||
|
||||
void PageTableEntry::setGlobal(bool global)
|
||||
{
|
||||
this->global = global ? 1 : 0;
|
||||
}
|
||||
|
||||
bool PageTableEntry::getPat() const
|
||||
{
|
||||
return pat == 1;
|
||||
}
|
||||
|
||||
void PageTableEntry::setPat(bool pat)
|
||||
{
|
||||
this->pat = pat ? 1 : 0;
|
||||
}
|
||||
|
||||
physaddr_t PageTableEntry::getPhysicalAddress() const {
|
||||
physaddr_t physicalAddress = this->physicalAddress;
|
||||
return physicalAddress << 12;
|
||||
}
|
||||
|
||||
physaddr_t PageTableEntry::setPhysicalAddress(physaddr_t physicalAddress)
|
||||
{
|
||||
this->physicalAddress = physicalAddress >> 12;
|
||||
return this->physicalAddress << 12;
|
||||
}
|
||||
|
||||
bool PageTableEntry::getPresent() const
|
||||
{
|
||||
return present == 1;
|
||||
}
|
||||
|
||||
void PageTableEntry::setPresent(bool present)
|
||||
{
|
||||
this->present = present ? 1 : 0;
|
||||
}
|
||||
|
||||
bool PageTableEntry::getRw() const
|
||||
{
|
||||
return rw == 1;
|
||||
}
|
||||
|
||||
void PageTableEntry::setRw(bool rw)
|
||||
{
|
||||
this->rw = rw ? 1 : 0;
|
||||
}
|
||||
|
||||
bool PageTableEntry::getUsermode() const
|
||||
{
|
||||
return usermode == 1;
|
||||
}
|
||||
|
||||
void PageTableEntry::setUsermode(bool usermode)
|
||||
{
|
||||
this->usermode = usermode ? 1 : 0;
|
||||
}
|
||||
|
||||
bool PageTableEntry::getWriteThrough() const {
|
||||
return writeThrough == 1;
|
||||
}
|
||||
|
||||
bool PageTableEntry::getShared() const
|
||||
{
|
||||
return shared == 1;
|
||||
}
|
||||
|
||||
void PageTableEntry::setShared(bool shared)
|
||||
{
|
||||
this->shared = shared ? 1 : 0;
|
||||
}
|
||||
|
||||
void PageTableEntry::setWriteThrough(bool writeThrough)
|
||||
{
|
||||
this->writeThrough = writeThrough ? 1 : 0;
|
||||
}
|
||||
|
||||
physaddr_t PageTableEntry::operator=(physaddr_t rhs)
|
||||
{
|
||||
return setPhysicalAddress(rhs);
|
||||
}
|
||||
|
||||
PageTableEntry PageTableEntry::operator=(PageTableEntry rhs)
|
||||
{
|
||||
uint32_t* iThis = (uint32_t*) this;
|
||||
uint32_t* iThat = (uint32_t*) &rhs;
|
||||
*iThis = *iThat;
|
||||
return rhs;
|
||||
}
|
||||
|
||||
}
|
||||
52
src/x86/pagetableentry.hpp
Executable file
52
src/x86/pagetableentry.hpp
Executable file
@@ -0,0 +1,52 @@
|
||||
#ifndef SRC_PAGETABLEENTRY_H_
|
||||
#define SRC_PAGETABLEENTRY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../systypes.hpp"
|
||||
|
||||
namespace kernel {
|
||||
|
||||
class PageTableEntry {
|
||||
public:
|
||||
PageTableEntry();
|
||||
bool getAccessed() const;
|
||||
bool getCacheDisable() const;
|
||||
void setCacheDisable(bool cacheDisable);
|
||||
bool getDirty() const;
|
||||
bool getGlobal() const;
|
||||
void setGlobal(bool global);
|
||||
bool getPat() const;
|
||||
void setPat(bool pat);
|
||||
physaddr_t getPhysicalAddress() const;
|
||||
physaddr_t setPhysicalAddress(physaddr_t physicalAddress);
|
||||
bool getPresent() const;
|
||||
void setPresent(bool present);
|
||||
bool getRw() const;
|
||||
void setRw(bool rw);
|
||||
bool getShared() const;
|
||||
void setShared(bool shared);
|
||||
bool getUsermode() const;
|
||||
void setUsermode(bool usermode);
|
||||
bool getWriteThrough() const;
|
||||
void setWriteThrough(bool writeThrough);
|
||||
physaddr_t operator=(physaddr_t rhs);
|
||||
PageTableEntry operator=(PageTableEntry rhs);
|
||||
|
||||
private:
|
||||
uint32_t present : 1;
|
||||
uint32_t rw : 1;
|
||||
uint32_t usermode : 1;
|
||||
uint32_t writeThrough : 1;
|
||||
uint32_t cacheDisable : 1;
|
||||
uint32_t accessed : 1;
|
||||
uint32_t dirty : 1;
|
||||
uint32_t pat : 1;
|
||||
uint32_t global : 1;
|
||||
uint32_t shared : 1;
|
||||
uint32_t ignored : 2;
|
||||
uint32_t physicalAddress : 20;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
13
src/x86/pio.S
Normal file
13
src/x86/pio.S
Normal file
@@ -0,0 +1,13 @@
|
||||
.global outb
|
||||
outb:
|
||||
mov 4(%esp), %dx
|
||||
mov 8(%esp), %al
|
||||
out %al, %dx
|
||||
ret
|
||||
|
||||
.global inb
|
||||
inb:
|
||||
mov 4(%esp), %dx
|
||||
xor %eax, %eax
|
||||
in %dx, %al
|
||||
ret
|
||||
8
src/x86/pio.hpp
Normal file
8
src/x86/pio.hpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef PIO_H
|
||||
#define PIO_H
|
||||
|
||||
extern "C" void outb(short port, char data);
|
||||
|
||||
extern "C" char inb(short port);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user