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 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.
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.
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.
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
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
- “Mainboard vendor” → “PC Engines” ; “Mainboard model” → “APU1” : just select the board to get the right preset of options.
- “Use LZMA compression for payloads” → disable : all my payload fit in the ROM without the need for lzma so I disabled this. If you want to use LZMA compression, enable this and use
-c lzmaoption of cbfstool when you
- “Room allocated for console output in CBMEM” → “0x10000” : space that will be allocated to save the coreboot log in RAM. See cbmem section.
- “Default console log level” → “0: EMERG” : less verbose default log level.
- “Don’t show any POST codes” → enable : POST is for Power On Self Test. I don’t want coreboot to display anything.
Simply run :
max@laptop % make
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.
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
- “Use CMOS for configuration values” → enable : enable the use of CMOS/NVRAM for runtime configuration of coreboot. It allows you to change some coreboot parameter without having to reflash the board. See nvramtool.
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
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
- “Build Target” → “Build for coreboot” : requiered to make SeaBIOS compatible with coreboot
- “Graphical boot splash screen” → disabled : just because I don’t use the boot splash screen.
- “ATA DMA” & “ATA 32bit PIO” → enabled : I don’t think it’s important, when I did this configuration I didn’t have a lpc1aapu and didn’t want to brick my board. I thought it should be safer to add this configurations, also in the Xen mailing list it is recommanded to enable it. I think it should work with those disabled but didn’t test it.
- “LSI MegaRAID SAS controllers” → disabled : I don’t use that kind of hardware.
- “Parallel port” → disabled : I don’t use that kind of hardware.
- “Serial port” → disabled : this is were it gets funny ;) read the following
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.
As previously said I use the coreboot building process to build SeaBIOS to toolchain.
The boot sequence of SeaBIOS, related to the option ROMs and ELF files :
- 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
- it run all the file in the
vgaromsfolder (in the cbfs filesystem) as VGA Option ROM
- 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
- it run all the file in the
genromsfolder (in the cbfs filesystem) as Option ROM
- the boot options correspond to all the option ROMs previously runed and all the ELF files found in the
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
/pci@i0cf8/*@11/drive@0/disk@0: mSATA drive
/pci@i0cf8/*@11/drive@1/disk@0: SATA drive
/pci@i0cf8/usb@12,2/usb-*@1: USB (top)
/pci@i0cf8/usb@12,2/storage@1/*@0/*@0,0: I tried using this one has I prefered it (much self explanatory) but it doesn’t work. You can only use lines that are not followed by another “Searching bootorder for” line.
/pci@i0cf8/usb@12,2/usb-*@5: USB (bottom)
HALT: if the previous fail stop here
- the rest it pretty self explanatory
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 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.
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
max@laptop % cd build max@laptop % ./cbfstool coreboot.rom add -f ../payloads/perso/sgabios/sgabios.bin -n vgaroms/sgabios -t raw
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
This section in no longuer needed as the patches mentioned have been commited in the memtest86plus coreboot repository :
- update inb_p and outb_p implementation
- Add support for serial ports 2 & 3
- fix serial output (popup)
- fix serial console keyboard input
- Add Bay Trail support
- rewrite popup popdown popclear
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
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 */
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
max@laptop % cd build max@laptop % ./cbfstool coreboot.rom add-payload -f ../payloads/perso/memtest86+-5.01/memtest -n img/memtest
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.
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
- “Multiboot header support” → disable : we don’t need it.
- “See output on a video console” → disable : libpayload doesn’t use sgabios API, so we don’t need “video”, we only use the serial console.
build & install
libpayload will be installed in
It automaticaly use the coreboot toolchain.
max@laptop % cd payloads/libpayload max@laptop % make max@laptop % make install
max@laptop % cd payloads/coreinfo max@laptop % make menuconfig
I did not change anything.
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
max@laptop % cd build max@laptop % ./cbfstool coreboot.rom add-payload -f ../payloads/coreinfo/build/coreinfo.elf -n img/coreinfo
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
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 :
disable the defaults console output and enable the serial port. There is no point using the sgabios interface if iPXE support serial port.
--- a/src/config/console.h +++ b/src/config/console.h @@ -25,3 +25,3 @@ -//#undef CONSOLE_PCBIOS /* Default BIOS console */ -//#undef CONSOLE_EFI /* Default EFI console */ -//#undef CONSOLE_LINUX /* Default Linux console */ +#undef CONSOLE_PCBIOS /* Default BIOS console */ +#undef CONSOLE_EFI /* Default EFI console */ +#undef CONSOLE_LINUX /* Default Linux console */ @@ -37 +37 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); -//#define CONSOLE_SERIAL /* Serial port console */ +#define CONSOLE_SERIAL /* Serial port console */
disable the prompt “Press Ctrl-B to configure iPXE” when the option ROM is loaded but not when iPXE is launched by SeaBIOS.
--- a/src/config/general.h +++ b/src/config/general.h @@ -29,2 +29,2 @@ -#define BANNER_TIMEOUT 20 -#define ROM_BANNER_TIMEOUT ( 2 * BANNER_TIMEOUT ) +#define BANNER_TIMEOUT 30 +#define ROM_BANNER_TIMEOUT 0
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 : 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
max@laptop % cd payloads/perso/ipxe/src max@laptop % make CROSS_COMPILE="$COREBOOT_DIRECTORY/util/crossgcc/xgcc/bin/i386-elf-" bin/10ec8168.rom
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
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
+REQUIRE_OBJECT ( shell );
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).
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
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.
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
- 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
- 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.
max@laptop % make grub2
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
BIOS ROM Extensions can be add to the main ROM file with the
add command of
ELF files can be add to the main ROM file with the
add-payload command of
They have to be placed in the img directory to be recognise by SeaBIOS.
You can display the content of the ROM with the
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
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-payload command of
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
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”.
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
- “last_boot” and “boot_option” are related to the fallback mechanism of coreboot/cbfs.
- “multi_core” enable/disable multicore support (I didn’t test it).
- “baud_rate” controle the baud rade of the serial port coreboot will use (coreboot… not SeaBIOS !)
- “debug_level” controle the debug level of coreboot (coreboot… not SeaBIOS !)
You can see those logs with :
root@laptop # cbmem -c
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.