Build the Coreboot ROM Image (ThinkPad X220)
============================================


Copyright (C) 2017, 2018, 2019, 2021, 2022  Kai Mertens <kmx@posteo.net>  

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
copy of the license is included in the section entitled "GNU Free
Documentation License".


TODO: This file lists essential steps for reference only and should be
thoroughly reviewed. Please use the toolchain scripts instead. See
`../doc/toolchain.md`.


Prepare
-------


See Coreboot Build How-To: <https://www.coreboot.org/Build_HOWTO>

Basically:

    $ git clone https://review.coreboot.org/coreboot
    $ cd coreboot
    $ git checkout 4.8.1
    $ git submodule update --init --checkout
    $ make crossgcc-i386


Extract Binary Blobs from Original Firmware Dump
------------------------------------------------


Place your original `lenovo.bin` firmware dump into folder
`util/ifdtool/`, then use `ifdtool` to extract flashregions, i.e.:

    $ cd util/ifdtool
    $ make
    $ ./ifdtool -x lenovo.bin
    File lenovo.bin is 8388608 bytes
      Flash Region 0 (Flash Descriptor): 00000000 - 00000fff
      Flash Region 1 (BIOS): 00500000 - 007fffff
      Flash Region 2 (Intel ME): 00003000 - 004fffff
      Flash Region 3 (GbE): 00001000 - 00002fff
      Flash Region 4 (Platform Data): 00fff000 - 00000fff (unused)
    $ ls *.bin
    flashregion_0_flashdescriptor.bin  flashregion_1_bios.bin  flashregion_2_intel_me.bin  flashregion_3_gbe.bin  lenovo.bin

* Flash region 0 will be used as is by this How-to.

* Flash region 1 will be replaced by coreboot firmware. From the output
  above, the original size of that region is obvious: 0x300000. This
  region might be increased if region ME is shrunk.

* Flash region 2 will be cleaned by means of ME_Cleaner. See
  `build/me_cleaner.log` for more infos. However, shrinking the region
  ME down from 5MB to 884KBytes is a different step, not yet documented
  here. See `../doc/how-to-modify-ifd.md` and `../doc/toolchain.md`
  instead.

* Flash region 3 will be used as is with this How-to.


Coreboot Configuration
----------------------


    $ make menuconfig

Use default values, but additionally select/deselect as specified:

* Mainboard
    - Select: Mainboard vendor (Lenovo)
    - Select: Mainboard model (ThinkPad X220)
    - Select: ROM chip size (8MB)
    - Select: Size of CBFS filesystem in ROM = 0x300000

* General Setup
    - Select: Use CMOS configuration values

* Chipset

    - Include CPU microcode in CBFS (Generate from tree)  --->

    - Select: Add Intel descriptor.bin file

        `"(util/ifdtool/flashregion_0_flashdescriptor.bin)"` Path and
        filename of the descriptor.bin file

    - Select: Add Intel ME/TXE firmware

        `"(util/ifdtool/flashregion_2_intel_me.bin)"` Path to
        management engine firmware

    - Select: Verify the integrity of the supplied ME/TXE firmware

    - Select: Strip down the Intel ME/TXE firmware

        *** Please test the modified ME/TXE firmware and coreboot in two steps ***

    - Select: Add gigabit ethernet firmware

        `"(util/ifdtool/flashregion_3_gbe.bin)"` Path to gigabit
        ethernet firmware

* Devices
    - Graphics initialization (Use native graphics init)  --->
    - Display  --->
        + Framebuffer mode (Linear "high-resolution" framebuffer)  --->

* Payload
    - Select: Add a payload (An ELF executable payload)
    - `"(payload.elf)"` Payload path and filename

        NOTE: File `payload.elf` should match your previously built
        executable GRUB payload file for platform i386-coreboot. See
        [GRUB How-To][].

    - Secondary Payloads --->
        + Select: Load coreinfo as a secondary payload
        + Select: Load nvramcui as a secondary payload

NOTE: The `.config` file may contain your paths which you probably
don't want to share with others.


Compile
-------


When you have exit the `menuconfig` tool, type:

    $ make

This will provide the `coreboot.rom` in folder `build/`.


Add Custom Files
----------------


### Add Zerocat’s GRUB Configuration File


Use coreboot’s `cbfstool` to add the custom configuration file as
`etc/zerocat.cfg`:

    $ build/cbfstool build/coreboot.rom \
        add -t raw -n etc/zerocat.cfg -f <your/path/to/grub@2.02_zerocat.cfg>
    $ build/cbfstool build/coreboot.rom \
        print

See [grub@2.02_zerocat.cfg][] for reference. Before using it, please
edit the file and adjust your keyboard layout which is currently
pre-set via `keymap`.


### Secondary Payloads


#### NVRAMCUI and Coreinfo


Secondary payloads `nvramcui` and `coreinfo` should be accompanied with
an informative message about occasional freezes, what can be achieved
with GRUB, but not with SeaBIOS. Therefor, let’s move them out of the
SeaBIOS `img/` search path:

    $ for i in coreinfo nvramcui; do \
        build/cbfstool build/coreboot.rom \
          extract -m x86 -n img/$i -f $i.extracted && \
        build/cbfstool build/coreboot.rom \
          remove -n img/$i && \
        build/cbfstool build/coreboot.rom \
          add-payload -c lzma -n $i -f $i.extracted && \
        rm $i.extracted; \
      done;

NOTE: When invoking `coreinfo` fromout the GRUB Boot Menu, please get
prepared for occasional freezes due to CPU exceptions and faults. See
[Coreinfo CPU Exceptions][].

NOTE: When invoking `nvramcui` fromout the GRUB Boot Menu, switch your
RF Kill Switch off! Active bluetooth devices might freeze the
application.


#### Add SeaBIOS Payload


[Zerocat’s GRUB Configuration File][grub@2.02_zerocat.cfg] already
comes with a menu entry to chainload the SeaBIOS payload. Add files to
the `coreboot.rom` as required:

    $ build/cbfstool build/coreboot.rom \
        add -t raw -n config-seabios -f <your/path/to/seabios/.config>
    $ build/cbfstool build/coreboot.rom \
        add -t raw -n vgaroms/vgabios.bin -f <your/path/to/seabios/out/vgabios.bin>
    $ build/cbfstool build/coreboot.rom \
        add-payload -n seabios.elf -f <your/path/to/seabios/out/bios.bin.elf>
    $ build/cbfstool build/coreboot.rom \
        print

Please read section “Adding SeaBIOS Payload” of the [GRUB How-To][] for
more information.


### Add Background Images


The ZC-X220 machine comes with a special 1280x800px PNG background
image. Note the module `png` has already been packed in section "Build
GRUB", therefore you can just add your image like so:

    $ build/cbfstool build/coreboot.rom \
        add -t raw -n background.png -f <your/path/to/background.png>
    $ build/cbfstool build/coreboot.rom \
        print

You may add up to three more images named `background_1.png`,
`background_2.png` and `background_3.png`. This feature provides space
for additional information, such as a documented flash procedure for
example. Use hotkey 'i' in GRUB’s Boot Menu to cycle through the
images.


Tweak Parameters in `cmos.default`
----------------------------------


Get an overview of tweakable parameters:

    $ build/util/nvramtool/nvramtool -C build/coreboot.rom -a

Tweak parameters `gfx_uma_size`, `wwan` and `bluetooth` in the ROM’s `cmos.default` file:

    $ build/util/nvramtool/nvramtool -C build/coreboot.rom -w gfx_uma_size=224M
    $ build/util/nvramtool/nvramtool -C build/coreboot.rom -w wwan=Disable
    $ build/util/nvramtool/nvramtool -C build/coreboot.rom -w bluetooth=Disable

Inquire parameter’s possible values with option `-e`, i.e.:

    $ build/util/nvramtool/nvramtool -C build/coreboot.rom -e gfx_uma_size

As a result, these are the ROM’s standard settings for the NVRAM:

    $ build/util/nvramtool/nvramtool -C build/coreboot.rom -a
    boot_option = Fallback
    reboot_counter = 0x0
    debug_level = Spew
    nmi = Enable
    power_on_after_fail = Disable
    first_battery = Primary
    bluetooth = Disable
    wwan = Disable
    touchpad = Enable
    wlan = Enable
    trackpoint = Enable
    fn_ctrl_swap = Disable
    sticky_fn = Disable
    power_management_beeps = Disable
    sata_mode = AHCI
    usb_always_on = Disable
    gfx_uma_size = 224M
    volume = 0x3

NOTE: You will be able to modify these settings with the NVRAMCUI
payload upon boot time.


Done!
-----


Your ROM file should now be ready to go!

Remember to clean up folder `util/ifdtool/` by removing binaries or by
creating a backup, i.e.:

    $ cd coreboot/util/ifdtool
    $ mkdir backup-x220
    $ mv *.bin backup-x220

Don't forget to reset the checksum of your NVRAM Option Table to zero
by unplugging the small coin battery for some seconds.



[GRUB How-To]:                ../doc/grub-how-to.md
[Coreinfo CPU Exceptions]:    ../doc/coreinfo-cpu-exceptions.md
[grub@2.02_zerocat.cfg]:      ../templates/grub@2.02_zerocat.cfg
