Now that the OpenPower sources are available, it's possible to build custom firmware images for OpenPower machines. Here's a little guide to show how that's done.

The build process

OpenPower firmware has a number of different components, and some infrastructure to pull it all together. We use buildroot to do most of the heavy lifting, plus a little wrapper, called op-build.

There's a README file, containing build instructions in the op-build git repository, but here's a quick overview:

To build an OpenPower PNOR image from scratch, we'll need a few prerequisites (assuming recent Ubuntu):

sudo apt-get install cscope ctags libz-dev libexpat-dev libc6-dev-i386 \
    gcc g++ git bison flex gcc-multilib g++-multilib libxml-simple-perl \
    libxml-sax-perl

Then we can grab the op-build repository, along with the git submodules:

git clone --recursive git://github.com/open-power/op-build.git

set up our environment and configure using the "palmetto" machine configuration:

. op-build-env
op-build palmetto_defconfig

and build:

op-build

After a while (there is quite a bit of downloading to do on the first build), the build should complete successfully, and you'll have a PNOR image build in output/images/palmetto.pnor.

If you have an existing op-build tree around (colleagues working on OpenPower perhaps?), you can share or copy the dl/ directory to save on download time.

The op-build command is just a shortcut for a make in the buildroot tree, so the general buildroot documentation applies here too. Just replace "make" with "op-build". For example, we can enable a verbose build with:

op-build V=1

Changing the build configuration

Above, we used a palmetto_defconfig as the base buildroot configuration. This defines overall options for the build; things like:

  • Toolchain details used to build the image
  • Which firmware packages are used
  • Which packages are used in the petitboot bootloader environment
  • Which kernel configuration is used for the petitboot bootloader environment

This configuration can be changed through buildroot's menuconfig UI. To adjust the configuration:

op-build menuconfig

And busybox's configuration interface will be shown:

As an example, let's say we want to add the "file" utility to the petitboot environment. To do this, we can nagivate to that option in the Target Packages section (Target Packages → Shell and Utilities → file), and enable the option:

Then exit (saving changes) and rebuild:

op-build

- the resulting image will have the file command present in the petitboot shell environment.

Kernel configuration

There are a few other configuration targets to influence the build process; the most interesting for our case will be the kernel configuration. Since we use petitboot as our bootloader, it requires a Linux kernel for the initial bootloader environment. The set of drivers in this kernel will dictate which devices you'll be able to boot from.

So, if we want to enable booting from a new device, we'll need to include an appropriate driver in the kernel. To adjust the kernel configuration, use the linux-menuconfig target:

op-build linux-menuconfig

- which will show the standard Linux "menuconfig" interface:

From here, you can alter the kernel configuration. Once you're done, save changes and exit. Then, to build the new PNOR image:

op-build

Customised packages

If you have a customised version of one of the packages used in the OpenPower build, you can easily tell op-build to use your local package. There are a number of package-specific make variables documented in the buildroot generic package reference, the most interesting ones being the _VERSION and _SITE variables.

For example, let's say we have a custom petitboot tree that we want to use for the build. We've committed our changes in the petitboot tree, and want to build a new PNOR image. For the sake of this example, the git SHA petitboot commit we'd like to build is 2468ace0, and our custom petitboot tree is at /home/jk/devel/petitboot.

To build a new PNOR image with this particular petitboot source, we need to specify a few buildroot make variables:

op-build PETITBOOT_SITE=/home/jk/devel/petitboot \
    PETITBOOT_SITE_METHOD=git \
    PETITBOOT_VERSION=2468ace0

This is what these variables are doing:

  • PETITBOOT_SITE=/home/jk/devel/petitboot - tells op-build where our custom source tree is. This could be a git URL or a local path.
  • PETITBOOT_SITE_METHOD=git - telsl op-build that PETITBOOT_SITE is a git tree. If we were using a git:// URL for PETITBOOT_SITE, then this variable would be set automatically
  • PETITBOOT_VERSION=2468ace0 - tells op-build which version of petitboot to checkout. This can be any commit reference that git understands.

The same method can be used for any of the other packages used during build. For OpenPower builds, you may also want to use the SKIBOOT_* and LINUX_* variables to include custom skiboot firmware and kernel in the build.

If you'd prefer to test new sources without committing to git, you can use _SITE_METHOD=local. This will copy the source tree (defined by _SITE) to the buildroot tree and use it directly. For example:

op-build SKIBOOT_SITE=/home/jk/devel/skiboot \
    SKIBOOT_SITE_METHOD=local

- will build the current (and not-necessarily-committed) sources in /home/jk/devel/skiboot. Note that buildroot has no way to tell if your code has changed with _SITE_METHOD=local. If you re-build with this, it's safer to clean the relevant source tree first:

op-build skiboot-dirclean