Now Reading
GRUB2 Modules « Musings

GRUB2 Modules « Musings

2024-02-15 05:44:06

GRUB2 has a modular structure with help for loading and unloading code modules as wanted. Modules are much like Linux kernel modules in some respects however in different methods they’re like plugins for Mozilla Firefox or the Eclipse IDE. On this put up I present an summary of what a GRUB2 module is and present you the way to modify an present module so as to add new performance. I additionally reveal the way to develop, combine and check your personal customized module utilizing the GRUB2 grub-emu userspace emulator.

The present model of GRUB2 (v1.98) has 159 modules:


acpi.mod          date.mod                     gcry_sha1.mod       loopback.mod         pbkdf2.mod          terminfo.mod
affs.mod          datetime.mod                 gcry_sha256.mod     lsmmap.mod           pci.mod             check.mod
afs_be.mod        dm_nv.mod                    gcry_sha512.mod     ls.mod               play.mod            tga.mod
afs.mod           drivemap.mod                 gcry_tiger.mod      lspci.mod            png.mod             trig.mod
aout.mod          echo.mod                     gcry_twofish.mod    lvm.mod              probe.mod           true.mod
ata.mod           efiemu.mod                   gcry_whirlpool.mod  mdraid.mod           pxecmd.mod          udf.mod
ata_pthru.mod     elf.mod                      gettext.mod         memdisk.mod          pxe.mod             ufs1.mod
at_keyboard.mod   example_functional_test.mod  gfxmenu.mod         memrw.mod            raid5rec.mod        ufs2.mod
befs_be.mod       ext2.mod                     gfxterm.mod         minicmd.mod          raid6rec.mod        uhci.mod
befs.mod          extcmd.mod                   gptsync.mod         minix.mod            raid.mod            usb_keyboard.mod
biosdisk.mod      fats.mod                      gzio.mod            mmap.mod             learn.mod            usb.mod
bitmap.mod        font.mod                     halt.mod            msdospart.mod        reboot.mod          usbms.mod
bitmap_scale.mod  fshelp.mod                   handler.mod         multiboot2.mod       reiserfs.mod        usbtest.mod
blocklist.mod     functional_test.mod          hashsum.mod         multiboot.mod        relocator.mod       vbeinfo.mod
boot.mod          gcry_arcfour.mod             hdparm.mod          regular.mod           scsi.mod            vbe.mod
bsd.mod           gcry_blowfish.mod            howdy.mod           ntfscomp.mod         search_fs_file.mod  vbetest.mod
bufio.mod         gcry_camellia.mod            assist.mod            ntfs.mod             search_fs_uuid.mod  vga.mod
cat.mod           gcry_cast5.mod               hexdump.mod         ohci.mod             search_label.mod    vga_text.mod
chain.mod         gcry_crc.mod                 hfs.mod             part_acorn.mod       search.mod          video_fb.mod
charset.mod       gcry_des.mod                 hfsplus.mod         part_amiga.mod       serial.mod          video.mod
cmp.mod           gcry_md4.mod                 iso9660.mod         part_apple.mod       setjmp.mod          videotest.mod
configfile.mod    gcry_md5.mod                 jfs.mod             part_gpt.mod         setpci.mod          xfs.mod
cpio.mod          gcry_rfc2268.mod             jpeg.mod            part_msdos.mod       sfs.mod             xnu.mod
cpuid.mod         gcry_rijndael.mod            keystatus.mod       part_sun.mod         sh.mod              xnu_uuid.mod
crc.mod           gcry_rmd160.mod              linux16.mod         parttool.mod         sleep.mod
crypto.mod        gcry_seed.mod                linux.mod           password.mod         tar.mod
datehook.mod      gcry_serpent.mod             loadenv.mod         password_pbkdf2.mod  terminal.mod


A few of the extra noteworthy modules are:

  • ls, cat, echo, cmp: Present related performance to their Unix command couterparts.
  • ext2, iso9660, reiserfs, xfs: Present help for filesystems of the identical title.
  • part_sun, part_gpt, part_msdos: Present help for varied partition schemes.
  • linux: Loader for Linux photographs
  • vga, tga, vbe, png,jpeg: Present help for graphics and background photographs.

The instructions to load (insmod) or unload (rmmod) a module into GRUB2 have the identical names as in GNU/Linux.

When a module is loaded, or a linked-in module is initialized, the module registers a number of instructions, and can even register variables, parsers, and drivers. A GRUB2 command similar to hexdump requires a mapping from a reputation to a particular module operate The file /boot/grub/command.lst comprises the mappings from the command title to the module that comprises the operate (and code to implement that command). Right here is a part of the command.lst file:


cat: minicmd
chainloader: chain
clear: minicmd
cmp: cmp
.: configfile
configfile: configfile
*cpuid: cpuid
crc: crc
date: date
*drivemap: drivemap
dump: minicmd
*echo: echo
hexdump: hexdump


In lots of instances the command title is identical title because the module title, e.g. hexdump and hexdump.mod. In different instances a loaded module might register a number of instructions, e.g. loadenv.mod registers the load_env and save_env. If a command is entered (both instantly or by way of a script) the suitable module(s) is loaded if the command is just not already registered. A variable is a mapping from a reputation to a variable outlined within the module. Scripts can entry the variable as $title. Module variable eventing is supported; a module can get a callback when a worth is assigned to a variable.

Modules are literally ELF format information. The principle GRUB2 file core.img comprises the mandatory code to parse the ELF headers, load the module and do dynamic-linking (i.e., resolve calls to capabilities and variables exported by the core.img to be used by modules). A module is usually a built-in, i.e. a part of core.img or dynamically loaded utilizing insmod, or it may be loaded robotically when one other module is loaded by way of insmod as a result of the module being loaded has a dependency on it.

Dependency mappings are listed within the file moddep.lst. Right here is a part of this file:


video:
font: bufio video
hfsplus: fshelp
gettext: regular gzio
extcmd:
regular: crypto boot terminal charset
hashsum: extcmd regular crypto
search: extcmd search_label search_fs_uuid search_fs_file
xnu_uuid: gcry_md5
drivemap: extcmd boot mmap
password: crypto regular
learn:


From the above you may see that the password module has dependencies on the crypto and regular modules. Observe that the regular module is robotically loaded by core.img at startup and thus the modules crypto, boot, terminal and charset are additionally loaded at the moment as a result of regular has dependencies on these modules.

The supply code for GRUB2 is pretty properly structured and is usually ANSI C code. Naturally there’s a certain quantity of assembler code (that’s the nature of the beast) however the quantity is small and it is best to by no means have any want to change and even have a look at such code. It runs in 32-bit actual mode and is single-threaded. Usually there are not any synchronization points or races circumstances to contemplate.

Turning now to the query of the way to create and construct a GRUB2 module. The compulsory Hey World module (./howdy/howdy.mod) is included with the GRUB2 supply code tarball. Right here is the supply code for this module:


/* howdy.c - check module for dynamic loading */
/*
 *  GRUB  --  GRand Unified Bootloader
 *  Copyright (C) 2003,2007  Free Software program Basis, Inc.
 *  Copyright (C) 2003  NIIBE Yutaka <gniibe@m17n.org>
 *
 *  GRUB is free software program: you may redistribute it and/or modify
 *  it underneath the phrases of the GNU Normal Public License as printed by
 *  the Free Software program Basis, both model 3 of the License, or
 *  (at your choice) any later model.
 *
 *  GRUB is distributed within the hope that it is going to be helpful,
 *  however WITHOUT ANY WARRANTY; with out even the implied guarantee of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Normal Public License for extra particulars.
 *
 *  You need to have acquired a replica of the GNU Normal Public License
 *  together with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 */
#embrace <grub/sorts.h>
#embrace <grub/misc.h>
#embrace <grub/mm.h>
#embrace <grub/err.h>
#embrace <grub/dl.h>
#embrace <grub/extcmd.h>
#embrace <grub/i18n.h>

static grub_err_t
grub_cmd_hello (struct grub_extcmd *cmd __attribute__ ((unused)),
                int argc __attribute__ ((unused)),
                char **args __attribute__ ((unused)))
{
  grub_printf ("Hey Worldn");
  return 0;
}

static grub_extcmd_t cmd;

GRUB_MOD_INIT(howdy)
{
  cmd = grub_register_extcmd ("howdy", grub_cmd_hello, GRUB_COMMAND_FLAG_BOTH,
                              0, N_("Say "Hey World"."), 0);
}

GRUB_MOD_FINI(howdy)
{
  grub_unregister_extcmd (cmd);
}


The above C language code shouldn’t be obscure. The definitions for GRUB_MOD_INIT and GRUB_MOD_FINI are within the header dl.h. These capabilities are principally used to register and unregister a command, on this case howdy. While you enter the command howdy the operate grub_cmd_hello within the dynamically loaded module howdy.mod is invoked. By no means attempt to use libc library capabilities in a module. All of the capabilities it is best to want can be found within the supply tarball and have the identical title because the equal libc operate besides that they’re prefixed by grub_, e.g. grub_printf() and printf(), grub_strcpy() and strcpy. As well as don’t embrace common headers similar to stdio.h.

If you’re not going to cross any arguments right into a command, you will need to particularly declare this reality within the operate declaration as follows:


function_name (struct grub_extcmd *cmd __attribute__ ((unused)),
                int argc __attribute__ ((unused)),
                char **args __attribute__ ((unused)))


The mandatory construct directives are already current for the howdy module. After compiling and putting in GRUB2, it is best to discover that the howdy module was put in in /boot/grub. On the GRUB2 command immediate, you may load and execute the howdy command as follows:


grub> insmod howdy.mod
grub> howdy
Hey World
grub>


Turning now to to the hexdump command. The supply code for this command is within the ../instructions subdirectory. At the moment there isn’t a choice to dump your complete contents of a file on this command so I’ve determined so as to add this performance. I see from the next code snippet that presently hexdump can take two elective arguments:


static const struct grub_arg_option choices[] = {
  {"skip", 's', 0, N_("Skip offset bytes from the start of file."), 0, ARG_TYPE_INT},
  {"size", 'n', 0, N_("Learn solely LENGTH bytes."), 0, ARG_TYPE_INT},
  {0, 0, 0, 0, 0, 0}
};

static grub_err_t
grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args)
{
  struct grub_arg_list *state = cmd->state;
  grub_ssize_t dimension, size;
  grub_disk_addr_t skip;
   ....
  skip = (state[0].set) ? grub_strtoull (state[0].arg, 0, 0) : 0;
  size = (state[1].set) ? grub_strtoul (state[1].arg, 0, 0) : 256;


Observe that state[0] refers back to the first choice argument outlined in choices array, i.e. skip, and state[1] refers back to the second choice argument, i.e. size. Thus if one thing like -s 200 is handed as a command line argument to the hexdump command, state[0] is about to a non-zero worth. I exploit this reality to resolve when to hexdump the whole file. This I do if each state[0] and state[1} are set to 0.

Here is the source code for the new functionality:


.....
  if (!grub_strcmp (args[0], "(mem)"))
    hexdump (skip, (char *) (grub_addr_t) skip, size);
  /* new performance */
  else if (state[0].set == 0 && state[1].set == 0)
    {
      file = grub_gzfile_open (args[0], 1);
      if (! file)
        return grub_errno;

      skip = 0;

      whereas ((dimension = grub_file_read (file, buf, 256)) > 0
             && key != GRUB_TERM_ESC)
        {
           hexdump (skip, buf, dimension);
           skip += dimension;

           whereas (grub_checkkey () >= 0 &&
             (key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != GRUB_TERM_ESC)
           ;
        }

      grub_putchar ('n');
      grub_refresh ();
      grub_file_close (file);
    }
  /* finish new performance */
  else if ((args[0][0] == '(') && (args[0][namelen - 1] == ')'))
.....


The code needs to be just about self explanatory. Observe that hexdump is a separate library operate which codecs and shows all or a part of no matter is the buf buffer (is determined by the numeric values in skip and dimension). Additionally, the inside whereas loop is activated if the pagerenvironmental variable is about. On this case, hexdump shows a —MORE— immediate and solely shows the following display screen of knowledge when a key’s pressed. No modifications to the construct system are required; you may simply rebuild GRUB2, copy hexdump.mod to /boot/grub, reboot your system and check hexdump from the GRUB2 command immediate.

Subsequent we develop a model new module known as colortest from scratch. This module will show all the colour mixtures supported by GRUB2 (it the identical set as for GRUB Legacy) to be able to test that they’re appropriately displayed by GRUB2.

Right here is the supply code for the module. Observe for the sake of brevity I’ve not noted many of the potential shade mixtures as these would solely add a number of hundred extra strains of repetitive code to the itemizing. The supply code is commented the place I believe an evidence is warranted.


#embrace <grub/env.h>
#embrace <grub/sorts.h>
#embrace <grub/dl.h>
#embrace <grub/misc.h>
#embrace <grub/mm.h>
#embrace <grub/font.h>
#embrace <grub/time period.h>
#embrace <grub/command.h>
#embrace <grub/extcmd.h>
#embrace <grub/i18n.h>

/* takes one elective argument -c */
static const struct grub_arg_option choices[] =
{
     {"clear", 'c', 0, N_("Clear the display screen first."), 0, 0},
     {0, 0, 0, 0, 0, 0}
};

/* since argc and argv aren't used throughout the operate they */ 
/* have to be declared unused - in any other case the construct fails */
static grub_err_t
grub_cmd_colortest (grub_extcmd_t cmd,
                   int argc __attribute__ ((unused)),
                   char **args __attribute__ ((unused)))
{
  struct grub_arg_list *state = cmd->state;
  grub_err_t err = GRUB_ERR_NONE;
  char color_normal[50];
  const char *tmp;

  /* save the present shade string for color_normal. It's within the atmosphere  */
  /* set default if none within the atmosphere in any other case error messages in grub-emu */.
  tmp = grub_env_get("color_normal");
  if (*tmp)
      grub_strcpy(color_normal, tmp);
  else
      grub_strcpy(color_normal, "light-gray/black");

  /* clear the display screen if -c handed on command line */
  if (state[0].set)
    grub_cls();

  /* set the present shade state to regular jsut in case it it presently spotlight */
  grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);

  /* black */
  /* change the color_normal setting within the atmosphere */
  grub_env_set ("color_normal", "dark-gray/black");
  /* print this string in dark-gray on black.  Black as background is clear */
  grub_printf (" dark-gray/black          ");
  grub_env_set ("color_normal", "light-blue/black");
  grub_printf (" light-blue/black         ");
  grub_env_set ("color_normal", "light-green/black");
  grub_printf (" light-green/black        ");
  grub_env_set ("color_normal", "light-cyan/black");
  grub_printf (" light-cyan/black         n");
  grub_env_set ("color_normal", "light-red/black");
  grub_printf (" light-red/black          ");
  grub_env_set ("color_normal", "light-magenta/black");
  grub_printf (" light-magenta/black      ");
  grub_env_set ("color_normal", "yellow/black");
  grub_printf (" yellow/black             ");
  grub_env_set ("color_normal", "white/black");
  grub_printf (" white/black              n");

  /* blue */
  grub_env_set ("color_normal", "dark-gray/blue");
  grub_printf (" dark-gray/blue           ");
  grub_env_set ("color_normal", "light-blue/blue");
  grub_printf (" light-blue/blue          ");
  grub_env_set ("color_normal", "light-green/blue");
  grub_printf (" light-green/blue         ");
  grub_env_set ("color_normal", "light-cyan/blue");
  grub_printf (" light-cyan/blue          n");

  grub_env_set ("color_normal", "light-red/blue");
  grub_printf (" light-red/blue           ");
  grub_env_set ("color_normal", "light-magenta/blue");
  grub_printf (" light-magenta/blue       ");
  grub_env_set ("color_normal", "yellow/blue");
  grub_printf (" yellow/blue              ");
  grub_env_set ("color_normal", "white/blue");
  grub_printf (" white/blue               n");

  /* revert to the unique color_normal */
  grub_env_set ("color_normal", color_normal); 
  grub_printf ("nn");

  /* black spotlight */
  /* change the color_highlight setting within the atmosphere */
  grub_env_set ("color_highlight", "black/blue");
  /* allow color_highlight and print a string */
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" black/blue               ");
  grub_env_set ("color_highlight", "black/inexperienced");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" black/inexperienced              ");
  grub_env_set ("color_highlight", "black/cyan");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" black/cyan               ");
  grub_env_set ("color_highlight", "black/purple");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" black/purple                n");

  grub_env_set ("color_highlight", "black/magenta");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" black/magenta            ");
  grub_env_set ("color_highlight", "black/brown");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" black/brown              ");
  grub_env_set ("color_highlight", "black/light-gray");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" black/light-gray         n");

  /* blue spotlight */
  grub_env_set ("color_highlight", "blue/inexperienced");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" blue/inexperienced               ");
  grub_env_set ("color_highlight", "blue/cyan");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" blue/cyan                ");
  grub_env_set ("color_highlight", "blue/purple");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" blue/purple                 n");

  grub_env_set ("color_highlight", "blue/magenta");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" blue/magenta             ");
  grub_env_set ("color_highlight", "blue/brown");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" blue/brown               ");
  grub_env_set ("color_highlight", "blue/light-gray");
  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
  grub_printf (" blue/light-gray          n");

  /* revert to authentic color_normal */
  grub_env_set ("color_normal", color_normal);
  grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
  grub_printf ("n");

  /* and exit */
  return err;
}

static grub_extcmd_t cmd;

GRUB_MOD_INIT(colortest)
{
  cmd = grub_register_extcmd ("colortest", grub_cmd_colortest,
                               GRUB_COMMAND_FLAG_BOTH,
                               "[-c]",
                               /* the _N assemble is for message localization */
                               N_("Check supported shade mixtures."),
                               choices);
}

GRUB_MOD_FINI(colortest)
{
    grub_unregister_extcmd (cmd);
}


Now that the C code is written, how can we combine colortest into the present GRUB2 construct system in order that colortest.mod is robotically constructed once we enter make. on the GRUB2 construct prime stage listing? It seems to be long-winded however straightforward. Simply add the next strains to ../conf/widespread.mk:


# For colortest.mod.
pkglib_MODULES += colortest.mod
colortest_mod_SOURCES = instructions/colortest.c

clean-module-colortest.mod.1:
        rm -f colortest.mod mod-colortest.o mod-colortest.c pre-colortest.o colortest_mod-commands_colortest.o und-colortest.lst

CLEAN_MODULE_TARGETS += clean-module-colortest.mod.1

clean-module-colortest.mod-symbol.1:
        rm -f def-colortest.lst

CLEAN_MODULE_TARGETS += clean-module-colortest.mod-symbol.1
DEFSYMFILES += def-colortest.lst
mostlyclean-module-colortest.mod.1:
        rm -f colortest_mod-commands_colortest.d

MOSTLYCLEAN_MODULE_TARGETS += mostlyclean-module-colortest.mod.1
UNDSYMFILES += und-colortest.lst
ifneq ($(TARGET_APPLE_CC),1)
colortest.mod: pre-colortest.o mod-colortest.o $(TARGET_OBJ2ELF)
        -rm -f $@
        $(TARGET_CC) $(colortest_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ pre-colortest.o mod-colortest.o
        if check ! -z "$(TARGET_OBJ2ELF)"; then ./$(TARGET_OBJ2ELF) $@ || (rm -f $@; exit 1); fi
        $(STRIP) --strip-unneeded -Okay grub_mod_init -Okay grub_mod_fini -Okay _grub_mod_init -Okay _grub_mod_fini -R .be aware -R .remark $@
else
colortest.mod: pre-colortest.o mod-colortest.o $(TARGET_OBJ2ELF)
        -rm -f $@
        -rm -f $@.bin
        $(TARGET_CC) $(colortest_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@.bin pre-colortest.o mod-colortest.o
        $(OBJCONV) -f$(TARGET_MODULE_FORMAT) -nr:_grub_mod_init:grub_mod_init -nr:_grub_mod_fini:grub_mod_fini -wd1106 -nu -nd $@.bin $@
        -rm -f $@.bin
endif

pre-colortest.o: $(colortest_mod_DEPENDENCIES) colortest_mod-commands_colortest.o
        -rm -f $@
        $(TARGET_CC) $(colortest_mod_LDFLAGS) $(TARGET_LDFLAGS) -Wl,-r,-d -o $@ colortest_mod-commands_colortest.o

mod-colortest.o: mod-colortest.c
        $(TARGET_CC) $(TARGET_CPPFLAGS) $(TARGET_CFLAGS) $(colortest_mod_CFLAGS) -c -o $@ $<

mod-colortest.c: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh
        sh $(srcdir)/genmodsrc.sh 'colortest' $< > $@ || (rm -f $@; exit 1)
ifneq ($(TARGET_APPLE_CC),1)
def-colortest.lst: pre-colortest.o
        $(NM) -g --defined-only -P -p $< | sed 's/^([^ ]*).*/1 colortest/' > $@
else
def-colortest.lst: pre-colortest.o
        $(NM) -g -P -p $< | grep -E '^[a-zA-Z0-9_]* [TDS]'  | sed 's/^([^ ]*).*/1 colortest/' > $@
endif

und-colortest.lst: pre-colortest.o
        echo 'colortest' > $@
        $(NM) -u -P -p $< | lower -f1 -d' ' >> $@

colortest_mod-commands_colortest.o: instructions/colortest.c $(instructions/colortest.c_DEPENDENCIES)
        $(TARGET_CC) -Icommands -I$(srcdir)/instructions $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(colortest_mod_CFLAGS) -MD -c -o $@ $<
-include colortest_mod-commands_colortest.d

clean-module-colortest_mod-commands_colortest-extra.1:
        rm -f cmd-colortest_mod-commands_colortest.lst fs-colortest_mod-commands_colortest.lst partmap-colortest_mod-commands_colortest.lst handler-colortest_mod-commands_colortest.lst parttool-colortest_mod-commands_colortest.lst video-colortest_mod-commands_colortest.lst terminal-colortest_mod-commands_colortest.lst

CLEAN_MODULE_TARGETS += clean-module-colortest_mod-commands_colortest-extra.1

COMMANDFILES += cmd-colortest_mod-commands_colortest.lst
FSFILES += fs-colortest_mod-commands_colortest.lst
PARTTOOLFILES += parttool-colortest_mod-commands_colortest.lst
PARTMAPFILES += partmap-colortest_mod-commands_colortest.lst
HANDLERFILES += handler-colortest_mod-commands_colortest.lst
TERMINALFILES += terminal-colortest_mod-commands_colortest.lst
VIDEOFILES += video-colortest_mod-commands_colortest.lst
cmd-colortest_mod-commands_colortest.lst: instructions/colortest.c $(instructions/colortest.c_DEPENDENCIES) gencmdlist.sh
        set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/instructions $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(colortest_mod_CFLAGS) -E $<         | sh $(srcdir)/gencmdlist.sh colortest > $@ || (rm -f $@; exit 1)

fs-colortest_mod-commands_colortest.lst: instructions/colortest.c $(instructions/colortest.c_DEPENDENCIES) genfslist.sh
        set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/instructions $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(colortest_mod_CFLAGS) -E $<         | sh $(srcdir)/genfslist.sh colortest > $@ || (rm -f $@; exit 1)

parttool-colortest_mod-commands_colortest.lst: instructions/colortest.c $(instructions/colortest.c_DEPENDENCIES) genparttoollist.sh
        set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/instructions $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(colortest_mod_CFLAGS) -E $<         | sh $(srcdir)/genparttoollist.sh colortest > $@ || (rm -f $@; exit 1)

partmap-colortest_mod-commands_colortest.lst: instructions/colortest.c $(instructions/colortest.c_DEPENDENCIES) genpartmaplist.sh
        set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/instructions $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(colortest_mod_CFLAGS) -E $<         | sh $(srcdir)/genpartmaplist.sh colortest > $@ || (rm -f $@; exit 1)

handler-colortest_mod-commands_colortest.lst: instructions/colortest.c $(instructions/colortest.c_DEPENDENCIES) genhandlerlist.sh
        set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/instructions $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(colortest_mod_CFLAGS) -E $<         | sh $(srcdir)/genhandlerlist.sh colortest > $@ || (rm -f $@; exit 1)

terminal-colortest_mod-commands_colortest.lst: instructions/colortest.c $(instructions/colortest.c_DEPENDENCIES) genterminallist.sh
        set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/instructions $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(colortest_mod_CFLAGS) -E $<         | sh $(srcdir)/genterminallist.sh colortest > $@ || (rm -f $@; exit 1)

video-colortest_mod-commands_colortest.lst: instructions/colortest.c $(instructions/colortest.c_DEPENDENCIES) genvideolist.sh
        set -e;           $(TARGET_CC) -Icommands -I$(srcdir)/instructions $(TARGET_CPPFLAGS)  $(TARGET_CFLAGS) $(colortest_mod_CFLAGS) -E $<         | sh $(srcdir)/genvideolist.sh colortest > $@ || (rm -f $@; exit 1)

colortest_mod_CFLAGS = $(COMMON_CFLAGS)
colortest_mod_LDFLAGS = $(COMMON_LDFLAGS)


A lot of the above is boilerplate. I merely copied it from an present goal similar to tga in widespread.mk and altered the goal title to colortest. If you happen to now execute make from the GRUB2 construct toplevel listing, it ought to comprise the module colortest.mod after the construct completes if the construct was profitable.

Here’s a detailed itemizing of the instructions used to construct colortest.mod:


gcc -Icommands -I./instructions -nostdinc -isystem /usr/lib/gcc/x86_64-redhat-linux/4.4.4/embrace  
       -I./embrace -I. -I./embrace -Wall -W  -Os  -DGRUB_MACHINE_PCBIOS=1 -Wall -W -Wshadow  
      -Wpointer-arith -Wmissing-prototypes  -Wundef -Wstrict-prototypes -g -falign-jumps=1  
      -falign-loops=1 -falign-functions=1 -mno-mmx -mno-sse -mno-sse2 -mno-3dnow  
      -fno-dwarf2-cfi-asm -m32 -fno-stack-protector -mno-stack-arg-probe -Werror -fno-builtin -mrtd  
      -mregparm=3 -m32 -MD -c -o colortest_mod-commands_colortest.o instructions/colortest.c
rm -f pre-colortest.o
gcc -m32 -nostdlib -m32 -Wl,--build-id=none -Wl,-r,-d -o pre-colortest.o colortest_mod-commands_colortest.o
nm -g --defined-only -P -p pre-colortest.o | sed 's/^([^ ]*).*/1 colortest/' > def-colortest.lst
echo 'colortest' > und-colortest.lst
nm -u -P -p pre-colortest.o | lower -f1 -d' ' >> und-colortest.lst


As you may see beneath, a 32-bit ELF relocatable binary is produced.


file colortest.mod
colortest.mod: ELF 32-bit LSB relocatable, Intel 80386, model 1 (SYSV), not stripped
# 


There are a selection of how to check and confirm the brand new colortest module. You possibly can copy colortest.mod into /boot/grub, modify /boot/grub/command.lst so as to add the next entry:


and reboot your system to the GRUB2 command immediate. From there you may load the colortest module utilizing insmod and invoke the grub_colortest operate by coming into the command colortest or colortest -c on the grub> immediate. A downside to this technique is that it requires you to reboot your system each time you make a change to the colortest supply code or construct atmosphere.

If you wish to keep away from having to repeatedly reboot your system you may check the performance of colortest utilizing the GRUB2 userspace emulator grub-emu. Observe that grub-emu is just not used for system booting; it’s a standalone utility which you’ll run from the command line after you boot your system into GNU/Linux. It emulates, as greatest it could actually however with some limitations, the conduct of the GRUB2 command line.

To construct grub-emu you must have each the ncurses-libs and ncurses-devel packages put in. I didn’t discover a lot documentation on the way to construct grub-emu however found how to take action principally by trial and error. In the long run it turned out to be fairly easy.


./make clear
./configure --platform=emu
./make
./grub-emu


This could get you to the grub-emu immediate after a number of warning messages are displayed. These warning messages are regular. Here’s what grub-emu outputs when it’s invoked with the -h choice:


# ./grub-emu -h
Utilization: ./grub-emu [OPTION]...

GRUB emulator.

  -r, --root-device=DEV     use DEV as the foundation system [default=guessed]
  -m, --device-map=FILE     use FILE because the system map [default=/boot/grub/device.map]
  -d, --directory=DIR       use GRUB information within the listing DIR [default=/boot/grub]
  -v, --verbose             print verbose messages
  -H, --hold[=SECONDS]      wait till a debugger will connect
  -h, --help                show this message and exit
  -V, --version             print model data and exit

Report bugs to .
#


By the way in which, enter exit or reboot to exit grub-emu. Discover that no modules similar to regular.mod or colortest.mod are constructed when constructing the GRUB2 emulator. That’s as a result of insmod doesn’t work in grub-emu and subsequently constructing the modules is pointless. The insmod command is there but it surely can’t do something. If you happen to attempt to use insmod to load a module from /boot/grub, it should reply with an invalid arch impartial ELF magic error message. Modules are both built-in in the course of the construct course of or aren’t out there. At the moment, in case you attempt to execute colortest from inside grub-emu you’ll get a error: unknown command ‘colortest’ error message.

To get grub-emu to acknowledge the colortest command a variety of information should be modified and grub-emu rebuilt. First, add the next two strains to grub-emu-init.c:


  grub_colortest_init ();
  grub_colortest_fini ();


The primary line needs to be added to the grub_init_all process and the second line to the grub_fini_all process. Two appropriate operate prototypes, modeled on the opposite present operate prototypes, needs to be added to grub-emu-init.h additionally. The aim of grub_init_all and grub_fini_all (see …/util/grub-emu.c) is to load the desired modules at grub-emu startup and unload them when grub-emu is terminating.

Subsequent you must modify ../conf/any-emu.mk so as to add help for linking colortest into grub-emu when constructing grun-emu. At a minimal add instructions/colortest.c to the grub_emu_SOURCES record. Whereas not completely required, I’d add grub_emu-commands_colortest.o and grub_emu-commands_colortest.d to the record of information to be eliminated by the cleanup directives, e.g. clean-utility-grub-emu.1:, and many others. Lastly, we have to inform any-emu.mk the way to compile colortest.o for inclusion in grub-emu by including the next directives to the file:


grub_emu-commands_colortest.o: instructions/colortest.c $(instructions/colortest.c_DEPENDENCIES)
        $(CC) -Icommands -I$(srcdir)/instructions $(CPPFLAGS) $(CFLAGS) -DGRUB_UTIL=1 $(grub_emu_CFLAGS) -MD -c -o $@ $<
-include grub_emu-commands_colortest.d


After rebuilding grub-emu, the colortest command needs to be listed once you enter the assist command.

Here’s a screenshot of grub-emu displaying the outcomes of the colortest command.
grub2 emulator image 1
One other technique to safely check a brand new module is to host GRUB2 on an IA32 processor emulator similar to Qemu or Bochs. Nevertheless, I’m not going to cowl these strategies on this put up. If I discover the time I’ll cowl them in a separate put up within the close to future.

I’m going to cease writing now. Hopefully, after studying this put up, you might have a greater understanding of the way to write, combine and check a GRUB2 module. Please let me know if there’s different pertinent data I ought to add to this put up which might help readers in understanding the related points.
 

P.S. I constructed and examined the examples included on this put up on X64 platform working Fedora 13.

Source Link

What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top