Support i386

This commit is contained in:
Alex
2023-03-29 03:02:49 +03:00
parent 38dae2c9f7
commit 9e21c5326b
28 changed files with 31 additions and 31 deletions

View File

@ -0,0 +1,327 @@
/* Source: https://github.com/glitchub/arith64 */
#define arith64_u64 unsigned long long int
#define arith64_s64 signed long long int
#define arith64_u32 unsigned int
#define arith64_s32 int
typedef union
{
arith64_u64 u64;
arith64_s64 s64;
struct
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
arith64_u32 hi;
arith64_u32 lo;
#else
arith64_u32 lo;
arith64_u32 hi;
#endif
} u32;
struct
{
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
arith64_s32 hi;
arith64_s32 lo;
#else
arith64_s32 lo;
arith64_s32 hi;
#endif
} s32;
} arith64_word;
#define arith64_hi(n) (arith64_word){.u64 = n}.u32.hi
#define arith64_lo(n) (arith64_word){.u64 = n}.u32.lo
#define arith64_neg(a, b) (((a) ^ ((((arith64_s64)(b)) >= 0) - 1)) + (((arith64_s64)(b)) < 0))
#define arith64_abs(a) arith64_neg(a, a)
arith64_s64 __absvdi2(arith64_s64 a)
{
return arith64_abs(a);
}
arith64_s64 __ashldi3(arith64_s64 a, int b)
{
arith64_word w = {.s64 = a};
b &= 63;
if (b >= 32)
{
w.u32.hi = w.u32.lo << (b - 32);
w.u32.lo = 0;
}
else if (b)
{
w.u32.hi = (w.u32.lo >> (32 - b)) | (w.u32.hi << b);
w.u32.lo <<= b;
}
return w.s64;
}
arith64_s64 __ashrdi3(arith64_s64 a, int b)
{
arith64_word w = {.s64 = a};
b &= 63;
if (b >= 32)
{
w.s32.lo = w.s32.hi >> (b - 32);
w.s32.hi >>= 31; // 0xFFFFFFFF or 0
}
else if (b)
{
w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
w.s32.hi >>= b;
}
return w.s64;
}
int __clzsi2(arith64_u32 a)
{
int b, n = 0;
b = !(a & 0xffff0000) << 4;
n += b;
a <<= b;
b = !(a & 0xff000000) << 3;
n += b;
a <<= b;
b = !(a & 0xf0000000) << 2;
n += b;
a <<= b;
b = !(a & 0xc0000000) << 1;
n += b;
a <<= b;
return n + !(a & 0x80000000);
}
int __clzdi2(arith64_u64 a)
{
int b, n = 0;
b = !(a & 0xffffffff00000000ULL) << 5;
n += b;
a <<= b;
b = !(a & 0xffff000000000000ULL) << 4;
n += b;
a <<= b;
b = !(a & 0xff00000000000000ULL) << 3;
n += b;
a <<= b;
b = !(a & 0xf000000000000000ULL) << 2;
n += b;
a <<= b;
b = !(a & 0xc000000000000000ULL) << 1;
n += b;
a <<= b;
return n + !(a & 0x8000000000000000ULL);
}
int __ctzsi2(arith64_u32 a)
{
int b, n = 0;
b = !(a & 0x0000ffff) << 4;
n += b;
a >>= b;
b = !(a & 0x000000ff) << 3;
n += b;
a >>= b;
b = !(a & 0x0000000f) << 2;
n += b;
a >>= b;
b = !(a & 0x00000003) << 1;
n += b;
a >>= b;
return n + !(a & 0x00000001);
}
int __ctzdi2(arith64_u64 a)
{
int b, n = 0;
b = !(a & 0x00000000ffffffffULL) << 5;
n += b;
a >>= b;
b = !(a & 0x000000000000ffffULL) << 4;
n += b;
a >>= b;
b = !(a & 0x00000000000000ffULL) << 3;
n += b;
a >>= b;
b = !(a & 0x000000000000000fULL) << 2;
n += b;
a >>= b;
b = !(a & 0x0000000000000003ULL) << 1;
n += b;
a >>= b;
return n + !(a & 0x0000000000000001ULL);
}
arith64_u64 __divmoddi4(arith64_u64 a, arith64_u64 b, arith64_u64 *c)
{
if (b > a)
{
if (c)
*c = a;
return 0;
}
if (!arith64_hi(b))
{
if (b == 0)
{
volatile char x = 0;
x = 1 / x;
}
if (b == 1)
{
if (c)
*c = 0;
return a;
}
if (!arith64_hi(a))
{
if (c)
*c = arith64_lo(a) % arith64_lo(b);
return arith64_lo(a) / arith64_lo(b);
}
}
char bits = __clzdi2(b) - __clzdi2(a) + 1;
arith64_u64 rem = a >> bits;
a <<= 64 - bits;
arith64_u64 wrap = 0;
while (bits-- > 0)
{
rem = (rem << 1) | (a >> 63);
a = (a << 1) | (wrap & 1);
wrap = ((arith64_s64)(b - rem - 1) >> 63);
rem -= b & wrap;
}
if (c)
*c = rem;
return (a << 1) | (wrap & 1);
}
arith64_s64 __divdi3(arith64_s64 a, arith64_s64 b)
{
arith64_u64 q = __divmoddi4(arith64_abs(a), arith64_abs(b), (void *)0);
return arith64_neg(q, a ^ b);
}
int __ffsdi2(arith64_u64 a) { return a ? __ctzdi2(a) + 1 : 0; }
arith64_u64 __lshrdi3(arith64_u64 a, int b)
{
arith64_word w = {.u64 = a};
b &= 63;
if (b >= 32)
{
w.u32.lo = w.u32.hi >> (b - 32);
w.u32.hi = 0;
}
else if (b)
{
w.u32.lo = (w.u32.hi << (32 - b)) | (w.u32.lo >> b);
w.u32.hi >>= b;
}
return w.u64;
}
arith64_s64 __moddi3(arith64_s64 a, arith64_s64 b)
{
arith64_u64 r;
__divmoddi4(arith64_abs(a), arith64_abs(b), &r);
return arith64_neg(r, a);
}
int __popcountsi2(arith64_u32 a)
{
a = a - ((a >> 1) & 0x55555555);
a = ((a >> 2) & 0x33333333) + (a & 0x33333333);
a = (a + (a >> 4)) & 0x0F0F0F0F;
a = (a + (a >> 16));
return (a + (a >> 8)) & 63;
}
int __popcountdi2(arith64_u64 a)
{
a = a - ((a >> 1) & 0x5555555555555555ULL);
a = ((a >> 2) & 0x3333333333333333ULL) + (a & 0x3333333333333333ULL);
a = (a + (a >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
a = (a + (a >> 32));
a = (a + (a >> 16));
return (a + (a >> 8)) & 127;
}
arith64_u64 __udivdi3(arith64_u64 a, arith64_u64 b) { return __divmoddi4(a, b, (void *)0); }
arith64_u64 __umoddi3(arith64_u64 a, arith64_u64 b)
{
arith64_u64 r;
__divmoddi4(a, b, &r);
return r;
}
/* Good documentation: https://splichal.eu/scripts/sphinx/gccint/_build/html/the-gcc-low-level-runtime-library/routines-for-floating-point-emulation.html */
double __adddf3(double a, double b) { return a + b; }
double __muldf3(double a, double b) { return a * b; }
double __floatsidf(int i) { return (double)i; }
int __ltdf2(double a, double b) { return a < b; }
int __gtdf2(double a, double b) { return a > b; }
int __nedf2(double a, double b) { return a != b; }
int __eqdf2(double a, double b) { return a == b; }
double __floatdidf(long i) { return (double)i; }
double __divdf3(double a, double b) { return a / b; }
double __subdf3(double a, double b) { return a - b; }
int __gedf2(double a, double b) { return a >= b; }
int __fixdfsi(double a) { return (int)a; }
long __fixdfdi(double a) { return (long)a; }
int __ledf2(double a, double b) { return a <= b; }
/* FIXME: Check if these functions are implemented correctly */
typedef long long int64_t;
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
typedef struct
{
uint64_t value;
} atomic_uint64_t;
uint64_t __atomic_load_8(const atomic_uint64_t *p)
{
uint64_t value;
__asm__ volatile("lock cmpxchg8b %1"
: "=A"(value)
: "m"(*p)
: "memory");
return value;
}
void __atomic_store_8(atomic_uint64_t *p, uint64_t value)
{
__asm__ volatile("lock cmpxchg8b %0"
: "=m"(p->value)
: "a"((uint32_t)value), "d"((uint32_t)(value >> 32)), "m"(*p)
: "memory");
}
/* FIXME: __fixsfsi is not implemented correctly(?) */
int __fixsfsi(float a) { return (int)a; }
int __ltsf2(float a, float b) { return a < b; }
int __eqsf2(float a, float b) { return a == b; }
float __divsf3(float a, float b) { return a / b; }
double __extendsfdf2(float a) { return (double)a; }
float __truncdfsf2(double a) { return (float)a; }
float __subsf3(float a, float b) { return a - b; }
float __floatsisf(int a) { return (float)a; }
int __fixunssfsi(float a) { return (int)a; }
float __mulsf3(float a, float b) { return a * b; }
float __addsf3(float a, float b) { return a + b; }

View File

@ -0,0 +1,54 @@
; https://wiki.osdev.org/Higher_Half_x86_Bare_Bones
; https://wiki.osdev.org/Higher_Half_x86_Bare_Bones_(Backup)
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
extern Multiboot2Entry
extern BootPageTable
global MB2_start
section .text
MB2_start:
cli
mov word [0xb8F00], 0x072E ; .
mov ecx, (BootPageTable - KERNEL_VIRTUAL_BASE)
mov cr3, ecx
mov word [0xb8F02], 0x072E ; .
mov ecx, cr4
or ecx, 0x00000010 ; Set PSE in CR4
mov cr4, ecx
mov word [0xb8F04], 0x072E ; .
mov ecx, cr0
or ecx, 0x80000000 ; Set PG in CR0
mov cr0, ecx
mov word [0xb8F06], 0x072E ; .
lea ecx, [HigherHalfStart]
jmp ecx
HigherHalfStart:
mov word [0xb8F08], 0x072E ; .
mov dword [BootPageTable], 0
invlpg [0]
mov esp, KernelStack + KERNEL_STACK_SIZE
push eax ; Multiboot2 Magic
add ebx, KERNEL_VIRTUAL_BASE
push ebx ; Multiboot2 Header
call Multiboot2Entry
Loop:
hlt
jmp Loop
section .bss
align 16
KernelStack:
resb KERNEL_STACK_SIZE

View File

@ -0,0 +1,41 @@
section .multiboot2
align 4096
HEADER_START:
dd 0xE85250D6
dd 0
dd (HEADER_END - HEADER_START)
dd 0x100000000 - (HEADER_END - HEADER_START) - 0 - 0xE85250D6
align 8
MB2_INFO_REQUEST_TAG_START:
dw 1
dw 0
dd MB2_INFO_REQUEST_TAG_END - MB2_INFO_REQUEST_TAG_START
dd 1 ; Command Line
dd 2 ; Boot Loader Name
dd 3 ; Module
dd 4 ; Basic Memory Information
dd 5 ; BIOS Boot Device
dd 6 ; Memory Map
dd 7 ; VBE
dd 8 ; Framebuffer
dd 9 ; ELF Sections
dd 10 ; APM Table
dd 11 ; EFI 32-bit System Table Pointer
dd 12 ; EFI 64-bit System Table Pointer
; dd 13 ; SMBIOS
dd 14 ; ACPI Old
dd 15 ; ACPI New
dd 16 ; Network
dd 17 ; EFI Memory Map
dd 18 ; EFI Boot Services Notifier
dd 19 ; EFI 32-bit Image Handle Pointer
dd 20 ; EFI 64-bit Image Handle Pointer
dd 21 ; Load Base Address
MB2_INFO_REQUEST_TAG_END:
align 8
MB2_TAG_START:
dw 0
dw 0
dd MB2_TAG_END - MB2_TAG_START
MB2_TAG_END:
HEADER_END:

View File

@ -0,0 +1,13 @@
KERNEL_VIRTUAL_BASE equ 0xC0000000 ; 3GB
KERNEL_PAGE_NUMBER equ (KERNEL_VIRTUAL_BASE >> 22) ; 768
section .data
global BootPageTable
align 0x1000
BootPageTable:
dd 0x00000083
dd 0x00000083
times (KERNEL_PAGE_NUMBER - 2) dd 0
dd 0x00000083
dd 0x00000083
times (1024 - KERNEL_PAGE_NUMBER - 2) dd 0

View File

@ -0,0 +1,339 @@
#include <types.h>
#include <boot/protocols/multiboot2.h>
#include <memory.hpp>
#include <io.h>
#include "../../../kernel.h"
BootInfo mb2binfo;
enum VideoType
{
VIDEO_TYPE_NONE = 0x00,
VIDEO_TYPE_COLOUR = 0x20,
VIDEO_TYPE_MONOCHROME = 0x30,
};
uint16_t GetBiosAreaHardware()
{
const uint16_t *BIOSDataAreaDetectedHardware = (const uint16_t *)0x410;
return *BIOSDataAreaDetectedHardware;
}
enum VideoType GetVideoType() { return (enum VideoType)(GetBiosAreaHardware() & 0x30); }
void GetSMBIOS()
{
unsigned char *SMBIOSAddress = (unsigned char *)0xF0000;
while ((unsigned int)(unsigned long)SMBIOSAddress < 0x100000)
{
if (SMBIOSAddress[0] == '_' &&
SMBIOSAddress[1] == 'S' &&
SMBIOSAddress[2] == 'M' &&
SMBIOSAddress[3] == '_')
{
unsigned char Checksum = 0;
int Length = SMBIOSAddress[5];
for (int i = 0; i < Length; i++)
Checksum += SMBIOSAddress[i];
if (Checksum == 0)
break;
}
SMBIOSAddress += 16;
}
if ((unsigned int)(unsigned long)SMBIOSAddress == 0x100000)
{
// No SMBIOS found
}
}
void ProcessMB2(unsigned long Info)
{
uint8_t *VideoBuffer = (uint8_t *)0xB8F00 + 0xC0000000;
int pos = 0;
auto InfoAddress = Info;
for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8);
;
Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7)))
{
VideoBuffer[pos++] = '.';
VideoBuffer[pos++] = 0x2;
if (Tag->type == MULTIBOOT_TAG_TYPE_END)
{
debug("End of multiboot2 tags");
break;
}
switch (Tag->type)
{
case MULTIBOOT_TAG_TYPE_CMDLINE:
{
strncpy(mb2binfo.Kernel.CommandLine,
((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string));
debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine);
break;
}
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
{
strncpy(mb2binfo.Bootloader.Name,
((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string));
debug("Bootloader name: %s", mb2binfo.Bootloader.Name);
break;
}
case MULTIBOOT_TAG_TYPE_MODULE:
{
multiboot_tag_module *module = (multiboot_tag_module *)Tag;
static int module_count = 0;
mb2binfo.Modules[module_count++].Address = (void *)module->mod_start;
mb2binfo.Modules[module_count++].Size = module->size;
strncpy(mb2binfo.Modules[module_count++].Path, "(null)", 6);
strncpy(mb2binfo.Modules[module_count++].CommandLine, module->cmdline,
strlen(module->cmdline));
debug("Module: %s", mb2binfo.Modules[module_count++].Path);
break;
}
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
{
multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag;
fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]",
meminfo->mem_lower, meminfo->mem_upper);
break;
}
case MULTIBOOT_TAG_TYPE_BOOTDEV:
{
multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag;
fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]",
bootdev->biosdev, bootdev->slice, bootdev->part);
break;
}
case MULTIBOOT_TAG_TYPE_MMAP:
{
multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag;
uint32_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry);
mb2binfo.Memory.Entries = EntryCount;
for (uint32_t i = 0; i < EntryCount; i++)
{
if (EntryCount > MAX_MEMORY_ENTRIES)
{
warn("Too many memory entries, skipping the rest...");
break;
}
multiboot_mmap_entry entry = mmap->entries[i];
mb2binfo.Memory.Size += entry.len;
switch (entry.type)
{
case MULTIBOOT_MEMORY_AVAILABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = Usable;
break;
case MULTIBOOT_MEMORY_RESERVED:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = Reserved;
break;
case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = ACPIReclaimable;
break;
case MULTIBOOT_MEMORY_NVS:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = ACPINVS;
break;
case MULTIBOOT_MEMORY_BADRAM:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = BadMemory;
break;
default:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = entry.len;
mb2binfo.Memory.Entry[i].Type = Unknown;
break;
}
debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]",
mb2binfo.Memory.Entry[i].BaseAddress,
mb2binfo.Memory.Entry[i].Length,
mb2binfo.Memory.Entry[i].Type);
}
break;
}
case MULTIBOOT_TAG_TYPE_VBE:
{
multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag;
fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]",
vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len);
break;
}
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
{
multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag;
static int fb_count = 0;
mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width;
mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height;
mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch;
mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp;
mb2binfo.Framebuffer[fb_count].MemoryModel = fb->common.framebuffer_type;
switch (fb->common.framebuffer_type)
{
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
{
fixme("indexed");
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
{
mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size;
mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position;
mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size;
mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position;
mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size;
mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
break;
}
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
{
fixme("ega_text");
break;
}
}
debug("Framebuffer %d: %dx%d %d bpp", Tag, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp);
debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d",
fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type,
fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size,
fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position);
fb_count++;
break;
}
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
{
multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag;
fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]",
elf->num, elf->size, elf->entsize, elf->shndx);
break;
}
case MULTIBOOT_TAG_TYPE_APM:
{
multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag;
fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]",
apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len);
break;
}
case MULTIBOOT_TAG_TYPE_EFI32:
{
multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag;
fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size);
break;
}
case MULTIBOOT_TAG_TYPE_EFI64:
{
multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag;
fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size);
break;
}
case MULTIBOOT_TAG_TYPE_SMBIOS:
{
multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag;
fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor);
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_OLD:
{
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
debug("OLD ACPI RSDP: %p", mb2binfo.RSDP);
break;
}
case MULTIBOOT_TAG_TYPE_ACPI_NEW:
{
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
debug("NEW ACPI RSDP: %p", mb2binfo.RSDP);
break;
}
case MULTIBOOT_TAG_TYPE_NETWORK:
{
multiboot_tag_network *net = (multiboot_tag_network *)Tag;
fixme("network->[dhcpack: %p]", net->dhcpack);
break;
}
case MULTIBOOT_TAG_TYPE_EFI_MMAP:
{
multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag;
fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]",
efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap);
break;
}
case MULTIBOOT_TAG_TYPE_EFI_BS:
{
fixme("efi_bs->[%p] (unknown structure)", Tag);
break;
}
case MULTIBOOT_TAG_TYPE_EFI32_IH:
{
multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag;
fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer);
break;
}
case MULTIBOOT_TAG_TYPE_EFI64_IH:
{
multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag;
fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer);
break;
}
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
{
multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag;
mb2binfo.Kernel.PhysicalBase = (void *)load_base_addr->load_base_addr;
mb2binfo.Kernel.VirtualBase = (void *)(load_base_addr->load_base_addr + 0xC0000000);
debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase);
break;
}
default:
{
error("Unknown multiboot2 tag type: %d", Tag->type);
break;
}
}
}
}
EXTERNC void Multiboot2Entry(unsigned long Info, unsigned int Magic)
{
if (Info == NULL || Magic == NULL)
{
if (Magic == NULL)
error("Multiboot magic is NULL");
if (Info == NULL)
error("Multiboot info is NULL");
CPU::Stop();
}
else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC)
{
error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC);
CPU::Stop();
}
uint64_t div = 1193180 / 1000;
outb(0x43, 0xB6);
outb(0x42, (uint8_t)div);
outb(0x42, (uint8_t)(div >> 8));
uint8_t tmp = inb(0x61);
if (tmp != (tmp | 3))
outb(0x61, tmp | 3);
ProcessMB2(Info);
tmp = inb(0x61) & 0xFC;
outb(0x61, tmp);
CPU::Stop();
Entry(&mb2binfo);
}

View File

@ -0,0 +1,123 @@
#include "pic.hpp"
#include <io.h>
namespace PIC
{
PIC::PIC(uint8_t MasterCommandPort, uint8_t MasterDataPort, uint8_t SlaveCommandPort, uint8_t SlaveDataPort, uint8_t MasterOffset, uint8_t SlaveOffset)
{
this->MasterCommandPort = MasterCommandPort;
this->MasterDataPort = MasterDataPort;
this->SlaveCommandPort = SlaveCommandPort;
this->SlaveDataPort = SlaveDataPort;
this->MasterOffset = MasterOffset;
this->SlaveOffset = SlaveOffset;
MasterMask = 0xFF;
SlaveMask = 0xFF;
// ICW1
outb(MasterCommandPort, 0x11);
outb(SlaveCommandPort, 0x11);
// ICW2
outb(MasterDataPort, MasterOffset);
outb(SlaveDataPort, SlaveOffset);
// ICW3
outb(MasterDataPort, 0x04);
outb(SlaveDataPort, 0x02);
// ICW4
outb(MasterDataPort, 0x01);
outb(SlaveDataPort, 0x01);
// OCW1
outb(MasterDataPort, MasterMask);
outb(SlaveDataPort, SlaveMask);
}
PIC::~PIC()
{
outb(MasterDataPort, 0xFF);
outb(SlaveDataPort, 0xFF);
}
void PIC::Mask(uint8_t IRQ)
{
uint16_t Port;
uint8_t Value;
if (IRQ < 8)
{
Port = MasterDataPort;
Value = MasterMask & ~(1 << IRQ);
MasterMask = Value;
}
else
{
Port = SlaveDataPort;
Value = SlaveMask & ~(1 << (IRQ - 8));
SlaveMask = Value;
}
outb(Port, Value);
}
void PIC::Unmask(uint8_t IRQ)
{
uint16_t Port;
uint8_t Value;
if (IRQ < 8)
{
Port = MasterDataPort;
Value = MasterMask | (1 << IRQ);
MasterMask = Value;
}
else
{
Port = SlaveDataPort;
Value = SlaveMask | (1 << (IRQ - 8));
SlaveMask = Value;
}
outb(Port, Value);
}
void PIC::SendEOI(uint8_t IRQ)
{
if (IRQ >= 8)
outb(SlaveCommandPort, 0x20);
outb(MasterCommandPort, 0x20);
}
PIT::PIT(uint16_t Port, uint16_t Frequency)
{
this->Port = Port;
this->Frequency = Frequency;
}
PIT::~PIT()
{
}
void PIT::PrepareSleep(uint32_t Milliseconds)
{
uint16_t Divisor = 1193182 / Frequency;
uint8_t Low = (uint8_t)(Divisor & 0xFF);
uint8_t High = (uint8_t)((Divisor >> 8) & 0xFF);
outb(Port + 3, 0x36);
outb(Port + 0, Low);
outb(Port + 1, High);
}
void PIT::PerformSleep()
{
uint8_t Value = inb(Port + 0);
while (Value != 0)
Value = inb(Port + 0);
}
}

View File

@ -0,0 +1,42 @@
#ifndef __FENNIX_KERNEL_8259PIC_H__
#define __FENNIX_KERNEL_8259PIC_H__
#include <types.h>
namespace PIC
{
class PIC
{
private:
uint8_t MasterCommandPort;
uint8_t MasterDataPort;
uint8_t SlaveCommandPort;
uint8_t SlaveDataPort;
uint8_t MasterOffset;
uint8_t SlaveOffset;
uint8_t MasterMask;
uint8_t SlaveMask;
public:
PIC(uint8_t MasterCommandPort, uint8_t MasterDataPort, uint8_t SlaveCommandPort, uint8_t SlaveDataPort, uint8_t MasterOffset, uint8_t SlaveOffset);
~PIC();
void Mask(uint8_t IRQ);
void Unmask(uint8_t IRQ);
void SendEOI(uint8_t IRQ);
};
class PIT
{
private:
uint16_t Port;
uint16_t Frequency;
public:
PIT(uint16_t Port, uint16_t Frequency);
~PIT();
void PrepareSleep(uint32_t Milliseconds);
void PerformSleep();
};
}
#endif // !__FENNIX_KERNEL_8259PIC_H__

View File

@ -0,0 +1,13 @@
#include <syscalls.hpp>
#include <cpu.hpp>
#include "cpu/gdt.hpp"
using namespace CPU::x32;
extern "C" uint32_t SystemCallsHandler(SyscallsFrame *regs);
void InitializeSystemCalls()
{
}

View File

@ -0,0 +1,99 @@
#include "gdt.hpp"
#include <memory.hpp>
#include <smp.hpp>
#include <cpu.hpp>
#include <debug.h>
namespace GlobalDescriptorTable
{
static GlobalDescriptorTableEntries GDTEntriesTemplate = {
// null
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.Raw = 0x0},
.Flags = {.Raw = 0x0},
.BaseHigh = 0x0},
// kernel code
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.A = 0,
.RW = 1,
.DC = 0,
.E = 1,
.S = 1,
.DPL = 0,
.P = 1},
.Flags = {.Unknown = 0x0, .L = 1},
.BaseHigh = 0x0},
// kernel data
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.A = 0,
.RW = 1,
.DC = 0,
.E = 0,
.S = 1,
.DPL = 0,
.P = 1},
.Flags = {.Raw = 0x0},
.BaseHigh = 0x0},
// user data
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.A = 0,
.RW = 1,
.DC = 0,
.E = 0,
.S = 1,
.DPL = 3,
.P = 1},
.Flags = {.Raw = 0x0},
.BaseHigh = 0x0},
// user code
{.Length = 0x0,
.BaseLow = 0x0,
.BaseMiddle = 0x0,
.Access = {.A = 0,
.RW = 1,
.DC = 0,
.E = 1,
.S = 1,
.DPL = 3,
.P = 1},
.Flags = {.Unknown = 0x0, .L = 1},
.BaseHigh = 0x0},
// tss
{}};
GlobalDescriptorTableEntries GDTEntries[MAX_CPU];
GlobalDescriptorTableDescriptor gdt[MAX_CPU];
TaskStateSegment tss[MAX_CPU] = {
0,
{0, 0, 0},
0,
{0, 0, 0, 0, 0, 0, 0},
0,
0,
};
void *CPUStackPointer[MAX_CPU];
SafeFunction void Init(int Core)
{
}
SafeFunction void SetKernelStack(void *Stack)
{
}
}

View File

@ -0,0 +1,37 @@
#include <smp.hpp>
#include <ints.hpp>
#include <memory.hpp>
#include <assert.h>
#include <cpu.hpp>
#include "../../../kernel.h"
volatile bool CPUEnabled = false;
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
static __attribute__((aligned(PAGE_SIZE))) CPUData CPUs[MAX_CPU] = {0};
CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
CPUData *GetCurrentCPU()
{
uint64_t ret = 0;
if (!(&CPUs[ret])->IsActive)
{
error("CPU %d is not active!", ret);
return &CPUs[0];
}
assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM);
return &CPUs[ret];
}
namespace SMP
{
int CPUCores = 0;
void Initialize(void *madt)
{
fixme("SMP::Initialize() is not implemented!");
}
}

View File

@ -0,0 +1,337 @@
#ifndef __FENNIX_KERNEL_APIC_H__
#define __FENNIX_KERNEL_APIC_H__
#include <types.h>
#include <ints.hpp>
#include <cpu.hpp>
namespace APIC
{
enum APICRegisters
{
// source from: https://github.com/pdoane/osdev/blob/master/intr/local_apic.c
APIC_ID = 0x20, // Local APIC ID
APIC_VER = 0x30, // Local APIC Version
APIC_TPR = 0x80, // Task Priority
APIC_APR = 0x90, // Arbitration Priority
APIC_PPR = 0xA0, // Processor Priority
APIC_EOI = 0xB0, // EOI
APIC_RRD = 0xC0, // Remote Read
APIC_LDR = 0xD0, // Logical Destination
APIC_DFR = 0xE0, // Destination Format
APIC_SVR = 0xF0, // Spurious Interrupt Vector
APIC_ISR = 0x100, // In-Service (8 registers)
APIC_TMR = 0x180, // Trigger Mode (8 registers)
APIC_IRR = 0x200, // Interrupt Request (8 registers)
APIC_ESR = 0x280, // Error Status
APIC_ICRLO = 0x300, // Interrupt Command
APIC_ICRHI = 0x310, // Interrupt Command [63:32]
APIC_TIMER = 0x320, // LVT Timer
APIC_THERMAL = 0x330, // LVT Thermal Sensor
APIC_PERF = 0x340, // LVT Performance Counter
APIC_LINT0 = 0x350, // LVT LINT0
APIC_LINT1 = 0x360, // LVT LINT1
APIC_ERROR = 0x370, // LVT Error
APIC_TICR = 0x380, // Initial Count (for Timer)
APIC_TCCR = 0x390, // Current Count (for Timer)
APIC_TDCR = 0x3E0, // Divide Configuration (for Timer)
};
enum IOAPICRegisters
{
GetIOAPICVersion = 0x1
};
enum IOAPICFlags
{
ActiveHighLow = 2,
EdgeLevel = 8
};
enum APICDeliveryMode
{
Fixed = 0b000,
LowestPriority = 0b001, /* Reserved */
SMI = 0b010,
APIC_DELIVERY_MODE_RESERVED0 = 0b011, /* Reserved */
NMI = 0b100,
INIT = 0b101,
Startup = 0b110,
ExtINT = 0b111 /* Reserved */
};
enum APICDestinationMode
{
Physical = 0b0,
Logical = 0b1
};
enum APICDeliveryStatus
{
Idle = 0b0,
SendPending = 0b1
};
enum APICLevel
{
DeAssert = 0b0,
Assert = 0b1
};
enum APICTriggerMode
{
Edge = 0b0,
Level = 0b1
};
enum APICDestinationShorthand
{
NoShorthand = 0b00,
Self = 0b01,
AllIncludingSelf = 0b10,
AllExcludingSelf = 0b11
};
enum LVTTimerDivide
{
DivideBy2 = 0b000,
DivideBy4 = 0b001,
DivideBy8 = 0b010,
DivideBy16 = 0b011,
DivideBy32 = 0b100,
DivideBy64 = 0b101,
DivideBy128 = 0b110,
DivideBy1 = 0b111
};
enum LVTTimerMask
{
Unmasked = 0b0,
Masked = 0b1
};
enum LVTTimerMode
{
OneShot = 0b00,
Periodic = 0b01,
TSCDeadline = 0b10
};
typedef union
{
struct
{
/** @brief Interrupt Vector */
uint64_t Vector : 8;
/** @brief Reserved */
uint64_t Reserved0 : 4;
/**
* @brief Delivery Status
*
* 0: Idle
* 1: Send Pending
*/
uint64_t DeliveryStatus : 1;
/** @brief Reserved */
uint64_t Reserved1 : 3;
/**
* @brief Mask
*
* 0: Not masked
* 1: Masked
*/
uint64_t Mask : 1;
/** @brief Timer Mode
*
* 0: One-shot
* 1: Periodic
* 2: TSC-Deadline
*/
uint64_t TimerMode : 1;
/** @brief Reserved */
uint64_t Reserved2 : 14;
};
uint64_t raw;
} __attribute__((packed)) LVTTimer;
typedef union
{
struct
{
/** @brief Spurious Vector */
uint64_t Vector : 8;
/** @brief Enable or disable APIC software */
uint64_t Software : 1;
/** @brief Focus Processor Checking */
uint64_t FocusProcessorChecking : 1;
/** @brief Reserved */
uint64_t Reserved : 2;
/** @brief Disable EOI Broadcast */
uint64_t DisableEOIBroadcast : 1;
/** @brief Reserved */
uint64_t Reserved1 : 19;
};
uint64_t raw;
} __attribute__((packed)) Spurious;
typedef union
{
struct
{
/** @brief Interrupt Vector */
uint64_t Vector : 8;
/** @brief Delivery Mode */
uint64_t DeliveryMode : 3;
/** @brief Destination Mode
*
* 0: Physical
* 1: Logical
*/
uint64_t DestinationMode : 1;
/** @brief Delivery Status
*
* @note Reserved when in x2APIC mode
*/
uint64_t DeliveryStatus : 1;
/** @brief Reserved */
uint64_t Reserved0 : 1;
/** @brief Level
*
* 0: Deassert
* 1: Assert
*/
uint64_t Level : 1;
/** @brief Trigger Mode
*
* 0: Edge
* 1: Level
*/
uint64_t TriggerMode : 1;
/** @brief Reserved */
uint64_t Reserved1 : 2;
/** @brief Destination Shorthand
*
* 0: No shorthand
* 1: Self
* 2: All including self
* 3: All excluding self
*/
uint64_t DestinationShorthand : 2;
/** @brief Reserved */
uint64_t Reserved2 : 12;
};
uint64_t raw;
} __attribute__((packed)) InterruptCommandRegisterLow;
typedef union
{
struct
{
/** @brief Reserved */
uint64_t Reserved0 : 24;
/** @brief Destination */
uint64_t Destination : 8;
};
uint64_t raw;
} __attribute__((packed)) InterruptCommandRegisterHigh;
typedef union
{
struct
{
/** @brief Interrupt Vector */
uint64_t Vector : 8;
/** @brief Delivery Mode */
uint64_t DeliveryMode : 3;
/** @brief Destination Mode
*
* 0: Physical
* 1: Logical
*/
uint64_t DestinationMode : 1;
/** @brief Delivery Status */
uint64_t DeliveryStatus : 1;
/** @brief Interrupt Input Pin Polarity
*
* 0: Active High
* 1: Active Low
*/
uint64_t Polarity : 1;
/** @brief Remote IRR */
uint64_t RemoteIRR : 1;
/** @brief Trigger Mode
*
* 0: Edge
* 1: Level
*/
uint64_t TriggerMode : 1;
/** @brief Mask */
uint64_t Mask : 1;
/** @brief Reserved */
uint64_t Reserved0 : 15;
/** @brief Reserved */
uint64_t Reserved1 : 24;
/** @brief Destination */
uint64_t DestinationID : 8;
};
struct
{
uint64_t Low;
uint64_t High;
} split;
uint64_t raw;
} __attribute__((packed)) IOAPICRedirectEntry;
typedef union
{
struct
{
uint64_t Version : 8;
uint64_t Reserved : 8;
uint64_t MaximumRedirectionEntry : 8;
uint64_t Reserved2 : 8;
};
uint64_t raw;
} __attribute__((packed)) IOAPICVersion;
class APIC
{
private:
bool x2APICSupported = false;
uint64_t APICBaseAddress = 0;
public:
uint32_t Read(uint32_t Register);
void Write(uint32_t Register, uint32_t Value);
void IOWrite(uint64_t Base, uint32_t Register, uint32_t Value);
uint32_t IORead(uint64_t Base, uint32_t Register);
void EOI();
void RedirectIRQs(int CPU = 0);
void WaitForIPI();
void IPI(uint8_t CPU, InterruptCommandRegisterLow icr);
void SendInitIPI(uint8_t CPU);
void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress);
uint32_t IOGetMaxRedirect(uint32_t APICID);
void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
void RedirectIRQ(int CPU, uint16_t IRQ, int Status);
APIC(int Core);
~APIC();
};
class Timer : public Interrupts::Handler
{
private:
APIC *lapic;
uint64_t Ticks = 0;
void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
public:
uint64_t GetTicks() { return Ticks; }
void OneShot(uint32_t Vector, uint64_t Miliseconds);
Timer(APIC *apic);
~Timer();
};
}
#endif // !__FENNIX_KERNEL_APIC_H__

View File

@ -0,0 +1,145 @@
#ifndef __FENNIX_KERNEL_GDT_H__
#define __FENNIX_KERNEL_GDT_H__
#include <types.h>
namespace GlobalDescriptorTable
{
/** @brief The GDT Access Table
* @details For more information, see https://wiki.osdev.org/Global_Descriptor_Table
*/
union GlobalDescriptorTableAccess
{
struct
{
/** @brief Access bit.
* @note The CPU sets this bit to 1 when the segment is accessed.
*/
uint8_t A : 1;
/** @brief Readable bit for code segments, writable bit for data segments.
* @details For code segments, this bit must be 1 for the segment to be readable.
* @details For data segments, this bit must be 1 for the segment to be writable.
*/
uint8_t RW : 1;
/** @brief Direction bit for data segments, conforming bit for code segments.
* @details For data segments, this bit must be 1 for the segment to grow up (higher addresses).
* @details For code segments, this bit must be 1 for code in the segment to be able to be executed from an equal or lower privilege level.
*/
uint8_t DC : 1;
/** @brief Executable bit.
* @details This bit must be 1 for code-segment descriptors.
* @details This bit must be 0 for data-segment and system descriptors.
*/
uint8_t E : 1;
/** @brief Descriptor type.
* @details This bit must be 0 for system descriptors.
* @details This bit must be 1 for code or data segment descriptor.
*/
uint8_t S : 1;
/** @brief Descriptor privilege level.
* @details This field determines the privilege level of the segment.
* @details 0 = kernel mode, 3 = user mode.
*/
uint8_t DPL : 2;
/** @brief Present bit.
* @details This bit must be 1 for all valid descriptors.
*/
uint8_t P : 1;
} __attribute__((packed));
uint8_t Raw;
};
union GlobalDescriptorTableFlags
{
// TODO: Add more flags.
struct
{
/** @brief Unknown. */
uint8_t Unknown : 5;
/** @brief Long mode.
* @details If the long mode bit is clear, the segment is in 32-bit protected mode.
* @details If the long mode bit is set, the segment is in 64-bit long mode.
*/
uint8_t L : 1;
} __attribute__((packed));
uint8_t Raw;
};
typedef struct _TaskStateSegmentEntry
{
/* LOW */
uint16_t Length;
uint16_t BaseLow;
uint8_t BaseMiddle;
GlobalDescriptorTableAccess Flags;
uint8_t Granularity;
uint8_t BaseHigh;
/* HIGH */
uint32_t BaseUpper;
uint32_t Reserved;
} __attribute__((packed)) TaskStateSegmentEntry;
typedef struct _TaskStateSegment
{
uint32_t Reserved0 __attribute__((aligned(16)));
uint64_t StackPointer[3];
uint64_t Reserved1;
uint64_t InterruptStackTable[7];
uint16_t Reserved2;
uint16_t IOMapBaseAddressOffset;
} __attribute__((packed)) TaskStateSegment;
typedef struct _GlobalDescriptorTableEntry
{
/** @brief Length */
uint16_t Length;
/** @brief Low Base */
uint16_t BaseLow;
/** @brief Middle Base */
uint8_t BaseMiddle;
/** @brief Access */
GlobalDescriptorTableAccess Access;
/** @brief Flags */
GlobalDescriptorTableFlags Flags;
/** @brief High Base */
uint8_t BaseHigh;
} __attribute__((packed)) GlobalDescriptorTableEntry;
typedef struct _GlobalDescriptorTableEntries
{
GlobalDescriptorTableEntry Null;
GlobalDescriptorTableEntry Code;
GlobalDescriptorTableEntry Data;
GlobalDescriptorTableEntry UserData;
GlobalDescriptorTableEntry UserCode;
TaskStateSegmentEntry TaskStateSegment;
} __attribute__((packed)) GlobalDescriptorTableEntries;
typedef struct _GlobalDescriptorTableDescriptor
{
/** @brief GDT entries length */
uint16_t Length;
/** @brief GDT entries address */
GlobalDescriptorTableEntries *Entries;
} __attribute__((packed)) GlobalDescriptorTableDescriptor;
extern void *CPUStackPointer[];
extern TaskStateSegment tss[];
void Init(int Core);
void SetKernelStack(void *Stack);
}
#define GDT_KERNEL_CODE offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Code)
#define GDT_KERNEL_DATA offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, Data)
#define GDT_USER_CODE (offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, UserCode) | 3)
#define GDT_USER_DATA (offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, UserData) | 3)
#define GDT_TSS (offsetof(GlobalDescriptorTable::GlobalDescriptorTableEntries, TaskStateSegment) | 3)
#endif // !__FENNIX_KERNEL_GDT_H__

View File

@ -0,0 +1,11 @@
#ifndef __FENNIX_KERNEL_IDT_H__
#define __FENNIX_KERNEL_IDT_H__
#include <types.h>
namespace InterruptDescriptorTable
{
void Init(int Core);
}
#endif // !__FENNIX_KERNEL_IDT_H__

View File

@ -0,0 +1,59 @@
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386)
ENTRY(MB2_start)
SECTIONS
{
. = 0xC0100000;
_kernel_start = .;
.text ALIGN(4096) : AT(ADDR(.text) - 0xC0000000)
{
*(.multiboot2)
*(.text .text.*)
}
_kernel_text_end = .;
.data ALIGN (4096) : AT(ADDR(.data) - 0xC0000000)
{
*(.data .data.*)
}
_kernel_data_end = .;
.rodata ALIGN (4096) : AT(ADDR(.rodata) - 0xC0000000)
{
*(.rodata .rodata.*)
}
_kernel_rodata_end = .;
.init_array :
{
PROVIDE_HIDDEN(__init_array_start = .);
KEEP(*(.init_array .ctors))
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN(__fini_array_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP(*(.fini_array .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
. += CONSTANT(MAXPAGESIZE);
.bss ALIGN (4096) : AT(ADDR(.bss) - 0xC0000000)
{
*(COMMON)
*(.bss .bss.*)
}
_kernel_end = .;
/DISCARD/ :
{
*(.comment*)
*(.note*)
}
}

View File

@ -0,0 +1,15 @@
// #include <types.h>
// #include <debug.h>
// int Entry(void *Info);
// void _start(void *Raw)
// {
// error("Todo");
// while (1)
// asmv("hlt");
// Entry(NULL);
// return;
// }
// C stuff

View File

@ -0,0 +1,15 @@
#include <types.h>
#include <debug.h>
int Entry(void *Info);
void _start(void *Raw)
{
UNUSED(Raw);
error("ERROR! INVALID BOOT PROTOCOL!");
while (1)
asmv("hlt");
Entry(NULL);
return;
}

View File

@ -0,0 +1 @@
// C++ constructor/destructor stuff

View File

@ -0,0 +1 @@
// C++ constructor/destructor stuff

View File

@ -0,0 +1,13 @@
.section .init
.global _init
.type _init, @function
_init:
push %ebp
mov %esp, %ebp
.section .fini
.global _fini
.type _fini, @function
_fini:
push %ebp
mov %esp, %ebp

View File

@ -0,0 +1,7 @@
.section .init
pop %ebp
ret
.section .fini
pop %ebp
ret