Yeh I made it.

Now entering assembly to C Language entry.

It worked!

Today I’m going to google IO seoul so I’ll spend a night in cafe with acquaintance.

But Nobody came here so I’ve spent alone lol.

So I did coding in the cafe corner alone.

Like this

Of coruse I didn’t carry my book because that was so heavy. I started the development without the book.

I had little goals that were developments 64 bit entry code left and C Language entry.

That mean… I wanted success development booting step.

Anyway, I thoguht the structure is similar as before because I already had experience about switching 16 bit mode to 32 bit mode with my book.

And I almost completed page data structure related to 64 bit mode. So I thought It’s simple.

The first thing I have to do was moveing the 2MB area that we jumped before.

In another word, We need to change link script.

Well Before starting address is 0x10200, so I think that change to 0x200000.

Also Before thing was only 32 bit mode, so We need to support x86-64.

I decided to read already existed code.

The file /usr/lib/ldscript/elf_x86_64 was link script for 64 bit mode.

As I looked at this file and I think It wans’t so different LinkScript32.x, so I tried to command ‘diff’ to find editing point.

Plus, I wanna look properly, so I used colordiff.

ColorDiff

Oh? It hadn’t lots change points.

Set the starting point to 0x200000 and write the link script.

Because I didn’t have book, so I just try it by my sense.

But I felt liitle complicate because I thought ‘64 bit kernel didn’t have a asm entry points??’ like this.

Because when 32bit mode, I load EntryPoint.s to 0x10000 and call 0x102000 to C language entry.

I think one of them start address will start at 0x200000, so I start to research.

Because I didn’t have the book, So I check all of them.

I interpreted something secret hinding in the linker and I started the tests.

At the result of checking makefile:

EntryPoint’s binary was first target of linking, so as address 0x200000 started application like kernel functions or etc.

First, Almost understanding was done, so I started developments and edited file was LinkerScript and makefiles.

I’ve refered memory load part code from OS book community.

First, Load all of data by bootloader. Like stack. Unit is 512 bytes.

Already existed kernel32 will make 5 sector, Kernel64 will maek 1 sector.

That was loaded by bootloader at 0x10000.

I cannot understand why do like this because i didnt’t read books. So I’m so excited to read that.

As I expect, Something to use left areas or advantage of performence.

For the implementation, we need a information about sector number in front of disk image.

And that image used from that information.

Anyway, as 64bit kernel copy at 2MB position, and after IA-32e mode switch then jump to 2 MB.

If it was properly working when It jumped, it will simply success, but something misstype and unexpected bugs, so I spent quite hard time.

First, Wrong page directory pointer table position.

It wasn’t 0x10200 it was 0x102000.

//Page.c

	for(int i = 0; i < 64; i++)
	{
		SetPageEntryData(&pdptentry[i], 0, 0x10200 /*0x102000*/
        + i * PAGE_TABLE_SIZE, PAGE_FLAG_DEFAULT, 0);
	}


at the expression of calculating address,

PAGE_FLAG_DEFAULT was exsisted instead of PAGE_DEFAULT_SIZE.

damm it.

    //Page.c
	DWORD high = (i * (PAGE_FLAG_DEFAULT >> 20) ) >> 12;
	//Above is error code
    //Below is proper code
    DWORD high = (i * (PAGE_DEFAULT_SIZE) >> 20) ) >> 12;
	

It worked wrong like booting and flashing problems, I think paging setted by r0 register through the ModeSwitchAndJumpKernel64 function.

Well, I fixed that.

The real problem was notting happend when it jumped at 2MB entry.


ModeSwitchAndJumpKernel64:
	
	
	; Set 1 CR4 Register PAE Bit
	mov eax, cr4
	or eax, 0x20
	mov cr4, eax

	mov eax, 0x100000
	mov cr3, eax
	
	mov ecx, 0xC0000080
	rdmsr
	or eax, 0x0100
	wrmsr
	

	
	;Write Table
	mov eax, cr0
	or  eax, 0xE0000000
	xor eax, 0x60000000
	mov cr0, eax
	
	jmp 0x08:0x200000
	
	;Not Entry
	jmp $
	
	

Above codes has contained jumping to 0x200000 at “jmp 0x08:0x200000”, but notting happend.

I tried to check that codes are executed.

And I examine my OS with doubt.

So I found the clue.

On the QEMU, Press CTRL + R + 2 and you can access the command shell.

You can check the value in the address by that:

x 0x200000

Always I can’t find any value. I thought copying part or data set has been problems.

I thought the sector information was wrong, but it was not problem because hex value was properly by vim.

%!xxd

Not problem

And I should check the data copying, so I looked at the data at 0x10A00 by segment * 512 * 5, and I found it worked properly.

Let’s look at the copy function.



void LoadKernel64ImageToMemory(DWORD _address)
{
	WORD TotalKernelSector 	= *( (WORD*) 0x7C05);
	WORD Kernel32Sector 	= *( (WORD*) 0x7C07);
	
	DWORD* SourceAddress = (DWORD*) 0x10000 + Kernel32Sector * 512;
	DWORD* DestAddress	= (DWORD*) 0x200000; 
	
	for(int i=0; i< 512 * (TotalKernelSector -Kernel32Sector) / 4; i++)
	{
		*DestAddress = *SourceAddress;
		DestAddress++;
		SourceAddress++;
	}

	
}

Ah, There is it.

	DWORD* Source = ((DWORD*) (0x10000 + Kernel32Sector * 512));

Primary operators.

Dammit, that was mistake. I did like beginner.

Anyway, After fixing that miss, it would be load below entrypoint code on the 2MB:


[BITS 64]

SECTION .text

extern __KERNEL_ENTRY

START:

	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax

	mov ss,  ax
	mov rsp, 0x6FFFF8
	mov rbp, 0x6FFFF8

	call __KERNEL_ENTRY

	jmp $

That Entry call the C Entry:


#include "Types.h"

void PrintVideoMemory(int _x, int _y, BYTE _Attribute, const char* _str);

void __KERNEL_ENTRY()
{
	PrintVideoMemory(5,12, 0x0F,"64 bit C Language Kernel.");	
}




void PrintVideoMemory(int _x, int _y, BYTE _Attribute ,const char* _str)
{
	CHARACTER_MEMORY*  = ( CHARACTER_MEMORY* ) 0xB8000;
	
	int i = 0;
	
	Address+= ( _y * 80 ) + _x;
	
	for ( i = 0; _str[i] != 0; i++)
	{
		Address[i].bCharactor = _str[i];
		Address[i].bAttribute = _Attribute;
		
	}
}


It worked properly like above image!

Well, I spent a lot time of coding time for that, also I spent many debugging time.

I think, I should use GDB skillfully.

Now the booting steps are done.

I spent whole night, and I write this article while travel, so this article might be something weird i guess.

Please understanding me.

I think it is good compare what i’ve done and book.

after take a rest in a while, and I will fix the value in code on the previous article.

Now, Start!