basic 64 bit loading

alentours-dev
Sergiusz Bazanski 2011-06-28 13:15:42 +02:00
parent 164ea30d44
commit 1dba384739
79 changed files with 34031 additions and 191 deletions

View File

@ -10,8 +10,8 @@ u32 acpi_find_rsdp(void)
// Try to find the pointer... apparently it's 16byte-aligned...
u32 Address = 0;
for (u32 Search = 0x000E0000; Search <= 0x000FFFFF; Search += 4)
u64 Address = 0;
for (u64 Search = 0x000E0000; Search <= 0x000FFFFF; Search += 4)
{
if (kmemcmp((u8 *)Search, (u8 *)szMagic, 8) == 0)
{

View File

@ -3,15 +3,15 @@
#include "Tier0/cpp.h"
#include "Tier0/kstdio.h"
extern u32 g_start_ctors;
extern u32 g_end_ctors;
extern u64 g_start_ctors;
extern u64 g_end_ctors;
void CKernelStart(void);
void cpp_call_ctors(void)
{
u32 Number = ((void *)&g_end_ctors - (void *)&g_start_ctors) / 4;
kprintf("[i] Calling %i constructors before jumping to Tier1..\n", Number);
for(u32 *C = (u32*)&g_start_ctors; C < (u32*)&g_end_ctors; ++C)
for(u64 *C = (u64*)&g_start_ctors; C < (u64*)&g_end_ctors; ++C)
{
((void (*) (void)) (*C)) ();
}

View File

@ -30,7 +30,7 @@ void exceptions_division_by_zero_isr(T_ISR_REGISTERS Registers)
void exceptions_page_fault_isr(T_ISR_REGISTERS_ERR Registers)
{
u32 FaultAddress;
u64 FaultAddress;
__asm__ volatile("mov %%cr2, %0" : "=r" (FaultAddress));
u8 Present = !(Registers.Error & 0x01);

View File

@ -34,7 +34,7 @@ void gdt_entry_create_null(u8 Index)
void gdt_create_flat(void)
{
g_gdt_ptr.Size = sizeof(T_GDT_ENTRY) * 6 - 1;
g_gdt_ptr.Address = (u32)&g_gdt_entries;
g_gdt_ptr.Address = (u64)&g_gdt_entries;
gdt_entry_create_null(0);
gdt_entry_create(1, 0, 0xFFFFFFFF, GDT_RING0, GDT_EXECUTABLE, GDT_RW);

View File

@ -60,9 +60,9 @@ void heap_index_remove(T_HEAP_INDEX *Index, u32 Position)
Index->Size--;
}
T_HEAP *heap_create(u32 Start, u32 End, u32 Max)
T_HEAP *heap_create(u64 Start, u64 End, u64 Max)
{
u32 NumPages = (End - Start ) / (1024 * 4);
u64 NumPages = (End - Start ) / (1024 * 4);
if ((End - Start) % (1024 * 4) != 0)
NumPages++;
@ -70,8 +70,8 @@ T_HEAP *heap_create(u32 Start, u32 End, u32 Max)
NumPages, (End - Start) / 0x100000);
for (int i = 0; i < NumPages; i++)
{
u32 Page = physmem_allocate_page();
u32 Physical = physmem_page_to_physical(Page);
u64 Page = physmem_allocate_page();
u64 Physical = physmem_page_to_physical(Page);
paging_map_kernel_page(Start + i * 1024 * 4, Physical);
}
@ -96,21 +96,21 @@ T_HEAP *heap_create(u32 Start, u32 End, u32 Max)
return Heap;
}
s32 _heap_find_smallest_hole(T_HEAP *Heap, u32 Size, u8 Aligned)
s32 _heap_find_smallest_hole(T_HEAP *Heap, u64 Size, u8 Aligned)
{
u32 Iterator = 0;
u64 Iterator = 0;
while (Iterator < Heap->Index.Size)
{
T_HEAP_HEADER *Header = heap_index_get(&Heap->Index, Iterator);
if (Aligned > 0)
{
u32 Location = (u32)Header;
u32 Offset = 0;
u64 Location = (u64)Header;
u64 Offset = 0;
if (((Location + sizeof(T_HEAP_HEADER)) & 0xFFFFF000) != 0)
Offset = 0x1000 - (Location + sizeof(T_HEAP_HEADER)) % 0x1000;
u32 HoleSize = (u32)Header->Size - Offset;
u32 HoleSize = (u64)Header->Size - Offset;
if (HoleSize >= Size)
break;
@ -126,23 +126,23 @@ s32 _heap_find_smallest_hole(T_HEAP *Heap, u32 Size, u8 Aligned)
return Iterator;
}
void _heap_expand(T_HEAP *Heap, u32 Size)
void _heap_expand(T_HEAP *Heap, u64 Size)
{
u16 NumPages = Size / 0x1000;
if (Size % 0x1000 != 0)
NumPages++;
for (u32 i = 0; i < NumPages; i++)
for (u64 i = 0; i < NumPages; i++)
{
u32 Page = physmem_allocate_page();
u32 Physical = physmem_page_to_physical(Page);
u64 Page = physmem_allocate_page();
u64 Physical = physmem_page_to_physical(Page);
paging_map_kernel_page(Heap->End + i * 0x1000, Physical);
}
Heap->End = Heap->Start + NumPages * 0x1000;
}
u32 _heap_contract(T_HEAP *Heap, u32 Size)
u32 _heap_contract(T_HEAP *Heap, u64 Size)
{
if (Size & 0x1000)
{
@ -153,15 +153,15 @@ u32 _heap_contract(T_HEAP *Heap, u32 Size)
if (Size < HEAP_MIN_SIZE)
Size = HEAP_MIN_SIZE;
u32 OldSize = Heap->End - Heap->Start;
u32 NumberToDelete = (OldSize - Size) / 0x1000;
u64 OldSize = Heap->End - Heap->Start;
u64 NumberToDelete = (OldSize - Size) / 0x1000;
for (int i = 0; i < NumberToDelete; i++)
{
u32 Virtual = Heap->End + i * 0x1000;
u32 Physical;
u64 Virtual = Heap->End + i * 0x1000;
u64 Physical;
paging_get_physical(Virtual, &Physical);
u32 Page = Physical / 0x1000;
u64 Page = Physical / 0x1000;
physmem_free_page(Page);
}
@ -170,35 +170,35 @@ u32 _heap_contract(T_HEAP *Heap, u32 Size)
return (Heap->End - Heap->Start);
}
void *heap_alloc_p(T_HEAP *Heap, u32 Size, u8 Aligned, u32 *Physical)
void *heap_alloc_p(T_HEAP *Heap, u64 Size, u8 Aligned, u64 *Physical)
{
void *Address = heap_alloc(Heap, Size, Aligned);
if (Physical != 0)
paging_get_physical((u32)Address, Physical);
paging_get_physical((u64)Address, Physical);
return Address;
}
void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned)
void *heap_alloc(T_HEAP *Heap, u64 Size, u8 Aligned)
{
u32 RealSize = Size + sizeof(T_HEAP_HEADER) + sizeof(T_HEAP_FOOTER);
s32 Iterator = _heap_find_smallest_hole(Heap, RealSize, Aligned);
u64 RealSize = Size + sizeof(T_HEAP_HEADER) + sizeof(T_HEAP_FOOTER);
s64 Iterator = _heap_find_smallest_hole(Heap, RealSize, Aligned);
if (Iterator == -1)
{
u32 OldSize = Heap->End - Heap->Start;
u32 OldEnd = Heap->End;
u64 OldSize = Heap->End - Heap->Start;
u64 OldEnd = Heap->End;
_heap_expand(Heap, OldSize + RealSize);
u32 NewSize = Heap->End - Heap->Start;
u64 NewSize = Heap->End - Heap->Start;
Iterator = 0;
u32 Last = 0;
s32 LastIndex = -1;
u64 Last = 0;
s64 LastIndex = -1;
while (Iterator < Heap->Index.Size)
{
u32 Location = (u32)heap_index_get(&Heap->Index, Iterator);
u64 Location = (u64)heap_index_get(&Heap->Index, Iterator);
if (Location > Last)
{
Last = Location;
@ -226,7 +226,7 @@ void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned)
T_HEAP_HEADER *Header = (T_HEAP_HEADER *)Last;
Header->Size += NewSize - OldSize;
T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER *)((u32)Header
T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER *)((u64)Header
+ Header->Size - sizeof(T_HEAP_FOOTER));
Footer->Header = Header;
Footer->Magic = HEAP_FOOTER_MAGIC;
@ -237,8 +237,8 @@ void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned)
T_HEAP_HEADER *Header = (T_HEAP_HEADER*)heap_index_get(&Heap->Index,
Iterator);
u32 HoleStart = (u32)Header;
u32 HoleSize = Header->Size;
u64 HoleStart = (u64)Header;
u64 HoleSize = Header->Size;
if (HoleSize - RealSize < sizeof(T_HEAP_HEADER) + sizeof(T_HEAP_FOOTER))
{
@ -248,7 +248,7 @@ void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned)
if (Aligned && HoleStart & 0xFFFFF000)
{
u32 NewLocation = HoleStart + 0x1000 - (HoleStart & 0xFFF)
u64 NewLocation = HoleStart + 0x1000 - (HoleStart & 0xFFF)
- sizeof(T_HEAP_HEADER);
Header->Size = 0x1000 - (HoleStart & 0xFFF) - sizeof(T_HEAP_HEADER);
Header->Magic = HEAP_HEADER_MAGIC;
@ -283,10 +283,10 @@ void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned)
NewHoleHeader->Size = HoleSize - RealSize;
NewHoleHeader->Hole = 1;
T_HEAP_FOOTER *NewHoleFooter = (T_HEAP_FOOTER*)((u32)NewHoleHeader
T_HEAP_FOOTER *NewHoleFooter = (T_HEAP_FOOTER*)((u64)NewHoleHeader
+ NewHoleHeader->Size - sizeof(T_HEAP_FOOTER));
if ((u32)NewHoleFooter < Heap->End)
if ((u64)NewHoleFooter < Heap->End)
{
NewHoleFooter->Magic = HEAP_FOOTER_MAGIC;
NewHoleFooter->Header = NewHoleHeader;
@ -295,15 +295,15 @@ void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned)
heap_index_insert(&Heap->Index, (void*)NewHoleHeader);
}
return (void *)((u32)BlockHeader + sizeof(T_HEAP_HEADER));
return (void *)((u64)BlockHeader + sizeof(T_HEAP_HEADER));
}
void heap_free(T_HEAP *Heap, void *Data)
{
if (Data == 0) return;
T_HEAP_HEADER *Header = (T_HEAP_HEADER *)((u32)Data
T_HEAP_HEADER *Header = (T_HEAP_HEADER *)((u64)Data
- sizeof(T_HEAP_HEADER));
T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER *)((u32)Header + Header->Size
T_HEAP_FOOTER *Footer = (T_HEAP_FOOTER *)((u64)Header + Header->Size
- sizeof(T_HEAP_FOOTER));
if (Header->Magic != HEAP_HEADER_MAGIC)
@ -314,27 +314,27 @@ void heap_free(T_HEAP *Heap, void *Data)
u8 ShouldAdd = 1;
T_HEAP_FOOTER *FooterLeft = (T_HEAP_FOOTER *)((u32)Data
T_HEAP_FOOTER *FooterLeft = (T_HEAP_FOOTER *)((u64)Data
- sizeof(T_HEAP_FOOTER));
if (FooterLeft->Magic == HEAP_FOOTER_MAGIC && FooterLeft->Header->Hole)
{
u32 OurSize = Header->Size;
u64 OurSize = Header->Size;
Header = FooterLeft->Header;
Footer->Header = Header;
Header->Size += OurSize;
ShouldAdd = 0;
}
T_HEAP_HEADER *HeaderRight = (T_HEAP_HEADER *)((u32)Footer
T_HEAP_HEADER *HeaderRight = (T_HEAP_HEADER *)((u64)Footer
+ sizeof(T_HEAP_FOOTER));
if (HeaderRight->Magic == HEAP_HEADER_MAGIC && HeaderRight->Hole)
{
Header->Size += HeaderRight->Size;
Footer = (T_HEAP_FOOTER *)((u32)HeaderRight + HeaderRight->Size
Footer = (T_HEAP_FOOTER *)((u64)HeaderRight + HeaderRight->Size
- sizeof(T_HEAP_FOOTER));
Footer->Header = Header;
u32 Iterator = 0;
u64 Iterator = 0;
while (Iterator < Heap->Index.Size &&
heap_index_get(&Heap->Index, Iterator) != (void *)HeaderRight)
Iterator++;
@ -343,22 +343,22 @@ void heap_free(T_HEAP *Heap, void *Data)
heap_index_remove(&Heap->Index, Iterator);
}
if ((u32)Footer + sizeof(T_HEAP_FOOTER) == Heap->End)
if ((u64)Footer + sizeof(T_HEAP_FOOTER) == Heap->End)
{
u32 OldSize = Heap->End - Heap->Start;
u32 NewSize = _heap_contract(Heap, (u32)Header - Heap->Start);
u64 OldSize = Heap->End - Heap->Start;
u64 NewSize = _heap_contract(Heap, (u64)Header - Heap->Start);
if (Header->Size > (OldSize - NewSize))
{
Header->Size -= (OldSize - NewSize);
Footer = (T_HEAP_FOOTER *)((u32)Header + Header->Size
Footer = (T_HEAP_FOOTER *)((u64)Header + Header->Size
- sizeof(T_HEAP_FOOTER));
Footer->Magic = HEAP_FOOTER_MAGIC;
Footer->Header = Header;
}
else
{
u32 Iterator = 0;
u64 Iterator = 0;
while (Iterator < Heap->Index.Size &&
heap_index_get(&Heap->Index, Iterator) != (void *)Header)
Iterator++;
@ -381,12 +381,12 @@ void heap_init_simple(void)
HEAP_START + 0x0FFFF000);
}
void *kmalloc(u32 Size)
void *kmalloc(u64 Size)
{
return heap_alloc(g_heap, Size, 0);
}
void *kmalloc_p(u32 Size, u8 Aligned, u32 *Physical)
void *kmalloc_p(u64 Size, u8 Aligned, u64 *Physical)
{
return heap_alloc_p(g_heap, Size, Aligned, Physical);
}

65
Loader/Makefile Normal file
View File

@ -0,0 +1,65 @@
# I hate GNU Make
#
# Seriously.
#
# Fuck M4. I do this because it's probably the most portable way, and I don't
# want to write Yet Another Compile System because fuck that shit. I could
# use cmake but I don't know whether it is flexible enough. It probably is
# but whatever. I wrote this piece of shit below, let's just keep it that
# way. There are better way to do the hthings I do below, but who gives a
# shit.
default: emulate-nohdd
SHELL:=/bin/bash
ENV:=/usr/xdev/bin
TARGET:=i586-elf
CC:=$(ENV)/$(TARGET)-gcc
AS:=nasm
LD:=$(ENV)/$(TARGET)-ld
# -O2 sets -foptimize-sibling-calls which breaks code...
CFLAGS:=-Wall -Werror -nostdlib -nostartfiles -nodefaultlibs -std=c99 -g
CFLAGS+=-I ./include -Wno-packed-bitfield-compat -O2 -fno-optimize-sibling-calls
CFLAGS+= -fno-builtin
LFLAGS:=-nostdlib -nostartfiles -nodefaultlibs
.PHONY: all clean loader.bin emulate hdd.img
obj/src/%.nao : src/%.asm
@echo "[i] Assembling $*.asm..."
@$(AS) -f elf -o obj/src/$*.nao src/$*.asm
obj/src/%.o : src/%.c
@echo "[i] Compiling $*.c ..."
@if [ -e obj/src/$*.o ] ; then rm obj/src/$*.o ; fi
@mkdir -p obj/src/$*.o
@rmdir obj/src/$*.o
@$(CC) $(CFLAGS) -c src/$*.c -o obj/src/$*.o
SRC := $(shell find src -mindepth 1 -maxdepth 3 -name "*.c")
SRC += $(shell find src -mindepth 1 -maxdepth 3 -name "*.asm")
OBJ := $(patsubst %.c,%.o,$(SRC))
OBJ := $(patsubst %.asm,%.nao,$(OBJ))
OBJ_ALL := $(foreach i, $(OBJ), obj/$(i))
Loader: $(OBJ_ALL)
loader.bin: Loader
@echo "[i] Linking loader.bin..."
@$(LD) -T src/loader.ld -o loader.bin $(OBJ_ALL)
emulate-nohdd-debug: loader.bin
@echo "[i] Starting GDB..."
@gnome-terminal -x /bin/bash -c "gdb"
@echo "[i] Starting QEmu..."
@qemu -kernel loader.bin -S -gdb tcp::1234
emulate-nohdd: loader.bin
@echo "[i] Starting QEMU..."
@qemu -kernel loader.bin
clean:
@rm -Rf obj
@if [ -e loader.bin ] ; then rm loader.bin ; fi
@if [ -e hdd_temp.img ] ; then rm hdd_temp.img ; fi
@if [ -e hdd.img ] ; then rm hdd.img; fi

BIN
Loader/loader.bin Normal file

Binary file not shown.

BIN
Loader/obj/src/start.nao Normal file

Binary file not shown.

432
Loader/src/load.c Normal file
View File

@ -0,0 +1,432 @@
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef char s8;
u8 stdio_current_line = 0;
u8 stdio_cur_x = 0, stdio_cur_y = 0;
void outb(u16 Port, u8 Data)
{
__asm__ volatile("outb %1, %0" :: "dN" (Port), "a" (Data));
}
void *memcpy(void* Destination, const void *Source, u32 Count)
{
u8* Destination8 = (u8*)Destination;
u8* Source8 = (u8*)Source;
while (Count--)
{
*Destination8++ = *Source8++;
}
return Destination;
}
void *memset(void *Destination, u8 Value, u32 Count)
{
u8 *us = (u8 *)Destination;
while (Count-- != 0)
*us++ = Value;
return Destination;
}
void *memsetw(void *Destination, u16 Value, u32 Count)
{
u16 *us = (u16 *)Destination;
while (Count-- != 0)
*us++ = Value;
return Destination;
}
void scroll_up(void)
{
//semaphore_acquire(&ScreenWriteLock);
u16 Blank = 0x20 | (0x0F << 8);
u16 Temp;
if (stdio_cur_y >= 25)
{
Temp = stdio_cur_y - 25 + 1;
memcpy((void*)0xB8000, (void*)(0xB8000 + Temp * 80 * 2), (25 - Temp) * 80 * 2);
memsetw((void*)(0xB8000 + (25 - Temp) * 160), Blank, 160);
stdio_cur_y = 25 - 1;
}
//semaphore_release(&ScreenWriteLock);
}
void move_cursor(u8 X, u8 Y)
{
stdio_cur_x = X;
stdio_cur_y = Y;
//wraparound
if (stdio_cur_x >= 80)
{
stdio_cur_y += stdio_cur_y / 80;
stdio_cur_x = 0;
}
//wrapup
scroll_up();
if (Y > 24)
Y = 24;
u16 Position = Y * 80 + X;
outb(0x3D4, 0x0F);
outb(0x3D5, (u8)(Position & 0xFF));
outb(0x3D4, 0x0E);
outb(0x3D5, (u8)(Position >> 8 & 0xFF));
}
void putch(s8 Character)
{
volatile u8 *VideoMemory = (u8 *)0xB8000;
u16 Offset = (stdio_cur_y * 80 + stdio_cur_x) << 1;
if (Character == '\n')
move_cursor(0, stdio_cur_y + 1);
else
{
VideoMemory[Offset] = Character;
VideoMemory[Offset+1] = 0x0F;
if (stdio_cur_x + 1 >= 80)
move_cursor(0, stdio_cur_y + 1);
else
move_cursor(stdio_cur_x + 1, stdio_cur_y);
}
}
void puts(const s8 *szString)
{
while (*szString != 0)
{
putch(*szString);
szString++;
}
}
void clear(void)
{
volatile u8 *VideoMemory = (u8 *)0xB8000;
u32 Size = (80 * 25 ) << 1;
for (u32 i = 0; i < Size; i += 2)
{
VideoMemory[i] = 0;
VideoMemory[i+1] = 0xF;
}
move_cursor(0, 0);
}
void dump_nibble(u8 Nibble)
{
if (Nibble < 10)
putch(Nibble + 48);
else
putch(Nibble + 55);
}
void print_hex(u64 Number)
{
for (s8 i = 7; i >= 0; i--)
{
u8 Byte = (Number >> (i << 3)) & 0xFF; //switch i bytes to the right and mask as byte
dump_nibble((Byte >> 4) & 0x0F); //high nibble
dump_nibble(Byte & 0x0F); //low nibble
}
}
struct elf_ident {
u32 Magic; // \x7FELF
u8 Class;
u8 Data;
u8 Version;
u8 Padding[9];
};
struct elf_header {
struct elf_ident Identification;
u16 Type;
u16 Machine;
u32 Version;
u64 Entry;
u64 ProgramHeaderOffset;
u64 SectionHeaderOffset;
u32 Flags;
u16 HeaderSize;
u16 ProgramHeaderEntrySize;
u16 NumProgramHeaderEntries;
u16 SectionHeaderEntrySize;
u16 NumSectionHeaderEntries;
u16 SectionEntryStrings;
};
struct elf_section_header {
u32 Name;
u32 Type;
u64 Flags;
u64 Address;
u64 Offset;
u64 Size;
u32 Link;
u32 Info;
u64 Alignment;
u64 FixedSize;
};
static inline void cpuid(u32 code, u32 *a, u32 *d) {
__asm__ volatile("cpuid":"=a"(*a),"=d"(*d):"0"(code):"ecx","ebx");
}
// A simple PAE paging structure so we can jump into 64-bit.
// This will be replaced later on by the kernel code.
u64 pml4[512] __attribute__((aligned(0x1000)));
u64 page_dir_ptr_tab_low[512] __attribute__((aligned(0x1000)));
u64 page_dir_low[512] __attribute__((aligned(0x1000)));
u64 page_tab_low[512] __attribute__((aligned(0x1000)));
u64 page_dir_ptr_tab_high[512] __attribute__((aligned(0x1000)));
u64 page_dir_high[512] __attribute__((aligned(0x1000)));
u64 page_tab_high[512] __attribute__((aligned(0x1000)));
#define GET_PML4_ENTRY(x) (((u64)x >> 39) & 0x1FF)
#define GET_PDP_ENTRY(x) (((u64)x >> 30) & 0x1FF)
#define GET_DIR_ENTRY(x) (((u64)x >> 21) & 0x1FF)
#define GET_TAB_ENTRY(x) (((u64)x >> 12) & 0x1FF)
#define GET_OFFSET(x) (x & 0xFFF)
void create_ia32e_paging(u64 KernelPhysicalStart, u64 KernelVirtualStart, u64 KernelSize)
{
puts("Clearing paging structures...\n");
for (u16 i = 0; i < 512; i++)
{
pml4[i] = 0;
page_dir_ptr_tab_low[i] = 0;
page_dir_low[i] = 0;
page_tab_low[i] = 0;
page_dir_ptr_tab_high[i] = 0;
page_dir_high[i] = 0;
page_tab_high[i] = 0;
}
puts("Setting up identity paging for first 2MiB...\n");
pml4[GET_PML4_ENTRY(0)] = (u32)page_dir_ptr_tab_low | 3;
page_dir_ptr_tab_low[GET_PDP_ENTRY(0)] = (u32)page_dir_low | 3;
page_dir_low[GET_DIR_ENTRY(0)] = (u32)page_tab_low | 3;
u64 Address = 0;
for (u16 i = 0; i < 512; i++)
{
page_tab_low[i] = Address | 3;
Address += 0x1000;
}
puts("Setting up paging for the kernel...\n");
u16 NumPages = KernelSize / 0x1000;
puts(" (0x");
print_hex(NumPages);
puts(" pages)\n");
if (GET_PML4_ENTRY(KernelVirtualStart) != 0)
{
// We're NOT mapping the same PML4 entry as for identity mapping...
puts("Different PML4...\n");
pml4[GET_PML4_ENTRY(KernelVirtualStart)] = (u32)page_dir_ptr_tab_high | 3;
page_dir_ptr_tab_high[GET_PDP_ENTRY(KernelVirtualStart)] = (u32)page_dir_high | 3;
page_dir_high[GET_PDP_ENTRY(KernelVirtualStart)] = (u32)page_tab_high | 3;
}
else if (GET_PDP_ENTRY(KernelVirtualStart) != 0)
{
// We're NOT mapping the same page directory pointer table entry as for identity paging...
puts("Different PDPT... (");
print_hex(GET_PDP_ENTRY(KernelVirtualStart));
puts(")\n");
page_dir_ptr_tab_low[GET_PDP_ENTRY(KernelVirtualStart)] = (u32)page_dir_high | 3;
page_dir_high[GET_DIR_ENTRY(KernelVirtualStart)] = (u32)page_tab_high | 3;
}
else if (GET_DIR_ENTRY(KernelVirtualStart) != 0)
{
// We're NOT mapping the same page directory entry as for identity paging...
puts("Different DIR...\n");
page_dir_low[GET_DIR_ENTRY(KernelVirtualStart)] = (u32)page_tab_high | 3;
}
else
{
puts("Error: kernel overlaps 2MiB identity paging!\n");
return;
}
Address = KernelPhysicalStart;
for (u16 i = GET_TAB_ENTRY(KernelVirtualStart); i < GET_TAB_ENTRY(KernelVirtualStart) + NumPages; i++)
{
page_tab_high[i] = Address | 3;
print_hex(KernelVirtualStart + i * 0x1000);
puts(" -> ");
print_hex(Address);
puts("\n");
Address += 0x1000;
}
}
u32 load(void *Multiboot, unsigned int Magic)
{
clear();
puts("Cucumber x86-64 loader...\n");
if (Magic != 0x2BADB002)
{
puts("Error: not booted via Multiboot!\n");
return 0;
}
u32 CPUID_A, CPUID_D;
cpuid(0x80000001, &CPUID_A, &CPUID_D);
u8 SupportFor64 = (CPUID_D & (1 << 29)) > 0;
if (!SupportFor64)
{
puts("Error: You CPU does not support long mode!\n");
return 0;
}
u32 Flags = *((u32*)Multiboot);
u8 ModulesPresent = (Flags & (1 << 3)) > 0;
if (!ModulesPresent)
{
puts("Error: no 64-bit kernel loaded!\n");
puts(" (did you forget the module line in GRUB?)\n");
return 0;
}
u32 ModulesCount = *((u32*)Multiboot + 5);
u32 ModulesAddress = *((u32*)Multiboot + 6);
if (ModulesCount != 1)
{
puts("Error: just one module is enough. Don't load a ton of them.\n");
return 0;
}
puts("Kernel is @");
print_hex(ModulesAddress);
puts(".\n");
struct elf_header *Header = *((struct elf_header **)ModulesAddress);
if (Header->Identification.Magic != 0x464C457F)
{
puts("Error: Module is not an ELF file!\n");
return 0;
}
if (Header->Identification.Class != 2)
{
puts("Error: Module is not a 64-bit ELF file!\n");
return 0;
}
if (!Header->Entry)
{
puts("Error: Kernel does not have entry point!\n");
return 0;
}
puts("Entry point @");
print_hex(Header->Entry);
puts(".\n");
if (Header->SectionHeaderEntrySize != sizeof(struct elf_section_header))
{
puts("Error: Weird section header entry size!\n");
return 0;
}
struct elf_section_header *Sections = (struct elf_section_header *)((u32)Header + (u32)Header->SectionHeaderOffset);
struct elf_section_header *StringSection = &Sections[Header->SectionEntryStrings];
//u32 *Strings = (u32*)(ModulesAddress + (u32)StringSection->Offset);
puts("0x");
print_hex(Header->NumSectionHeaderEntries);
puts(" ELF sections.\n");
u64 ContinuityTest = 0;
u64 StartPhysical = 0;
u64 StartVirtual = 0;
u64 Size = 0;
for (u16 i = 0; i < Header->NumSectionHeaderEntries; i++)
{
s8* Name = (s8*)((u32)Header + (u32)StringSection->Offset + (u32)Sections[i].Name);
u64 PhysicalAddress = (u32)Header + Sections[i].Offset;
u64 VirtualAddress = Sections[i].Address;
if (VirtualAddress)
{
if (!StartVirtual)
StartVirtual = VirtualAddress;
if (!StartPhysical)
StartPhysical = PhysicalAddress;
if (ContinuityTest && VirtualAddress != ContinuityTest)
{
puts("Error: kernel is not continuous!\n");
return 0;
}
ContinuityTest = VirtualAddress + Sections[i].Size;
Size += Sections[i].Size;
puts("-> Section ");
puts(Name);
puts(", 0x");
print_hex(PhysicalAddress);
puts(" will be located at 0x");
print_hex(VirtualAddress);
puts(".\n");
}
}
puts("\nPaging setup:\n 0x");
print_hex(StartVirtual);
puts(" => 0x");
print_hex(StartPhysical);
puts("\n (0x");
print_hex(Size);
puts(" bytes)\n");
create_ia32e_paging(StartPhysical, StartVirtual, Size);
__asm__ volatile ("movl %cr4, %eax; bts $5, %eax; movl %eax, %cr4");
__asm__ volatile ("movl %%eax, %%cr3" :: "a" (pml4));
puts("CR3 is now pointing to PML4 (0x");
print_hex((u32)pml4);
puts(")\n");
puts("Here it goes, enabling long mode...\n");
__asm__ volatile( "movl $0xc0000080, %%ecx;\n"
"rdmsr;\n"
"orl $0x100, %%eax;\n"
"wrmsr;\n"
"movl %%cr0, %%ebx;\n"
"bts $31, %%ebx;\n"
"movl %%ebx, %%cr0;":::"eax","ebx","ecx");
puts("Now in 32-bit compability mode, jumping to the kernel...\n");
return (u32)Header->Entry;
}

41
Loader/src/loader.ld Normal file
View File

@ -0,0 +1,41 @@
OUTPUT_FORMAT("elf32-i386")
ENTRY(_loader)
Offset = 0x00100000;
SECTIONS
{
. = Offset;
.text :
{
*(.text)
. = ALIGN(0x1000);
}
.data :
{
*(.data*)
*(.gnu.linkonce.d*)
*(.rodata*)
*(.gnu.linkonce.r*)
. = ALIGN(0x1000);
}
.bss :
{
*(COMMON*)
*(.bss*)
. = ALIGN(0x1000);
}
. = ALIGN(0x1000);
/DISCARD/ :
{
*(.comment)
*(.eh_frame)
}
}

101
Loader/src/start.asm Normal file
View File

@ -0,0 +1,101 @@
extern load
extern puts
extern stdio_current_line
extern stdio_cur_x
extern stdio_cur_y
global _loader
; Multiboot-related constants
MODULEALIGN equ 1 << 0
MEMINFO equ 1 << 1
FLAGS equ MODULEALIGN | MEMINFO
MAGIC equ 0x1BADB002
CHECKSUM equ -(MAGIC + FLAGS)
; Other constants
STACKSIZE equ 0x1000
; #############################################################################
; ############################## text segment #################################
; #############################################################################
section .text
align 4
; Multiboot header
MultiBootHeader:
dd MAGIC
dd FLAGS
dd CHECKSUM
; GDTR
GDTR:
dw 5*8-1
dd GDT
dd 0
; GDT
GDT:
dw 0,0,0,0 ; null desciptor (0x00)
db 0xFF, 0xFF, 0, 0, 0, 10011010b, 11001111b, 0x00 ; 32-bit code segment (0x08)
db 0xFF, 0xFF, 0, 0, 0, 10010010b, 11001111b, 0x00 ; 32-bit data segment (0x10)
db 0xFF, 0xFF, 0, 0, 0, 10011010b, 10101111b, 0x00 ; 64-bit code segment (0x18)
db 0xFF, 0xFF, 0, 0, 0, 10010010b, 10101111b, 0x00 ; 64-bit data segment (0x20)
str_back_in_asm:
db "Back in assembler!", 0
; Actual entry point
_loader:
mov esp, stack+STACKSIZE
push eax
push ebx
lgdt [GDTR]
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
jmp 0x08:_loader_gdt
_loader_gdt:
call load
mov ebx, eax
mov ax, 0x20
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Did we get an entry point address?
test ebx, ebx
jz hang
movzx edi, byte [stdio_current_line]
movzx esi, byte [stdio_cur_x]
movzx edx, byte [stdio_cur_y]
; 64-bit, here we come!
call 0x18:0xFF000000
hang:
hlt
jmp hang
; #############################################################################
; ############################### bss segment #################################
; #############################################################################
section .bss
align 4
; here be 4k stack
stack:
resb STACKSIZE

33214
dump Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
#ifndef __KSTDLIB_H__
#define __KSTDLIB_H__
#include "types.h"
void *kmemcpy(void* Destination, const void *Source, u32 Count);
void *kmemset(void *Destination, u8 Value, u32 Count);
void *kmemsetw(void *Destination, u16 Value, u32 Count);
#endif

View File

@ -13,14 +13,14 @@ default: emulate-nohdd
SHELL:=/bin/bash
ENV:=/usr/xdev/bin
TARGET:=i586-elf
TARGET:=x86_64-elf
CC:=$(ENV)/$(TARGET)-gcc
CX:=$(ENV)/$(TARGET)-g++
AS:=nasm
LD:=$(ENV)/$(TARGET)-ld
# -O2 sets -foptimize-sibling-calls which breaks code...
CFLAGS:=-Wall -Werror -nostdlib -nostartfiles -nodefaultlibs -std=c99 -g
CFLAGS:=-m64 -mcmodel=large -Wall -Werror -nostdlib -nostartfiles -nodefaultlibs -std=c99 -g
CFLAGS+=-I ./include -Wno-packed-bitfield-compat -O2 -fno-optimize-sibling-calls
@ -33,10 +33,11 @@ LFLAGS:=-nostdlib -nostartfiles -nodefaultlibs
obj/src/%.nao : src/%.asm
@echo "[i] Assembling $*.asm..."
@$(AS) -f elf -o obj/src/$*.nao src/$*.asm
@$(AS) -f elf64 -o obj/src/$*.nao src/$*.asm
obj/src/%.o : src/%.c
@echo "[i] Compiling $*.c ..."
@if [ -e obj/src/$*.o ] ; then rm obj/src/$*.o ; fi
@mkdir -p obj/src/$*.o
@rmdir obj/src/$*.o
@$(CC) $(CFLAGS) -c src/$*.c -o obj/src/$*.o
@ -84,8 +85,10 @@ emulate-nohdd-debug: kernel.bin
@qemu -kernel kernel.bin -S -gdb tcp::1234
emulate-nohdd: kernel.bin
@echo "[i] Building loader..."
@pushd ../Loader > /dev/null && $(MAKE) -f Makefile loader.bin && popd > /dev/null
@echo "[i] Starting QEMU..."
@qemu -kernel kernel.bin
@qemu-system-x86_64 -kernel ../Loader/loader.bin -initrd kernel.bin
emulate: hdd.img
@echo "[i] Starting QEmu..."

View File

@ -15,7 +15,7 @@
typedef struct {
u32 Magic;
u8 Hole;
u32 Size;
u64 Size;
} T_HEAP_HEADER;
typedef struct {
@ -25,8 +25,8 @@ typedef struct {
typedef struct {
void **Array;
u32 Size;
u32 MaxSize;
u64 Size;
u64 MaxSize;
} T_HEAP_INDEX;
T_HEAP_INDEX heap_index_initialize(void *Address, u32 MaxSize);
@ -35,19 +35,19 @@ u8 heap_index_smaller(void *A, void *B);
typedef struct {
T_HEAP_INDEX Index;
u32 Start;
u32 End;
u32 Max;
u64 Start;
u64 End;
u64 Max;
} T_HEAP;
T_HEAP *heap_create(u32 Start, u32 End, u32 Max);
void *heap_alloc(T_HEAP *Heap, u32 Size, u8 Aligned);
void *heap_alloc_p(T_HEAP *Heap, u32 Size, u8 Aligned, u32 *Physical);
T_HEAP *heap_create(u64 Start, u64 End, u64 Max);
void *heap_alloc(T_HEAP *Heap, u64 Size, u8 Aligned);
void *heap_alloc_p(T_HEAP *Heap, u64 Size, u8 Aligned, u64 *Physical);
void heap_free(T_HEAP *Heap, void *Address);
void heap_init_simple(void);
void *kmalloc(u32 Size);
void *kmalloc_p(u32 Size, u8 Aligned, u32 *Physical);
void *kmalloc(u64 Size);
void *kmalloc_p(u64 Size, u8 Aligned, u64 *Physical);
void kfree(void *Data);
#endif

View File

@ -39,14 +39,14 @@ typedef enum E_INTERRUPTS_CHIP T_INTERRUPTS_CHIP;
struct S_ISR_STUB {
u16 Code1;
u8 Code2;
u32 Handler;
u64 Handler;
u32 Code3;
u8 Code4;
} __attribute__ ((packed));
typedef struct S_ISR_STUB T_ISR_STUB;
typedef struct {
u32 edi, esi, ebp, esp, ebx, edx, ecx, eax;
u64 edi, esi, ebp, esp, ebx, edx, ecx, eax;
u32 Error;
u32 eip, cs, eflags, useresp, ss;
} T_ISR_REGISTERS_ERR;

View File

@ -19,6 +19,7 @@ void kputi(s32 Number);
void kprintf(const s8 *Format, ...);
void kdump(u8 *bData, u32 Length);
void kprint_hex(u32 Number);
void kstdio_set_globals(u8 line, u8 cur_x, u8 cur_y);
s32 kmemcmp(u8 *MemA, u8 *MemB, u32 Length);
#endif

View File

@ -0,0 +1,10 @@
#ifndef __KSTDLIB_H__
#define __KSTDLIB_H__
#include "types.h"
void *kmemcpy(void* Destination, const void *Source, u64 Count);
void *kmemset(void *Destination, u8 Value, u64 Count);
void *kmemsetw(void *Destination, u16 Value, u64 Count);
#endif

View File

@ -25,12 +25,12 @@ typedef struct {
} T_PAGING_DIRECTORY;
void paging_init_simple(void);
u8 paging_get_physical(u32 Virtual, u32 *Physical);
u8 paging_get_physical_ex(u32 Virtual, u32 *Physical,
u8 paging_get_physical(u64 Virtual, u64 *Physical);
u8 paging_get_physical_ex(u64 Virtual, u64 *Physical,
T_PAGING_DIRECTORY *Directory);
void paging_map_kernel_page(u32 Virtual, u32 Physical);
void paging_map_kernel_table(u32 Virtual, u32 Physical);
void paging_map_page(u32 Virtual, u32 Physical, T_PAGING_DIRECTORY *Directory,
void paging_map_kernel_page(u64 Virtual, u64 Physical);
void paging_map_kernel_table(u64 Virtual, u64 Physical);
void paging_map_page(u64 Virtual, u64 Physical, T_PAGING_DIRECTORY *Directory,
u8 User, u8 RW);
void paging_use_directory(T_PAGING_DIRECTORY *Directory);
T_PAGING_DIRECTORY *paging_get_directory(void);

View File

@ -8,6 +8,7 @@ typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef long long s64;
typedef int s32;
typedef short s16;
typedef char s8;

View File

@ -1,6 +1,6 @@
#include "types.h"
#include "Tier0/kstdio.h"
#include "Tier0/gdt.h"
/*#include "Tier0/gdt.h"
#include "Tier0/paging.h"
#include "Tier0/acpi.h"
#include "Tier0/interrupts.h"
@ -13,31 +13,24 @@
#include "Tier0/cpp.h"
#include "Tier0/exceptions.h"
#include "Tier0/panic.h"
#include "Tier0/prng.h"
#include "Tier0/prng.h"*/
void interrupts_irq_sample(void);
// Just to see whether this stuff actually works
void sample_interrupt_0x2A(void)
{
kprintf("[i] Hello from ISR for interrupt 0x2A!\n");
return;
}
void kmain_newstack(void);
// Real kernel entry point, called from _start.asm
void kmain(void *MultibootHeader, u32 Magic)
// Real kernel entry point, called from loader
void kmain(u32 current_line, u32 cursor_x, u32 cursor_y)
{
kstdio_init();
kclear();
kprintf(" _ \n"
kstdio_set_globals(current_line, cursor_x, cursor_y);
//kclear();
kprintf("\n _ \n"
" ___ _ _ ___ _ _ _____| |_ ___ ___ \n"
" | _| | | _| | | | . | -_| _|\n"
" |___|___|___|___|_|_|_|___|___|_| \n\n");
kprintf("[i] Welcome to Cucumber!\n\n");
if (Magic != 0x2BADB002)
kprintf("[i] Welcome to Cucumber (x86-64)!\n");
//kprintf("%x %x %x\n", current_line, cursor_x, cursor_y);
for (;;) {}
/*if (Magic != 0x2BADB002)
{
kprintf("[e] Fatal! Boot via incompatible bootloader.\n");
return;
@ -84,8 +77,6 @@ void kmain(void *MultibootHeader, u32 Magic)
for (u32 Rl = 0; Rl < R; Rl++)
{
krand();
/*kseed(Rl);
krand();*/
}
// Let's create a new kernel stack
@ -96,14 +87,14 @@ void kmain(void *MultibootHeader, u32 Magic)
__asm__ volatile("mov %0, %%esp" : : "r" (0xA0000000 + 4095));
// This automagically creates a new usable stack frame
kmain_newstack();
kmain_newstack();*/
}
void kmain_newstack(void)
/*void kmain_newstack(void)
{
kprintf("[i] Now using real stack...\n");
cpp_call_ctors();
cpp_start_ckernel();
kprintf("[i] Returned from Tier1, sleeping forever.\n");
LOOPFOREVER;
}
}*/

View File

@ -1,7 +1,7 @@
#include "types.h"
#include "Tier0/kstdio.h"
#include "Tier0/kstdlib.h"
#include "Tier0/semaphore.h"
//#include "Tier0/semaphore.h"
#include <stdarg.h>
#define va_start(v,l) __builtin_va_start(v,l)
@ -13,11 +13,20 @@ typedef __builtin_va_list va_list;
u8 g_kstdio_current_line = 0;
u8 g_kstdio_cur_x = 0, g_kstdio_cur_y = 0;
T_SEMAPHORE ScreenWriteLock;
//T_SEMAPHORE ScreenWriteLock;
#define VIDEO_MEMORY ((u64)0xB8000)
void kstdio_set_globals(u8 line, u8 cur_x, u8 cur_y)
{
g_kstdio_current_line = line;
g_kstdio_cur_x = cur_x;
g_kstdio_cur_y = cur_y;
}
void kstdio_init(void)
{
semaphore_init(&ScreenWriteLock);
//semaphore_init(&ScreenWriteLock);
}
void koutb(u16 Port, u8 Data)
@ -124,9 +133,9 @@ void kscroll_up(void)
if (g_kstdio_cur_y >= 25)
{
Temp = g_kstdio_cur_y - 25 + 1;
kmemcpy((void*)0xC00B8000, (void*)(0xC00B8000 + Temp * 80 * 2), (25 - Temp) * 80 * 2);
kmemcpy((void*)VIDEO_MEMORY, (void*)(VIDEO_MEMORY + Temp * 80 * 2), (25 - Temp) * 80 * 2);
kmemsetw((void*)(0xC00B8000 + (25 - Temp) * 160), Blank, 160);
kmemsetw((void*)(VIDEO_MEMORY + (25 - Temp) * 160), Blank, 160);
g_kstdio_cur_y = 25 - 1;
}
//semaphore_release(&ScreenWriteLock);
@ -199,8 +208,8 @@ void kdump(u8 *bData, u32 Length)
void kputch(s8 Character)
{
semaphore_acquire(&ScreenWriteLock);
volatile u8 *VideoMemory = (u8 *)0xC00B8000;
//semaphore_acquire(&ScreenWriteLock);
volatile u8 *VideoMemory = (u8 *)VIDEO_MEMORY;
u16 Offset = (g_kstdio_cur_y * 80 + g_kstdio_cur_x) << 1;
if (Character == '\n')
@ -214,7 +223,7 @@ void kputch(s8 Character)
else
kmove_cursor(g_kstdio_cur_x + 1, g_kstdio_cur_y);
}
semaphore_release(&ScreenWriteLock);
//semaphore_release(&ScreenWriteLock);
}
void kputs(const s8 *szString)
@ -233,7 +242,7 @@ void kprint(const s8 *szString)
void kclear(void)
{
volatile u8 *VideoMemory = (u8 *)0xC00B8000;
volatile u8 *VideoMemory = (u8 *)VIDEO_MEMORY;
u32 Size = (80 * 25 ) << 1;
for (u32 i = 0; i < Size; i += 2)
{

View File

@ -1,7 +1,7 @@
#include "types.h"
#include "Tier0/kstdlib.h"
void *kmemcpy(void* Destination, const void *Source, u32 Count)
void *kmemcpy(void* Destination, const void *Source, u64 Count)
{
u8* Destination8 = (u8*)Destination;
u8* Source8 = (u8*)Source;
@ -13,7 +13,7 @@ void *kmemcpy(void* Destination, const void *Source, u32 Count)
return Destination;
}
void *kmemset(void *Destination, u8 Value, u32 Count)
void *kmemset(void *Destination, u8 Value, u64 Count)
{
u8 *us = (u8 *)Destination;
while (Count-- != 0)
@ -21,7 +21,7 @@ void *kmemset(void *Destination, u8 Value, u32 Count)
return Destination;
}
void *kmemsetw(void *Destination, u16 Value, u32 Count)
void *kmemsetw(void *Destination, u16 Value, u64 Count)
{
u16 *us = (u16 *)Destination;
while (Count-- != 0)

46
kernel/src/kernel.ld Normal file
View File

@ -0,0 +1,46 @@
OUTPUT_FORMAT(elf64-x86-64)
ENTRY(kmain)
KERNEL_VMA = 0x00000000FF000000;
SECTIONS
{
. = KERNEL_VMA;
.text : AT(ADDR(.text) - KERNEL_VMA)
{
_code = .;
*(.text)
*(.rodata*)
. = ALIGN(4096);
}
.data : AT(ADDR(.data) - KERNEL_VMA)
{
_data = .;
*(.data)
. = ALIGN(4096);
}
.ehframe : AT(ADDR(.ehframe) - KERNEL_VMA)
{
_ehframe = .;
*(.ehframe)
. = ALIGN(4096);
}
.bss : AT(ADDR(.bss) - KERNEL_VMA)
{
_bss = .;
*(.bss)
*(COMMON)
. = ALIGN(4096);
}
_end = .;
/DISCARD/ :
{
*(.comment)
}
}

View File

@ -1,64 +0,0 @@
OUTPUT_FORMAT("elf32-i386")
ENTRY(_start)
Offset = 0x00100000;
LMA = 0x00000000;
VMA = 0xC0000000;
SECTIONS
{
. = Offset;
g_setup_gdt_ptr = g_gdt_ptr - VMA;
g_setup_gdt_entries = g_gdt_entries - VMA;
.setup LMA + Offset : AT(LMA + Offset)
{
*(.setup)
. = ALIGN(0x1000);
}
. += VMA;
.text : AT(g_section_code)
{
g_section_code = . - VMA;
*(.text*)
*(.gnu.linkonce.t*)
. = ALIGN(0x4);
g_start_ctors = .;
*(.ctors)
g_end_ctors = .;
. = ALIGN(0x1000);
}
.data : AT(g_section_data)
{
g_section_data = . - VMA;
*(.data*)
*(.gnu.linkonce.d*)
*(.rodata*)
*(.gnu.linkonce.r*)
. = ALIGN(0x1000);
}
.bss : AT(g_section_bss)
{
g_section_bss = . - VMA;
*(COMMON*)
*(.bss*)
. = ALIGN(0x1000);
}
. = ALIGN(0x1000);
/DISCARD/ :
{
*(.comment)
*(.eh_frame)
}
}