GRUB2 + VS2010 Bare bones
Posted: Fri Jun 08, 2012 4:55 am
Requirements:
Configure the project like said here :
Visual_Studio --> compiler option
or here :
Os dev series : MSVC (thanks neon)
Note : the entry point is kernel_Startup
Add these 2 files :
Multiboot.h (see multiboot specification)
Kernel .cpp
Build ans test :
Go to the project properties
Now build your GRUB 2 ISO
|-----grub
------|------grub.cfg
set this in your grub.cfg file :
create a bat file : CreateISO.bat
run the bat file
Now you have an iso file with GRUB2
Test with any virtual machine or on a real PC [be careful]
- cygwin with basic + grub2[1.98-2] and dependencies
- make sure you add to path :
- PATH_TO_CYGWIN\bin
- PATH_TO_CYGWIN\usr\sbin
- VS 2010 express or not
- Install Qemu
- Add system variable QEMU_HOME = PATH_TO_QEMU
Configure the project like said here :
Visual_Studio --> compiler option
or here :
Os dev series : MSVC (thanks neon)
Note : the entry point is kernel_Startup
Add these 2 files :
Multiboot.h (see multiboot specification)
Code: Select all
#pragma once
/* Multiboot header magic number */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* Multiboot info magic number */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
#define MULTIBOOT_HEADER_FLAGS 0x00010003
#define STACK_SIZE 0x4000
#define CHECKSUM -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)
#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit)))
/* The Multiboot header. */
typedef struct multiboot_header
{
unsigned long magic;
unsigned long flags;
unsigned long checksum;
unsigned long header_addr;
unsigned long load_addr;
unsigned long load_end_addr;
unsigned long bss_end_addr;
unsigned long entry_addr;
unsigned long mode_type;
unsigned long width;
unsigned long height;
unsigned long depth;
} multiboot_header_t;
/* The symbol table for a.out. */
typedef struct aout_symbol_table
{
unsigned long tabsize;
unsigned long strsize;
unsigned long addr;
unsigned long reserved;
} aout_symbol_table_t;
/* The section header table for ELF. */
typedef struct elf_section_header_table
{
unsigned long num;
unsigned long size;
unsigned long addr;
unsigned long shndx;
} elf_section_header_table_t;
/* The Multiboot information. */
typedef struct multiboot_info
{
unsigned long flags;
unsigned long mem_lower;
unsigned long mem_upper;
unsigned long boot_device;
unsigned long cmdline;
unsigned long mods_count;
unsigned long mods_addr;
union
{
aout_symbol_table_t aout_sym;
elf_section_header_table_t elf_sec;
} u;
unsigned long mmap_length;
unsigned long mmap_addr;
unsigned long drives_length;
unsigned long drives_addr;
unsigned long config_table;
unsigned long boot_loader_name;
unsigned long apm_table;
unsigned long vbe_control_info;
unsigned long vbe_mode_info;
unsigned long vbe_mode;
unsigned long vbe_interface_seg;
unsigned long vbe_interface_off;
unsigned long vbe_interface_len;
} multiboot_info_t;
/* The module structure. */
typedef struct module
{
unsigned long mod_start;
unsigned long mod_end;
unsigned long string;
unsigned long reserved;
} module_t;
/* The memory map. Be careful that the offset 0 is base_addr_low
but no size. */
typedef struct memory_map
{
unsigned long size;
unsigned long base_addr_low;
unsigned long base_addr_high;
unsigned long length_low;
unsigned long length_high;
unsigned long type;
} memory_map_t;
Kernel .cpp
Code: Select all
#include <multiboot.h>
// declarations
void kernel_Startup( multiboot_header* header );
void kernel_main(unsigned long magic, unsigned long addr);
/* 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 linker option */
#define LOADBASE 0x100000
/* PE header are stored at the beginning of the file.
Code section is placed after */
#define HEADER_ADDRESS LOADBASE+ALIGN
/*************************************************************
* MULTIBOOT Header
* These data are placed at the beginning of the kernel file
* Grub 2 needs these data to boot properly
* see multiboot specification
*************************************************************/
#pragma code_seg(".a$0")
__declspec(allocate(".a$0"))
multiboot_header _MultibootHeader = {
MULTIBOOT_HEADER_MAGIC,
MULTIBOOT_HEADER_FLAGS,
CHECKSUM,
HEADER_ADDRESS,
LOADBASE,
0, //load end address
0, //bss end address
(unsigned long)DNA_Startup,
0,
800,
600,
8
};
#pragma comment(linker, "/merge:.text=.a")
/*************************************************************
* kernel_Startup
* this function is referenced by multiboot header to let
* Grub 2 start operating system
*************************************************************/
void kernel_Startup( multiboot_header* header ) {
unsigned long magic;
unsigned long multibootInfoPointer;
/* set parameters */
__asm {
mov magic, eax
mov multibootInfoPointer, ebx
}
/* Start operating system */
if (magic == 0x2BADB002)
{
kernel_main(magic, multibootInfoPointer);
}
// just stop if not loaded by Grub
_asm hlt;
}
/*************************************************************
* kernel_main
* The main entry for
* let Grub 2 start operating system
*************************************************************/
void kernel_main(unsigned long magic, unsigned long addr) {
char *sHello = "Hello from GRUB2 !\0";
char *videoMemory= (char*)(0xB8000);
char color= 0xF0;
// erase screen
for(int i=0; i< 80*25; i++)
{
*videoMemory++ = ' '; // character value
*videoMemory++ = 0x00; // color value
}
videoMemory= (char*)(0xB8000); // reset video memory pointer
// display message
while (*sHello!='\0')
{
*videoMemory++ = *sHello++; // character value
*videoMemory++ = color; // color value
}
_asm hlt; // stop to not hang on
}
Go to the project properties
- right clic on project --> Properties
- Configuration properties --> Debug
- Command : $(QEMU_HOME)qemu.exe
- Command args : -L Bios -kernel "$(TargetPath)" -m 128 -vga std
- Work directory :$(QEMU_HOME)
Now build your GRUB 2 ISO
- create a folder named boot
create a folder named grub in your boot folder
create a file grub.cfg in your grub folder
|-----grub
------|------grub.cfg
set this in your grub.cfg file :
Code: Select all
set timeout=0
set default=0 # Set the default menu entry
menuentry "MY_OPERATING_SYSTEM"
{
multiboot /boot/MYKERNEL_NAME # The multiboot command replaces the kernel command
}
Code: Select all
@SET KernelFile=PATH_TO_YOUR_KERNEL_YOU_HAVE_CREATED_WITH_VS2010
@SET ISOImageName=PATH_TO_YOUR_ISOFILE_YOU_WANT_TO_CREATE
@SET GrubFile=PATH_TO_THE_FOLDER_WHERE_IS_BOOT_FOLDER
Echo Build iso image with Grub 1.98
xcopy %KernelFile% %GrubFile%\boot\MYKERNEL_NAME /Y
sh grub-mkrescue --output=%ISOImageName% %GrubFile%
pause
Now you have an iso file with GRUB2
Test with any virtual machine or on a real PC [be careful]