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


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`.


Coreboot Documentation
----------------------


When reading this How-to, please go along with Coreboot Documentation:

* <https://doc.coreboot.org/getting_started/index.html>
* <https://doc.coreboot.org/mainboard/lenovo/x2xx_series.html>
* <https://doc.coreboot.org/mainboard/lenovo/xx30_series.html>


Retrieve Sources, Checkout and Compile Toolchain
------------------------------------------------


Basically:

    $ git clone https://review.coreboot.org/coreboot
    $ cd coreboot
    $ git checkout 4.9
    $ 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 12582912 bytes
      Flash Region 0 (Flash Descriptor): 00000000 - 00000fff
      Flash Region 1 (BIOS): 00500000 - 00bfffff
      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: 0x700000. 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, i.e.:

        [...]
        The ME minimum size should be 1667072 bytes (0x197000 bytes)
        The ME region can be reduced up to:
         00003000:00199fff me
        Setting the AltMeDisable bit in PCHSTRP10 to disable Intel ME...
        Checking the FTPR RSA signature... VALID
        Done! Good luck!

    However, shrinking the ME region down from 5MB to 1.6MB 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 X230)
  - Select: ROM chip size (12MB)
  - Select: Size of CBFS filesystem in ROM = 0x700000

* 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

        NOTE: It seems as if this blob is optional, in case you want to
        disable onboard LAN. See TODO notes above.

* Devices
    - Graphics initialization (Use libgfxinit)  --->
    - 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` or `coreinfo` 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-X230 machine comes with a special 1366x768px 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, “no image” included.


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
    usb_always_on = Disable
    sata_mode = AHCI
    backlight = Both
    gfx_uma_size = 224M
    volume = 0x3

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


Split into Top and Bottom ROM
-----------------------------


As two individual flash chips are used to form a virtual 12M BIOS chip
on the ThinkPad X230 systemboard, we have to split the generated ROM:

    $ dd \
        if=build/coreboot.rom \
        of=build/coreboot-bottom.rom \
        bs=1M count=8
    $ dd \
        if=build/coreboot.rom \
        of=build/coreboot-top.rom \
        bs=1M skip=8

The file `coreboot-bottom.rom` belongs into chip #1, located close to
the sysboard’s front edge.  
The file `coreboot-top.rom` belongs into chip #2, located between chip
#1 and screen.


Done!
-----


Your ROM files should now be ready to go!

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

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

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
