Code: Select all
KernelModule = (module_t*)MBT->mods_addr;
unsigned char *temp = (unsigned char*)KernelModule->mod_start;
// 2. Verify the ELF header:
puts("Loading kernel module from ");
puthex(KernelModule->mod_start);
puts(" of length ");
puthex(KernelModule->mod_end - KernelModule->mod_start);
puts("\n");
// 2.1: Check the header: [0] should be 0x7F, [1] E, [2] L, [3] F.
if(!(temp[0] == ELF_MAGIC0 && temp[1] == ELF_MAGIC1 && temp[2] == ELF_MAGIC2 && temp[3] == ELF_MAGIC3))
{
-snip-
}
// 2.2: If we got here, the kernel *should* be usable.
// Since the ELF Magic thingy is there, we can assume that the program header exists here:
KernelHeader = (TElf64Header*)KernelModule->mod_start;
// 2.3: Do some more checks, just in case:
// Check ELF Version
if(KernelHeader->ElfVersion != 1)
{
TextModeSetTextColour(LIGHTRED);
puts("ELF Kernel file was invalid: Expected ElfVersion to be 1, got ");
putnum(KernelHeader->ElfVersion);
HaltSystem();
}
// 2.4: Check if it's a 64-bit file:
if(KernelHeader->ElfIdentification[4] != 2)
{
TextModeSetTextColour(LIGHTRED);
puts("ELF Kernel was invalid: Expcted ElfIdentification[4] (ElfClass) to be 2 (64-bit file), got ");
putnum(KernelHeader->ElfIdentification[4]);
HaltSystem();
}
// 3: Begin loading ELF File into memory.
// Load the loadable segments:
for(unsigned int *i = 0; (unsigned int)i < KernelHeader->ElfSectionHeaderEntrySize * KernelHeader->ElfProgramHeaderEntries; i += KernelHeader->ElfSectionHeaderEntrySize)
{
// 3.1: Get ourselves a section header
TElf64SectionHeader *SectionHeader = (TElf64SectionHeader*)((unsigned int)KernelHeader + (KernelHeader->ElfSectionHeaderOffset + i));
if(SectionHeader->SectionHeaderAddress)
{
// 3.2: Check for BSS section:
if(SectionHeader->SectionHeaderType == SectionHeaderTypeNoBits)
{
// This is the BSS section, zero it
memset((void*)SectionHeader->SectionHeaderAddress, 0, SectionHeader->SectionHeaderSize);
}
else
{
// Copy it somewhere.
memcpy((void*)SectionHeader->SectionHeaderAddress, (void*)((unsigned int)KernelHeader + SectionHeader->SectionHeaderOffset), SectionHeader->SectionHeaderSize);
}
}
}
// 3.2: Store the entry point.
unsigned int *KernelEntryPoint = (unsigned int*)KernelHeader->ElfEntry;
puthex(KernelHeader->ElfEntry);
Code: Select all
[BITS 64]
global Execute
Execute:
; Indicate something to the outside world that we're here.
cli
hlt
.NoCPUID:
cli
hlt
.NoLongMode:
cli
hot
Code: Select all
ENTRY(Execute)
OUTPUT_FORMAT(elf64-x86-64)
SECTIONS
{
.text ALIGN(0x1000):
{
code = .;
*(.text)
*(.rodata)
. = ALIGN(4096);
}
.rodata ALIGN(0x1000):
{
*(.rodata*)
. = ALIGN(4096);
}
.data ALIGN(0x1000):
{
data = .;
*(.data)
. = ALIGN(4096);
}
.bss ALIGN(0x1000):
{
bss = .;
*(.bss)
. = ALIGN(4096);
}
end = .; _end = .; __end = .;
}
1. Verify the ELF file (I get no errors whatsoever)
2. Load it into memory
Basically, using the C code, I copy the things over to memory. Problem is, the entry address is 0x00000000. Which shouldn't be the case.
Also: This is the file start and size given by GRUB:
0x0010F000, 0x002012E3
I don't initialise my PMM before doing this, because i'm afraid it will ruin my GRUB structures.
What's the situation?
Also some other questions:
1. Do I need to set up a 64-bit IDT and GDT before or after entering long mode?
2. *how* do I enter long mode? I understand that I should set a certain bit in a certain register, but then what? How do I jump to the entry address (presuming I get the above problem resolved)?
EDIT: Also, I'm using
Code: Select all
nasm -f elf64 -o start.o src64/asm/start.s
Cross64/bin/x86_64-elf-ld -T link64.ld -o output/kernel.bin start.o