module development for GRUB2 – playground

posted by on 2011.02.19, under bootloader, linux, programming
19:

Since testing modules for GRUB by compile/reboot/test/boot/… is time consuming, frustrating – simply not very efficient, there was an utility shipped with the sources called grub-emu that (like the name states) emulates the grub console. But: it was/is not a perfect emulation (stm), no modules are loaded/loadable so every module must be hand-coded-added to the built and… it does not build (like descibed here).

The playground – world:

And thats is okay cause there is another great tool: grub_mkrescue – an image builder that creates floppy/cdrom-images with… grub on it. (and it supports the preloading of modules) Sample:

$>grub-mkrescue --output=grub_rescue.img --modules=hello
$>qemu grub_rescue.img

Gives a GRUB inside qemu with hello.mod already loaded. Fine. Put the lines into the Makefile of the module currently developed (maybe as run-target) and testing becomes a lot easier…

The playground – garden:

Assume you have checked out the (latest) sources of grub2, and now you stay into the source-dir grub-1.98. Your new module (for the firsttime a copy/paste/change of hello/hello.c) goes to grub-1.98/simplemod.

Building a module could be done two ways: the slower one by adding a probate entry in conf/common.mk (simple copy/paste an entry for a given module like hello) – results in building everything again, and again when calling make clean/make… or the good, fast and due to the handcrafted standalone-Makefile ugly one.
No more filling phrases… here is the makefile (to be placed in grub-1.98/simplemod/Makefile):

GRUB2_SRC_DIR=..
GRUB2_HOME_DIR=/boot/grub2
MOD_NAME=simplemod
MOD_DIR=$(GRUB2_SRC_DIR)/$(MOD_NAME)
MOD_DEPENDENCIES=extcmd

#for install - inspired from grub-mkrescue-script
prefix=/usr/local
target_cpu=i386
libdir=$(prefix)/lib
native_platform=pc
grub_name=grub
mod_target_dir=$(libdir)/$(grub_name)/$(target_cpu)-$(native_platform)

ctx=/tmp
target_dir=/tmp

all: $(MOD_NAME)

$(MOD_NAME): $(MOD_NAME).c  
  gcc  -I$(GRUB2_SRC_DIR) -I$(GRUB2_SRC_DIR)/include -I. -I$(MOD_DIR) -Wall -W  -Wshadow -Wpointer-arith -Wmissing-prototypes -Wundef -Wstrict-prototypes -Werror -Os -DGRUB_MACHINE_PCBIOS=1 -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 -fno-builtin -mrtd -mregparm=3 -m32 -MD -c -o $(MOD_NAME)_mod-$(MOD_NAME)_$(MOD_NAME).o $(MOD_DIR)/$(MOD_NAME).c 
  
  rm -f pre-$(MOD_NAME).o  
  gcc -m32 -nostdlib -m32 -Wl,--build-id=none -Wl,-r,-d -o pre-$(MOD_NAME).o $(MOD_NAME)_mod-$(MOD_NAME)_$(MOD_NAME).o

  nm -g --defined-only -P -p pre-$(MOD_NAME).o | sed 's/^\([^ ]*\).*/\1 $(MOD_NAME)/' > def-$(MOD_NAME).lst
  echo '$(MOD_NAME)' > und-$(MOD_NAME).lst
  nm -u -P -p pre-$(MOD_NAME).o | cut -f1 -d' ' >> und-$(MOD_NAME).lst
    
  echo "$(MOD_NAME): $(MOD_DEPENDENCIES)" > moddep.lst
  
  sh $(GRUB2_SRC_DIR)/genmodsrc.sh '$(MOD_NAME)' moddep.lst > mod-$(MOD_NAME).c  
  gcc -I$(GRUB2_SRC_DIR) -I$(GRUB2_SRC_DIR)/include -I. -I$(MOD_DIR) -Wall -W -Os -DGRUB_MACHINE_PCBIOS=1 -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 -c -o mod-$(MOD_NAME).o mod-$(MOD_NAME).c  
  rm -f $(MOD_NAME).mod  
  gcc -m32 -nostdlib -m32 -Wl,--build-id=none -Wl,-r,-d -o $(MOD_NAME).mod pre-$(MOD_NAME).o mod-$(MOD_NAME).o      

  strip --strip-unneeded -K grub_mod_init -K grub_mod_fini -K _grub_mod_init -K _grub_mod_fini -R .note -R .comment $(MOD_NAME).mod

test:
  ls $(pc_dir)

install: install_lib

install_lib: override ctx=lib
install_lib: override target_dir=$(mod_target_dir)
install_lib: install_to

install_boot: override ctx=boot
install_boot: override target_dir=$(GRUB2_HOME_DIR)
install_boot: install_to

install_to:    
  @echo "install to context $(ctx)......."
  sudo cp $(MOD_NAME).mod $(target_dir)/$(MOD_NAME).mod
  
  sudo cp $(target_dir)/moddep.lst $(target_dir)/moddep.lst.old  
  -rm moddep_$(ctx).lst
  sed  '/$(MOD_NAME)/d'  $(mod_target_dir)/moddep.lst >> moddep_$(ctx).lst
  echo "$(MOD_NAME): $(MOD_DEPENDENCIES)" >> moddep_$(ctx).lst
  sudo cp moddep_$(ctx).lst $(target_dir)/moddep.lst
  
  sudo cp $(target_dir)/command.lst $(target_dir)/command.lst.old
  -rm command_$(ctx).lst
  sed  '/$(MOD_NAME)/d'  $(target_dir)/command.lst >> command_$(ctx).lst
  echo "$(MOD_NAME): $(MOD_NAME)" >> command_$(ctx).lst
  sudo cp command_$(ctx).lst $(target_dir)/command.lst  
    
clean:
  -rm $(MOD_DIR)/*.lst  
  -rm $(MOD_DIR)/*.o
  -rm $(MOD_DIR)/*.mod
  -rm $(MOD_DIR)/mod-$(MOD_NAME).c
  -rm $(MOD_DIR)/$(MOD_NAME)_mod-$(MOD_NAME)_$(MOD_NAME).d  
  -rm $(MOD_DIR)/*.img

image:
  -rm grub2mod_$(MOD_NAME)_test.img
  grub-mkrescue --output=grub2mod_$(MOD_NAME)_test.img --modules=$(MOD_NAME)
  
imagerun: image
  qemu grub2mod_$(MOD_NAME)_test.img

Okay, on the first time you must create the surrounding grub2-ecosystem (grub-1.98/configure;make;make install). But after that you only need to compile your new module. That is efficient.

There are no comments.

Please Leave a Reply

*

pagetop