mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-25 23:10:32 +00:00
Merge branch limine2 into branch limine.
This commit is contained in:
commit
0a3923b7b9
7 changed files with 356 additions and 50 deletions
|
@ -35,9 +35,13 @@ umount_tempdisk() {
|
|||
|
||||
[ ! -d $TMPMOUNT ] && mkdir -p $TMPMOUNT
|
||||
|
||||
set -e
|
||||
|
||||
echo "Building ZealBooter..."
|
||||
( cd ../zealbooter && make clean all )
|
||||
|
||||
set +e
|
||||
|
||||
echo "Making temp vdisk, running auto-install..."
|
||||
qemu-img create -f raw $TMPDISK 192M
|
||||
qemu-system-x86_64 -machine q35,accel=kvm -drive format=raw,file=$TMPDISK -m 1G -rtc base=localtime -cdrom AUTO-VM-1.ISO -device isa-debug-exit
|
||||
|
|
|
@ -77,6 +77,10 @@ SYS_SEMAS:: DU8 SEMA_SEMAS_NUM * DEFAULT_CACHE_LINE_WIDTH DUP(0);
|
|||
//************************************
|
||||
ALIGN 16, OC_NOP
|
||||
|
||||
// Signature to find CORE0_32BIT_INIT
|
||||
DU64 0xaa23c08ed10bd4d7;
|
||||
DU64 0xf6ceba7d4b74179a;
|
||||
|
||||
CORE0_32BIT_INIT:: //Entry point for $LK,"BootRAM",A="MN:BootRAM"$.
|
||||
PUSH U32 RFLAGG_START
|
||||
POPFD
|
||||
|
|
|
@ -21,7 +21,7 @@ $(eval $(call DEFAULT_VAR,CC,cc))
|
|||
$(eval $(call DEFAULT_VAR,LD,ld))
|
||||
|
||||
# User controllable CFLAGS.
|
||||
CFLAGS ?= -O2 -g -Wall -Wextra -Wpedantic -pipe
|
||||
CFLAGS ?= -O2 -g -Wall -Wextra -pipe
|
||||
|
||||
# User controllable preprocessor flags. We set none by default.
|
||||
CPPFLAGS ?=
|
||||
|
@ -35,7 +35,7 @@ LDFLAGS ?=
|
|||
# Internal C flags that should not be changed by the user.
|
||||
override CFLAGS += \
|
||||
-I. \
|
||||
-std=c11 \
|
||||
-std=gnu11 \
|
||||
-ffreestanding \
|
||||
-fno-stack-protector \
|
||||
-fno-stack-check \
|
||||
|
|
105
zealbooter/lib.c
Normal file
105
zealbooter/lib.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <lib.h>
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n) {
|
||||
uint8_t *pdest = (uint8_t *)dest;
|
||||
const uint8_t *psrc = (const uint8_t *)src;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pdest[i] = psrc[i];
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
uint8_t *p = (uint8_t *)s;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
p[i] = (uint8_t)c;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void *memmove(void *dest, const void *src, size_t n) {
|
||||
uint8_t *pdest = (uint8_t *)dest;
|
||||
const uint8_t *psrc = (const uint8_t *)src;
|
||||
|
||||
if (src > dest) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pdest[i] = psrc[i];
|
||||
}
|
||||
} else if (src < dest) {
|
||||
for (size_t i = n; i > 0; i--) {
|
||||
pdest[i-1] = psrc[i-1];
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||
const uint8_t *p1 = (const uint8_t *)s1;
|
||||
const uint8_t *p2 = (const uint8_t *)s2;
|
||||
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
if (p1[i] != p2[i])
|
||||
return p1[i] < p2[i] ? -1 : 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *strcpy(char *dest, const char *src) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; src[i]; i++)
|
||||
dest[i] = src[i];
|
||||
|
||||
dest[i] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *strncpy(char *dest, const char *src, size_t n) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n && src[i]; i++)
|
||||
dest[i] = src[i];
|
||||
for ( ; i < n; i++)
|
||||
dest[i] = 0;
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2) {
|
||||
for (size_t i = 0; ; i++) {
|
||||
char c1 = s1[i], c2 = s2[i];
|
||||
if (c1 != c2)
|
||||
return c1 - c2;
|
||||
if (!c1)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int strncmp(const char *s1, const char *s2, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
char c1 = s1[i], c2 = s2[i];
|
||||
if (c1 != c2)
|
||||
return c1 - c2;
|
||||
if (!c1)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t strlen(const char *str) {
|
||||
size_t len;
|
||||
|
||||
for (len = 0; str[len]; len++);
|
||||
|
||||
return len;
|
||||
}
|
37
zealbooter/lib.h
Normal file
37
zealbooter/lib.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef __LIB_H__
|
||||
#define __LIB_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define DIV_ROUNDUP(A, B) ({ \
|
||||
typeof(A) _a_ = A; \
|
||||
typeof(B) _b_ = B; \
|
||||
(_a_ + (_b_ - 1)) / _b_; \
|
||||
})
|
||||
|
||||
#define ALIGN_UP(A, B) ({ \
|
||||
typeof(A) _a__ = A; \
|
||||
typeof(B) _b__ = B; \
|
||||
DIV_ROUNDUP(_a__, _b__) * _b__; \
|
||||
})
|
||||
|
||||
#define ALIGN_DOWN(A, B) ({ \
|
||||
typeof(A) _a_ = A; \
|
||||
typeof(B) _b_ = B; \
|
||||
(_a_ / _b_) * _b_; \
|
||||
})
|
||||
|
||||
typedef char symbol[];
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
int memcmp(const void *s1, const void *s2, size_t n);
|
||||
|
||||
char *strcpy(char *dest, const char *src);
|
||||
char *strncpy(char *dest, const char *src, size_t n);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
int strncmp(const char *s1, const char *s2, size_t n);
|
||||
size_t strlen(const char *str);
|
||||
|
||||
#endif
|
36
zealbooter/lower.S
Normal file
36
zealbooter/lower.S
Normal file
|
@ -0,0 +1,36 @@
|
|||
.section .text
|
||||
|
||||
.global lower
|
||||
lower:
|
||||
pushq $0x18
|
||||
addq $(1f - lower), %rax
|
||||
pushq %rax
|
||||
lretq
|
||||
|
||||
.code32
|
||||
1:
|
||||
|
||||
mov $0x20, %eax
|
||||
mov %eax, %ds
|
||||
mov %eax, %es
|
||||
mov %eax, %fs
|
||||
mov %eax, %gs
|
||||
mov %eax, %ss
|
||||
|
||||
lgdt (%ecx)
|
||||
|
||||
mov %cr0, %eax
|
||||
btr $31, %eax
|
||||
mov %eax, %cr0
|
||||
|
||||
mov $0xc0000080, %ecx
|
||||
xor %eax, %eax
|
||||
xor %edx, %edx
|
||||
wrmsr
|
||||
|
||||
mov %ebx, %eax
|
||||
mov $2, %ebx
|
||||
|
||||
mov $0x7c00, %esp
|
||||
jmp *%eax
|
||||
|
|
@ -1,26 +1,71 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <limine.h>
|
||||
|
||||
// The Limine requests can be placed anywhere, but it is important that
|
||||
// the compiler does not optimise them away, so, usually, they should
|
||||
// be made volatile or equivalent.
|
||||
#include <lib.h>
|
||||
|
||||
static volatile struct limine_module_request module_request = {
|
||||
.id = LIMINE_MODULE_REQUEST,
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
static volatile struct limine_terminal_request terminal_request = {
|
||||
.id = LIMINE_TERMINAL_REQUEST,
|
||||
static volatile struct limine_kernel_address_request kernel_address_request = {
|
||||
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
static void done(void) {
|
||||
for (;;) {
|
||||
__asm__("hlt");
|
||||
}
|
||||
}
|
||||
static volatile struct limine_memmap_request memmap_request = {
|
||||
.id = LIMINE_MEMMAP_REQUEST,
|
||||
.revision = 0
|
||||
};
|
||||
|
||||
struct CZXE {
|
||||
uint16_t jmp;
|
||||
uint8_t module_align_bits;
|
||||
uint8_t reserved;
|
||||
uint32_t signature;
|
||||
int64_t org;
|
||||
int64_t patch_table_offset;
|
||||
int64_t file_size;
|
||||
};
|
||||
|
||||
struct CDate {
|
||||
uint32_t time;
|
||||
int32_t date;
|
||||
};
|
||||
|
||||
#define MEM_E820_ENTRIES_NUM 48
|
||||
|
||||
#define MEM_E820T_USABLE 1
|
||||
#define MEM_E820T_RESERVED 2
|
||||
#define MEM_E820T_ACPI 3
|
||||
#define MEM_E820T_ACPI_NVS 4
|
||||
#define MEM_E820T_BAD_MEM 5
|
||||
#define MEM_E820T_PERM_MEM 7
|
||||
|
||||
struct CMemE820 {
|
||||
uint8_t *base;
|
||||
int64_t len;
|
||||
uint8_t type, pad[3];
|
||||
};
|
||||
|
||||
struct CGDTEntry {
|
||||
uint64_t lo, hi;
|
||||
};
|
||||
|
||||
#define MP_PROCESSORS_NUM 128
|
||||
|
||||
struct CGDT {
|
||||
struct CGDTEntry null;
|
||||
struct CGDTEntry boot_ds;
|
||||
struct CGDTEntry boot_cs;
|
||||
struct CGDTEntry cs32;
|
||||
struct CGDTEntry cs64;
|
||||
struct CGDTEntry cs64_ring3;
|
||||
struct CGDTEntry ds;
|
||||
struct CGDTEntry ds_ring3;
|
||||
struct CGDTEntry tr[MP_PROCESSORS_NUM];
|
||||
struct CGDTEntry tr_ring3[MP_PROCESSORS_NUM];
|
||||
};
|
||||
|
||||
struct CZXE {
|
||||
uint16_t jmp;
|
||||
|
@ -50,56 +95,131 @@ struct CSysLimitBase {
|
|||
};
|
||||
|
||||
struct CKernel {
|
||||
struct CZXE zxe;
|
||||
struct CZXE h;
|
||||
uint32_t jmp;
|
||||
uint32_t boot_src;
|
||||
uint32_t boot_blk;
|
||||
uint32_t boot_patch_table_base;
|
||||
uint32_t sys_run_level;
|
||||
struct CDate compile_time;
|
||||
//U0 start;
|
||||
// U0 start
|
||||
uint32_t boot_base;
|
||||
uint16_t mem_E801[2];
|
||||
struct CMemE820 mem_E820[48];
|
||||
struct CMemE820 mem_E820[MEM_E820_ENTRIES_NUM];
|
||||
uint64_t mem_physical_space;
|
||||
struct CSysLimitBase sys_gdt_ptr;
|
||||
struct {
|
||||
uint16_t limit;
|
||||
uint8_t *base;
|
||||
} __attribute__((packed)) sys_gdt_ptr;
|
||||
uint16_t sys_pci_buses;
|
||||
// ;$ = ($ + 15) & -16;
|
||||
// struct CGDT sys_gdt;
|
||||
// uint32_t sys_font_ptr;
|
||||
// struct CVBEInfo sys_vbe_info;
|
||||
// struct CVBEModeShort sys_vbe_modes[32];
|
||||
// struct CVBEMode sys_vbe_mode;
|
||||
// uint16_t sys_vbe_mode_num;
|
||||
struct CGDT sys_gdt;
|
||||
uint32_t sys_font_ptr;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define BOOT_SRC_RAM 2
|
||||
#define RLF_16BIT 0b01
|
||||
#define RLF_VESA 0b10
|
||||
|
||||
void lower(void);
|
||||
|
||||
struct E801 {
|
||||
size_t lowermem;
|
||||
size_t uppermem;
|
||||
};
|
||||
|
||||
// The following will be our kernel's entry point.
|
||||
void _start(void) {
|
||||
// Ensure we got a terminal
|
||||
if (terminal_request.response == NULL
|
||||
|| terminal_request.response->terminal_count < 1) {
|
||||
done();
|
||||
struct E801 get_E801(void) {
|
||||
struct E801 E801 = {0};
|
||||
|
||||
for (size_t i = 0; i < memmap_request.response->entry_count; i++) {
|
||||
struct limine_memmap_entry *entry = memmap_request.response->entries[i];
|
||||
|
||||
if (entry->type == LIMINE_MEMMAP_USABLE) {
|
||||
if (entry->base == 0x100000) {
|
||||
if (entry->length > 0xf00000) {
|
||||
E801.lowermem = 0x3c00;
|
||||
} else {
|
||||
E801.lowermem = entry->length / 1024;
|
||||
}
|
||||
}
|
||||
if (entry->base <= 0x1000000 && entry->base + entry->length > 0x1000000) {
|
||||
E801.uppermem = ((entry->length - (0x1000000 - entry->base)) / 1024) / 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We should now be able to call the Limine terminal to print out
|
||||
// a simple "Hello World" to screen.
|
||||
struct limine_terminal *terminal = terminal_request.response->terminals[0];
|
||||
terminal_request.response->write(terminal, "Hello World", 11);
|
||||
|
||||
struct limine_file *kernel_module = module_request.response->modules[0];
|
||||
struct CKernel *kernel = kernel_module->address;
|
||||
|
||||
char str[128];
|
||||
str[0] = ' ';
|
||||
str[1] = kernel->zxe.signature;
|
||||
str[2] = kernel->zxe.signature >> 8;
|
||||
str[3] = kernel->zxe.signature >> 16;
|
||||
str[4] = kernel->zxe.signature >> 24;
|
||||
str[5] = 0;
|
||||
|
||||
terminal_request.response->write(terminal, str, 5);
|
||||
|
||||
// We're done, just hang...
|
||||
done();
|
||||
return E801;
|
||||
}
|
||||
|
||||
void _start(void) {
|
||||
struct limine_file *kernel = module_request.response->modules[0];
|
||||
struct CKernel *CKernel = (void *)0x7c00;
|
||||
memcpy(CKernel, kernel->address, kernel->size);
|
||||
|
||||
void *CORE0_32BIT_INIT;
|
||||
for (uint64_t *p = (uint64_t *)CKernel; ; p++) {
|
||||
if (*p != 0xaa23c08ed10bd4d7) {
|
||||
continue;
|
||||
}
|
||||
p++;
|
||||
if (*p != 0xf6ceba7d4b74179a) {
|
||||
continue;
|
||||
}
|
||||
p++;
|
||||
CORE0_32BIT_INIT = p;
|
||||
break;
|
||||
}
|
||||
|
||||
CKernel->boot_src = BOOT_SRC_RAM;
|
||||
CKernel->boot_blk = 0;
|
||||
CKernel->boot_patch_table_base = (uintptr_t)CKernel + CKernel->h.patch_table_offset;
|
||||
CKernel->sys_run_level = RLF_VESA | RLF_16BIT;
|
||||
|
||||
CKernel->boot_base = (uintptr_t)&CKernel->jmp;
|
||||
|
||||
CKernel->sys_gdt.boot_ds.lo = 0x000093000000ffff;
|
||||
CKernel->sys_gdt.boot_cs.lo = 0x00009a000000ffff;
|
||||
CKernel->sys_gdt.cs32.lo = 0x00cf9a000000ffff;
|
||||
CKernel->sys_gdt.cs64.lo = 0x00af9b000000ffff;
|
||||
CKernel->sys_gdt.cs64_ring3.lo = 0x00affb000000ffff;
|
||||
CKernel->sys_gdt.ds.lo = 0x00af93000000ffff;
|
||||
CKernel->sys_gdt.ds_ring3.lo = 0x00aff3000000ffff;
|
||||
|
||||
CKernel->sys_gdt_ptr.limit = sizeof(CKernel->sys_gdt) - 1;
|
||||
CKernel->sys_gdt_ptr.base = (void *)&CKernel->sys_gdt;
|
||||
|
||||
struct E801 E801 = get_E801();
|
||||
CKernel->mem_E801[0] = E801.lowermem;
|
||||
CKernel->mem_E801[1] = E801.uppermem;
|
||||
|
||||
for (size_t i = 0; i < memmap_request.response->entry_count; i++) {
|
||||
struct limine_memmap_entry *entry = memmap_request.response->entries[i];
|
||||
|
||||
int our_type;
|
||||
switch (entry->type) {
|
||||
case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE:
|
||||
case LIMINE_MEMMAP_KERNEL_AND_MODULES:
|
||||
case LIMINE_MEMMAP_USABLE:
|
||||
our_type = MEM_E820T_USABLE; break;
|
||||
case LIMINE_MEMMAP_ACPI_RECLAIMABLE:
|
||||
our_type = MEM_E820T_ACPI; break;
|
||||
case LIMINE_MEMMAP_ACPI_NVS:
|
||||
our_type = MEM_E820T_ACPI_NVS; break;
|
||||
case LIMINE_MEMMAP_BAD_MEMORY:
|
||||
our_type = MEM_E820T_BAD_MEM; break;
|
||||
case LIMINE_MEMMAP_RESERVED:
|
||||
default:
|
||||
our_type = MEM_E820T_RESERVED; break;
|
||||
}
|
||||
|
||||
CKernel->mem_E820[i].base = (void *)entry->base;
|
||||
CKernel->mem_E820[i].len = entry->length;
|
||||
CKernel->mem_E820[i].type = our_type;
|
||||
}
|
||||
|
||||
void *target_addr = (void *)lower - kernel_address_request.response->virtual_base;
|
||||
target_addr += kernel_address_request.response->physical_base;
|
||||
|
||||
asm volatile ("jmp *%0" :: "a"(target_addr), "b"(CORE0_32BIT_INIT), "c"(&CKernel->sys_gdt_ptr) : "memory");
|
||||
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue