|
|
(90 intermediate revisions by 3 users not shown) |
Line 1: |
Line 1: |
| == Introduction == | | == Introduction == |
| The fallback mecanism permits to be able to use two different prefixes (normal/ and fallback/) for the romstage, ramstage and payload, in the same coreboot image.
| | This mechanism permits to test and recover from certain non-booting coreboot images. |
|
| |
|
| The switch between the two prefixes can be governed by an nvram configuration parameter. | | This works by having two coreboot images in the same flash chip: |
| | * One fallback/ image: The working image. |
| | * One normal/ image: The image to be tested. |
|
| |
|
| == Prefixes ==
| | This feature is not widely tested on all boards. It also requires it to have a reboot_counter exported in the CMOS layout. |
| fallback/ is expected to hold the good known working image.
| |
|
| |
|
| normal/ is expected to hold the image under test
| | This also doesn't protect against human errors when using such feature, or bugs in the code responsible for switching between the two images. |
|
| |
|
| == Uses cases == | | == Uses cases == |
| * Test new images way faster: if the image doesn't boot it will fallback on the old known-working image and save a long reflashing procedure | | * Test new images way faster: if the image doesn't boot it will fallback on the old known-working image and save a long reflashing procedure. Handy for bisecting faster. |
| * Test new images more safely: Despite of the recommendations of having a way to externally reflash, many new user don't. Assuming that the user don't screw up the fallback/ procedure (which adds a layer of complexity) he can test new images more safely because it will fallback on the known good image. | | * Test new images more safely: Despite of the recommendations of having a way to externally reflash, many new user don't. Still, this method is not totally foolproof. |
| * More compact testing setup: Since reflashing tools are not mandatory anymore, the tests can be done with less voluminous hardware, which means that the test setup is easier to bring with you while travelling. | | * More compact testing setup: Since reflashing tools are not mandatory anymore, the tests can be done with less hardware, very useful when traveling. |
| == Enabling the fallback switch ==
| |
| The Fallback switch behaviour is governed by the BOOTBLOCK_SIMPLE and BOOTBLOCK_NORMAL compilation options.
| |
|
| |
|
| They are selectable in "Bootblock behaviour" in make menuconfig.
| | == How it works == |
| | Coreboot increments a reboot count at each boot but never clears it. What runs after coreboot is responsible for that. |
|
| |
|
| Currently only two choices are available:
| | That way, the count can be cleared by the OS once it's fully booted. |
| * BOOTBLOCK_SIMPLE: "(X) Always load fallback"
| |
| * BOOTBLOCK_NORMAL: "(X) Switch to normal if CMOS says so"
| |
|
| |
|
| If BOOTBLOCK_SIMPLE is chosen, then fallback/ , then no siwtch will ever be done and fallback/ will always be chosen, since this is the default we have to change it to get it to work. | | If a certain threshold<ref>Defined by CONFIG_MAX_REBOOT_CNT, typically 3</ref> is attained at boot, coreboot will boot the fallback image. |
| If BOOTBLOCK_NORMAL is chosen, then the switch will be able to work.
| |
|
| |
|
| If the BOOTBLOCK_NORMAL is chosen, the functionality is disabled but can be enabled later if needed. | | == Warnings == |
| | Because we uses two images, it's easy to wrongly identify which image booted: |
| | * If the user mistakenly thinks the normal image is booting... |
| | * But the fallback image always boots... |
| | * And the normal image doesn't work... |
| | * And the user flashes the normal in fallback because she thinks it boots fine... |
| | * Then the user bricked her device and has to reflash it externally. |
|
| |
|
| Make sure that in "General setup --->" you have:
| | == Fallback build == |
| | To configure it for fallback, do: |
| | $ make menuconfig |
| | Then in "General setup --->", near the top use "fallback" in "CBFS prefix to use": |
| (fallback) CBFS prefix to use | | (fallback) CBFS prefix to use |
| | | Then near the bottom, make sure to have: |
| == How it works (summary) ==
| | [ ] Update existing coreboot.rom image |
| Coreboot will switch to fallback/ if the boot count is higher than CONFIG_MAX_REBOOT_CNT (or if normal/ isn't present).
| | And in the "Chipset --->" menu at the bottom: |
| | |
| Coreboot increments the reboot count at each boot.
| |
| | |
| Here, clearing the boot count is delegated to what is run after coreboot.
| |
| | |
| To get the maximum safety out of it, clearing the boot count after the last step of the boot is advised.
| |
| | |
| === Example of use ===
| |
| For instance once the system is fully booted, a systemd unit can reset the boot count.
| |
| | |
| That way if the coreboot changes makes it impossible to boot a linux kernel or even if GNU/Linux can't fully boot, the boot count won't be reset.
| |
| | |
| Then the user will power off the computer, and at the next boot CONFIG_MAX_REBOOT_CNT will hopefully be reached. | |
| Then coreboot will boot on the good known working image and the boot will complete.
| |
| | |
| At that point the user is expected to reflash a good image in order not to go in normal/ again at the next boot.
| |
| | |
| == Current limitations ==
| |
| * scripts exist only for the systemd init system, but they are easy to adapt to other init systems
| |
| * suspend/resume systemd scripts not written yet
| |
| * some issues can arrise when the nvram layout is not the same between normal/ and fallback/
| |
| * The number of failed boot is 3 by default (for all boards that don't set CONFIG_MAX_REBOOT_CNT)
| |
| * In order to fully boot, some boards do reboot once during the boot procedure. The issue is that it reboot conditionally, and no code has been written yet to take that into account.
| |
| * Payloads can have non-configurable default locations when loading things from cbfs:
| |
| ** When using grub as a payload, grub.cfg is at etc/grub.cfg by default, so if you want to test grub as a payload, remember to change grub.cfg's path not to interfer with the fallback's grub configuration.
| |
| ** Changing the path of what SeaBIOS loads from cbfs is probably configurable with SeaBIOS cbfs symlinks but not yet tested/documented with the use of the fallback mecanism
| |
| | |
| == Using it with systemd ==
| |
| === Prerequisites ===
| |
| * Make sure that your fallback/ image has the [[Fallback_mechanism#Enabling_the_fallback_switch|fallback switch mecanism enabled]]
| |
| * Build the fallback image as you would build an image usually
| |
| | |
| == Example of use with systemd ==
| |
| | |
| * The code dependencies can be found [http://review.coreboot.org/#/q/status:open+project:coreboot+branch:master+topic:falback-patches-v2,n,z in gerrit]
| |
| | |
| === Mandatory configuration (in make menuconfig) ===
| |
| You will have to make two configurations:
| |
| * one for the fallback image
| |
| * one for the normal image
| |
| ==== First image ====
| |
| start configuring the first image with:
| |
| make menuconfig
| |
| Then configure it like that:
| |
| | |
| Go in the following menu:
| |
| Architecture (x86) --->
| |
| And then select that:
| |
| Bootblock behaviour (Switch to normal if CMOS says so) ---> | | Bootblock behaviour (Switch to normal if CMOS says so) ---> |
| Which will bring that menu:
| | [*] Do not clear reboot count after successful boot |
| ( ) Always load fallback
| |
| (X) Switch to normal if CMOS says so
| |
| Select the "Switch to normal if CMOS says so" line like described above.
| |
| | |
| In order to know if your computer booted correctly the last time, coreboot reads it in the nvram.
| |
| There are two ways to make it know that it booted fine the last time:
| |
| * The automatic way, which happens inside the ramstage of coreboot.
| |
| * The manual way, which happens when you want after the ramstage.
| |
| | |
| If you want it to happen after the ramstage Select the following menu:
| |
| General setup --->
| |
| And inside select the following if you want the manual way:
| |
| [*] Keep boot count | |
| Or don't select it if you want the automatic way:
| |
| [ ] Keep boot count
| |
| Then choose the number of times you want it to try to boot, before switching back to fallback/
| |
| (1) Number of failed boot attempts before switching back to fallback/
| |
| Note that the minimum number could be device specific.
| |
| Setting the minimum to 1 on the Lenovo x60 worked well.
| |
| | |
| In any case, make sure that you have:
| |
| (fallback-mode) Local version string
| |
| (fallback) CBFS prefix to use
| |
| | |
| Verify that you have the following in .config (that make menuconfig just generated if you followed the previous instructions correctly)
| |
| CONFIG_X86_BOOTBLOCK_NORMAL=y
| |
| CONFIG_BOOTBLOCK_SOURCE="bootblock_normal.c"
| |
| And that you have:
| |
| CONFIG_LOCALVERSION="fallback-mode"
| |
| CONFIG_CBFS_PREFIX="fallback"
| |
|
| |
|
| If you selected "Keep boot count", also verify that you have:
| | You can then build the fallback image with the [[Fallback mechanism/fallback.sh|fallback.sh]] script. |
| CONFIG_KEEP_BOOT_COUNT=y
| |
|
| |
|
| At the end copy the .config to defconfig-fallback (that will erase the file named defconfig-fallback if there was one):
| | == Normal build == |
| cp .config defconfig-fallback
| | To configure it for normal, do: |
| | | $ make menuconfig |
| ==== Second image ====
| | Then in "General setup --->", near the top use "normal" in "CBFS prefix to use": |
| After configuring the first image, you should configure the second one.
| |
| use "make menuconfig" again to change the current configuration in .config (you already copied it to defconfig-fallback, so you will only modify a copy of it).
| |
| make menuconfig | |
| Then go in "General setup" | |
| General setup --->
| |
| And modify the prefix and the version string to look like that:
| |
| (normal-mode) Local version string
| |
| (normal) CBFS prefix to use | | (normal) CBFS prefix to use |
| So that the second image that we will build later will be put in the "normal/" prefix and not in the "fallback/" one.
| | Then near the bottom, make sure to have: |
| | |
| Then go in Architecture: | |
| Architecture (x86) --->
| |
| And enable the "Update existing coreboot.rom image" option:
| |
| [*] Update existing coreboot.rom image | | [*] Update existing coreboot.rom image |
| | And in the "Chipset --->" menu at the bottom: |
| | Bootblock behaviour (Switch to normal if CMOS says so) ---> |
| | [*] Do not clear reboot count after successful boot |
|
| |
|
| At the end copy the .config to defconfig-normal (that will erase the file named defconfig-normal if there was one):
| | You can then build with the normal part with the [[Fallback mechanism/normal.sh|normal.sh]] script. It takes an existing coreboot image as argument. |
| cp .config defconfig-normal
| |
|
| |
|
| ==== Pseudo-diff ==== | | == OS configuration == |
| Then compare the two resulting configurations to be sure of what you did:
| |
| $ diff -u defconfig-fallback defconfig-normal
| |
|
| |
|
| The output should look a bit like that but with more context lines(the lines not starting with a "+" or a "-"): | | === The manual way === |
| --- defconfig-fallback 2013-10-26 22:27:19.471326092 +0200
| | An approach is to run switch-to-normal.sh before trying an image. |
| +++ defconfig-normal 2013-10-26 22:26:44.471328732 +0200
| | It's however more error prone than the systemd approach because: |
| -CONFIG_LOCALVERSION="fallback-mode"
| | * you have to do it manually, each time, before testing an image. |
| -CONFIG_CBFS_PREFIX="fallback"
| | * If you then want to use that new image, you have to flash it, again, to fallback. |
| +CONFIG_LOCALVERSION="normal-mode"
| |
| +CONFIG_CBFS_PREFIX="normal"
| |
| -# CONFIG_UPDATE_IMAGE is not set
| |
| +CONFIG_UPDATE_IMAGE=y
| |
|
| |
|
| === Compilation === | | ==== switch-to-normal.sh ==== |
| ==== Build script ====
| |
| This is a build script for the first build that will contains both /fallback and /normal:
| |
| #!/bin/sh | | #!/bin/sh |
| # In the cases where this work is copyrightable, it falls under the GPLv2 | | nvramtool -w boot_option=Normal |
| # or later license that is available here:
| | nvramtool -w reboot_counter=0 |
| # https://www.gnu.org/licenses/gpl-2.0.txt
| |
|
| |
| #verbose="V=1"
| |
|
| |
| die() {
| |
| echo
| |
| echo "!!!! Compilation failed !!!!"
| |
| exit 1
| |
| }
| |
|
| |
| success() {
| |
| echo
| |
| echo "!!!! Compilation finished !!!!"
| |
| echo
| |
| }
| |
|
| |
| separator() {
| |
| echo
| |
| echo "!!!! First prefix compilation finished !!!!"
| |
| echo
| |
| }
| |
|
| |
| fallback() {
| |
| make clean || die
| |
|
| |
| #fallback image
| |
| cp defconfig-fallback .config || die
| |
| make ${verbose} || die
| |
| ./build/cbfstool ./build/coreboot.rom add -f .config -n config-fallback -t raw || die
| |
|
| |
| #because it could be re-included it in the second build...
| |
| #./build/cbfstool ./build/coreboot.rom remove -n etc/ps2-keyboard-spinup || die
| |
| #./build/cbfstool ./build/coreboot.rom remove -n pci8086,109a.rom || die
| |
| }
| |
|
| |
|
| |
| save_clean_and_restore_fallback() {
| |
| cp ./build/coreboot.rom ./build-save/coreboot.rom.fallback || die
| |
| | |
| make clean || die
| |
| mkdir -p build/
| |
| cp ./build-save/coreboot.rom.fallback ./build/coreboot.rom || die
| |
|
| |
| separator
| |
| }
| |
|
| |
| normal() {
| |
| #normal image
| |
| cp defconfig-normal .config || die
| |
| make ${verbose} || die
| |
| ./build/cbfstool ./build/coreboot.rom add -f .config -n config-normal -t raw || die
| |
|
| |
| }
| |
|
| |
| add_external_cbfs() {
| |
| #Add the remaining files
| |
| ./build/cbfstool ./build/coreboot.rom add -f /home/gnutoo/x86/ipxe/src/bin/8086109a.rom -n pci8086,109a.rom -t raw || die
| |
| }
| |
|
| |
| fallback
| |
| save_clean_and_restore_fallback
| |
| normal
| |
| add_external_cbfs
| |
| success
| |
| ==== Update script ==== | |
| Before using that script, you should do:
| |
| make menuconfig #change the options if you need it, and save
| |
| And:
| |
| cp .config defconfig-normal-update
| |
|
| |
|
| This script is meant for updating an existing coreboot.rom image while not touching the fallback/ part
| | ==== switch-to-fallback.sh ==== |
| #!/bin/sh | | #!/bin/sh |
| # In the cases where this work is copyrightable, it falls under the GPLv2 | | nvramtool -w boot_option=Fallback |
| # or later license that is available here:
| | nvramtool -w reboot_counter=15 |
| # https://www.gnu.org/licenses/gpl-2.0.txt
| |
|
| |
| #verbose="V=1"
| |
| | |
| die() {
| |
| echo
| |
| echo "!!!! Compilation failed !!!!"
| |
| exit 1
| |
| }
| |
|
| |
| success() {
| |
| echo
| |
| echo "!!!! Compilation finished !!!!"
| |
| echo
| |
| }
| |
|
| |
| separator() {
| |
| echo
| |
| echo "!!!! First prefix compilation finished !!!!"
| |
| echo
| |
| }
| |
|
| |
| build_cbfstool() {
| |
| make -C util/cbfstool
| |
| }
| |
| save_clean_and_restore_image() {
| |
| if [ -f ./build/coreboot.rom ] ; then
| |
| cp ./build/coreboot.rom ./build-save/coreboot.rom.fallback || die
| |
| fi
| |
|
| |
| make clean || die
| |
| mkdir -p build/
| |
| cp ./build-save/coreboot.rom.fallback ./build/coreboot.rom || die
| |
|
| |
| separator
| |
| }
| |
|
| |
| remove_normal_from_image() {
| |
| ./util/cbfstool/cbfstool ./build/coreboot.rom remove -n normal/romstage || die
| |
| ./util/cbfstool/cbfstool ./build/coreboot.rom remove -n normal/coreboot_ram || die
| |
| ./util/cbfstool/cbfstool ./build/coreboot.rom remove -n normal/payload || die
| |
| ./util/cbfstool/cbfstool ./build/coreboot.rom remove -n config-normal
| |
| }
| |
|
| |
| normal() {
| |
| #normal image
| |
| cp defconfig-normal-update .config || die
| |
| make ${verbose} || die
| |
| ./util/cbfstool/cbfstool ./build/coreboot.rom add -f .config -n config-normal -t raw || die
| |
|
| |
| }
| |
|
| |
| remove_external_cbfs() {
| |
| ./util/cbfstool/cbfstool ./build/coreboot.rom remove -n pci8086,109a.rom
| |
| }
| |
|
| |
| re_add_external_cbfs() {
| |
| ./util/cbfstool/cbfstool ./build/coreboot.rom add -f /home/gnutoo/x86/ipxe/src/bin/8086109a.rom -n pci8086,109a.rom -t raw || die
| |
| }
| |
|
| |
| build_cbfstool
| |
| save_clean_and_restore_image
| |
| remove_normal_from_image
| |
| remove_external_cbfs
| |
| normal
| |
| re_add_external_cbfs
| |
| success
| |
|
| |
|
| === Use it ===
| | (Assuming that 15 is the maximum that can be stored in reboot_counter.) |
| If you chose the following option:
| |
| [*] Keep boot count
| |
| Then you or something will need to tell coreboot that the computer booted correctly.
| |
| Here are some example scripts.
| |
|
| |
|
| ==== set-fallback-1.sh ==== | | === Systemd === |
| #!/bin/sh | | Here we use systemd to automatically reset the boot counter after each successful boot (or resume). |
| nvramtool -w boot_option=Fallback | | |
| nvramtool -w last_boot=Fallback | | We are then supposed to use the normal image daily and only resort to fallback in case of issues. |
| nvramtool -w reboot_bits=1
| | |
| ==== set-normal-0.sh ====
| | To install it, first install nvramtool (from coreboot sources): |
| #!/bin/sh
| | $ cd util/nvramtool |
| nvramtool -w boot_option=Normal
| | $ make |
| nvramtool -w last_boot=Normal
| | $ sudo make install |
| nvramtool -w reboot_bits=0
| | |
| | Then add the following systemd units at their respective paths: |
| | * [[Fallback_mechanism/coreboot@boot.service|/etc/systemd/system/coreboot@boot.service]] |
| | * [[Fallback_mechanism/coreboot@resume.service|/etc/systemd/system/coreboot@resume.service]] |
|
| |
|
| ==== get-nvram.sh ====
| | Then enable them with: |
| #!/bin/sh | | $ sudo systemctl enable coreboot@boot.service |
| nvramtool -a | grep -e boot_option -e last_boot -e reboot_bits | | $ sudo systemctl start coreboot@boot.service |
| | $ sudo systemctl enable coreboot@resume.service |
| | $ sudo systemctl start coreboot@resume.service |
|
| |
|
| ==== Systemd units ==== | | == Current limitations == |
| /etc/systemd/system/coreboot-booted-ok.service:
| | * '''Use of the same cmos.layout in fallback and normal !''' |
| # This file is not part of systemd.
| | * The user may wrongly identify which image booted, and because of that, end up reflashing a non-working image. |
| #
| | * Some issues can arrise when the nvram layout is not the same between normal/ and fallback/ |
| # this file is free software; you can redistribute it and/or modify it
| | * The number of failed boot is fixed at compilation time. |
| # under the terms of the GNU Lesser General Public License as published by
| | * In order to fully boot, some boards do reset conditionally during the boot process resulting in a non-predictable increment of the boot count. |
| # the Free Software Foundation; either version 2.1 of the License, or
| | * Example script exist only for systemd. Still, they are trivial to adapt to other init systems. |
| # (at your option) any later version.
| | * Payloads sometime have fixed default locations when loading things from cbfs: |
|
| | ** When using grub as a payload, grub.cfg is at etc/grub.cfg by default, so if you want to test grub as a payload, remember to change grub.cfg's path not to interfer with the fallback's grub configuration. |
| [Unit]
| | ** Changing the path of what SeaBIOS loads from cbfs is probably configurable with SeaBIOS cbfs symlinks but not yet tested/documented with the use of the fallback mecanism |
| Description=Tell coreboot that the computer booted fine.
| | * Tested boards need to be listed somewhere. |
| DefaultDependencies=no
| |
| Wants=display-manager.service
| |
| After=display-manager.service
| |
|
| |
| [Service]
| |
| Type=oneshot
| |
| RemainAfterExit=yes
| |
| ExecStart=/usr/local/sbin/nvramtool -w boot_option=Normal
| |
| ExecStart=/usr/local/sbin/nvramtool -w last_boot=Normal
| |
| ExecStart=/usr/local/sbin/nvramtool -w reboot_bits=0
| |
|
| |
| [Install]
| |
| WantedBy=multi-user.target
| |
|
| |
|
| == Update build script == | | == Issues == |
| #!/bin/sh
| | === thinkpad_acpi === |
|
| | This linux driver can have some bad interactions with the fallback/normal mecanism: when using it with the volume_control=1 option, volume_mode=1 is required, otherwise after shutting down the computer, it will always boot from fallback. |
| if [ $# -ne 1 ] ; then
| |
| echo "Usage $0 <image>"
| |
| exit 1
| |
| fi
| |
|
| |
| image="$1"
| |
|
| |
| die() {
| |
| echo "Failed"
| |
| exit 1
| |
| }
| |
|
| |
| cbfs_remove() {
| |
| file=$1
| |
| ./util/cbfstool/cbfstool ./build/coreboot.rom remove -n ${file}
| |
| }
| |
|
| |
| make oldconfig || die
| |
| make clean || die
| |
| mkdir build/ || die
| |
|
| |
| cp ${image} ./build/coreboot.rom || die
| |
|
| |
| cbfs_remove normal/romstage
| |
| cbfs_remove normal/coreboot_ram
| |
| cbfs_remove normal/payload
| |
| cbfs_remove config
| |
| cbfs_remove etc/grub.cfg
| |
|
| |
| make || die
| |
|
| |
|
| == Old Howto (will be replaced) ==
| | This might be because as the default settings of volume_mode touches the nvram, it probably corrupts it at shutdown when saving the alsa state of the volume buttons "sound card" (called EC Mixer). Then at boot, coreboot will detects a corrupted nvram and restore its valid defaults. |
| * build the coreboot image as usual, it will produce an image in build/coreboot.rom
| |
| * After the first build run:
| |
| make menuconfig
| |
| * Optionally change the payload.
| |
| * Go in
| |
| General setup --->
| |
| * Change:
| |
| (fallback) CBFS prefix to use
| |
| To:
| |
| (normal) CBFS prefix to use
| |
| * Go back to the main menu and select:
| |
| Architecture (x86) --->
| |
| select the following option:
| |
| [*] Update existing coreboot.rom image
| |
| Exit and save and rebuild...
| |
|
| |
|
| The image will then have fallback and normal:
| | == references == |
| Name Offset Type Size
| | <references/> |
| cmos_layout.bin 0x0 cmos_layout 1776
| |
| pci1002,9710.rom 0x740 optionrom 60928
| |
| fallback/romstage 0xf580 stage 92823
| |
| fallback/coreboot_ram 0x26080 stage 66639
| |
| fallback/payload 0x36540 payload 54976
| |
| config 0x43c40 raw 4455
| |
| normal/romstage 0x44e00 stage 92823
| |
| normal/coreboot_ram 0x5b8c0 stage 68820
| |
| normal/payload 0x6c600 payload 159949
| |
| (empty) 0x93700 null 442136
| |
Introduction
This mechanism permits to test and recover from certain non-booting coreboot images.
This works by having two coreboot images in the same flash chip:
- One fallback/ image: The working image.
- One normal/ image: The image to be tested.
This feature is not widely tested on all boards. It also requires it to have a reboot_counter exported in the CMOS layout.
This also doesn't protect against human errors when using such feature, or bugs in the code responsible for switching between the two images.
Uses cases
- Test new images way faster: if the image doesn't boot it will fallback on the old known-working image and save a long reflashing procedure. Handy for bisecting faster.
- Test new images more safely: Despite of the recommendations of having a way to externally reflash, many new user don't. Still, this method is not totally foolproof.
- More compact testing setup: Since reflashing tools are not mandatory anymore, the tests can be done with less hardware, very useful when traveling.
How it works
Coreboot increments a reboot count at each boot but never clears it. What runs after coreboot is responsible for that.
That way, the count can be cleared by the OS once it's fully booted.
If a certain threshold<ref>Defined by CONFIG_MAX_REBOOT_CNT, typically 3</ref> is attained at boot, coreboot will boot the fallback image.
Warnings
Because we uses two images, it's easy to wrongly identify which image booted:
- If the user mistakenly thinks the normal image is booting...
- But the fallback image always boots...
- And the normal image doesn't work...
- And the user flashes the normal in fallback because she thinks it boots fine...
- Then the user bricked her device and has to reflash it externally.
Fallback build
To configure it for fallback, do:
$ make menuconfig
Then in "General setup --->", near the top use "fallback" in "CBFS prefix to use":
(fallback) CBFS prefix to use
Then near the bottom, make sure to have:
[ ] Update existing coreboot.rom image
And in the "Chipset --->" menu at the bottom:
Bootblock behaviour (Switch to normal if CMOS says so) --->
[*] Do not clear reboot count after successful boot
You can then build the fallback image with the fallback.sh script.
Normal build
To configure it for normal, do:
$ make menuconfig
Then in "General setup --->", near the top use "normal" in "CBFS prefix to use":
(normal) CBFS prefix to use
Then near the bottom, make sure to have:
[*] Update existing coreboot.rom image
And in the "Chipset --->" menu at the bottom:
Bootblock behaviour (Switch to normal if CMOS says so) --->
[*] Do not clear reboot count after successful boot
You can then build with the normal part with the normal.sh script. It takes an existing coreboot image as argument.
OS configuration
The manual way
An approach is to run switch-to-normal.sh before trying an image.
It's however more error prone than the systemd approach because:
- you have to do it manually, each time, before testing an image.
- If you then want to use that new image, you have to flash it, again, to fallback.
switch-to-normal.sh
#!/bin/sh
nvramtool -w boot_option=Normal
nvramtool -w reboot_counter=0
switch-to-fallback.sh
#!/bin/sh
nvramtool -w boot_option=Fallback
nvramtool -w reboot_counter=15
(Assuming that 15 is the maximum that can be stored in reboot_counter.)
Systemd
Here we use systemd to automatically reset the boot counter after each successful boot (or resume).
We are then supposed to use the normal image daily and only resort to fallback in case of issues.
To install it, first install nvramtool (from coreboot sources):
$ cd util/nvramtool
$ make
$ sudo make install
Then add the following systemd units at their respective paths:
Then enable them with:
$ sudo systemctl enable coreboot@boot.service
$ sudo systemctl start coreboot@boot.service
$ sudo systemctl enable coreboot@resume.service
$ sudo systemctl start coreboot@resume.service
Current limitations
- Use of the same cmos.layout in fallback and normal !
- The user may wrongly identify which image booted, and because of that, end up reflashing a non-working image.
- Some issues can arrise when the nvram layout is not the same between normal/ and fallback/
- The number of failed boot is fixed at compilation time.
- In order to fully boot, some boards do reset conditionally during the boot process resulting in a non-predictable increment of the boot count.
- Example script exist only for systemd. Still, they are trivial to adapt to other init systems.
- Payloads sometime have fixed default locations when loading things from cbfs:
- When using grub as a payload, grub.cfg is at etc/grub.cfg by default, so if you want to test grub as a payload, remember to change grub.cfg's path not to interfer with the fallback's grub configuration.
- Changing the path of what SeaBIOS loads from cbfs is probably configurable with SeaBIOS cbfs symlinks but not yet tested/documented with the use of the fallback mecanism
- Tested boards need to be listed somewhere.
Issues
thinkpad_acpi
This linux driver can have some bad interactions with the fallback/normal mecanism: when using it with the volume_control=1 option, volume_mode=1 is required, otherwise after shutting down the computer, it will always boot from fallback.
This might be because as the default settings of volume_mode touches the nvram, it probably corrupts it at shutdown when saving the alsa state of the volume buttons "sound card" (called EC Mixer). Then at boot, coreboot will detects a corrupted nvram and restore its valid defaults.
references
<references/>