Writing GRUB Modules

From OSDev.wiki
Jump to navigation Jump to search
Difficulty level

Master

The whole architecture of GRUB changed as of version 2. The big new feature is modules. This lead to the elimination of Stage 1.5. It also means it is easier for you to put lot of cool functionality into your bootloader. You can now add support for new executable formats, filesystems, video drivers, kernel boot protocols, and so on.

Modules

GRUB modules are relocatable ELF32 binaries. They have the extension .mod.

Header files

All the standard GRUB header files from the source distribution can be included. If you are building out-of-tree and have not configured the source for your system, then these can still be used with a few modifications:

  • define GRUB_MACHINE_PCBIOS to be 1
  • define GRUB_UTIL
  • define GRUB_FILE to be something appriopriate
  • provide include/grub/cpu/memory.h to typedef grub_phys_addr_t to something appropriate (e.g. intptr_t)

Special Sections

Each module is required to contain three special pieces of information: the module name, the dependencies of the module (i.e. which other modules need to be loaded prior to this one) and the licence of the module. For GRUB 2, the licence is required to be GPL otherwise it will not be loaded. These need to be placed in special sections within the module. The following piece of code (GCC specific) at module scope will achieve the required functionality:

char modname[] __attribute__((section(".modname"))) = "mymodule";

/* Example dependencies */
char moddeps[] __attribute__((section(".moddeps"))) = "relocator\0video\0vbe\0multiboot\0gfxterm";

GRUB_MOD_LICENSE("GPLv3+");

Initialization

You need to provide initialization and finalization functions for your module. These are called when the module is loaded/unloaded, and should register the commands that the module provides along with any other resources it requires. A short example is:

static grub_extcmd_t cmd;

GRUB_MOD_INIT(mymodule)
{
    cmd = grub_register_extcmd("mycommand" /* name of the command */,
            grub_cmd_mycommand /* function to call when the command is run */,
            0 /* flags */,
            0 /* summary */,
            N_("In-depth description of this command") /* description */,
            0 /* argument parser */);
}

GRUB_MOD_FINI(mymodule)
{
    grub_unregister_extcmd(cmd);
}

See the GRUB source/example modules for more information about the other options here.

Functions

int EXPORT_FUNC() grub_printf(const char* func, ...);  //Very similar to standard printf()
grub_extcmd_t grub_register_extcmd (const char * name, grub_extcmd_func_t func, 
    grub_command_flags_t flags, const char * summary, const char * description, 
    const struct grub_arg_option * parser);  //Registers a command on the GRUB command line
grub_fs_register (struct grub_fs* fs);       //Registers a filesystem with GRUB (grub_fs is a set of function pointers)

Building

Modules are object files. You therefore need to use GCC (i686-elf recommended) to build your C files, then use ld's -r option to combine your object files (if necessary). the final output needs to be named .mod.

Loading

Modules can be loaded with the insmod command, from the GRUB configuration file. For filesystem modules, this allows your OS to be booted from your FS, but requires a recognized format for your module. To solve this, you will need to add your module to core.img using grub-mkimage, which can be installed using grub-setup, or possibly grub-install (which is a shell script wrapper to mkimage and setup).

This page is a stub.
You can help the wiki by accurately adding more contents to it.

External Links