Octacone wrote:They are shown as PROGBITS. I will try what you suggested and report back.
I assume you mean that .bss_higher_half in Kernel_Assembly.o was PROGBITS? From your following discoveries, I gather that the .bss sections of all input files were NOBITS (except in the output).
Octacone wrote:Edit 3: fixed, I'm something of a scientist myself.
I just did this: section .bss_higher_half nobits inside my assembly file and boom, marked as NOBITS! That was an easy fix. Looks like the linker only marks something as NOBITS if it's called .bss or explicitly declared as such lol.
Actually, originally you had only .bss in the assembly. In any case, this is documented behavior. The assembler guesses the "type" of the section if has a "standard" name, but otherwise you need to specify the type (such as nobits) and the access flags explicitly if you need to.
Octacone wrote:Edit 5: I found out my problem:
Code: Select all
for(uint32_t current_address = 0; current_address <= 0x1000000; current_address += 0x1000)
{
Map_Virtual_To_Physical(current_address, current_address, true, true, false);
Map_Virtual_To_Physical(0xC0000000 + current_address, current_address, true, true, false);
}
That is not going to work.
I checked with Bochs and page 0xC0000000 maps to 0x00000000, which means that the CPU will actually jump at 0x0 in reality an execute garbage. Now I need to figure out how to solve this. There must be an offset that I have to add to 0xC0000000 + current_address to make it work.
Well. You have two options here. One is to identity map the space between 1M and the end of the kernel and to map the addresses between higher_physical_start and the end of the kernel to the higher half, like this:
Code: Select all
for(uint32_t physical_address = 0x100000; physical_address < higher_physical_start; physical_address += 0x1000)
{
Map_Virtual_To_Physical(physical_address , physical_address , true, true, false);
}
for(uint32_t virtual_address = 0xC0000000; virtual_address < kernel_end; virtual_address += 0x1000)
{
/* This can be optimized, but the compiler might optimize it automatically. */
uint32_t physical_address = virtual_address - 0xC0000000 + higher_physical_start;
Map_Virtual_To_Physical(physical_address, physical_address, true, true, false);
Map_Virtual_To_Physical(virtual_address, physical_address, true, true, false);
}
This means that you have to subtract 0xC0000000 and add higher_physical_start if you ever want to compute the physical address of a page in the higher kernel. (You may not need this.)
Alternatively, you could have the identity mapping as before, but map higher_physical_start to the end of the kernel to the higher half at the same offset as the physical address. You need to modify the linker script:
Code: Select all
ENTRY(Pre_Kernel_Main_Lower_Half)
OUTPUT_FORMAT("elf32-i386")
SECTIONS
{
. = 0x100000;
.text_lower_half :
{
Objects/Kernel_Assembly.o(.text_lower_half)
Objects/Higher_Half.o(.text)
}
.rodata_lower_half :
{
Objects/Higher_Half.o(.rodata)
}
.data_lower_half :
{
Objects/Kernel_Assembly.o(.data_lower_half)
Objects/Higher_Half.o(.data)
}
.bss_lower_half :
{
bss_start_lower_half = .;
Objects/Higher_Half.o(.bss)
Objects/Higher_Half.o(COMMON)
bss_end_lower_half = .;
}
higher_physical_start = ABSOLUTE(ALIGN(0x1000);
. = 0xC0000000 + higher_physical_start;
kernel_start = ABSOLUTE(.);
.text_higher_half : AT(higher_physical_start)
{
Objects/Kernel_Assembly.o(.text_higher_half)
*(.text)
}
.rodata_higher_half :
{
start_constructors = .;
*(SORT(.ctors*))
end_constructors = .;
*(.rodata)
}
.data_higher_half :
{
*(.data)
}
.bss_higher_half :
{
bss_start_higher_half = .;
Objects/Kernel_Assembly.o(.bss_higher_half)
*(.bss)
*(COMMON)
bss_end_higher_half = .;
}
kernel_end = ABSOLUTE(.);
}
And the mapping code would look like this:
Code: Select all
for(uint32_t physical_address = 0x100000; physical_address < higher_physical_start; physical_address += 0x1000)
{
Map_Virtual_To_Physical(physical_address , physical_address , true, true, false);
}
for(uint32_t virtual_address = kernel_start; virtual_address < kernel_end; virtual_address += 0x1000)
{
/* This can be optimized, but the compiler might optimize it automatically. */
uint32_t physical_address = virtual_address - 0xC0000000;
Map_Virtual_To_Physical(physical_address, physical_address, true, true, false);
Map_Virtual_To_Physical(virtual_address, physical_address, true, true, false);
}