Page 1 of 1

end of kernel

Posted: Sun Feb 26, 2006 4:15 pm
by McZ
I have put an kernel_end = .; at the end of my linker script so I know where the end of the kernel is.. but how can I use the kernel_end ?

I have tried this:

Code: Select all

extern void kernel_end;
...

char end = (char)&kernel_end;
kprintf("end of kernel 0x%x", end);
the above prints 0x24, this doesn't look correct to me maybe kernel_start + 0x24 is correct.. I have tried with long and int instead of char for the end variable but then I get nothing.

linker.ld

Code: Select all

OUTPUT_FORMAT("elf32-i386")
ENTRY(start)

SECTIONS
{
        . = 0x100000;

        .setup :
        {
                *(.setup)
        }

        . += 0xC0000000;

        .text : AT(ADDR(.text) - 0xC0000000)
        {
                *(.text)
        }

        .data ALIGN (4096) : AT(ADDR(.data) - 0xC0000000)
        {
                *(.data)
                *(.rodata*)
        }

        .bss ALIGN (4096) : AT(ADDR(.bss) - 0xC0000000)
        {
                *(COMMON*)
                *(.bss*)
        }
   kernel_end = .;
}

Re:end of kernel

Posted: Sun Feb 26, 2006 9:18 pm
by iammisc
you are getting 0x24 because that is the offset from the base, 0x100000

Re:end of kernel

Posted: Mon Feb 27, 2006 1:32 am
by xenos
Your kernel_end is much larger than 255 bytes, so it won't fit into a char. Try this instead:

Code: Select all

extern void kernel_end;
...

long end = (long)&kernel_end;
kprintf("end of kernel 0x%x", end);

Re:end of kernel

Posted: Mon Feb 27, 2006 1:59 am
by Solar
Ahem...

Code: Select all

void * end = &((char)kernel_end);
printf( "end of kernel: %p\n", end );
IMHO and without testing. But [tt]kernel_end[/tt] is not a [tt]long[/tt], and [tt]end[/tt] is not an integer. ;)

Re:end of kernel

Posted: Mon Feb 27, 2006 6:31 am
by McZ
I user the char because that was what used in some other code I found, altough I have tried with unsigned long/int & signed long/int too but without any success.

I played with objdump and got this with objdump -x kernel.bin

Code: Select all

...
c010a024 g       *ABS*  00000000 kernel_end
...
so as someone said the value will not fit in one char (only 24 fits) I thougth so too but if I use a unsigned long I get 0xE (I'm checking my kprintf now to see if there is something wrong there)

Re:end of kernel

Posted: Mon Feb 27, 2006 6:36 am
by Pype.Clicker
okay. whatever you define "kernel_end" in your code, the linker script will just assign the _address_ of that variable. That is, you shouldn't try to retrieve the _value_ of kernel_end.

E.g. Clicker has

Code: Select all

SECTIONS
{
    . = 0x00100000;
__start_image = .;
__start_init = .;
...
in "barebones.ld" ... then

Code: Select all

void __end_bss(void);
void __start_system(void);
void __start_image(void);
which lets me cast __start_system to a void pointer as needed. If i had "extern char __start_system;" then the proper use would have been "void* start_of_kernel = &__start_system;"

Re:end of kernel

Posted: Mon Feb 27, 2006 6:57 am
by McZ
Pype.Clicker wrote: you shouldn't try to retrieve the _value_ of kernel_end.
Why? so I can't print the address of the kernel_end then

So then this code I found somewhere would be valid then

Code: Select all

extern void kernel_end;
...

char *ptr = (char*)&kernel_end;
...
will the ptr actually point to the end of the kernel so I can start write something there?

is there any way to validate so that ptr actually is the correct address?

Re:end of kernel

Posted: Mon Feb 27, 2006 9:04 am
by Pype.Clicker
okay ... let's put it differently.

Code: Select all

// the linker script
SECTIONS {
   ...
__kernel_end = .; // assign current address to 'kernel_end' symbol
   LONG(0xcafebabe); // generate 4 bytes with value "CAFEBABE" in the program
}
now, __kernel_end can be declared as an unsigned long which has the value 0xcafebabe, that is ...

Code: Select all

extern __kernel_end
mov eax,[__kernel_end]
will load eax with 0xcafebabe
and

Code: Select all

extern unsigned long __kernel_end;

void kmain()
{
    kprint("__kernel_end = %x",__kernel_end);
}
will print out "cafebabe" on screen.

Pretty cool, but absolutely not what we want. What we want is to know _where_ the kernel ends ... and that is the address of __kernel_end:

Code: Select all

void kmain()
{
    kprint("__kernel_end = %x\n",__kernel_end);
    kprint("kernel ends at %x\n",&__kernel_end);
}
will now print something like "__kernel_end = cafebabe ... kernel ends at c010a024

Let's say you want to use that in order to initialise some memory manager:

Code: Select all

void mmInit(void *lowest_avl_byte, void* highest_avl_byte);

void kmain()
{
    kprint("__kernel_end = %x\n",__kernel_end);
    kprint("kernel ends at %x\n",&__kernel_end);
    mmInit(&__kernel_end, size_of_RAM);
}
should do it. Hope that makes it clearer.

btw, i'm off for a cup of 0xcoffee ... anyone wants some :P

Re:end of kernel

Posted: Mon Feb 27, 2006 9:37 am
by McZ
Verry good explaination.

but I can't get LONG(0xcafebabe) to work >:(

Code: Select all

/usr/cross/bin/i586-elf-ld:linker.ld:32: parse error
that is exactly the line where I have LONG(0xcafebabe) am I doing something wrong? I have looked at the manual for LD "using LD, the GNU linker" and there it says I can use LONG(expression)

btw, I don't like 0xc0ffee so I take a 0xbeef instead ::)

EDIT: now I can kprintf the vaule of kernel_end but I can't get the address from it if I do I get a zero value.

Re:end of kernel

Posted: Mon Feb 27, 2006 10:03 am
by Pype.Clicker
hmm ... i may have oversimplified things. actual code i have in clicker is

Code: Select all

SECTIONS
{
   // stuff

. = 0x00800000;
__start_system = .;
    .system :
    {
       // other stuff
        . = ALIGN(65536);
       LONG(0xcafebabe);
    }
__end_system = .;
__end_image = .;
}
it might happen that LONG(xxx) is only allowed within an output section (and that would make sense: while you can have symbols pointing "out" of the loadable bits, adding bits in no section sounds like an error).

Re:end of kernel

Posted: Mon Feb 27, 2006 10:56 am
by osbios
Use ASM:

Code: Select all

Code...
END_OF_KERNEL:
;D

Re:end of kernel

Posted: Mon Feb 27, 2006 11:00 am
by McZ
I made my own .end section altough I don't know if I can write like this but the code compiles and if I print kernel_end it will output cafebabe. BUT I still can't get the correct address of kernel_end all I get is zero.

Code: Select all

.end ALIGN (4096) : AT(ADDR(.end) - 0xC0000000)
{
   kernel_end = .;
   LONG(0xCAFEBABE);
}
EDIT: Now I have found out that the size of the kernel is 44kb if I calculate kernel_end - 0xC0000000 can this be true? kernel.bin is 21kb

Re:end of kernel

Posted: Mon Feb 27, 2006 4:28 pm
by Pype.Clicker
if your kernel.bin is actually an elf file, that could very well be:
- alignment instructions make the loader insert "padding" bytes that are not present in the binary
- .bss section (that is, uninitialized data) do not need to be present in the binary, but the loader will still allocate it.

In both case, "objdump -x kernel.bin" should give you more hints about what's going on (assuming .bin is not a raw binary as it looks to be). If it's really a binary, try asking your linker for a map of the generated binary: that too could give you more hints on what's going on.

Re:end of kernel

Posted: Mon Mar 13, 2006 8:15 pm
by B.E
McZ wrote:

Code: Select all

extern void kernel_end;
...

char *ptr = (char*)&kernel_end;
...
Isn't better to declare kernel_end as as void* like this

Code: Select all

extern void kernel_end;
...

char *ptr = (char*)&kernel_end;
...