Squash commits for public release
This commit is contained in:
67
boot/x86/stage1/boot.s
Normal file
67
boot/x86/stage1/boot.s
Normal file
@@ -0,0 +1,67 @@
|
||||
[org 0x7c00]
|
||||
|
||||
KERNEL_OFFSET equ 0x1000
|
||||
KERNEL_SIZE equ 32 ; (KBytes) 32KB
|
||||
MEMORY_MAP_REGION equ 0xA00
|
||||
|
||||
mov [BOOT_DISK], dl ; saving boot disk
|
||||
|
||||
mov bp, 0x8000 ; stack init in 16bits
|
||||
mov sp, bp
|
||||
|
||||
mov bx, MSG_REAL_MODE
|
||||
call print_string
|
||||
|
||||
mov eax, 0
|
||||
mov es, ax
|
||||
mov di, MEMORY_MAP_REGION
|
||||
call bios_get_memory_map
|
||||
|
||||
call load_kernel
|
||||
call switch_to_pm
|
||||
jmp $
|
||||
|
||||
%include "boot/x86/stage1/utils16/print.s"
|
||||
%include "boot/x86/stage1/utils16/smm.s"
|
||||
%include "boot/x86/stage1/utils16/disk_load.s"
|
||||
%include "boot/x86/stage1/utils16/switch_to_pm.s"
|
||||
|
||||
%include "boot/x86/stage1/utils32/print.s"
|
||||
%include "boot/x86/stage1/utils32/gdt.s"
|
||||
|
||||
|
||||
[bits 16]
|
||||
load_kernel:
|
||||
mov bx, MSG_KERNEL_LOAD
|
||||
call print_string
|
||||
|
||||
mov bx, KERNEL_OFFSET
|
||||
mov dh, 50
|
||||
mov dl, [BOOT_DISK]
|
||||
call disk_load
|
||||
ret
|
||||
|
||||
[bits 32]
|
||||
begin_pm:
|
||||
mov ebx, MSG_PROT_MODE
|
||||
call print_string_pm
|
||||
mov eax, dword [memory_map_size]
|
||||
push eax
|
||||
mov eax, dword KERNEL_SIZE
|
||||
push eax
|
||||
push esp
|
||||
call KERNEL_OFFSET
|
||||
jmp $
|
||||
|
||||
MSG_REAL_MODE:
|
||||
db 'Starting real mode', 0
|
||||
MSG_PROT_MODE:
|
||||
db 'Switched to prot mode', 0
|
||||
MSG_KERNEL_LOAD:
|
||||
db ' Loading kernel from drive', 0
|
||||
|
||||
BOOT_DISK: db 0
|
||||
|
||||
times (510-($-$$)) db 0
|
||||
db 0x55
|
||||
db 0xaa
|
||||
23
boot/x86/stage1/utils16/disk_load.s
Normal file
23
boot/x86/stage1/utils16/disk_load.s
Normal file
@@ -0,0 +1,23 @@
|
||||
[bits 16]
|
||||
|
||||
disk_load:
|
||||
push dx
|
||||
mov ah, 0x02
|
||||
mov al, dh
|
||||
mov ch, 0x00
|
||||
mov dh, 0x00
|
||||
mov cl, 0x02
|
||||
|
||||
int 0x13
|
||||
|
||||
jc disk_error
|
||||
|
||||
pop dx
|
||||
cmp al, dh
|
||||
jne disk_error
|
||||
ret
|
||||
disk_error:
|
||||
mov bx, MSG_DISK_ERROR
|
||||
call print_string
|
||||
jmp $
|
||||
MSG_DISK_ERROR: db 'disk ERROR!', 0
|
||||
15
boot/x86/stage1/utils16/print.s
Normal file
15
boot/x86/stage1/utils16/print.s
Normal file
@@ -0,0 +1,15 @@
|
||||
[bits 16]
|
||||
|
||||
print_string:
|
||||
pusha
|
||||
mov ah, 0x0e
|
||||
print_string_cycle:
|
||||
cmp [bx], BYTE 0
|
||||
je print_string_end
|
||||
mov al, [bx]
|
||||
int 0x10
|
||||
add bx, 1
|
||||
jmp print_string_cycle
|
||||
print_string_end:
|
||||
popa
|
||||
ret
|
||||
55
boot/x86/stage1/utils16/smm.s
Normal file
55
boot/x86/stage1/utils16/smm.s
Normal file
@@ -0,0 +1,55 @@
|
||||
[bits 16]
|
||||
|
||||
memory_map_entry:
|
||||
base_address:
|
||||
dq 0x0
|
||||
length:
|
||||
dq 0x0
|
||||
type:
|
||||
dq 0x0
|
||||
acpi_null:
|
||||
dq 0x0
|
||||
memory_map_entry_end:
|
||||
|
||||
memory_map_size: dw 0
|
||||
|
||||
bios_get_memory_map:
|
||||
pushad
|
||||
xor ebx, ebx
|
||||
xor bp, bp
|
||||
mov edx, 'PAMS'
|
||||
mov eax, 0xe820
|
||||
mov ecx, 24
|
||||
int 0x15
|
||||
jc memory_map_error
|
||||
cmp eax, 'PAMS'
|
||||
jne memory_map_error
|
||||
test ebx, ebx
|
||||
je memory_map_error
|
||||
jmp memory_map_start
|
||||
memory_map_next:
|
||||
mov edx, 'PAMS'
|
||||
mov ecx, 24
|
||||
mov eax, 0xe820
|
||||
int 0x15
|
||||
memory_map_start:
|
||||
jcxz memory_map_skip_entry
|
||||
memory_map_common:
|
||||
mov ecx, [es:di + 8]
|
||||
test ecx, ecx
|
||||
jne memory_map_good_entry
|
||||
mov ecx, [es:di + 12]
|
||||
jecxz memory_map_skip_entry
|
||||
memory_map_good_entry:
|
||||
inc bp
|
||||
add di, 24
|
||||
memory_map_skip_entry:
|
||||
cmp ebx, 0
|
||||
jne memory_map_next
|
||||
jmp memory_map_done
|
||||
memory_map_error:
|
||||
stc
|
||||
memory_map_done:
|
||||
mov [memory_map_size], bp
|
||||
popad
|
||||
ret
|
||||
22
boot/x86/stage1/utils16/switch_to_pm.s
Normal file
22
boot/x86/stage1/utils16/switch_to_pm.s
Normal file
@@ -0,0 +1,22 @@
|
||||
[bits 16]
|
||||
switch_to_pm:
|
||||
cli ; turn off interupts
|
||||
lgdt [gdt_descriptor]
|
||||
mov eax, cr0
|
||||
or eax, 0x1
|
||||
mov cr0, eax
|
||||
call CODE_SEG:init_pm
|
||||
|
||||
[bits 32]
|
||||
init_pm:
|
||||
mov ax, DATA_SEG
|
||||
mov ds, ax
|
||||
mov ss, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
|
||||
mov ebp, 0x90000 ; stack's init
|
||||
mov esp, ebp
|
||||
|
||||
call begin_pm
|
||||
27
boot/x86/stage1/utils32/gdt.s
Normal file
27
boot/x86/stage1/utils32/gdt.s
Normal file
@@ -0,0 +1,27 @@
|
||||
gdt_begin:
|
||||
|
||||
gdt_null:
|
||||
dd 0x00
|
||||
dd 0x00
|
||||
gdt_code:
|
||||
dw 0xffff
|
||||
dw 0x0000
|
||||
db 0x0
|
||||
db 10011010b
|
||||
db 11001111b
|
||||
db 0x0
|
||||
gdt_data:
|
||||
dw 0xffff
|
||||
dw 0x0000
|
||||
db 0x0
|
||||
db 10010010b
|
||||
db 11001111b
|
||||
db 0x0
|
||||
gdt_end:
|
||||
|
||||
gdt_descriptor:
|
||||
dw gdt_end - gdt_begin - 1
|
||||
dd gdt_begin
|
||||
|
||||
CODE_SEG equ gdt_code - gdt_begin
|
||||
DATA_SEG equ gdt_data - gdt_begin
|
||||
22
boot/x86/stage1/utils32/print.s
Normal file
22
boot/x86/stage1/utils32/print.s
Normal file
@@ -0,0 +1,22 @@
|
||||
[bits 32]
|
||||
|
||||
VIDEO_MEMORY equ 0xb8000
|
||||
WHITE_ON_BLACK equ 0x0f
|
||||
|
||||
print_string_pm:
|
||||
pusha
|
||||
mov edx, VIDEO_MEMORY
|
||||
print_string_pm_cycle:
|
||||
cmp [ebx], BYTE 0
|
||||
je print_string_pm_end
|
||||
mov ah, WHITE_ON_BLACK
|
||||
mov al, [ebx]
|
||||
mov [edx], ax
|
||||
|
||||
add ebx, 1
|
||||
add edx, 2
|
||||
|
||||
jmp print_string_pm_cycle
|
||||
print_string_pm_end:
|
||||
popa
|
||||
ret
|
||||
24
boot/x86/stage2/config.h
Normal file
24
boot/x86/stage2/config.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef STAGE2_CONFIG
|
||||
#define STAGE2_CONFIG
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
#define KERNEL_BASE 0x100000
|
||||
|
||||
struct x86_memory_map {
|
||||
uint32_t startLo;
|
||||
uint32_t startHi;
|
||||
uint32_t sizeLo;
|
||||
uint32_t sizeHi;
|
||||
uint32_t type;
|
||||
uint32_t acpi_3_0;
|
||||
};
|
||||
typedef struct x86_memory_map x86_memory_map_t;
|
||||
|
||||
struct x86_mem_desc {
|
||||
uint32_t memory_map_size;
|
||||
uint32_t kernel_size;
|
||||
};
|
||||
typedef struct x86_mem_desc x86_mem_desc_t;
|
||||
|
||||
#endif // STAGE2_CONFIG
|
||||
135
boot/x86/stage2/drivers/ata.c
Normal file
135
boot/x86/stage2/drivers/ata.c
Normal file
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Ata Stage2 driver. This is a lite version, since it can work with
|
||||
* only one drive at time. The @active_ata_drive is a boot drive.
|
||||
*/
|
||||
|
||||
#include "ata.h"
|
||||
#include <libboot/log/log.h>
|
||||
|
||||
// #define DEBUG_ATA
|
||||
|
||||
ata_t active_ata_drive;
|
||||
|
||||
void init_ata(uint32_t port, char is_master)
|
||||
{
|
||||
active_ata_drive.is_master = is_master;
|
||||
active_ata_drive.data_port = port;
|
||||
active_ata_drive.error_port = port + 0x1;
|
||||
active_ata_drive.sector_count_port = port + 0x2;
|
||||
active_ata_drive.lba_lo_port = port + 0x3;
|
||||
active_ata_drive.lba_mid_port = port + 0x4;
|
||||
active_ata_drive.lba_hi_port = port + 0x5;
|
||||
active_ata_drive.device_port = port + 0x6;
|
||||
active_ata_drive.command_port = port + 0x7;
|
||||
active_ata_drive.control_port = port + 0x206;
|
||||
}
|
||||
|
||||
int indentify_ata_device(drive_desc_t* drive_desc)
|
||||
{
|
||||
port_write8(active_ata_drive.device_port, active_ata_drive.is_master ? 0xA0 : 0xB0);
|
||||
port_write8(active_ata_drive.sector_count_port, 0);
|
||||
port_write8(active_ata_drive.lba_lo_port, 0);
|
||||
port_write8(active_ata_drive.lba_mid_port, 0);
|
||||
port_write8(active_ata_drive.lba_hi_port, 0);
|
||||
port_write8(active_ata_drive.command_port, 0xEC);
|
||||
|
||||
// check the acceptance of a command
|
||||
uint8_t status = port_read8(active_ata_drive.command_port);
|
||||
if (status == 0x00) {
|
||||
// printf("Cmd isn't accepted");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// waiting for processing
|
||||
// while BSY is on
|
||||
while ((status & 0x80) == 0x80) {
|
||||
status = port_read8(active_ata_drive.command_port);
|
||||
}
|
||||
|
||||
// check if drive isn't ready to transer DRQ
|
||||
if ((status & 0x08) != 0x08) {
|
||||
// printf("Don't ready for transport");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// transfering 256 bytes of data
|
||||
for (int i = 0; i < 256; i++) {
|
||||
uint16_t data = port_read16(active_ata_drive.data_port);
|
||||
char* text = " \0";
|
||||
text[0] = (data >> 8) & 0xFF;
|
||||
text[1] = data & 0xFF;
|
||||
if (i == 1) {
|
||||
#ifdef DEBUG_ATA
|
||||
log("Logical cylindres %x", data);
|
||||
#endif
|
||||
}
|
||||
if (i == 3) {
|
||||
#ifdef DEBUG_ATA
|
||||
log("Logical heads %x", data);
|
||||
#endif
|
||||
}
|
||||
if (i == 6) {
|
||||
#ifdef DEBUG_ATA
|
||||
log("Logical sectors %x", data);
|
||||
#endif
|
||||
}
|
||||
if (i == 49) {
|
||||
if (((data >> 8) & 0x1) == 1) {
|
||||
#ifdef DEBUG_ATA
|
||||
log("Dma supported");
|
||||
#endif
|
||||
}
|
||||
if (((data >> 9) & 0x1) == 1) {
|
||||
#ifdef DEBUG_ATA
|
||||
log("Lba supported");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drive_desc->read = ata_read;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returning 2 head read bytes (used to get size of kernel)
|
||||
int ata_read(uint32_t sector, uint8_t* read_to)
|
||||
{
|
||||
uint8_t dev_config = 0xA0;
|
||||
// lba support
|
||||
dev_config |= (1 << 6);
|
||||
if (!active_ata_drive.is_master) {
|
||||
dev_config |= (1 << 4);
|
||||
}
|
||||
|
||||
port_write8(active_ata_drive.device_port, dev_config);
|
||||
port_write8(active_ata_drive.sector_count_port, 1);
|
||||
port_write8(active_ata_drive.lba_lo_port, sector & 0x000000FF);
|
||||
port_write8(active_ata_drive.lba_mid_port, (sector & 0x0000FF00) >> 8);
|
||||
port_write8(active_ata_drive.lba_hi_port, (sector & 0x00FF0000) >> 16);
|
||||
port_write8(active_ata_drive.error_port, 0);
|
||||
port_write8(active_ata_drive.command_port, 0x21);
|
||||
|
||||
// waiting for processing
|
||||
// while BSY is on and no Errors
|
||||
uint8_t status = port_read8(active_ata_drive.command_port);
|
||||
while (((status >> 7) & 1) == 1 && ((status >> 0) & 1) != 1) {
|
||||
status = port_read8(active_ata_drive.command_port);
|
||||
}
|
||||
|
||||
// check if drive isn't ready to transer DRQ
|
||||
if (((status >> 0) & 1) == 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((status >> 3) & 1) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
uint16_t data = port_read16(active_ata_drive.data_port);
|
||||
read_to[2 * i + 1] = (data >> 8) & 0xFF;
|
||||
read_to[2 * i] = data & 0xFF;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
25
boot/x86/stage2/drivers/ata.h
Normal file
25
boot/x86/stage2/drivers/ata.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef _BOOT_X86_STAGE2_DRIVERS_ATA_H
|
||||
#define _BOOT_X86_STAGE2_DRIVERS_ATA_H
|
||||
|
||||
#include "port.h"
|
||||
#include <libboot/abi/drivers.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
typedef struct { // LBA28 | LBA48
|
||||
uint32_t data_port; // 16bit | 16 bits
|
||||
uint32_t error_port; // 8 bit | 16 bits
|
||||
uint32_t sector_count_port; // 8 bit | 16 bits
|
||||
uint32_t lba_lo_port; // 8 bit | 16 bits
|
||||
uint32_t lba_mid_port; // 8 bit | 16 bits
|
||||
uint32_t lba_hi_port; // 8 bit | 16 bits
|
||||
uint32_t device_port; // 8 bit
|
||||
uint32_t command_port; // 8 bit
|
||||
uint32_t control_port; // 8 bit
|
||||
char is_master;
|
||||
} ata_t;
|
||||
|
||||
void init_ata(uint32_t port, char is_master);
|
||||
int indentify_ata_device(drive_desc_t* drive_desc);
|
||||
int ata_read(uint32_t sector, uint8_t* read_to);
|
||||
|
||||
#endif
|
||||
56
boot/x86/stage2/drivers/port.c
Normal file
56
boot/x86/stage2/drivers/port.c
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "port.h"
|
||||
|
||||
unsigned char port_read8(unsigned short port)
|
||||
{
|
||||
unsigned char result_data;
|
||||
asm volatile("inb %%dx, %%al"
|
||||
: "=a"(result_data)
|
||||
: "d"(port));
|
||||
return result_data;
|
||||
}
|
||||
|
||||
void port_write8(unsigned short port, unsigned char data)
|
||||
{
|
||||
asm volatile("outb %%al, %%dx"
|
||||
:
|
||||
: "a"(data), "d"(port));
|
||||
}
|
||||
|
||||
unsigned short port_read16(unsigned short port)
|
||||
{
|
||||
unsigned short result_data;
|
||||
asm volatile("inw %%dx, %%ax"
|
||||
: "=a"(result_data)
|
||||
: "d"(port));
|
||||
return result_data;
|
||||
}
|
||||
|
||||
void port_write16(unsigned short port, unsigned short data)
|
||||
{
|
||||
asm volatile("outw %%ax, %%dx"
|
||||
:
|
||||
: "a"(data), "d"(port));
|
||||
}
|
||||
|
||||
unsigned int port_read32(unsigned short port)
|
||||
{
|
||||
unsigned int result_data;
|
||||
asm volatile("inl %%dx, %%eax"
|
||||
: "=a"(result_data)
|
||||
: "d"(port));
|
||||
return result_data;
|
||||
}
|
||||
|
||||
void port_write32(unsigned short port, unsigned int data)
|
||||
{
|
||||
asm volatile("outl %%eax, %%dx"
|
||||
:
|
||||
: "a"(data), "d"(port));
|
||||
}
|
||||
|
||||
void port_wait_io()
|
||||
{
|
||||
asm volatile("out %%al, $0x80"
|
||||
:
|
||||
: "a"(0)); // writing to "unused" port
|
||||
}
|
||||
15
boot/x86/stage2/drivers/port.h
Normal file
15
boot/x86/stage2/drivers/port.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _BOOT_X86_STAGE2_DRIVERS_PORT_H
|
||||
#define _BOOT_X86_STAGE2_DRIVERS_PORT_H
|
||||
|
||||
unsigned char port_read8(unsigned short port);
|
||||
void port_write8(unsigned short port, unsigned char data);
|
||||
|
||||
unsigned short port_read16(unsigned short port);
|
||||
void port_write16(unsigned short port, unsigned short data);
|
||||
|
||||
unsigned int port_read32(unsigned short port);
|
||||
void port_write32(unsigned short port, unsigned int data);
|
||||
|
||||
void port_wait_io();
|
||||
|
||||
#endif // _BOOT_X86_STAGE2_DRIVERS_PORT_H
|
||||
36
boot/x86/stage2/drivers/uart.c
Normal file
36
boot/x86/stage2/drivers/uart.c
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "uart.h"
|
||||
#include "port.h"
|
||||
|
||||
static int _uart_setup_impl(int port)
|
||||
{
|
||||
port_write8(port + 1, 0x00);
|
||||
port_write8(port + 3, 0x80);
|
||||
port_write8(port + 0, 0x03);
|
||||
port_write8(port + 1, 0x00);
|
||||
port_write8(port + 3, 0x03);
|
||||
port_write8(port + 2, 0xC7);
|
||||
port_write8(port + 4, 0x0B);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart_init()
|
||||
{
|
||||
_uart_setup_impl(COM1);
|
||||
}
|
||||
|
||||
static inline bool _uart_is_free_in(int port)
|
||||
{
|
||||
return port_read8(port + 5) & 0x01;
|
||||
}
|
||||
|
||||
static inline bool _uart_is_free_out(int port)
|
||||
{
|
||||
return port_read8(port + 5) & 0x20;
|
||||
}
|
||||
|
||||
int uart_write(uint8_t data)
|
||||
{
|
||||
while (!_uart_is_free_out(COM1)) { }
|
||||
port_write8(COM1, data);
|
||||
return 0;
|
||||
}
|
||||
14
boot/x86/stage2/drivers/uart.h
Normal file
14
boot/x86/stage2/drivers/uart.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef _STAGE2_DRIVERS_X86_UART_H
|
||||
#define _STAGE2_DRIVERS_X86_UART_H
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
#define COM1 0x3F8
|
||||
#define COM2 0x2F8
|
||||
#define COM3 0x3E8
|
||||
#define COM4 0x2E8
|
||||
|
||||
void uart_init();
|
||||
int uart_write(uint8_t data);
|
||||
|
||||
#endif //_STAGE2_DRIVERS_X86_UART_H
|
||||
23
boot/x86/stage2/mem/pde.h
Normal file
23
boot/x86/stage2/mem/pde.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef _BOOT_X86_STAGE2_MEM_PDE_H
|
||||
#define _BOOT_X86_STAGE2_MEM_PDE_H
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
#define table_desc_t uint32_t
|
||||
#define pde_t uint32_t
|
||||
|
||||
enum TABLE_DESC_PAGE_FLAGS {
|
||||
TABLE_DESC_PRESENT = 0,
|
||||
TABLE_DESC_WRITABLE,
|
||||
TABLE_DESC_USER,
|
||||
TABLE_DESC_PWT,
|
||||
TABLE_DESC_PCD,
|
||||
TABLE_DESC_ACCESSED,
|
||||
TABLE_DESC_DIRTY,
|
||||
TABLE_DESC_4MB,
|
||||
TABLE_DESC_CPU_GLOBAL,
|
||||
TABLE_DESC_LV4_GLOBAL,
|
||||
TABLE_DESC_FRAME = 12
|
||||
};
|
||||
|
||||
#endif //_BOOT_X86_STAGE2_MEM_PDE_H
|
||||
23
boot/x86/stage2/mem/pte.h
Normal file
23
boot/x86/stage2/mem/pte.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef _BOOT_X86_STAGE2_MEM_PTE_H
|
||||
#define _BOOT_X86_STAGE2_MEM_PTE_H
|
||||
|
||||
#include <libboot/types.h>
|
||||
|
||||
#define page_desc_t uint32_t
|
||||
#define pte_t uint32_t
|
||||
|
||||
enum PAGE_DESC_PAGE_FLAGS {
|
||||
PAGE_DESC_PRESENT = 0,
|
||||
PAGE_DESC_WRITABLE,
|
||||
PAGE_DESC_USER,
|
||||
PAGE_DESC_WRITETHOUGH,
|
||||
PAGE_DESC_NOT_CACHEABLE,
|
||||
PAGE_DESC_ACCESSED,
|
||||
PAGE_DESC_DIRTY,
|
||||
PAGE_DESC_PAT,
|
||||
PAGE_DESC_CPU_GLOBAL,
|
||||
PAGE_DESC_LV4_GLOBAL,
|
||||
PAGE_DESC_FRAME = 12
|
||||
};
|
||||
|
||||
#endif //_BOOT_X86_STAGE2_MEM_PTE_H
|
||||
77
boot/x86/stage2/mem/vm.c
Normal file
77
boot/x86/stage2/mem/vm.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "vm.h"
|
||||
|
||||
int vm_setup()
|
||||
{
|
||||
ptable_t* table_0mb = (ptable_t*)0x9A000;
|
||||
ptable_t* table_0mbplus = (ptable_t*)0x98000;
|
||||
ptable_t* table_3gb = (ptable_t*)0x9B000;
|
||||
ptable_t* table_3gbplus = (ptable_t*)0x99000;
|
||||
ptable_t* table_stack = (ptable_t*)0x9C000;
|
||||
pdirectory_t* dir = (pdirectory_t*)0x9D000;
|
||||
|
||||
for (uint32_t phyz = 0, virt = 0, i = 0; i < 1024; phyz += VMM_PAGE_SIZE, virt += VMM_PAGE_SIZE, i++) {
|
||||
pte_t new_page = 0;
|
||||
new_page |= 3;
|
||||
new_page |= ((phyz / VMM_PAGE_SIZE) << 12);
|
||||
table_0mb->entities[i] = new_page;
|
||||
}
|
||||
|
||||
for (uint32_t phyz = 0x400000, virt = 0x400000, i = 0; i < 1024; phyz += VMM_PAGE_SIZE, virt += VMM_PAGE_SIZE, i++) {
|
||||
pte_t new_page = 0;
|
||||
new_page |= 3;
|
||||
new_page |= ((phyz / VMM_PAGE_SIZE) << 12);
|
||||
table_0mbplus->entities[i] = new_page;
|
||||
}
|
||||
|
||||
for (uint32_t phyz = 0x100000, virt = 0xc0000000, i = 0; i < 1024; phyz += VMM_PAGE_SIZE, virt += VMM_PAGE_SIZE, i++) {
|
||||
pte_t new_page = 0;
|
||||
new_page |= 3;
|
||||
new_page |= ((phyz / VMM_PAGE_SIZE) << 12);
|
||||
table_3gb->entities[i] = new_page;
|
||||
}
|
||||
|
||||
for (uint32_t phyz = 0x500000, virt = 0xc0400000, i = 0; i < 1024; phyz += VMM_PAGE_SIZE, virt += VMM_PAGE_SIZE, i++) {
|
||||
pte_t new_page = 0;
|
||||
new_page |= 3;
|
||||
new_page |= ((phyz / VMM_PAGE_SIZE) << 12);
|
||||
table_3gbplus->entities[i] = new_page;
|
||||
}
|
||||
|
||||
for (uint32_t phyz = 0x000000, virt = 0xffc00000, i = 0; i < 1024; phyz += VMM_PAGE_SIZE, virt += VMM_PAGE_SIZE, i++) {
|
||||
pte_t new_page = 0;
|
||||
new_page |= 3;
|
||||
new_page |= ((phyz / VMM_PAGE_SIZE) << 12);
|
||||
table_stack->entities[i] = new_page;
|
||||
}
|
||||
|
||||
uint8_t* dir_for_memset = (uint8_t*)dir;
|
||||
for (int i = 0; i < 1024; i++) {
|
||||
dir->entities[i] = 0;
|
||||
}
|
||||
|
||||
uint32_t table_0mb_int = (uint32_t)table_0mb;
|
||||
dir->entities[0] |= 3;
|
||||
dir->entities[0] |= ((table_0mb_int / VMM_PAGE_SIZE) << 12);
|
||||
|
||||
table_0mb_int = (uint32_t)table_0mbplus;
|
||||
dir->entities[1] |= 3;
|
||||
dir->entities[1] |= ((table_0mb_int / VMM_PAGE_SIZE) << 12);
|
||||
|
||||
uint32_t table_3gb_int = (uint32_t)table_3gb;
|
||||
dir->entities[768] |= 3;
|
||||
dir->entities[768] |= ((table_3gb_int / VMM_PAGE_SIZE) << 12);
|
||||
|
||||
table_3gb_int = (uint32_t)table_3gbplus;
|
||||
dir->entities[769] |= 3;
|
||||
dir->entities[769] |= ((table_3gb_int / VMM_PAGE_SIZE) << 12);
|
||||
|
||||
uint32_t table_stack_int = (uint32_t)table_stack;
|
||||
dir->entities[1023] |= 3;
|
||||
dir->entities[1023] |= ((table_stack_int / VMM_PAGE_SIZE) << 12);
|
||||
|
||||
asm volatile("mov %%eax, %%cr3"
|
||||
:
|
||||
: "a"(dir));
|
||||
|
||||
return 0;
|
||||
}
|
||||
28
boot/x86/stage2/mem/vm.h
Normal file
28
boot/x86/stage2/mem/vm.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _BOOT_X86_STAGE2_MEM_VM_H
|
||||
#define _BOOT_X86_STAGE2_MEM_VM_H
|
||||
|
||||
#include "pde.h"
|
||||
#include "pte.h"
|
||||
#include <libboot/types.h>
|
||||
|
||||
#define VMM_LV0_ENTITY_COUNT (1024)
|
||||
#define VMM_LV1_ENTITY_COUNT (1024)
|
||||
#define VMM_PAGE_SIZE (4096)
|
||||
|
||||
enum VMM_ERR_CODES {
|
||||
VMM_ERR_PDIR,
|
||||
VMM_ERR_NO_SPACE,
|
||||
VMM_ERR_BAD_ADDR,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
page_desc_t entities[VMM_LV0_ENTITY_COUNT];
|
||||
} ptable_t;
|
||||
|
||||
typedef struct pdirectory {
|
||||
table_desc_t entities[VMM_LV1_ENTITY_COUNT];
|
||||
} pdirectory_t;
|
||||
|
||||
int vm_setup();
|
||||
|
||||
#endif // _BOOT_X86_STAGE2_MEM_VM_H
|
||||
156
boot/x86/stage2/stage2.c
Normal file
156
boot/x86/stage2/stage2.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Stage2 is used to load main kernel.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "drivers/ata.h"
|
||||
#include "drivers/uart.h"
|
||||
#include "mem/vm.h"
|
||||
#include <libboot/abi/drivers.h>
|
||||
#include <libboot/abi/memory.h>
|
||||
#include <libboot/crypto/validate.h>
|
||||
#include <libboot/elf/elf_lite.h>
|
||||
#include <libboot/fs/ext2_lite.h>
|
||||
#include <libboot/log/log.h>
|
||||
#include <libboot/mem/alloc.h>
|
||||
#include <libboot/mem/mem.h>
|
||||
#include <libboot/types.h>
|
||||
|
||||
// #define DEBUG_BOOT
|
||||
#define KERNEL_PATH "/boot/kernel.bin"
|
||||
#define LAUNCH_SERVER_PATH "/System/launch_server"
|
||||
|
||||
static boot_args_t boot_args;
|
||||
static size_t kernel_vaddr = 0;
|
||||
static size_t kernel_paddr = 0;
|
||||
static size_t kernel_size = 0;
|
||||
|
||||
static void alloc_init(x86_mem_desc_t* mem_desc)
|
||||
{
|
||||
// TODO: We use manual layouting in this bootloader. Thus
|
||||
// all addresses are hardcoded, no need to use allocator at all.
|
||||
}
|
||||
|
||||
static memory_boot_desc_t memory_boot_desc_init(x86_mem_desc_t* mem_desc)
|
||||
{
|
||||
char dummy_data = 0x0;
|
||||
size_t ram_last_addr = 0x0;
|
||||
size_t next_id = 0;
|
||||
memory_layout_t* mem_layout_paddr = copy_after_kernel(kernel_paddr, &dummy_data, sizeof(dummy_data), &kernel_size, VMM_PAGE_SIZE);
|
||||
x86_memory_map_t* memory_map = (x86_memory_map_t*)0xA00;
|
||||
|
||||
for (int i = 0; i < mem_desc->memory_map_size; i++) {
|
||||
if (memory_map[i].type == 0x2) {
|
||||
// The region is marked as reserved, removing it.
|
||||
mem_layout_paddr[next_id].base = memory_map[i].startLo;
|
||||
mem_layout_paddr[next_id].size = memory_map[i].sizeLo;
|
||||
mem_layout_paddr[next_id].flags = 0;
|
||||
next_id++;
|
||||
} else {
|
||||
ram_last_addr = max(ram_last_addr, memory_map[i].startLo + memory_map[i].sizeLo);
|
||||
}
|
||||
}
|
||||
mem_layout_paddr[next_id].flags = MEMORY_LAYOUT_FLAG_TERMINATE;
|
||||
memory_layout_t* mem_layout_vaddr = paddr_to_vaddr(mem_layout_paddr, kernel_paddr, kernel_vaddr);
|
||||
|
||||
memory_boot_desc_t res;
|
||||
res.ram_base = 0x0;
|
||||
res.ram_size = ram_last_addr;
|
||||
res.reserved_areas = mem_layout_vaddr;
|
||||
return res;
|
||||
}
|
||||
|
||||
int prepare_boot_disk(drive_desc_t* drive_desc)
|
||||
{
|
||||
init_ata(0x1F0, 1);
|
||||
if (indentify_ata_device(drive_desc) == 0) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int prepare_fs(drive_desc_t* drive_desc, fs_desc_t* fs_desc)
|
||||
{
|
||||
if (ext2_lite_init(drive_desc, fs_desc) == 0) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int validate_kernel(drive_desc_t* drive_desc, fs_desc_t* fs_desc)
|
||||
{
|
||||
log("Validating Kernel...");
|
||||
if (!validate_elf(KERNEL_PATH, drive_desc, fs_desc)) {
|
||||
log("Can't validate kernel");
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
if (!validate_elf(LAUNCH_SERVER_PATH, drive_desc, fs_desc)) {
|
||||
log("Can't validate launch_server");
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* bootdesc_ptr;
|
||||
void load_kernel(drive_desc_t* drive_desc, fs_desc_t* fs_desc, x86_mem_desc_t* mem_desc)
|
||||
{
|
||||
int res = elf_load_kernel(drive_desc, fs_desc, KERNEL_PATH, &kernel_vaddr, &kernel_paddr, &kernel_size);
|
||||
kernel_size = align_size(kernel_size, VMM_PAGE_SIZE);
|
||||
|
||||
size_t kernel_data_size = kernel_size + align_size(sizeof(boot_args_t), VMM_PAGE_SIZE) + VMM_PAGE_SIZE;
|
||||
|
||||
boot_args_t boot_args;
|
||||
boot_args.vaddr = kernel_vaddr;
|
||||
boot_args.paddr = kernel_paddr;
|
||||
boot_args.kernel_data_size = kernel_data_size;
|
||||
boot_args.devtree = NULL;
|
||||
boot_args.mem_boot_desc = memory_boot_desc_init(mem_desc);
|
||||
memcpy(boot_args.init_process, LAUNCH_SERVER_PATH, sizeof(LAUNCH_SERVER_PATH));
|
||||
|
||||
bootdesc_ptr = paddr_to_vaddr(copy_after_kernel(kernel_paddr, &boot_args, sizeof(boot_args), &kernel_size, VMM_PAGE_SIZE), kernel_paddr, kernel_vaddr);
|
||||
}
|
||||
|
||||
void stage2(x86_mem_desc_t* mem_desc)
|
||||
{
|
||||
uart_init();
|
||||
log_init(uart_write);
|
||||
alloc_init(mem_desc);
|
||||
|
||||
#ifdef DEBUG_BOOT
|
||||
log("STAGE2");
|
||||
#endif
|
||||
drive_desc_t drive_desc;
|
||||
fs_desc_t fs_desc;
|
||||
|
||||
if (prepare_boot_disk(&drive_desc) != 0) {
|
||||
#ifdef DEBUG_BOOT
|
||||
log("STAGE2");
|
||||
#endif
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
if (prepare_fs(&drive_desc, &fs_desc) != 0) {
|
||||
#ifdef DEBUG_BOOT
|
||||
log("STAGE2");
|
||||
#endif
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
validate_kernel(&drive_desc, &fs_desc);
|
||||
load_kernel(&drive_desc, &fs_desc, mem_desc);
|
||||
vm_setup();
|
||||
|
||||
// enabling paging
|
||||
asm volatile("mov %cr0, %eax");
|
||||
asm volatile("or $0x80000000, %eax");
|
||||
asm volatile("mov %eax, %cr0");
|
||||
|
||||
asm volatile("push %0"
|
||||
:
|
||||
: "r"(bootdesc_ptr));
|
||||
asm volatile("mov $0xc0000000, %eax");
|
||||
asm volatile("call *%eax");
|
||||
while (1) { }
|
||||
}
|
||||
12
boot/x86/stage2/stage2_entry.s
Normal file
12
boot/x86/stage2/stage2_entry.s
Normal file
@@ -0,0 +1,12 @@
|
||||
section .xos_boot_text
|
||||
|
||||
[bits 32]
|
||||
extern stage2
|
||||
extern STACK_PHYZ_TOP
|
||||
global _start
|
||||
_start:
|
||||
mov eax, esp
|
||||
mov esp, STACK_PHYZ_TOP
|
||||
push dword [eax+4]
|
||||
call stage2
|
||||
jmp $
|
||||
Reference in New Issue
Block a user