OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Apr 18, 2024 7:24 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: Compiling to 32 bit Kernel from 64 bit linux using gcc
PostPosted: Mon May 22, 2017 1:04 am 
Offline
Member
Member

Joined: Sat Apr 29, 2017 6:56 am
Posts: 26
Hello,
I am trying to compile the kernel to 32 bit, under linux 64 bit using gcc compiler. I am succeeded in compiling the kernel to 32 bit but when i use
command kernel=Kernel/kernel.bin (using grub1) getting error message Invalid or unsupport executable format .

gcc -c -m32 entry.c -o entry.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
gcc -m32 -T linker.ld -o kernel.bin -ffreestanding -O2 -nostdlib entry.o -lgcc

By using above commands i am able to get 32 bit kernel elf executable format

My menu.lst

Os
root (fd0)
kernel=/Kernel/kernel.bin

My linker.ld


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

SECTIONS
{
. = 1M;

.text BLOCK(512) : ALIGN(512)
{
*(.multiboot)
*(.text)
}
.rodata BLOCK(512) : ALIGN(512)
{
*(.rodata)
}
.data BLOCK(512) : ALIGN(512)
{
*(.data)
}
.bss BLOCK(512) : ALIGN(512)
{
*(COMMON)
*(.bss)
}

}


Top
 Profile  
 
 Post subject: Re: Compiling to 32 bit Kernel from 64 bit linux using gcc
PostPosted: Mon May 22, 2017 2:54 am 
Offline
Member
Member

Joined: Wed Oct 30, 2013 1:57 pm
Posts: 306
Location: Germany
Please learn to read. You are required to have a GCC_Cross-Compiler. You should never just pass -m32 to your system compiler.

I don't know anything about GRUB Legacy, mostly because I haven't seen any reasonable justification to use it. Just compile GRUB2 from source and use that, it takes 3 minutes of your lifetime to do it properly.

At least set a cross compiler up, and report back.

_________________
managarm


Top
 Profile  
 
 Post subject: Re: Compiling to 32 bit Kernel from 64 bit linux using gcc
PostPosted: Mon May 22, 2017 7:04 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 692
Two concerns I have. The linker script suggests you are trying to make a multiboot compliant bootloader. You will need a multiboot header in your code. Most people place that in a separate assembly file and then make a call to their kernel's C entry point. In your case the header is expected to be located in the .multiboot section according to the linker script.

So first question is. Do you have a multiboot header?

Edit: Originally I commented about the multiboot directive in grub.cfg, but as was pointed out you are using Legacy Grub so using kernel= would be correct.


Last edited by MichaelPetch on Mon May 22, 2017 7:31 am, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: Compiling to 32 bit Kernel from 64 bit linux using gcc
PostPosted: Mon May 22, 2017 7:14 am 
Offline
Member
Member

Joined: Wed Oct 30, 2013 1:57 pm
Posts: 306
Location: Germany
He's using the kernel line because he's using GRUB Legacy (OP called GRUB 1 in his post). There's no multiboot command there, so the kernel command is right in this case. As I said above, I would still advise to just use GRUB2 instead.

Other than that, you're right.

_________________
managarm


Top
 Profile  
 
 Post subject: Re: Compiling to 32 bit Kernel from 64 bit linux using gcc
PostPosted: Mon May 22, 2017 10:57 am 
Offline
Member
Member

Joined: Fri Aug 26, 2016 1:41 pm
Posts: 692
In my first comment I suggested that most people simply create their multiboot header (and bootstrap) code in a separate assembly module. Although that is normal and cleaner it is possible to do in C as well using basic inline assembly statements outside a function. A basic entry.c that should work and be compatible with legacy multiboot:
Code:
#include <multiboot/multiboot.h>
#include <stdint.h>

/* STRINGIZE is a C macro that allow us to convert an integer to a string
* for use by the C pre-processor */
#define STRINGIZE_INTERNAL(x) #x
#define STRINGIZE(x) STRINGIZE_INTERNAL(x)

/* 32k stack */
#define STACK_SIZE 32768

/* Define the multiboot structure that will be detectable by the multiboot
* loader. Request the loader to provide us a memory information */

#define MULTIBOOT_FLAGS MULTIBOOT_MEMORY_INFO

struct multiboot_header mb_header
__attribute__ ((aligned (4), section(".multiboot"))) = {
    .magic    = MULTIBOOT_HEADER_MAGIC,
    .flags    = MULTIBOOT_FLAGS,
    .checksum = -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_FLAGS)
};

/* Allocate space for a stack */
uint8_t stack[STACK_SIZE];

/* Entry point set in linker script that the mulitboot loader will transfer control to */
extern void Kernel_entry(void);
__asm__ (".global Kernel_entry\n"
         "Kernel_entry:\n\t"
             /* Set stack pointer to end of stack variable.
                Stack grows down. Align stack to 16 byte boundary */
             "mov $stack + " STRINGIZE(STACK_SIZE) ", %esp\n\t"
             "and $-16, %esp\n\t"

             "cld\n\t"         /* Ensure string instructions have forward movement */
             "sub $8, %esp\n\t"/* For alignment on call to kmain */
             "push %eax\n\t"   /* Pass magicnum in EAX as 2nd parameter */
             "push %ebx\n\t"   /* Pass multiboot info struct in EBX as 1st parameter */
             "call kmain\n\t"  /* At this point stack 16 byte aligned, call kernel */
             "add $16, %esp\n\t"

             /* Infinite loop to end */
             "cli\n"
         ".L0:\n\t"
             "hlt\n\t"
             "jmp .L0\n"
         );

/* Text mode video pointer */
volatile uint16_t *const video_memory = (uint16_t *)0xb8000;

/* kmain is main C entry point */
void kmain(multiboot_info_t *mb_info, uint32_t magicnum)
{
    (void)mb_info;             /* Suppress warning */

    /* Verify we were booted from multiboot loader and print MB to the display */
    if (magicnum == MULTIBOOT_BOOTLOADER_MAGIC) {
        video_memory[0] = 0x57 << 8 | 'M';
        video_memory[1] = 0x57 << 8 | 'B';
    }
}

As was mentioned by no92 using a cross compiler is much preferred to avoid potential problems. Using your host GCC may also present a particular problem if the build-id gets generated. This build id section may end up getting placed in such a way as to push your mulitboot header beyond the first 8k of the file where a multiboot loader may not detect it. I'd add the -Wl,--build-id=none option to the GCC command that links and generated your final executable.


Last edited by MichaelPetch on Tue May 23, 2017 8:26 am, edited 3 times in total.

Top
 Profile  
 
 Post subject: Re: Compiling to 32 bit Kernel from 64 bit linux using gcc
PostPosted: Mon May 22, 2017 11:35 pm 
Offline
Member
Member

Joined: Sat Apr 29, 2017 6:56 am
Posts: 26
Thank you everyone and MichaelPetch for replies.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 84 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group