OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Mar 19, 2024 2:09 am

All times are UTC - 6 hours




Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: Booting non-ELF kernel with GRUB tutorial
PostPosted: Tue Dec 01, 2009 11:08 am 
Offline
Member
Member

Joined: Thu Apr 10, 2008 1:47 am
Posts: 104
Here are 2 basic tutorials to make GRUB booting non-ELF kernel, one for flat binary and one for PE format kernel.
Both have been tested on windows

Prerequisites

- A correct floppy with GRUB installed to match this menu.cfg
Code:
default=0
timeout=0
title   DNA Workstation
root    (fd0)
kernel  /init.bin

- nasm
- Visual C++ [Express edition is enough and free]


Flat binary kernel

the code init.asm
Code:

         [map all init.map]         ;Nasm directive to produce map file
         bits 32                  ;necessary to avoid Nasm to produce 16 bits  code
   
MULTIBOOT_HEADER_MAGIC   equ   0x1BADB002   ;magic number, GRUB search for it in the first 8k
                              ;of the specified file in GRUB menu
         
MULTIBOOT_HEADER_FLAGS   equ   0x00010000   ;FLAGS[16] say to GRUB we are not
                              ;an ELF executable and the fields
                              ;header adress, load adress, load end adress;
                              ;bss end adress and entry adress will be available
                              ;in Multiboot header
                              
CHECKSUM            equ   -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)

                                    
LOADBASE            equ 0x00100000   ;Must be >= 1Mo

STACK_SIZE              equ   0x4000
_start:

         
       jmp     multiboot_entry         ;if you want use you own bootloader               

       align  4                     ;Multiboot header must be 32
                                 ;bits aligned to avoid error 13
multiboot_header:
       dd   MULTIBOOT_HEADER_MAGIC      ;magic number
       dd   MULTIBOOT_HEADER_FLAGS      ;flags
       dd   CHECKSUM                  ;checksum
       dd   LOADBASE + multiboot_header   ;header adress
       dd   LOADBASE                  ;load adress
       dd   00                     ;load end adress : not necessary
       dd   00                     ;bss end adress : not necessary
       dd   LOADBASE + multiboot_entry   ;entry adress
     
multiboot_entry:
      mov    esp, stack + STACK_SIZE      ;Setup the stack
      push   0                     ;Reset EFLAGS
      popf
      push   ebx                     ;Push magic number and
      push   eax                     ;multiboot info adress
                                 ;which are loaded in registers
                                 ;eax and ebx before jump to
                                 ;entry adress
                                 ;[LOADBASE + multiboot_entry]
                              
      ;call   EXT_C(main)               ; !! commented
                                 ;main (unsigned long magic, unsigned long addr)
                                 ;your kernel entry point
                                    
       mov   edi, 0xB8000            ;Msg to check the boot was OK
       mov   esi, hello
       add   esi, LOADBASE            ;hello is just an offset
msg:      
       mov   byte al, [esi]
       cmp   al, '\0'
       je   loop
       mov   ah, 0xa0                                     
       mov   word [edi],   ax         
       add   edi, 2
       inc   esi
       jmp   msg
             
       loop:   hlt                        ;Halt processor
             jmp     loop
   
_edata:                                 
hello:
   db   "Hello world from GRUB and flat binary kernel !\0"   
   align 4
   times (128) db 0x00                     ;foo data
stack:
   align 4
   times (STACK_SIZE) db 00
_end:


-Assemble with nasm : nasm -f bin -o init.bin init.asm
-copy init.bin at the floppy root
-test


PE Kernel

This is a bit more complicated

First you must setup a Visual C++ project named init like as describe in the famous BrokenThorn tutorials Setup Visual c++

Some modificatione are required
C/C++
in code generation set Enable Function level linking to yes (/Gy)
Linker
in command line set /ALIGN=1024
and add in Optimisation-> Functions order : @order.txt (@ is to avoid LNK warning)

Add a txt file order.txt (without @), leave blank

Add init .h file

Code:
/*   _emit is DB equivalent but not DD equivalent exist
   so we define it ourself */
#define dd(x)                            \
        __asm _emit     (x)       & 0xff \
        __asm _emit     (x) >> 8  & 0xff \
        __asm _emit     (x) >> 16 & 0xff \
        __asm _emit     (x) >> 24 & 0xff

#define KERNEL_STACK         0x00104000

/*  This is the one of most important thing to be able to load a PE kernel
   with GRUB. Because PE header are in the begining of the file, code section
   will be shifted. The value used to shift the code section is the linker
   align option /ALIGN:value. Note the header size sum is larger than 512,
   so ALIGN value must be greater */
#define   ALIGN               0x400

/*   Must be >= 1Mo for GRUB
   Base adress from advanced libker option
*/
#define LOADBASE            0x100000


#define   HEADER_ADRESS         LOADBASE+ALIGN

#define MULTIBOOT_HEADER_MAGIC         0x1BADB002
#define MULTIBOOT_BOOTLOADER_MAGIC      0x2BADB002
#define MULTIBOOT_HEADER_FLAGS         0x00010003
#define STACK_SIZE              0x4000   
#define CHECKSUM            -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)



void main(unsigned long, unsigned long);


Add init.cpp file
Code:
// init.cpp : définit le point d'entrée pour l'application console.
//

#include "init.h"

__declspec(naked) void multiboot_entry(void)
{
   __asm{
      align 4

   multiboot_header:
                dd(MULTIBOOT_HEADER_MAGIC)      ; magic number
                dd(MULTIBOOT_HEADER_FLAGS)      ; flags
                dd(CHECKSUM)               ; checksum
                dd(HEADER_ADRESS)            ; header address
                dd(LOADBASE)               ; load address
            dd(00)                     ; load end address : not used
            dd(00)                     ; bss end addr : not used
            dd(HEADER_ADRESS + 0x20)      ; entry_addr : equ kernel entry      
                                    ; 0x20 is the size of multiboot heeader
         
   kernel_entry:
                mov     esp,     KERNEL_STACK   ;Setup the stack

                push    0                  ;Reset EFLAGS
                popf

                push    ebx                  ;Push multiboot info adress
                push    eax                  ;and magic number 
                                    ;which are loaded in registers
                                    ;eax and ebx before jump to
                                    ;entry adress
                                    ;[HEADER_ADRESS + 0x20]
                call    main               ;kernel entry
   halt:
            jmp halt                  ; halt processor

        }
}

void main(unsigned long magic, unsigned long addr)
{
   char *string = "Hello World from GRUB and PE kernel !", *ch;
    unsigned short *vidmem = (unsigned short *) 0xB8000;
    int i;
   if (magic == MULTIBOOT_BOOTLOADER_MAGIC){
      
       
        for(ch = string, i = 0; *ch; ch++, i++)
                vidmem[i] = (unsigned char) *ch | 0xA000;
   }else
   {
      // DO SOMETHING
   }
}


Build

Take a look at your map file, it should be like this :
Code:
init

Timestamp is 4b1549e9 (Tue Dec 01 17:52:57 2009)

Preferred load address is 00100000

Start         Length     Name                   Class
0001:00000000 000000a5H .text                   CODE
0002:00000000 00000026H .rdata                  DATA

  Address         Publics by Value              Rva+Base       Lib:Object

0000:00000000       ___safe_se_handler_count   00000000     <absolute>
0000:00000000       ___safe_se_handler_table   00000000     <absolute>
0001:00000000       ?multiboot_entry@@YAXXZ    00100400 f   init.obj
0001:00000040       _main                      00100440 f   init.obj
0002:00000000       ??_C@_0CG@IINAHCGJ@Hello?5World?5from?5GRUB?5and?5PE?5ker@ 00100800     init.obj

entry point at        0000:00000000

Static symbols



Put this in your order.txt ?multiboot_entry@@YAXXZ
This ensure that when your kernel will growing, the multiboot_entry function will be at the beginning of file

- build
- copy the output file in the floppy root
- test


This is not a perfect tutorial but it is quite good to begin

Please report me any error, suggestion and your test result

_________________
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !


Last edited by gedd on Wed Dec 02, 2009 1:58 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Booting non-ELF kernel with GRUB tutorial by a prick
PostPosted: Tue Dec 01, 2009 12:04 pm 
Offline
Member
Member

Joined: Thu Apr 12, 2007 8:15 am
Posts: 204
Location: Michigan
Interesting, but I was a little disappointed that none of your comments or your tutorial in general made you sound like a prick, as promised by the thread title.

It looks like a useful tutorial, I admit I skimmed it a bit because I'm not currently working on anything related, but I may save a copy for reference later.

The only thing I did notice is that you should use the hlt instruction between the "halt" label and "jmp halt" command in init.cpp; perhaps disabling maskable interrupts with cli before the "halt" label.

_________________
Some people are offended by the verifiable truth; such people tend to remain blissfully unencumbered by fact.
If you are one of these people, my posts may cause considerable discomfort. Read at your own risk.


Top
 Profile  
 
 Post subject: Re: Booting non-ELF kernel with GRUB tutorial by a prick
PostPosted: Tue Dec 01, 2009 12:36 pm 
Offline
Member
Member

Joined: Thu Apr 10, 2008 1:47 am
Posts: 104
The prick was a reference from another thread wich have been locked.

Few year ago hlt instruction doesn't work fine in some virtualizer, it's an hold habit tu use infinite loop.
The forgoten CLI is clearly a mistake

_________________
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !


Top
 Profile  
 
 Post subject: Re: Booting non-ELF kernel with GRUB tutorial by a prick
PostPosted: Tue Dec 01, 2009 1:02 pm 
Offline
Member
Member
User avatar

Joined: Sun Feb 18, 2007 7:28 pm
Posts: 1564
Id remove that "reference" from the thread title. Its nice that you are sharing self written tutorials, I would keep it at that :)

_________________
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}


Top
 Profile  
 
 Post subject: Re: Booting non-ELF kernel with GRUB tutorial
PostPosted: Mon Jan 11, 2010 12:07 pm 
Offline
Member
Member
User avatar

Joined: Fri Mar 07, 2008 5:36 pm
Posts: 2111
Location: Bucharest, Romania
Can you really be far even as decided half as much to use go wish for that?

_________________
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]


Last edited by Love4Boobies on Tue Jan 12, 2010 2:57 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Booting non-ELF kernel with GRUB tutorial
PostPosted: Tue Jan 12, 2010 2:37 am 
Offline
Member
Member

Joined: Thu Apr 10, 2008 1:47 am
Posts: 104
Sorry for my question but i'm not understand your sentence
I 'm not english, can you rewrite ?

_________________
[ Grub 2 | Visual Studio 2013 | PE File ]
The OsDev E.T.
Don't send OsDev MIB !


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 22 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