Compare commits
10 Commits
87c79f50be
...
ffebc6de45
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffebc6de45 | ||
|
|
68458ffca5 | ||
|
|
c364f7d019 | ||
|
|
8a81bb0c87 | ||
|
|
3e54b53f4b | ||
|
|
f1c055db2a | ||
|
|
c062a6fb34 | ||
|
|
9fd2d0ca6d | ||
|
|
a9b25c5b9e | ||
|
|
d15609e5c0 |
@@ -1,67 +1,8 @@
|
|||||||
#include "console.h"
|
#include "console.h"
|
||||||
#include "multiboot2.h"
|
#include "pmm.h"
|
||||||
|
|
||||||
#include <def.h>
|
// We are now in long mode with kernel pages and vga buffer identity mapped
|
||||||
#include "console.h"
|
void x86_64_main() {
|
||||||
#include "multiboot2.h"
|
console_clear();
|
||||||
#include "panic.h"
|
pmm_init();
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
static void *multiboot_find_tag(uptr multiboot_info, u32 type) {
|
|
||||||
uptr next = multiboot_info + 8;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
multiboot_tag *tag = (multiboot_tag*)next;
|
|
||||||
|
|
||||||
if (tag->type == MULTIBOOT_TAG_TYPE_END) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tag->type == type) {
|
|
||||||
return tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
next = align(next + tag->size, MULTIBOOT_TAG_ALIGN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_REGIONS 64
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u64 base_address;
|
|
||||||
u64 length;
|
|
||||||
} region;
|
|
||||||
|
|
||||||
extern uptr kernel_start;
|
|
||||||
extern uptr kernel_end;
|
|
||||||
|
|
||||||
static region regions[MAX_REGIONS] = {0};
|
|
||||||
static size_t region_count = 0;
|
|
||||||
|
|
||||||
static void find_memory_regions(uptr multiboot_info) {
|
|
||||||
multiboot_tag_mmap *tag = multiboot_find_tag(multiboot_info, MULTIBOOT_TAG_TYPE_MMAP);
|
|
||||||
if (tag == NULL) {
|
|
||||||
boot_panic("Multiboot did not provide mmap tag");
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 entry_count = (tag->size - 16) / tag->entry_size;
|
|
||||||
u8 *entry_ptr = (u8*)tag->entries;
|
|
||||||
|
|
||||||
for (u32 i = 0; i < entry_count; ++i) {
|
|
||||||
multiboot_mmap_entry *entry = (multiboot_mmap_entry*)entry_ptr;
|
|
||||||
|
|
||||||
if (entry->type == MULTIBOOT_MEMORY_AVAILABLE) {
|
|
||||||
if (region_count >= MAX_REGIONS) {
|
|
||||||
boot_panic("Too many memory regions");
|
|
||||||
}
|
|
||||||
|
|
||||||
regions[region_count++] = (region){ entry->base_address, entry->length };
|
|
||||||
}
|
|
||||||
|
|
||||||
entry_ptr += tag->entry_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void kmain(uptr multiboot_info) {
|
|
||||||
find_memory_regions(multiboot_info);
|
|
||||||
}
|
}
|
||||||
31
src/boot/multiboot2.c
Normal file
31
src/boot/multiboot2.c
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include "multiboot2.h"
|
||||||
|
#include "symbols.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
// [size:4][reserved:4][data:N]
|
||||||
|
#define INFO_DATA_OFFSET 8
|
||||||
|
|
||||||
|
#define TAG_TYPE_OFFSET 0
|
||||||
|
#define TAG_SIZE_OFFSET 4
|
||||||
|
|
||||||
|
void *multiboot_get_tag(u32 type) {
|
||||||
|
uptr current = get_multiboot_info() + INFO_DATA_OFFSET;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
u32 tag_type = *(u32*)(current + TAG_TYPE_OFFSET);
|
||||||
|
u32 tag_size = *(u32*)(current + TAG_SIZE_OFFSET);
|
||||||
|
|
||||||
|
if (tag_type == MULTIBOOT_TAG_TYPE_END) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag_type == type) {
|
||||||
|
return (void*)current;
|
||||||
|
}
|
||||||
|
|
||||||
|
// note(nub31): Each tag is aligned to 8 bytes
|
||||||
|
current = ALIGN_UP(current + tag_size, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -19,9 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define MULTIBOOT_BOOTLOADER_MAGIC 0x36d76289
|
#include <def.h>
|
||||||
|
|
||||||
#define MULTIBOOT_TAG_ALIGN 8
|
|
||||||
|
|
||||||
#define MULTIBOOT_TAG_TYPE_END 0
|
#define MULTIBOOT_TAG_TYPE_END 0
|
||||||
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
|
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
|
||||||
@@ -44,30 +42,19 @@
|
|||||||
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
|
||||||
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
|
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
|
||||||
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
|
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
|
||||||
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDRESS 21
|
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u8 red;
|
|
||||||
u8 green;
|
|
||||||
u8 blue;
|
|
||||||
} multiboot_color;
|
|
||||||
|
|
||||||
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
|
||||||
#define MULTIBOOT_MEMORY_RESERVED 2
|
|
||||||
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
|
||||||
#define MULTIBOOT_MEMORY_NVS 4
|
|
||||||
#define MULTIBOOT_MEMORY_BADRAM 5
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 size;
|
u32 size;
|
||||||
} multiboot_tag;
|
char cmdline[0];
|
||||||
|
} multiboot_tag_cmdline;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 size;
|
u32 size;
|
||||||
char string[0];
|
char bootloader_name[0];
|
||||||
} multiboot_tag_string;
|
} multiboot_tag_bootloader_name;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 type;
|
u32 type;
|
||||||
@@ -92,8 +79,14 @@ typedef struct {
|
|||||||
u32 sub_partition;
|
u32 sub_partition;
|
||||||
} multiboot_tag_bootdev;
|
} multiboot_tag_bootdev;
|
||||||
|
|
||||||
|
#define MULTIBOOT_MEMORY_AVAILABLE 1
|
||||||
|
#define MULTIBOOT_MEMORY_RESERVED 2
|
||||||
|
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
|
||||||
|
#define MULTIBOOT_MEMORY_NVS 4
|
||||||
|
#define MULTIBOOT_MEMORY_BADRAM 5
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u64 base_address;
|
u64 base_addr;
|
||||||
u64 length;
|
u64 length;
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 reserved;
|
u32 reserved;
|
||||||
@@ -124,10 +117,16 @@ typedef struct {
|
|||||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
|
||||||
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
|
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 red;
|
||||||
|
u8 green;
|
||||||
|
u8 blue;
|
||||||
|
} multiboot_color;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 size;
|
u32 size;
|
||||||
u64 framebuffer_address;
|
u64 framebuffer_addr;
|
||||||
u32 framebuffer_pitch;
|
u32 framebuffer_pitch;
|
||||||
u32 framebuffer_width;
|
u32 framebuffer_width;
|
||||||
u32 framebuffer_height;
|
u32 framebuffer_height;
|
||||||
@@ -199,13 +198,13 @@ typedef struct {
|
|||||||
u32 type;
|
u32 type;
|
||||||
u32 size;
|
u32 size;
|
||||||
u8 rsdp[0];
|
u8 rsdp[0];
|
||||||
} multiboot_tag_old_acpi;
|
} multiboot_tag_acpi_old;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 size;
|
u32 size;
|
||||||
u8 rsdp[0];
|
u8 rsdp[0];
|
||||||
} multiboot_tag_new_acpi;
|
} multiboot_tag_acpi_new;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 type;
|
u32 type;
|
||||||
@@ -236,5 +235,95 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 size;
|
u32 size;
|
||||||
u32 load_base_address;
|
u32 load_base_addr;
|
||||||
} multiboot_tag_load_base_address;
|
} multiboot_tag_load_base_addr;
|
||||||
|
|
||||||
|
void *multiboot_get_tag(u32 type);
|
||||||
|
|
||||||
|
static inline multiboot_tag_cmdline *multiboot_get_cmdline() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_CMDLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_bootloader_name *multiboot_get_bootloader_name() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_module *multiboot_get_module() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_basic_meminfo *multiboot_get_basic_meminfo() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_BASIC_MEMINFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_bootdev *multiboot_get_bootdev() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_BOOTDEV);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_mmap *multiboot_get_mmap() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_MMAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t get_mmap_entry_count(multiboot_tag_mmap *mmap) {
|
||||||
|
return (mmap->size - 16) / mmap->entry_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_vbe *multiboot_get_vbe() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_VBE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_framebuffer *multiboot_get_framebuffer() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_FRAMEBUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_elf_sections *multiboot_get_elf_sections() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_ELF_SECTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_apm *multiboot_get_apm() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_APM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_efi32 *multiboot_get_efi32() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_EFI32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_efi64 *multiboot_get_efi64() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_EFI64);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_smbios *multiboot_get_smbios() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_SMBIOS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_acpi_old *multiboot_get_acpi_old() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_ACPI_OLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_acpi_new *multiboot_get_acpi_new() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_ACPI_NEW);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_network *multiboot_get_network() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_NETWORK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_efi_mmap *multiboot_get_efi_mmap() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_EFI_MMAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool multiboot_get_efi_bs() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_EFI_BS) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_efi32_ih *multiboot_get_efi32_ih() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_EFI32_IH);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_efi64_ih *multiboot_get_efi64_ih() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_EFI64_IH);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline multiboot_tag_load_base_addr *multiboot_get_load_base_addr() {
|
||||||
|
return multiboot_get_tag(MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR);
|
||||||
|
}
|
||||||
|
|||||||
116
src/boot/pmm.c
Normal file
116
src/boot/pmm.c
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
#include "pmm.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "panic.h"
|
||||||
|
#include "multiboot2.h"
|
||||||
|
#include "symbols.h"
|
||||||
|
#include <def.h>
|
||||||
|
|
||||||
|
#define PAGE_SIZE 4096
|
||||||
|
#define MAX_PHYS_MEM GiB(128)
|
||||||
|
#define MAX_PAGES (MAX_PHYS_MEM / PAGE_SIZE)
|
||||||
|
#define BITMAP_SIZE ((MAX_PAGES + 63) / 64)
|
||||||
|
|
||||||
|
static u64 pmm_bitmap[BITMAP_SIZE];
|
||||||
|
|
||||||
|
static inline void bitmap_set(size_t bit) {
|
||||||
|
pmm_bitmap[bit / 64] |= (1ULL << (bit % 64));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bitmap_clear(size_t bit) {
|
||||||
|
pmm_bitmap[bit / 64] &= ~(1ULL << (bit % 64));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int bitmap_test(size_t bit) {
|
||||||
|
return pmm_bitmap[bit / 64] & (1ULL << (bit % 64));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t to_page(uptr addr) {
|
||||||
|
if (addr % PAGE_SIZE != 0) {
|
||||||
|
boot_panic("Address is not page aligned");
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr / PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uptr to_addr(size_t page) {
|
||||||
|
return page * PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_range(size_t start_page, size_t end_page) {
|
||||||
|
if (start_page >= MAX_PAGES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end_page > MAX_PAGES) {
|
||||||
|
end_page = MAX_PAGES;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = start_page; j < end_page; ++j) {
|
||||||
|
bitmap_clear(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_range(size_t start_page, size_t end_page) {
|
||||||
|
if (start_page >= MAX_PAGES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end_page > MAX_PAGES) {
|
||||||
|
end_page = MAX_PAGES;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = start_page; j < end_page; ++j) {
|
||||||
|
bitmap_set(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_init() {
|
||||||
|
for (size_t i = 0; i < BITMAP_SIZE; i++) {
|
||||||
|
pmm_bitmap[i] = U64_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiboot_tag_mmap *mmap = multiboot_get_mmap();
|
||||||
|
if (mmap == NULL) {
|
||||||
|
boot_panic("No memory map found");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < get_mmap_entry_count(mmap); ++i) {
|
||||||
|
multiboot_mmap_entry entry = mmap->entries[i];
|
||||||
|
if (entry.type == MULTIBOOT_MEMORY_AVAILABLE) {
|
||||||
|
size_t start_page = to_page(ALIGN_DOWN(entry.base_addr, PAGE_SIZE));
|
||||||
|
size_t end_page = to_page(ALIGN_UP(entry.base_addr + entry.length, PAGE_SIZE));
|
||||||
|
|
||||||
|
clear_range(start_page, end_page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t start_page = to_page(ALIGN_DOWN(get_kernel_start(), PAGE_SIZE));
|
||||||
|
size_t end_page = to_page(ALIGN_UP(get_kernel_end(), PAGE_SIZE));
|
||||||
|
|
||||||
|
set_range(start_page, end_page);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pmm_alloc_page() {
|
||||||
|
for (size_t i = 0; i < MAX_PAGES; ++i) {
|
||||||
|
if (!bitmap_test(i)) {
|
||||||
|
bitmap_set(i);
|
||||||
|
return (void*)to_addr(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boot_panic("Out of physical memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_free_page(void *addr) {
|
||||||
|
size_t page = to_page((uptr)addr);
|
||||||
|
|
||||||
|
if (page >= MAX_PAGES) {
|
||||||
|
boot_panic("Trying to free page beyond physical memory limit");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bitmap_test(page)) {
|
||||||
|
boot_panic("Page is already free");
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap_clear(page);
|
||||||
|
}
|
||||||
5
src/boot/pmm.h
Normal file
5
src/boot/pmm.h
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void pmm_init();
|
||||||
|
void *pmm_alloc_page();
|
||||||
|
void pmm_free_page(void *addr);
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
global _start
|
global _start
|
||||||
|
global multiboot_info
|
||||||
extern kernel_start
|
extern kernel_start
|
||||||
extern kernel_end
|
extern kernel_end
|
||||||
extern kmain
|
extern x86_64_main
|
||||||
|
|
||||||
%define MAGIC 0xe85250d6
|
%define MAGIC 0xe85250d6
|
||||||
%define ARCH 0x0
|
%define ARCH 0x0
|
||||||
@@ -21,10 +22,6 @@ header:
|
|||||||
dd 8
|
dd 8
|
||||||
.end:
|
.end:
|
||||||
|
|
||||||
section .data
|
|
||||||
align 8
|
|
||||||
multiboot_info: dq 0
|
|
||||||
|
|
||||||
%define PRESENT 1 << 7
|
%define PRESENT 1 << 7
|
||||||
%define NOT_SYS 1 << 4
|
%define NOT_SYS 1 << 4
|
||||||
%define EXEC 1 << 3
|
%define EXEC 1 << 3
|
||||||
@@ -58,6 +55,11 @@ gdt:
|
|||||||
dq gdt
|
dq gdt
|
||||||
|
|
||||||
section .bss
|
section .bss
|
||||||
|
%define MULTIBOOT_INFO_MAX_SIZE 1024 * 64
|
||||||
|
|
||||||
|
align 8
|
||||||
|
multiboot_info: resb MULTIBOOT_INFO_MAX_SIZE
|
||||||
|
|
||||||
align 16
|
align 16
|
||||||
stack:
|
stack:
|
||||||
.bottom:
|
.bottom:
|
||||||
@@ -79,29 +81,38 @@ _start:
|
|||||||
cmp eax, BOOTLOADER_MAGIC
|
cmp eax, BOOTLOADER_MAGIC
|
||||||
jne .halt
|
jne .halt
|
||||||
|
|
||||||
; Save pointer to info gathered by multiboot
|
; Copy multiboot structure to kernel owned memory
|
||||||
mov [multiboot_info], ebx
|
mov esi, ebx
|
||||||
|
mov eax, [esi]
|
||||||
|
|
||||||
|
cmp eax, MULTIBOOT_INFO_MAX_SIZE
|
||||||
|
ja .halt
|
||||||
|
|
||||||
|
mov edi, multiboot_info
|
||||||
|
mov ecx, eax
|
||||||
|
cld
|
||||||
|
rep movsb
|
||||||
|
|
||||||
; Tell the cpu where the pages area
|
; Tell the cpu where the pages area
|
||||||
mov edi, pml4t
|
mov edi, pml4t
|
||||||
mov cr3, edi
|
mov cr3, edi
|
||||||
|
|
||||||
%define PT_PRESENT 1
|
%define PT_PRESENT 1
|
||||||
%define PT_READABLE 2
|
%define PT_RW 2
|
||||||
|
|
||||||
; pml4t[0] -> pdpt
|
; pml4t[0] -> pdpt
|
||||||
mov edi, pdpt
|
mov edi, pdpt
|
||||||
or edi, PT_PRESENT | PT_READABLE
|
or edi, PT_PRESENT | PT_RW
|
||||||
mov [pml4t], edi
|
mov [pml4t], edi
|
||||||
|
|
||||||
; pdpt[0] -> pdt
|
; pdpt[0] -> pdt
|
||||||
mov edi, pdt
|
mov edi, pdt
|
||||||
or edi, PT_PRESENT | PT_READABLE
|
or edi, PT_PRESENT | PT_RW
|
||||||
mov [pdpt], edi
|
mov [pdpt], edi
|
||||||
|
|
||||||
; pdt[0] -> pt
|
; pdt[0] -> pt
|
||||||
mov edi, pt
|
mov edi, pt
|
||||||
or edi, PT_PRESENT | PT_READABLE
|
or edi, PT_PRESENT | PT_RW
|
||||||
mov [pdt], edi
|
mov [pdt], edi
|
||||||
|
|
||||||
%define ENTRIES_PER_PT 512
|
%define ENTRIES_PER_PT 512
|
||||||
@@ -113,7 +124,7 @@ _start:
|
|||||||
mov edi, pt
|
mov edi, pt
|
||||||
mov ebx, kernel_start
|
mov ebx, kernel_start
|
||||||
and ebx, 0xfffff000
|
and ebx, 0xfffff000
|
||||||
or ebx, PT_PRESENT | PT_READABLE
|
or ebx, PT_PRESENT | PT_RW
|
||||||
|
|
||||||
mov eax, kernel_end
|
mov eax, kernel_end
|
||||||
sub eax, kernel_start
|
sub eax, kernel_start
|
||||||
@@ -127,6 +138,17 @@ _start:
|
|||||||
add edi, SIZEOF_PT_ENTRY
|
add edi, SIZEOF_PT_ENTRY
|
||||||
loop .set_pt_entry
|
loop .set_pt_entry
|
||||||
|
|
||||||
|
; note(nub31): Vga buffer is already page aligned
|
||||||
|
%define VGA_BUFFER 0xb8000
|
||||||
|
|
||||||
|
; Identity map vga buffer
|
||||||
|
mov ebx, VGA_BUFFER
|
||||||
|
or ebx, PT_PRESENT | PT_RW
|
||||||
|
|
||||||
|
mov edi, pt
|
||||||
|
add edi, VGA_BUFFER / PAGE_SIZE * SIZEOF_PT_ENTRY
|
||||||
|
mov [edi], ebx
|
||||||
|
|
||||||
%define CR4_PAE_ENABLE 1 << 5
|
%define CR4_PAE_ENABLE 1 << 5
|
||||||
|
|
||||||
; Enable pae
|
; Enable pae
|
||||||
@@ -169,8 +191,8 @@ start64:
|
|||||||
mov ss, ax
|
mov ss, ax
|
||||||
|
|
||||||
mov rsp, stack.top
|
mov rsp, stack.top
|
||||||
mov rdi, [multiboot_info]
|
mov rdi, multiboot_info
|
||||||
call kmain
|
call x86_64_main
|
||||||
.halt:
|
.halt:
|
||||||
cli
|
cli
|
||||||
hlt
|
hlt
|
||||||
|
|||||||
19
src/boot/symbols.c
Normal file
19
src/boot/symbols.c
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#include "symbols.h"
|
||||||
|
|
||||||
|
extern u8 kernel_start[];
|
||||||
|
|
||||||
|
uptr get_kernel_start() {
|
||||||
|
return (uptr)&kernel_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern u8 kernel_end[];
|
||||||
|
|
||||||
|
uptr get_kernel_end() {
|
||||||
|
return (uptr)&kernel_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern u8 multiboot_info[];
|
||||||
|
|
||||||
|
uptr get_multiboot_info() {
|
||||||
|
return (uptr)&multiboot_info;
|
||||||
|
}
|
||||||
7
src/boot/symbols.h
Normal file
7
src/boot/symbols.h
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <def.h>
|
||||||
|
|
||||||
|
uptr get_kernel_start();
|
||||||
|
uptr get_kernel_end();
|
||||||
|
uptr get_multiboot_info();
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
static inline u32 align(u32 num, u32 alignment) {
|
#include <def.h>
|
||||||
return (num + alignment - 1) & ~(alignment - 1);
|
|
||||||
}
|
#define ALIGN_UP(value, alignment) ((value + alignment - 1) / alignment * alignment)
|
||||||
|
#define ALIGN_DOWN(value, alignment) (value - (value % alignment))
|
||||||
|
|
||||||
static inline void hlt() {
|
static inline void hlt() {
|
||||||
asm("hlt");
|
asm("hlt");
|
||||||
|
|||||||
@@ -53,19 +53,7 @@ typedef signed long long i64;
|
|||||||
#define U64_MIN 0x0
|
#define U64_MIN 0x0
|
||||||
#define U64_MAX 0xffffffffffffffffULL
|
#define U64_MAX 0xffffffffffffffffULL
|
||||||
|
|
||||||
#define I8_C(x) x
|
#define KiB(count) (count##ULL * 1024##ULL)
|
||||||
#define U8_C(x) x##U
|
#define MiB(count) (count##ULL * KiB(1024))
|
||||||
|
#define GiB(count) (count##ULL * MiB(1024))
|
||||||
#define I16_C(x) x
|
#define TiB(count) (count##ULL * GiB(1024))
|
||||||
#define U16_C(x) x##U
|
|
||||||
|
|
||||||
#define I32_C(x) x
|
|
||||||
#define U32_C(x) x##U
|
|
||||||
|
|
||||||
#define I64_C(x) x##LL
|
|
||||||
#define U64_C(x) x##ULL
|
|
||||||
|
|
||||||
#define KiB(count) (U64_C(count) * U64_C(1024))
|
|
||||||
#define MiB(count) (U64_C(count) * U64_C(1024) * U64_C(1024))
|
|
||||||
#define GiB(count) (U64_C(count) * U64_C(1024) * U64_C(1024) * U64_C(1024))
|
|
||||||
#define TiB(count) (U64_C(count) * U64_C(1024) * U64_C(1024) * U64_C(1024) * U64_C(1024))
|
|
||||||
@@ -83,55 +83,25 @@ void itoa64(i64 value, char *buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void uitoa64(u64 value, char *buffer) {
|
void uitoa64(u64 value, char *buffer) {
|
||||||
char *p = buffer;
|
char tmp[20];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
*p++ = '0';
|
buffer[0] = '0';
|
||||||
*p = '\0';
|
buffer[1] = '\0';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const u64 powers[] = {
|
while (value > 0) {
|
||||||
10000000000000000000ULL,
|
tmp[i++] = '0' + (value % 10);
|
||||||
1000000000000000000ULL,
|
value /= 10;
|
||||||
100000000000000000ULL,
|
|
||||||
10000000000000000ULL,
|
|
||||||
1000000000000000ULL,
|
|
||||||
100000000000000ULL,
|
|
||||||
10000000000000ULL,
|
|
||||||
1000000000000ULL,
|
|
||||||
100000000000ULL,
|
|
||||||
10000000000ULL,
|
|
||||||
1000000000ULL,
|
|
||||||
100000000ULL,
|
|
||||||
10000000ULL,
|
|
||||||
1000000ULL,
|
|
||||||
100000ULL,
|
|
||||||
10000ULL,
|
|
||||||
1000ULL,
|
|
||||||
100ULL,
|
|
||||||
10ULL,
|
|
||||||
1ULL
|
|
||||||
};
|
|
||||||
|
|
||||||
bool started = false;
|
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++) {
|
|
||||||
u64 power = powers[i];
|
|
||||||
u32 digit = 0;
|
|
||||||
|
|
||||||
while (value >= power) {
|
|
||||||
value -= power;
|
|
||||||
digit++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (digit || started) {
|
|
||||||
*p++ = '0' + digit;
|
|
||||||
started = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*p = '\0';
|
for (int j = 0; j < i; j++) {
|
||||||
|
buffer[j] = tmp[i - j - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
void uitoa64_hex(u64 value, char *buffer) {
|
void uitoa64_hex(u64 value, char *buffer) {
|
||||||
|
|||||||
Reference in New Issue
Block a user