Coreboot

Published: 13-08-2015

Updated: 25-01-2017

By: Maxime de Roucy

tags: apu1d coreboot seabios sgabios

This article will be in english as it as been explicitely asked by pcengines forum member.

I recently bought an pcengines apu1d. The board is supposed to run coreboot, in fact it is not a vanilla version of coreboot but a modified one from Sage. Sage releases its source code of the last rom they provide for the apu on the pcengines howto page.

Coreboot is an opensource software designed to replace traditionnal BIOS. In fact it is not a replacement on its own, it has to work with other software (payload) to be usable. Coreboot does only hardware initialisation (POST), it then launch a payload that bing “function” to the user.

One of this payload is Seabios, which bring BIOS function to the user. Tianocore is another one which implement UEFI.

Seabios can run other peaces of software like memtest86+, iPXE, nvramcui, coreinfo…

All these softwares (coreboot, seabios, memtest86+…) are packed in a rom file which is write in the flash chip of the board to be launch in the boot process.

Bewared, to write a rom in the flash chip you have to run the command flashrom in an operating system running on the board. To run an operating system you have to boot on a working coreboot/seabios. So if you write a wrong coreboot/seabios rom on your board you wont be able to run anything on it anymore and so you won’t be able to run a system necessary to rewrite a good rom. To recover from this situation you have to use a lpc1aapu.

In this article I will give some general informations about coreboot/BIOS/payloads and explain how I build my coreboot ROM which contain :

I used an 64bits Archlinux system to build the ROM.

coreboot

Coreboot is the main code that will run at the first boot step. It then load the first payload.

I use the coreboot master branch (development branch) but you can use other releases.

max@laptop % git clone http://review.coreboot.org/coreboot.git
max@laptop % cd coreboot
max@laptop % COREBOOT_DIRECTORY=`pwd`

From now on all the code block in this article will start inside the coreboot directory.

modifications

This section in no longuer needed as the patches mentioned have been commited :

Sage did some change in the coreboot sources without redistribute it to the community.

I order to make coreboot able to use CMOS/NVRAM on pcengines apu you will have to apply a patch I sent to the community. A CMOS/NVRAM is a memory where the board can store information that will be kept even if the board is unplug from power supply. The APU1D have a CMOS/NVRAM.

I also increased the stack size from 0x1000 to 0x2000 to solve a stack overrun error at boot. To do so I applied a patch which cannot be included as is upstream as it change the default stack size for all the board. I reported the problem.

SeaBIOS

I choose to run SeaBIOS as my first coreboot payload. SeaBIOS can be built in the coreboot building process.

Follow the SeaBIOS section below to download and configure it and get back here when it’s done.

toolchain

Coreboot sources come with it’s own unmodified version of gcc that is known to generate correcte ROM. You can build it with make crossgcc but it will build gcc for all the available target architectures (x86_64, x86_32, arm…) which will take a long time. That’s why I advice you to only build the gcc you need, the one for the architecture of your board. I am building coreboot for a PCEngines APU and as the following command point it I need to build the x86_32 gcc which is crossgcc-i386.

max@laptop % grep CPU_ src/mainboard/pcengines/apu1/Kconfig
        select CPU_AMD_AGESA_FAMILY14

max@laptop % grep ARCH_ src/cpu/amd/agesa/Kconfig
        select ARCH_BOOTBLOCK_X86_32
        select ARCH_VERSTAGE_X86_32
        select ARCH_ROMSTAGE_X86_32
        select ARCH_RAMSTAGE_X86_32

max@laptop % grep 'crossgcc:' Makefile.inc
crossgcc: crossgcc-i386 crossgcc-x64 crossgcc-arm crossgcc-aarch64 crossgcc-mips crossgcc-riscv

max@laptop % make crossgcc-i386

Even if I build only one architecture (make crossgcc-i386) it take aproximately 3 hours on my computer (Celeron 1.10GHz × 2 ; 4Go RAM) to finish.

max@laptop % make menuconfig

I did some changes in the “Mainboard”, “General setup”, “Payload” and “Console” sections (in that order) :

lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq Mainboard qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x …                                                                       x
x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x
x x        Mainboard vendor (PC Engines)  --->                          x x
x x        Mainboard model (APU1)  --->                                 x x
x x        …                                                            x x
x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x
tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu
x        <Select>    < Exit >    < Help >    < Save >    < Load >         x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq Payload qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x …                                                                       x
x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x
x x    …                                                                x x
x x    [ ] Use LZMA compression for payloads                            x x
x x    …                                                                x x
x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x
tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu
x        <Select>    < Exit >    < Help >    < Save >    < Load >         x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq Console qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x  …                                                                      x
x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x
x x    …                                                                x x
x x    (0x10000) Room allocated for console output in CBMEM (NEW)       x x
x x        Default console log level (0: EMERG)  --->                   x x
x x    [*] Don't show any POST codes                                    x x
x x    …                                                                x x
x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x
tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu
x        <Select>    < Exit >    < Help >    < Save >    < Load >         x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

build

Simply run :

max@laptop % make

notes

Here is some notes I took during my try/fail/success experiences with coreboot.

coreboot can’t handle intXX callback after it is finished running. So running sgabios directly from coreboot and bypass SeaBIOS is pointless. Furthermore it is not possible to launch an option ROM in coreboot which is not a VGA option ROM. I tried binding it to some random pci card since I don’t have a VGA card. It failed and later I understand why by reading the code. It is also not possible to launch it without binding it to an actual hardware which has to be an authentic VGA hardware.

It is explain in the following commit message :

Remove PCI_ROM_RUN option The main purpose of option rom is to supply int* handlers. But supplying those is outside of coreboot scope and if someone needs those they should run SeaBIOS anyway which runs the option roms wonderfully. Running VGA oprom is kept because they’re needed to init graphics.

CMOS/NVRAM

I tried to use the CMOS feature of coreboot, but currently (16/11/2015) it failed (it once worked). I think it’s a coreboot bug so maybe it will work in the future. You should try it, it’s great when it works.

To enable it :

lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq General setup qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x …                                                                               x
x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x
x x    …                                                                        x x
x x    [*] Use CMOS for configuration values                                    x x
x x    …                                                                        x x
x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x
tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu
x            <Select>    < Exit >    < Help >    < Save >    < Load >             x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

SeaBIOS

I choose to run SeaBIOS as my first coreboot payload. SeaBIOS can be built in the coreboot building process. The main advantage is that it will automaticaly use the coreboot cross compilation toolchain. But it has the disadvatage that you can’t choose your SeaBIOS configuration anymore ; a default SeaBIOS config is applied by the coreboot building process.

I wanted to benefit from the coreboot cross compilation toolchain but also to configure my SeaBIOS build. To do so I applied the following patch in the coreboot source tree :

diff --git a/payloads/external/SeaBIOS/Makefile.inc b/payloads/external/SeaBIOS/Makefile.inc
index 7fb63d4..25c4da0 100644
--- a/payloads/external/SeaBIOS/Makefile.inc
+++ b/payloads/external/SeaBIOS/Makefile.inc
@@ -45,7 +45,7 @@ endif
        #echo "# CONFIG_SMBIOS is not set" >> seabios/.config
        $(MAKE) -C seabios olddefconfig OUT=out/

-build: config
+build:
        echo "    MAKE       SeaBIOS $(TAG-y)"
        export VERSION=$$(cd seabios && \
                git describe --tags --long --dirty 2>/dev/null || \

Normaly the SeaBIOS code is downloaded by the coreboot build process if it’s not found. The previous patch break this fonctionality so I have to get the SeaBIOS code myself and put it where it should in the coreboot code directory tree.

max@laptop % git clone http://review.coreboot.org/p/seabios.git payloads/external/SeaBIOS/seabios

I choosed to use the master branch (developpement branch) from SeaBIOS but you can also choose to use a specific release. If you do so you should change the export VERSION=… code in payloads/external/SeaBIOS/Makefile.inc to match yours (for example export VERSION="1.8.2").

max@laptop % cd payloads/external/SeaBIOS/seabios
max@laptop % make menuconfig

I did some changes in the “General Features” and “Hardware support” sections :

lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq General Features qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x …                                                                               x
x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x
x x        Build Target (Build for coreboot)  --->                              x x
x x       …                                                                     x x
x x    [ ]   Graphical boot splash screen                                       x x
x x       …                                                                     x x
x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x
tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu
x            <Select>    < Exit >    < Help >    < Save >    < Load >             x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq Hardware support qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x …                                                                               x
x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x
x x       …                                                                     x x
x x    [*]   ATA DMA                                                            x x
x x    [*]   ATA 32bit PIO                                                      x x
x x       …                                                                     x x
x x    [ ] LSI MegaRAID SAS controllers                                         x x
x x       …                                                                     x x
x x    [ ] Serial port                                                          x x
x x    [ ] Parallel port                                                        x x
x x       …                                                                     x x
x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x
tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu
x            <Select>    < Exit >    < Help >    < Save >    < Load >             x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

SeaBIOS can output (normal and debug output) to serial port but can’t read from it. As a workaround, it is adviced to use sgabios. It’s a ROM that simulate a VGA device and display it over the serial port. It transform the serial port in a VGA display and can read input from it.

The problems comes when other software try to use the serial console. If you configure SeaBIOS to use the serial console as a screen display, each characters will be display twice. The Archlinux installation media bootloader (syslinux or pxelinux if you run it throught the network) is configured to reset the baud rate to 38400bps and use the serial console. It will complettely messed up the serial console as sgabios will copy the VGA output at 115200bps and the bootloader will write at 38400bps.

By complettely disabeling the serial port hardware support in SeaBIOS, SeaBIOS will not show/advertise any serial port to other software anymore. For the Archlinux bootloader it’s as there is a VGA display and no serial port, so it write only on the VGA and sgabios will map it in the serial console.

After I disabled the serial port support in SeaBIOS I tried to enable VGA support and disable serial support in coreinfo and memtest86+ but it seams those payload doesn’t use sgabios and they ended up without display. On the contrary it works with iPXE. I don’t know why some payload are working well with sgabios and others don’t. PXELinux and other syslinux tools (e.g. launched through iPXE) are working great when serial port is disabled in SeaBIOS and sgabios is included in the final ROM. coreinfo, memtest86+ and iPXE are also working great when they are built with serial support, serial support is disabled in SeaBIOS and sgabios is include in the final ROM.

build

As previously said I use the coreboot building process to build SeaBIOS to toolchain.

boot sequence

The boot sequence of SeaBIOS, related to the option ROMs and ELF files :

  1. it run the Option ROM named pciVVVV,DDDD.rom where VVVV,DDDD correspond to the PCI vendor and device ID of the VGA device
    • if there is no such file, and there is a Option ROM embeded in the device itself it will run it
  2. it run all the file in the vgaroms folder (in the cbfs filesystem) as VGA Option ROM
  3. it run the Option ROMs named pciVVVV,DDDD.rom where VVVV,DDDD correspond to the PCI vendor and device ID of all the PCI device found in the system except the VGA ones
    • if there is a PCI device for which there is no pciVVVV,DDDD.rom matching in the cbfs filesystem and which embeded an option ROM, SeaBIOS run it
  4. it run all the file in the genroms folder (in the cbfs filesystem) as Option ROM
  5. the boot options correspond to all the option ROMs previously runed and all the ELF files found in the img directory

bootorder

You can configure SeaBIOS to change the boot order of the different payloads you add in the final ROM and the hardware it found. The boot order have to be stored in a file named “bootorder” in the CBFS. Each line of this file have to be a device specifier except for “HALT”.

Here is my bootorder file :

/pci@i0cf8/*@11/drive@0/disk@0
HALT
/pci@i0cf8/*@11/drive@1/disk@0
/pci@i0cf8/usb@12,2/usb-*@1
/pci@i0cf8/usb@12,2/usb-*@5
/pci@i0cf8/usb@16,2/usb-*@1
/rom@genroms/ipxe
/rom@img/coreinfo
/rom@img/memtest

I made it by parsing the SeaBIOS output :

max@laptop % ./cbmem -c | grep bootorder -A 1
Searching bootorder for: /rom@img/coreinfo
Searching bootorder for: /rom@img/memtest
Searching bootorder for: /pci@i0cf8/*@11/drive@0/disk@0
AHCI/0: registering: "AHCI/0: SATA SSD ATA-10 Hard-Disk (15272 MiBytes)"
Searching bootorder for: /pci@i0cf8/usb@12,2/storage@1/*@0/*@0,0
Searching bootorder for: /pci@i0cf8/usb@12,2/usb-*@1
USB MSC vendor='USB 2.0' product='Flash Disk' rev='0.00' type=0 removable=1
--
Searching bootorder for: /pci@i0cf8/usb@16,2/storage@1/*@0/*@0,0
Searching bootorder for: /pci@i0cf8/usb@16,2/usb-*@1
USB MSC vendor='Multiple' product='Card  Reader' rev='1.00' type=0 removable=1
--
Searching bootorder for: /pci@i0cf8/*@11/drive@1/disk@0
AHCI/1: registering: "AHCI/1: Samsung SSD 840 Series ATA-9 Hard-Disk (232 GiBytes)"
--
Searching bootorder for: /rom@genroms/ipxe

--
Searching bootorder for: HALT
drive 0x000f1330: PCHS=0/0/0 translation=lba LCHS=999/32/63 s=2015231

Things that doesn’t appear in the bootorder file are placed, in the SeaBIOS Menu, after all the devices that where describe in the bootorder file. They appear in the order of apareance in the SeaBIOS log.

In the SeaBIOS code there is pretty interresting comment :

See if ‘str’ starts with ‘glob’ - if glob contains an ‘*’ character it will match any number of characters in str that aren’t a ‘/’ or the next glob character.

‘str’ is bootorder file line, ‘glob’ is the line you can read in SeaBIOS logs. So don’t bother studying the device specifier syntax. Just copy past what you found in the SeaBIOS log.

To include it in the final ROM :

max@laptop % ./cbfstool coreboot.rom add -f ../bootorder -n bootorder -t raw

Beware it might not do what you think. It try to run from the USB and then from the drive, if there is no USB or drive device plugged it stop (all the payload are still available through the menu). If there is a USB device plugged but not bootable the drive will not be tried ! Imagine I put the ipxe line before the HALT ; if there is a USB device plugged but not bootable the drive will not be tried… but the ipxe ROM will ! It’s not very intuitive.

The thing is SeaBIOS can only try one boot of each “type”, “usb” and “drive” are of the same “type” ; “ipxe” isn’t. You can find more information about that here.

sgabios

sgabios is a tool (an option ROM) that transform a serial device in a vga device. It can be used to provide an output to software that doesn’t support serial port on board that doesn’t have VGA card.

There is some precision about sgabios and things to take care of when you use it, in the Seabios section.

build

To build the sgabios.bin option ROM file :

max@laptop % mkdir -p payloads/perso/sgabios
max@laptop % git clone https://github.com/computerline1z/sgabios.git payloads/perso/sgabios
max@laptop % cd payloads/perso/sgabios
max@laptop % make

cbfstool

We put it in the vgaroms directory in the cbfs filesystem.

max@laptop % cd build
max@laptop % ./cbfstool coreboot.rom add -f ../payloads/perso/sgabios/sgabios.bin -n vgaroms/sgabios -t raw

memtest86+

memtest86+ is a tool to check RAM of the ROM.

Coreboot has it’s own repository for memtest86+ source. Coreboot project doesn’t intend to fork memtest86+, but created this repository to be able to review and maintained it’s own set of patch and easily include memtest86+ in it’s building process.

Download the sources :

max@laptop % mkdir -p payloads/perso
max@laptop % cd payloads/perso
max@laptop % git clone https://review.coreboot.org/memtest86plus.git
max@laptop % cd memtest86plus

modifications

This section in no longuer needed as the patches mentioned have been commited in the memtest86plus coreboot repository :

In order to build it and make it work correctly (mostly problems with serial console input/output) I applied some patches. I send them to the community, you can find more informations about them on the following links 1 & 2, 3, 4, 5, 6, 7, 8, 9.

Prepare the sources :

max@laptop % mkdir -p payloads/perso
max@laptop % cd payloads/perso
max@laptop % wget http://www.memtest.org/download/5.01/memtest86+-5.01.tar.gz
max@laptop % tar xvaf memtest86+-5.01.tar.gz
max@laptop % rm memtest86+-5.01.tar.gz
max@laptop % cd memtest86+-5.01
max@laptop % wget https://ftp.craoc.fr/memtest/memtest86%2B-5.01-patches.tar.xz
max@laptop % tar xvaf memtest86+-5.01-patches.tar.xz
max@laptop % patch -p1 < 000*.patch

configure

Enable/Configure the serial port by applying the following patch (memtest86+ doesn’t have a menuconfig). As I said before this is necessary even if you embeded sgabios in the final ROM. memtest86+ doesn’t seams to use the API provided by sgabios.

diff --git a/config.h b/config.h
index e12d0a1..1baa513 100644
--- a/config.h
+++ b/config.h
@@ -29,13 +29,13 @@
 /* SERIAL_CONSOLE_DEFAULT -  The default state of the serial console. */
 /*     This is normally off since it slows down testing.  Change to a 1 */
 /*     to enable. */
-#define SERIAL_CONSOLE_DEFAULT 0
+#define SERIAL_CONSOLE_DEFAULT 1

 /* SERIAL_TTY - The default serial port to use. 0=ttyS0, 1=ttyS1, 2=ttyS2, 3=ttyS3 */
 #define SERIAL_TTY 0

 /* SERIAL_BAUD_RATE - Baud rate for the serial console */
-#define SERIAL_BAUD_RATE 9600
+#define SERIAL_BAUD_RATE 115200

 /* SCRN_DEBUG - extra check for SCREEN_BUFFER
  */

build

To build the memtest86+ with the coreboot toolchain we have to explicitely specify the path of each tool :

max@laptop % cd payloads/perso/memtest86+-5.01
max@laptop % CB_TOOLCHAIN="$COREBOOT_DIRECTORY/util/crossgcc/xgcc/bin/i386-elf"
max@laptop % make AS="$CB_TOOLCHAIN-as" CC="$CB_TOOLCHAIN-gcc" LD="$CB_TOOLCHAIN-ld" memtest

cbfstool

We put it in the img directory in the cbfs filesystem.

max@laptop % cd build
max@laptop % ./cbfstool coreboot.rom add-payload -f ../payloads/perso/memtest86+-5.01/memtest -n img/memtest

coreinfo

coreinfo is a tool which can display some informations.

It use libpayload. By default it will configure, build and install libpayload in …/coreinfo/build but you will not be able to configure libpayload to your need. If you want to configure libpayload go to the next section, if you don’t, skip it and go directly to the coreinfo menuconfig section.

libpayload

Here is how I configured and build libpayload for coreinfo.

max@laptop % cd payloads/libpayload
max@laptop % make menuconfig

I did some changes in the “Architecture Options” and “Console Options” sections :

lqqqqqqqqqqqqqqqqqqqqqqqqqq Architecture Options qqqqqqqqqqqqqqqqqqqqqqqqqqqk
x  …                                                                        x
x lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x
x x    …                                                                  x x
x x    [ ] Multiboot header support                                       x x
x x    …                                                                  x x
x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x
tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu
x         <Select>    < Exit >    < Help >    < Save >    < Load >          x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

lqqqqqqqqqqqqqqqqqqqqqqqqqqqqq Console Options qqqqqqqqqqqqqqqqqqqqqqqqqqqqqk
x  …                                                                        x
x lqqqq-(-)qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk x
x x    …                                                                  x x
x x    [ ] See output on a video console                                  x x
x x    …                                                                  x x
x mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj x
tqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqu
x         <Select>    < Exit >    < Help >    < Save >    < Load >          x
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj

build & install

libpayload will be installed in $COREBOOT_DIRECTORY/payloads/libpayload/install It automaticaly use the coreboot toolchain.

max@laptop % cd payloads/libpayload
max@laptop % make
max@laptop % make install

coreinfo menuconfig

max@laptop % cd payloads/coreinfo
max@laptop % make menuconfig

I did not change anything.

build

By default, coreinfo doesn’t use the coreboot toolchain so I add CC="$COREBOOT_DIRECTORY/util/crossgcc/xgcc/bin/i386-elf-gcc" to the make command line.

To build coreinfo with the previously built libpayload :

max@laptop % cd payloads/coreinfo
max@laptop % make LIBPAYLOAD_DIR="$COREBOOT_DIRECTORY/payloads/libpayload/install" CC="$COREBOOT_DIRECTORY/util/crossgcc/xgcc/bin/i386-elf-gcc"

To build it with it’s own libpayload just remove the LIBPAYLOAD_DIR parameter.

cbfstool

We put it in the img directory in the cbfs filesystem.

max@laptop % cd build
max@laptop % ./cbfstool coreboot.rom add-payload -f ../payloads/coreinfo/build/coreinfo.elf -n img/coreinfo

iPXE

iPXE is a tool for loading OS over the network.

It it not the same as pxelinux, both tools use differentes configuration files and different commandes.

I advice you to read the list of commands available in iPXE.

max@laptop % mkdir -p payloads/perso/ipxe
max@laptop % git clone git://git.ipxe.org/ipxe.git payloads/perso/ipxe

configure

There is no other way to configure it than modifying the sources header files. To configure iPXE to my need I applied this patch. It basicaly disable and enable features and commandes but their is somes modifications I should clarify :

build

In order to build the right ROM I also need to know the vendor ID and device ID of the ethernet card iPXE will use. To get those informations I need to launch command in a running environment in the APU.

[+44.6 C][root@box:/mnt/sdb1]$ lspci
…
01:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 06)
02:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 06)
03:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 06)
…
[+44.5 C][root@box:/mnt/sdb1]$ lspci -nn -s 01:00.0
01:00.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller [10ec:8168] (rev 06)

Here the vendor ID is “10ec” and the device ID is “8168”. I will build the ROM 10ec8168.rom.

max@laptop % cd payloads/perso/ipxe/src
max@laptop % make CROSS_COMPILE="$COREBOOT_DIRECTORY/util/crossgcc/xgcc/bin/i386-elf-" bin/10ec8168.rom

cbfstool

We put the iPXE ROM in the genroms directory in the cbfs filesystem. If we attach the ROM to the ethernet card by putting it in the root directory (with the right name : pci10ec,8168.rom) in the cbfs filesystem iPXE will be launch three time and will appear three time in the SeaBIOS menu. It’s because the APU has three ethernet card with same vendor and device ID.

max@laptop % cd build
max@laptop % ./cbfstool coreboot.rom add -f ../payloads/perso/ipxe/src/bin/10ec8168.rom -n genroms/ipxe -t raw

notes

If you want to completly disable the prompt “Press Ctrl-B to configure iPXE” when the option ROM is loaded and when iPXE is launched by SeaBIOS, but you steel want to be able to use the shell command you will have to add the following line in src/config/config.c (source).

+REQUIRE_OBJECT ( shell );

nvramcui

At first I added nvramcui in the main ROM but I found the tool have some very annoying limitation so I decided to removed it.

nvramcui is a tool to change the config values store in cmos/nvram. That could be great to change for example the coreboot debug level without reflashing the ROM.

It doesn’t read the values stored in nvram before asking the user to change it. So you can’t use it to read the nvram content, see it as a write only tool.

There is a field in the nvram where the checksum of the values is stored. If this checksum is wrong coreboot write in the nvram the default values (sanitize) before reading it. The default values are stored in the cmos.default file and it’s taken into account if the HAVE_CMOS_DEFAULT config option is set.

nvramcui doesn’t compute and write the checksum when it change a value.

At first, when I changed the coreboot code to handle nvram values I didn’t enable HAVE_CMOS_DEFAULT so coreboot didn’t “sanitize” the nvram and read values even if the checksum was wrong.

To make thing better I enable HAVE_CMOS_DEFAULT and created the cmos.default file. Then nvramcui become useless since it’s a write only tool and every time you change a value with it, the nvram is restored to the default as the checksum isn’t recompute (so is wrong).

grub2

grub2 is able to launch coreboot payload.

I tried to use grub2 as my payload, in replacement of SeaBIOS. It seems a good idea at first but there is a problem with sgabios. grub2 support serial input/output on it’s own, without sgabios, but I wanted sgabios as it allow me to chainload most bootloader without special configuration (to support serial). Has I said in the coreboot – notes section, coreboot can only run option ROM for VGA device… which I don’t have since the APU don’t have any graphical device.

Also, grub2 can’t launch the iPXE payload alone as iPXE need the BIOS interface that only SeaBIOS provide.

So I tried to use grub2 as a SeaBIOS payload. But grub2 built as coreboot payload (configured with --with-platform=coreboot) is very different from the standard one (BIOS, configured with --with-platform=pc). For exemple standard version can’t chainload a coreboot payload (elf file). On the contrary I didn’t manage to chainload a standard syslinux with the coreboot version. Also the coreboot version behave differently when it is run by coreboot and SeaBIOS.

It is possible to embed the standard grub2 version in the coreboot ROM by using the floppy image SeaBIOS feature. It will not be able to chainload the other payload, so you need to keep the SeaBIOS menu.

The floppy img will be load in RAM as soon it is discovered by SeaBIOS in the floppyimg directory of the CBFS, before the drawing of the SeaBIOS menu. The RAM is not freed so not available to the OS. So you “lose” 2880 KiB (maximum floppy image size) of RAM for your system as soon as SeaBIOS discover the floppy image.

I didn’t want that as I only wanted to use the embeded grub2 as a backup. So I finaly didn’t include it in my ROM.

configuration

In order to build grub2 with the coreboot toolchain I use the coreboot source tree.

diff --git a/payloads/external/GRUB2/Makefile.inc b/payloads/external/GRUB2/Makefile.inc
index 4b08e7d..9d397b0 100644
--- a/payloads/external/GRUB2/Makefile.inc
+++ b/payloads/external/GRUB2/Makefile.inc
@@ -37,12 +37,16 @@ config: checkout
        cd grub2 && ./autogen.sh
        cd grub2/build && ../configure BUILD_CC="$(HOSTCC)" CC="$(HOSTCC)" \
        TARGET_CC="$(CC)" \
-       TARGET_OBJCOPY="$(OBJCOPY)" TARGET_STRIP="$(STRIP)" CFLAGS=-O2 TARGET_CFLAGS=-Os --with-platform=coreboot
+       TARGET_OBJCOPY="$(OBJCOPY)" TARGET_STRIP="$(STRIP)" CFLAGS=-O2 TARGET_CFLAGS=-Os --with-platform=pc

 grub2: config
        echo "    MAKE       GRUB2 $(NAME-y)"
        $(MAKE) -C grub2/build CC="$(HOSTCC)"
-       $(MAKE) -C grub2/build default_payload.elf
+       cd grub2/build ;\
+       pkgdatadir=. ./grub-mkrescue --grub-mkimage=./grub-mkimage -o grub2-floppy.dsk.tmp --modules='part_msdos part_gpt btrfs' --fonts= --themes= --locales= -d grub-core/ /boot/grub/grub.cfg=../coreboot.cfg ;\
+       dd if=/dev/zero of=grub2-floppy.dsk bs=512 count=5760 ;\
+       dd if=grub2-floppy.dsk.tmp of=grub2-floppy.dsk conv=notrunc

 clean:
        test -d grub2 && $(MAKE) -C grub2 clean || exit 0
--with-platform=pc
Has I said I want to build the standard grub2 version
--modules='part_msdos part_gpt btrfs'
The modules (rechecher « module =  ») that will always be load at grub2 start
grub2-floppy.dsk
The floppy disk image containing grub2. The floppy image have to be of a specific size for SeaBIOS to load it. The dd commandes ensure the floppy image will be 2880 KiB.

build

max@laptop % make grub2

cbfstool

The floppy image is big but it feets in the ROM if it is compress with lzma :

max@laptop % build/cbfstool build/coreboot.rom add -f ~/coreboot/payloads/external/GRUB2/grub2/build/grub2-floppy.dsk -n floppyimg/grub2.lzma -t raw -c lzma

cbfstool

BIOS ROM Extensions can be add to the main ROM file with the add command of cbfstool.

ELF files can be add to the main ROM file with the add-payload command of cbfstool. They have to be placed in the img directory to be recognise by SeaBIOS.

You can display the content of the ROM with the print command of cbfstool. It also allow you to see how much space is left in the ROM. You can see the space your payload will take in the ROM with the du -b. If it doesn’t fit you can try enabeling the lzma coreboot and SeaBIOS support and add your payload with the -c lzma option to the add or add-payload command of cbfstool. Beware, SeaBIOS need the file name to be suffix with .lzma to treate it as a compressed payload.

max@laptop % build/cbfstool build/coreboot.rom add -f ~/coreboot/payloads/perso/sgabios/sgabios.bin -n vgaroms/sgabios -t raw
max@laptop % build/cbfstool build/coreboot.rom add -f payloads/perso/ipxe/src/bin/10ec8168.rom -n genroms/ipxe.lzma -t raw -c lzma
max@laptop % build/cbfstool build/coreboot.rom add-payload -f ~/coreboot/payloads/coreinfo/build/coreinfo.elf -n img/coreinfo
max@laptop % build/cbfstool build/coreboot.rom add-payload -f ~/coreboot/payloads/perso/memtest86+-5.01/memtest -n img/memtest.lzma -c lzma

elf & rom

Some files are ROM some others are ELF.

max@laptop % file payloads/external/SeaBIOS/seabios/out/bios.bin.elf
coreboot/payloads/external/SeaBIOS/seabios/out/bios.bin.elf: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped

max@laptop % file sgabios/sgabios.bin
sgabios/sgabios.bin: BIOS (ia32) ROM Ext. (8*512)

max@laptop % file coreboot/payloads/perso/ipxe/src/bin/10ec8168.rom
coreboot/payloads/perso/ipxe/src/bin/10ec8168.rom: BIOS (ia32) ROM Ext. (111*512)

max@laptop % file coreboot/payloads/perso/memtest86+-5.01/memtest
coreboot/payloads/perso/memtest86+-5.01/memtest: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, stripped

max@laptop % file coreboot/payloads/nvramcui/nvramcui.elf
coreboot/payloads/nvramcui/nvramcui.elf: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped

max@laptop % file coreboot/payloads/coreinfo/build/coreinfo.elf
coreboot/payloads/coreinfo/build/coreinfo.elf: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped

What is a BIOS ROM Extension and how it works is very well explained in the etherboot documentation. I realy advice you to read it since I deduce all the following from it.

BIOS ROM Extensions are packed of code to do hardware initialisation and user fonction that normal BIOS don’t know how to do. Normally BIOS ROM Extension are stored in the hardware they where disign to initialise. For example, in a very old past when ethernet card wheren’t commun, motherboard BIOS doesn’t know how to initialise the cards or do PXE boot. So manufacturers include BIOS ROM Extension in some ship of their ethernet card.

When the BIOS run, it initialise the motherboard and look for BIOS ROM Extension in some specific memory adresses. After some checks it pass control it (run it). The BIOS ROM Extension do some hardware initialisation, register itself to run in the later phase of the boot (hook to the interrupt 0x19 and/or something else on PnP ROMs) and return control to the main BIOS.

If the user choose to boot on the device (e.g. to do a network boot), the second part of the BIOS ROM Extension is run.

So a BIOS ROM Extension file contain program which run in differente phase of the boot. It is also (normaly) design to run in combination with a specific hardware (ethernet card, graphic card…). BIOS ROM Extension are also called “Option ROMs”.

ELF file are executable files which can be put anywhere in the RAM and run. It’s the main executable format in GNU/Linux operating systems. To quote a stackoverflow answer from t0mm13b :

ELF files are Executable Linkable Format which consists of a symbol look-ups and relocatable table, that is, it can be loaded at any memory address by the kernel and automatically, all symbols used, are adjusted to the offset from that memory address where it was loaded into. Usually ELF files have a number of sections, such as ‘data’, ‘text’, ‘bss’, to name but a few… it is within those sections where the run-time can calculate where to adjust the symbol’s memory references dynamically at run-time.

PCEngines TinyCore Linux

PCEngines provide a mini linux distribution which contain flashrom and can be put on a usb stick.

Here is how I created my bootable usb stick. /dev/sdb is my usb device.

root@laptop # parted /dev/sdb
…
(parted) mktable msdos
(parted) mkpart primary fat32 0% 100%
(parted) set 1 boot on
(parted) print
Model: USB 2.0 Flash Disk (scsi)
Disk /dev/sdb: 1032MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  1031MB  1030MB  primary  fat32        boot, lba

(parted) quit
Information: You may need to update /etc/fstab.

root@laptop # mkfs.fat -n CBOOT -F 32 /dev/sdb1
mkfs.fat 3.0.28 (2015-05-16)
root@laptop # syslinux -i /dev/sdb1
root@laptop # dd if=/usr/lib/syslinux/bios/mbr.bin of=/dev/sdb
0+1 enregistrements lus
0+1 enregistrements écrits
440 octets (440 B) copiés, 0,009147 s, 48,1 kB/s
root@laptop # mkdir /tmp/CBOOT
root@laptop # mount /dev/sdb1 /tmp/CBOOT
root@laptop # cd /tmp
root@laptop # wget http://www.pcengines.ch/file/apu_tinycore.tar.bz2
…
root@laptop # cd /tmp/CBOOT
root@laptop # tar xvaf /tmp/apu_tinycore.tar.bz2
…
root@laptop # cp $COREBOOT_DIRECTORY/build/coreboot.rom .
root@laptop # cd ~
root@laptop # umount /tmp/CBOOT

flashrom

To flash the coreboot ROM to the APU board inside the TinyCore Linux usb stick environment :

[+41.0 C][root@box:/mnt/sdb1]$ flashrom -w coreboot.rom

The first time you flash the ROM flashrom will complain that the ROM inside the board doesn’t have the same device name as the one you are trying to write. Sage use “APU” and vanilla coreboot “APU1”. You will have to force the write :

[+41.0 C][root@box:/mnt/sdb1]$ flashrom -w coreboot.rom -p internal:boardmismatch=force

With newer version of flashrom (e.g. 0.9.8-r1888) you will have to specify other options :

archlinux # flashrom -w coreboot.rom -p internal -c "MX25L1605A/MX25L1606E/MX25L1608E"
sysrescd # flashrom -w coreboot.rom -p internal:boardmismatch=force -c "MX25L1605A/MX25L1606E"

I use the chipname “MX25L1605A/MX25L1606E/MX25L1608E” and “MX25L1605A/MX25L1606E” because the 0.9.7 flashrom version detect a “MX25L1605A/MX25L1606E”.

nvramtool

As I said in the CMOS/NVRAM section this tool need the “CMOS” coreboot feature to be activated. It doesn’t currently (16/11/2015) works.

nvramtool will allow you to read and modify the CMOS/NVRAM memory of the board.

It’s not build automaticaly during coreboot build. You will have to go to the source directory to build it. It’s not supposed to be built with the coreboot toolchain as it will run in a GNU/Linux environment with the same architecture as the building one.

% cd util/nvramtool
% make LDFLAGS=-static

I add the “static” flag to be able to launch the built binary to any system as long as it is the same architecture (x86, x86_64…) as the build system.

Then just run it in a GNU/Linux environment running inside the board. It’s pretty self-explanatory…

root@archiso ~ # ./nvramtool
Usage: nvramtool [-y LAYOUT_FILE | -t] PARAMETER ...

       Read/write coreboot parameters or show info from coreboot table.

       -y LAYOUT_FILE: Use CMOS layout specified by LAYOUT_FILE.
       -t:             Use CMOS layout specified by CMOS option table.
       -C CBFS_FILE:   Use CBFS file for layout and CMOS data.
       -D CMOS_FILE:   Use CMOS file for CMOS data (overrides CMOS of -C).
       [-n] -r NAME:   Show parameter NAME.  If -n is given, show value only.
       -e NAME:        Show all possible values for parameter NAME.
       -a:             Show names and values for all parameters.
       -w NAME=VALUE:  Set parameter NAME to VALUE.
       -p INPUT_FILE:  Set parameters according to INPUT_FILE.
       -i:             Same as -p but file contents taken from standard input.
       -c [VALUE]:     Show CMOS checksum or set checksum to VALUE.
       -l [ARG]:       Show coreboot table info for ARG, or all ARG choices.
       -L OUTPUT_BIN   Write CMOS layout file in binary format
       -H OUTPUT_HDR   Write CMOS layout file in header format
       -d:             Show low-level dump of coreboot table.
       -Y:             Show CMOS layout info.
       -b OUTPUT_FILE: Dump CMOS memory contents to file.
       -B INPUT_FILE:  Write file contents to CMOS memory.
       -x:             Show hex dump of CMOS memory.
       -X DUMPFILE:    Show hex dump of CMOS dumpfile.
       -v:             Show version info for this program.
       -h:             Show this message.

root@archiso ~ # ./nvramtool -a
last_boot = Fallback
boot_option = Fallback
multi_core = Enable
baud_rate = 115200
debug_level = Spew

root@archiso ~ # ./nvramtool -e debug_level
Emerg
Alert
Crit
Err
Warning
Notice
Info
Debug
Spew

root@archiso ~ # ./nvramtool -w debug_level=Emerg

cbmem

cbmem is a tool to access the CBMEM where coreboot sent it’s output when you tell it to (as I did in my ROM).

You can see those logs with :

root@laptop # cbmem -c

build

max@laptop % cd util/cbmem
max@laptop % make LDFLAGS=-static

I add the “static” flag to be able to launch the built binary to any system as long as it is the same architecture (x86, x86_64…) as the build system.