Page 1 of 4

GRUB2 + VS2010 Bare bones

Posted: Fri Jun 08, 2012 4:55 am
by gedd
Requirements:
  • 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
Create an empty C++ project in VS2010
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
}
Build ans test :

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)
To build and test press F5 ,this should work.


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
boot
|-----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
}
create a bat file : CreateISO.bat

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
run the bat file

Now you have an iso file with GRUB2

Test with any virtual machine or on a real PC [be careful]

Re: GRUB2 + VS2010 Bare bones

Posted: Fri Jun 08, 2012 8:20 am
by Nessphoro
This setup makes me cringe a little, as I think my setup with VS2012 (Yes 2012, intelisense is great)
is better.
First of all I use the gcc-g++ compiler as imo its better. Secondly I use VHDs, so I always have direct access to the os's hard drive.

Re: GRUB2 + VS2010 Bare bones

Posted: Fri Jun 08, 2012 8:41 am
by gedd
Sorry for your teeth !
Where is your post with the best configuration ?
I am eager to learn and improve myself.

Re: GRUB2 + VS2010 Bare bones

Posted: Fri Jun 08, 2012 9:08 am
by Nessphoro
As soon as I get home.
I'm on my phone right now.

Re: GRUB2 + VS2010 Bare bones

Posted: Fri Jun 08, 2012 9:22 am
by Ameise
When I'm back from work (programming here atm) I will addend with a VS2010/VS2012 (the latter is what I use) build system that is entirely native to Visual C++ (no GCC or Cygwin required, only NASM). 'Tis what I use. It does require a few custom tools to be written; I have them build as part of the build process.

Nessphoro: If you use SSE in your kernel (you have no choice if using VC's compiler and you're writing it in 64-bit - SSE cannot be disabled in that case) then the VC compiler will auto-vectorize far better than GCC would.

Re: GRUB2 + VS2010 Bare bones

Posted: Fri Jun 08, 2012 10:13 am
by Nessphoro
Perhaps,

But kernels do not do billions of math operations to benefit in most cases. And in those that do need speed, I will probably write it manually in asm. And I still really feel gcc is more flexible

Re: GRUB2 + VS2010 Bare bones

Posted: Fri Jun 08, 2012 12:36 pm
by Ameise
Let me reiterate: If you use the Visual C++ Compiler, and you are in x86-64 mode, it is impossible to disable the generation of SSE2 code. It will generate it for relatively trivial things: memcpys/memmoves, replacements of loops that act like memcpys/memmoves, function calls, pretty much anything. VC is extremely aggressive with SSE2.

Therefore, since it will no matter what generate SSE2 opcodes, you might as well use SSE2 where appropriate (copying large amounts of data, for instance).

Also, there is no negative difference between intrinsics and asm. Intrinsics give the compiler the chance to optimize further, which asm does not.

Also, you cannot use inline assembly in VC in x86-64 mode. Only .S files and intrinsics. Not that I've ever needed more than intrinsics... they supply 80% of opcodes I'd need as intrinsics, the rest are supplied by a simple .S stub.

From what I understand, NT Kernel actually has SSE2 enabled and SSE2 opcodes are used within the kernel itself.

Re: GRUB2 + VS2010 Bare bones

Posted: Sat Jun 09, 2012 10:44 pm
by jbemmel
See http://social.msdn.microsoft.com/Forums ... 27341f6d30

Design choices in VC++ Compiler are very much tied to Windows, which makes it less suitable for creating alternative OSes (unless you copy the Windows kernel design...)

Re: GRUB2 + VS2010 Bare bones

Posted: Sun Jun 10, 2012 4:39 am
by Ameise
jbemmel wrote:See http://social.msdn.microsoft.com/Forums ... 27341f6d30

Design choices in VC++ Compiler are very much tied to Windows, which makes it less suitable for creating alternative OSes (unless you copy the Windows kernel design...)
You don't need to copy the Windows Kernel design, you just need to work within the limitations... which aren't that substantial, really. The primary issue is the complete inability to prevent the compiler from generating SSE code, and that limitation only exists for x86-64 builds.

Past that, you will probably notice if you read the name of the original poster for that link that he is probably involved in this very chat!


I'd also point out that the OP's method won't actually work in the long run. Without suitable expansion of the PE binary, once the binary gets to a specific size, the code that is stored in the binary will no longer match the positioning that is being assumed for the multiboot header. You must expand the PE binary into a binary blob.

Re: GRUB2 + VS2010 Bare bones

Posted: Sun Jun 10, 2012 2:46 pm
by Combuster
Ameise wrote:
jbemmel wrote:See http://social.msdn.microsoft.com/Forums ... 27341f6d30

Design choices in VC++ Compiler are very much tied to Windows, which makes it less suitable for creating alternative OSes (unless you copy the Windows kernel design...)
You don't need to copy the Windows Kernel design, you just need to work within the limitations...
Which as demonstrated might prevent you from making your own proper design decisions.

As far as I'm concerned, GCC is the right choice unless you can specifically and personally argue otherwise.

Re: GRUB2 + VS2010 Bare bones

Posted: Sun Jun 10, 2012 5:14 pm
by Ameise
Combuster wrote:
Ameise wrote:
jbemmel wrote:See http://social.msdn.microsoft.com/Forums ... 27341f6d30

Design choices in VC++ Compiler are very much tied to Windows, which makes it less suitable for creating alternative OSes (unless you copy the Windows kernel design...)
You don't need to copy the Windows Kernel design, you just need to work within the limitations...
Which as demonstrated might prevent you from making your own proper design decisions.

As far as I'm concerned, GCC is the right choice unless you can specifically and personally argue otherwise.
The only design decision that it prevents you from making is performing lazy SSE/SSE2 enabling during context switches; you instead always have it enabled. I don't consider that horribly significant in regards to overall design, as that's an implementation detail.

VC allows for other things which I prefer, such as naked functions. Any perceived limitation is only a limitation if you are expecting it act as though it were GCC... sort of like being mad at an orange for not tasting like a banana.

Overall, VC11 seems to generate better code than GCC does, which is also a good thing. It's also vastly easier to manage development using VC than it is with any available tools for Linux/OS X/whatever - one thing that Visual Studio does extremely well is its IDE and project system.

Past that, why is the burden of proof on me? Don't you need to prove explicitly that GCC is better as well?

Re: GRUB2 + VS2010 Bare bones

Posted: Sun Jun 10, 2012 11:46 pm
by neon
It has already been shown that a variety of OS designs can be implemented using either GCC or MSVC. MSVC does not limit OS designs in the same way GCC doesnt. It is ridiculous that this argument is still going on.

As far as Im concerned, any tool chain that can produce stand-alone software and cross-compilation can be used.

Re: GRUB2 + VS2010 Bare bones

Posted: Mon Jun 11, 2012 1:19 am
by Combuster
neon wrote:As far as Im concerned, any tool chain that can produce stand-alone software and cross-compilation can be used.
And MSVC (except EVC) is not a crosscompiler :wink:
It's also vastly easier to manage development using VC than it is with any available tools for Linux/OS X/whatever
That only shows you can't make the distinction between IDE and compiler.
VC allows for other things which I prefer, such as naked functions
Which only saves you from not having to write files in assembly. It won't help you a thing in 64-bit code since you can't do inline assembly there. Technically speaking, counting the limitations actually makes GCC better at naked functions.

Past that, why is the burden of proof on me? Don't you need to prove explicitly that GCC is better as well?
Here's the rant you asked for: GCC works everywhere, GCC works for everywhere, GCC supports pretty much all output formats, GCC is not sub-par in performance (and choosing MSVC for that reason makes you look silly for not choosing ICC instead). GCC is less than 10% in size. GCC has much better support for standards. GCC is not threatening users to drop C support altogether.

And most importantly, what matters for all the other readers of the forum is that it's an order of a magnitude less prone to get all the noobs stuck during kernel development. How many people here do you think can answer toolchain issues with MSVC?

So yes, choosing a different compiler than gcc involves a concious choice of trading your support options for a few comfy features or bragging rights. The vast majority of people don't realize that, and some of the remaining people - like you - don't realize that it holds for others.

Mind you, my compiler of choice is not GCC, and yet I'm advocating it.

Re: GRUB2 + VS2010 Bare bones

Posted: Mon Jun 11, 2012 2:56 am
by Solar
Ameise wrote:It's also vastly easier to manage development using VC than it is with any available tools for Linux/OS X/whatever - one thing that Visual Studio does extremely well is its IDE and project system.
As a full-time maintainer of Windows / Unix cross-platform software, and having previously worked in a MSVS-only environment for several years, I can say that I prefer the available tools for Linux over the available tools for Windows any time of the day. The time I've sunk in straightening MSVC project files, updating them when new versions of MSVC changed everything, and keeping the seperate versions in sync could have been spent much more productively - and to get things worked out properly, I've taken to editing the project files manually instead of through MSVC...

If you feel the Linux tools are deficient in any way, perhaps you should look for a better tutor / tutorial. ;-)

Re: GRUB2 + VS2010 Bare bones

Posted: Mon Jun 11, 2012 8:14 am
by gedd
Solar wrote:... The time I've sunk in straightening MSVC project files, updating them when new versions of MSVC changed everything, and keeping the seperate versions in sync could have been spent much more productively - and to get things worked out properly, I've taken to editing the project files manually instead of through MSVC...
It seems it was a long time ago.
VC 2010 convert automaticaly VC2008 project and it take few seconds.
I use Visual Studio since... the last century and I recognize that the use prior to the 2005 version was painful.

In General, it is sure that there are more tools on Linux to develop an operating system but there are also tools under Windows. The purpose of my post was to help a little not trigger a controversy.