#!/bin/sh


# Zerocat Coreboot Machines --- Create very satisfying free software devices.
#
# Copyright (C) 2019, 2020, 2021, 2022  Kai Mertens <kmx@posteo.net>
# Re-exec code suggested by Ricardo Wurmus, 03/2021
#
# This file is part of Zerocat Coreboot Machines.
#
# Zerocat Coreboot Machines is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# Zerocat Coreboot Machines is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Zerocat Coreboot Machines.  If not, see <http://www.gnu.org/licenses/>.


# Purpose
# =======
#
# Generate Zerocat’s ROM.


# Usage
# =====
#
#     ./gen-rom-zerocat.sh --usage


# Re-exec if we are not using Bash or are using Bash in POSIX mode.
if [ -z "$BASH" ] || [ "$BASH" = "/bin/sh" ]; then
  bash=`command -v bash`
  if [ -z "$bash" ]; then
    echo "Couldn't find Bash, sorry!"
    exit 1
  else
    exec "$bash" "$0" "$@"
  fi
fi

# We're using Bash now.
set +o errexit
set +o nounset
set -o pipefail

# external sources ###
source ./globals__ANSI-color-escapes.sh
source ./globals__project.sh
source ./lib__debug.sh
source ./lib__get-input.sh
source ./func__print_licheader.sh
source ./func__print_logo.sh

# global constants ###

# global variables ###

# functions ###
usage()
{
  _funcstart "$FUNCNAME"

  _info "Provide usage information ..."
  cat<<EOF

${SET_BOLD}NAME${CLR_INTENSITY}
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} – Generate your Zerocat ROM.

${SET_BOLD}USAGE${CLR_INTENSITY}
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        [<Help-Options>] \\
        [<Screen-Output-Control>]
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        [<Clean-Options>] \\
        [<Screen-Output-Control>]
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        [<Toolbox-Options>] \\
        [<Target-Options>] \\
        [<Coreboot-Options>] \\
        [<Options-Primary-Payload>] \\
        [<Options-Secondary-Payload>] \\
        [<Screen-Output-Control>]
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        [<Toolbox-Options>] \\
        [<Target-Options>] \\
        [<Proprietary-Binaries>] \\
        [<Intel-Firmware-Options>] \\
        [<Coreboot-Options>] \\
        [<Options-Primary-Payload>] \\
        [<Options-Secondary-Payload>] \\
        [<Screen-Output-Control>]

    See Section “WORKED EXAMPLES”.

${SET_BOLD}DESCRIPTION${CLR_INTENSITY}
    This script generates Zerocat’s ready to use firmware images for a small but interesting
    set of laptops¹. The basic configuration makes use of ${SET_UNDERLINE}Coreboot${CLR_UNDERLINE} with
    ${SET_UNDERLINE}GRUB2${CLR_UNDERLINE} as the primary payload. Secondary payloads like
    SeaBIOS, NVRAMCUI and Coreinfo are optionally available if the GRUB configuration has been set up to
    provide related menu entries – see ${SET_BOLD}${TOOLCHAIN_SCRIPT[3]} --usage${CLR_INTENSITY}.

    ¹ThinkPad X60, X60s, X60t, T60, T60 with ATI_Mobility_Radeon_X1300, T60 with ATI_Mobility_Radeon_X1400,
     X200, X200s, X200t, T400(!), T400s, X201(!), X220, X220i, T420, T420s, T520/T520i(!), X230, X230t, X230s,
     T430, T430s, T530

${SET_BOLD}OPTIONS${CLR_INTENSITY}
    Note the order of options on the command line should have no importance.
    Options and files marked in ${FG_YELLOW}yellow color${FG_DEFAULT} are likely to introduce non-free, proprietary blobs.
    Warnings marked in ${FG_RED}red color${FG_DEFAULT} are meant to save you from trouble and from unbootable machines.

    ${SET_BOLD}<Help-Options>${CLR_INTENSITY}
        ${SET_BOLD}--help${CLR_INTENSITY}
        ${SET_BOLD}--usage${CLR_INTENSITY}
            Show usage information.

    ${SET_BOLD}<Clean-Options>${CLR_INTENSITY}
        ${SET_BOLD}--clean${CLR_INTENSITY}
            clean up generated files
        ${SET_BOLD}--remove-all${CLR_INTENSITY}
            remove generated build folders

    ${SET_BOLD}<Screen-Output-Control>${CLR_INTENSITY}
        ${SET_BOLD}--mute${CLR_INTENSITY}
            Discard standard output of verbose external processes.
            However, their output to stderr will still be visible.
        ${SET_BOLD}--debug${CLR_INTENSITY}
            Enable extra screen output which eases debugging.

    ${SET_BOLD}<Toolbox-Options>${CLR_INTENSITY}
        ${SET_BOLD}--toolbox${CLR_INTENSITY} <path/to/toolbox-folder>
            Specify a toolbox folder that holds required external projects.

        <path/to/toolbox-folder>
            This folder should have previously been created by ${SET_BOLD}${TOOLCHAIN_SCRIPT[1]}${CLR_INTENSITY}.

    ${SET_BOLD}<Target-Options>${CLR_INTENSITY}
        With a specified target, a ${SET_UNDERLINE}temporary target folder${CLR_UNDERLINE} will be created, which will hold
        the generated ${SET_BOLD}${ROM_ZEROCAT}${CLR_INTENSITY} along with more files, subfolders and checksums. The name pattern of
        this folder will reflect the selected configuration and will be suffixed by a 10 digit random string.

        ${SET_BOLD}--target${CLR_INTENSITY}  x60_32bit|x60s_32bit|x60t_32bit|
                  x60|x60s|x60t|
                  t60|t60_ati_mobility_radeon_x1300|t60_ati_mobility_radeon_x1400|
                  x200|x200t|t400|t400s|t500|
                  x201|
                  x220|x220i|t420|t420s|t520|t520i
                  x1_carbon_gen1|
                  x230|x230t|t430|t530|w530
                  x230s|t430s
            x60_32bit, x60s_32bit, x60t_32bit
                Target is a ThinkPad X60/X60s/X60-Tablet with a 2MB SPI Chip and 32 bit CPU.
            x60, x60s, x60t
                Target is a ThinkPad X60/X60s/X60-Tablet with a 2MB SPI Chip.
            t60
                Target is a ThinkPad T60 with a 2MB SPI Chip and both, 32 and 64 bit CPU.
                To be used with “coreboot@4.8.1”.
            t60_ati_mobility_radeon_x1300
                Target is a ThinkPad T60 with a 2MB SPI Chip, 32 or 64 bit CPU, and ATI Mobility Radeon X1300 graphic
                controller. You must provide an extracted VGA Option ROM by means of option ${SET_BOLD}--rom-vga${CLR_INTENSITY}.
                To be used with “coreboot@4.8.1”.
            t60_ati_mobility_radeon_x1400
                Target is a ThinkPad T60 with a 2MB SPI Chip, 32 or 64 bit CPU, and ATI Mobility Radeon X1400 graphic
                controller. You must provide an extracted VGA Option ROM by means of option ${SET_BOLD}--rom-vga${CLR_INTENSITY}.
                To be used with “coreboot@4.8.1”.
            x200, x200s, x200t
                Target is a ThinkPad X200/X200s or X200-Tablet with a 4, 8 or 16MB SPI Chip.
            t400, t400s
                Target is a ThinkPad T400/T400s with a 4, 8 or 16MB SPI Chip.
                Use coreboot@4.8.1 in case your T400 has a TFT with 1440×900px resolution.
            t500
                Target is a ThinkPad T500 with a 4, 8 or 16MB SPI Chip.
            x201
                Target is a ThinkPad X201 with an 8MB SPI Chip.
                Don’t expect too much, IME-Firmware must be used as is, otherwise FAN control is broken.
            x220
                Target is a ThinkPad X220 with an 8MB SPI Chip.
            x220i
                Target is a ThinkPad X220i with an 8MB SPI Chip.
            t420
                Target is a ThinkPad T420 with an 8MB SPI Chip.
            t420s
                Target is a ThinkPad T420s with an 8MB SPI Chip.
            t520/t520i
                Target is a ThinkPad T520/T520i with an 8MB SPI Chip. This device gets into ${FG_RED}trouble with coreboot${FG_DEFAULT}
                firmware (even if IME firmware is not touched), as occasional freezes, crashes or reboots might
                occur. Try with kernel option ${SET_BOLD}intel_idle.max_cstate=2${CLR_INTENSITY}. A fallback ROM will be created by injecting the original BIOS
                dump into flash region ‘BIOS’. Use switch ${SET_BOLD}--ifd-lock-regions${CLR_INTENSITY} to preserve original
                region access permissions.
            x1_carbon_gen1
                Target is a ThinkPad X1 Carbon Gen1 with a virtual 12MB SPI Chip.
            x230, x230t
                Target is a ThinkPad X230 or X230-Tablet with a virtual 12MB SPI Chip.
            x230s
                Target is a ThinkPad X230s with a 16MB SPI Chip.
            t430
                Target is a ThinkPad T430 with a virtual 12MB SPI Chip.
            t430s
                Target is a ThinkPad T430s with a 16MB SPI Chip.
            t530
                Target is a ThinkPad T530 with a virtual 12MB SPI Chip.
            w530
                Target is a ThinkPad W530 with a virtual 12MB SPI Chip.

        ${SET_BOLD}--chipsize${CLR_INTENSITY} 2mb|4mb|8mb|12mb|16mb
            2mb
                Your target has a SPI chip of 2MB size (0x00200000 Bytes).
                This is a valid option for x60 and t60 family of targets.
            4mb
                Your target has an SPI chip of 4mb size (0x00400000 Bytes).
                This might be a valid option for your x200, x200s, x200t, t400, t400s and t500.
            8mb
                Your target has an SPI chip of 8mb size (0x00800000 Bytes).
                This might be a valid option for targets x200, x200s, x200t, t400, t400s and t500.
                This is a valid option for targets x201, x220, x220i, t420, t420s, t520 and t520i.
            12mb
                Your target has a (virtual) SPI chip of 12mb size (0x00c00000 Bytes).
                The virtual chip is formed by two concatenated physical chips, and the final
                ROM image will be split to ease flashing with an external programmer.
                This is a valid option for targets x1_carbon_gen1, x230, x230t, t430, t530 and w530.
            16mb
                Your target has a SPI chip of 16mb size (0x01000000 Bytes).
                This might be a valid option for targets x200, x200s, x200t, t400, t400s and t500.
                It is the default size for x230s and t430s.

    ${SET_BOLD}<Proprietary-Binaries>${CLR_INTENSITY}
        ${SET_BOLD}--rom-factory${CLR_INTENSITY} ${FG_YELLOW}<path/to/factory.rom>${FG_DEFAULT}
            Specify <path/to/factory.rom>, your backup file of vendor’s firmware. Must be provided for:
            x200/x200s/x200t with ime, t400/t400s with ime, x201, x220, x220i, t420, t420s, t520, t520i,
            x1_carbon_gen1, x230, x230t, x230s, t430, t430s, t530, w530
        ${SET_BOLD}--rom-vga${CLR_INTENSITY} ${FG_YELLOW}<path/to/pciVVVV,DDDD.rom>${FG_DEFAULT}
            Specify an extracted VGA Option ROM and activate corresponding settings. This option
            is not available for all targets. It must be used for targets t60_ati_mobility_radeon_x1300 and t60_ati_mobility_radeon_x1400.
            Note ${SET_UNDERLINE}with a VGA ROM provided${CLR_UNDERLINE}, you should have used ${SET_BOLD}${TOOLCHAIN_SCRIPT[2]}${CLR_INTENSITY}
            with option ${SET_BOLD}--config-no-vgarom${CLR_INTENSITY} to compile the SeaBIOS Payload!

        ${FG_YELLOW}<path/to/factory.rom>${FG_DEFAULT}
            Name of the binary backup file of vendor’s firmware. This file will be copied into
            the temporary target folder as file ${SET_BOLD}${ROM_FACTORY}${CLR_INTENSITY}.
        ${FG_YELLOW}<path/to/pciVVVV,DDDD.rom>${FG_DEFAULT}
            Name of a VGA Option ROM, preferably manually extracted from <path/to/factory.rom> by means
            of projects ${SET_UNDERLINE}bios_extract${CLR_UNDERLINE} or ${SET_UNDERLINE}UEFITool${CLR_UNDERLINE}. For targets t60_ati_mobility_radeon_x1300 and
            t60_ati_mobility_radeon_x1400 you are to have extracted that ROM from memory instead, while running vendor BIOS.
            This file will be copied into the temporary target folder. Note VVVV and DDDD should match pci vendor and device ids.

    ${SET_BOLD}<Intel-Firmware-Options>${CLR_INTENSITY}
        Not applicable for targets without Intel Firmware Descriptor (IFD) as like x60 and t60 family of targets.

        ${SET_BOLD}--ifd-lock-regions${CLR_INTENSITY}
            Modify the IFD and restrict read and write access to selected, standard firmware regions.
            Otherwise (if this option is not provided), ${SET_UNDERLINE}unlock${CLR_UNDERLINE} selected flash regions.
        ${SET_BOLD}--ifd-medisable${CLR_INTENSITY}
            Modify IFD and set the ${SET_UNDERLINE}MeDisable${CLR_UNDERLINE} bit.
        ${SET_BOLD}--ifd-altmedisable${CLR_INTENSITY}
            Modify IFD and set the ${SET_UNDERLINE}AltMeDisable${CLR_UNDERLINE} bit.
        ${SET_BOLD}--ime${CLR_INTENSITY} ${FG_YELLOW}keep${FG_DEFAULT}|${FG_YELLOW}trunc${FG_DEFAULT}|${FG_YELLOW}xtrunc${FG_DEFAULT}|none
            How to modify the proprietary Intel Management Engine Firmware:
            ${FG_YELLOW}keep${FG_DEFAULT}
                Re-use the original Intel Management Engine (IME) Firmware Image, extracted
                from <path/to/factory.rom>. This is a valid option for all targets but x60 and t60 family of targets.
            ${FG_YELLOW}trunc${FG_DEFAULT}
                The IME Firmware Image will be stripped down as much as possible by means
                of ME_Cleaner. The IME firmware region will be shrunk, the BIOS region will
                be augmented (exept for target t520). This requires to modify the Intel Flash
                Descriptor (IFD). This is a valid option for targets x220, x220i, t420, t420s, t520, t520i,
                x1_carbon_gen1, x230, x230t, t430, t430s, t530 and w530.
            ${FG_YELLOW}xtrunc${FG_DEFAULT}
                Like ‘trunc’, but truncate the ME Firmware Image even more.
            none
                The IFD will be modified and firmware region ME will be deleted. This is a valid option for
                targets x200, x200s, x200t, t400, t400s and t500.
        ${SET_BOLD}--gbe${CLR_INTENSITY} keep|set_<macaddr-without-colons>|disable
            How to modify the Gigabit Ethernet (GbE) Configuration Data:
            keep
                Re-use a the original data image, extracted from <path/to/factory.rom>.
            set_<macaddr-without-colons>
                Build GbE configuration data blob (ICH9m | Intel 6 Series) from scratch.
                Change MAC Address to <macaddr>, to be specified ${SET_UNDERLINE}without colons${CLR_UNDERLINE}.
                According to IEEE standards, a MAC Address of 000000000000 shall not be used.
                - Values commonly found on X200 and alike targets are: 001f16xxxxxx, 00262dxxxxxx
                - Values commonly found on X230 and alike targets are: 3c970exxxxxx
                - Bits of the first octet’s lower nibble have special meanings
                - Lower three octets are available for random, user defined values
                Clear bit ${SET_UNDERLINE}l1_gbedis${CLR_UNDERLINE} in order to enable GbE operation.
            disable
                Build GbE configuration data blob (ICH9m | Intel 6 Series) from scratch.
                Change MAC Address to ffffffffffff and set bit ${SET_UNDERLINE}l1_gbedis${CLR_UNDERLINE} in order to disable GbE operation.

    ${SET_BOLD}<Coreboot-Options>${CLR_INTENSITY}
        ${SET_BOLD}${FG_YELLOW}--microcode${FG_DEFAULT}${CLR_INTENSITY}
            Include a proprietary blob of CPU Microcode Updates into the Coreboot File System (CBFS).
            ${SET_UNDERLINE}In case you omit this option${CLR_UNDERLINE}, your coreboot firmware will be initialized in a blobfree manner.
            However, mind the following advices:
            · check the ringbuffer of your kernel and watch for error reports
            · only some machines might operate well, other machines will freeze for sure
            · video processing is very likely to cause freezes in any case
            · consider to load the blob as soon as possible via kernel (see ‘man iucode_tool’)

    ${SET_BOLD}<Options-Primary-Payload>${CLR_INTENSITY}
        ${SET_BOLD}--payload-grub-dir${CLR_INTENSITY} <path/to/grub-payload-folder>
            Specify <path/to/grub-payload-folder>, the directory that contains executable *.elf files and configuration files
            previously generated by ${SET_BOLD}${TOOLCHAIN_SCRIPT[3]}${CLR_INTENSITY}.

    ${SET_BOLD}<Options-Secondary-Payload>${CLR_INTENSITY}
        No options available, here. Secondary payloads will be configured by means of
        ${SET_BOLD}${TOOLCHAIN_SCRIPT[2]}${CLR_INTENSITY} and ${SET_BOLD}${TOOLCHAIN_SCRIPT[3]}${CLR_INTENSITY}.

${SET_BOLD}EXIT CODES${CLR_INTENSITY}
    ${SET_BOLD}0${CLR_INTENSITY}
        normal exit
    ${SET_BOLD}1${CLR_INTENSITY}
        an error occurred

${SET_BOLD}WORKED EXAMPLES${CLR_INTENSITY}
    Generate a ROM Image with Zerocat’s Configuration and Coreboot Firmware for a ${SET_UNDERLINE}ThinkPad T60 with ATI Graphics${CLR_UNDERLINE}:
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        ${SET_BOLD}--toolbox${CLR_INTENSITY} <path/to/toolbox-folder> \\
        ${SET_BOLD}--target${CLR_INTENSITY} t60_ati_mobility_radeon_x1300 \\
        ${SET_BOLD}--rom-vga${CLR_INTENSITY} ${FG_YELLOW}<path/to/pci1002,7149.rom>${FG_DEFAULT} \\
        ${SET_BOLD}--payload-grub-dir${CLR_INTENSITY} <path/to/grub-payload-folder>

    Generate a ROM Image with Zerocat’s Configuration and Coreboot Firmware for a ${SET_UNDERLINE}ThinkPad X200${CLR_UNDERLINE}:
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        ${SET_BOLD}--toolbox${CLR_INTENSITY} <path/to/toolbox-folder> \\
        ${SET_BOLD}--target${CLR_INTENSITY} x200 \\
        ${SET_BOLD}--chipsize${CLR_INTENSITY} 8mb \\
        ${SET_BOLD}--ifd-lock-regions${CLR_INTENSITY} \\
        ${SET_BOLD}--ifd-medisable${CLR_INTENSITY} \\
        ${SET_BOLD}--ime${CLR_INTENSITY} none \\
        ${SET_BOLD}--gbe${CLR_INTENSITY} set_<macaddr-without-colons> \\
        ${SET_BOLD}--payload-grub-dir${CLR_INTENSITY} <path/to/grub-payload-folder>

    Generate a ROM Image with Zerocat’s Configuration and Coreboot Firmware for a ${SET_UNDERLINE}ThinkPad X201${CLR_UNDERLINE}:
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        ${SET_BOLD}--toolbox${CLR_INTENSITY} <path/to/toolbox-folder> \\
        ${SET_BOLD}--target${CLR_INTENSITY} x201 \\
        ${SET_BOLD}--rom-factory${CLR_INTENSITY} ${FG_YELLOW}<path/to/factory.rom>${FG_DEFAULT} \\
        ${SET_BOLD}--ifd-lock-regions${CLR_INTENSITY} \\
        ${SET_BOLD}--ime${CLR_INTENSITY} ${FG_YELLOW}keep${FG_DEFAULT} \\
        ${SET_BOLD}--gbe${CLR_INTENSITY} keep \\
        ${SET_BOLD}${FG_YELLOW}--microcode${FG_DEFAULT}${CLR_INTENSITY} \\
        ${SET_BOLD}--payload-grub-dir${CLR_INTENSITY} <path/to/grub-payload-folder>

    Generate a ROM Image with Zerocat’s Configuration and Coreboot Firmware for a ${SET_UNDERLINE}ThinkPad X220${CLR_UNDERLINE}:
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        ${SET_BOLD}--toolbox${CLR_INTENSITY} <path/to/toolbox-folder> \\
        ${SET_BOLD}--target${CLR_INTENSITY} x220 \\
        ${SET_BOLD}--rom-factory${CLR_INTENSITY} ${FG_YELLOW}<path/to/factory.rom>${FG_DEFAULT} \\
        ${SET_BOLD}--ifd-lock-regions${CLR_INTENSITY} \\
        ${SET_BOLD}--ifd-altmedisable${CLR_INTENSITY} \\
        ${SET_BOLD}--ime${CLR_INTENSITY} ${FG_YELLOW}xtrunc${FG_DEFAULT} \\
        ${SET_BOLD}--gbe${CLR_INTENSITY} set_<macaddr-without-colons> \\
        ${SET_BOLD}--payload-grub-dir${CLR_INTENSITY} <path/to/grub-payload-folder>

    Generate a ROM Image with Zerocat’s Configuration and Coreboot Firmware for a ${SET_UNDERLINE}ThinkPad T420${CLR_UNDERLINE}:
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        ${SET_BOLD}--toolbox${CLR_INTENSITY} <path/to/toolbox-folder> \\
        ${SET_BOLD}--target${CLR_INTENSITY} t420 \\
        ${SET_BOLD}--rom-factory${CLR_INTENSITY} ${FG_YELLOW}<path/to/factory.rom>${FG_DEFAULT} \\
        ${SET_BOLD}--ifd-lock-regions${CLR_INTENSITY} \\
        ${SET_BOLD}--ifd-altmedisable${CLR_INTENSITY} \\
        ${SET_BOLD}--ime${CLR_INTENSITY} ${FG_YELLOW}trunc${FG_DEFAULT} \\
        ${SET_BOLD}--gbe${CLR_INTENSITY} set_<macaddr-without-colons> \\
        ${SET_BOLD}--payload-grub-dir${CLR_INTENSITY} <path/to/grub-payload-folder>

    Generate a ROM Image with Zerocat’s Configuration and Coreboot Firmware for a ${SET_UNDERLINE}ThinkPad T520${CLR_UNDERLINE}:
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        ${SET_BOLD}--toolbox${CLR_INTENSITY} <path/to/toolbox-folder> \\
        ${SET_BOLD}--target${CLR_INTENSITY} t520 \\
        ${SET_BOLD}--rom-factory${CLR_INTENSITY} ${FG_YELLOW}<path/to/factory.rom>${FG_DEFAULT} \\
        ${SET_BOLD}--ifd-lock-regions${CLR_INTENSITY} \\
        ${SET_BOLD}--ifd-altmedisable${CLR_INTENSITY} \\
        ${SET_BOLD}--ime${CLR_INTENSITY} ${FG_YELLOW}xtrunc${FG_DEFAULT} \\
        ${SET_BOLD}--gbe${CLR_INTENSITY} set_<macaddr-without-colons> \\
        ${SET_BOLD}${FG_YELLOW}--microcode${FG_DEFAULT}${CLR_INTENSITY} \\
        ${SET_BOLD}--payload-grub-dir${CLR_INTENSITY} <path/to/grub-payload-folder>

    Generate a ROM Image with Zerocat’s Configuration and Coreboot Firmware for a ${SET_UNDERLINE}ThinkPad X1 Carbon Gen1${CLR_UNDERLINE}:
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        ${SET_BOLD}--toolbox${CLR_INTENSITY} <path/to/toolbox-folder> \\
        ${SET_BOLD}--target${CLR_INTENSITY} x1_carbon_gen1 \\
        ${SET_BOLD}--rom-factory${CLR_INTENSITY} ${FG_YELLOW}<path/to/factory.rom>${FG_DEFAULT} \\
        ${SET_BOLD}--ifd-lock-regions${CLR_INTENSITY} \\
        ${SET_BOLD}--ifd-altmedisable${CLR_INTENSITY} \\
        ${SET_BOLD}--ime${CLR_INTENSITY} ${FG_YELLOW}xtrunc${FG_DEFAULT} \\
        ${SET_BOLD}${FG_YELLOW}--microcode${FG_DEFAULT}${CLR_INTENSITY} \\
        ${SET_BOLD}--payload-grub-dir${CLR_INTENSITY} <path/to/grub-payload-folder/>

    Generate a ROM Image with Zerocat’s Configuration and Coreboot Firmware for a ${SET_UNDERLINE}ThinkPad X230${CLR_UNDERLINE}:
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        ${SET_BOLD}--toolbox${CLR_INTENSITY} <path/to/toolbox-folder> \\
        ${SET_BOLD}--target${CLR_INTENSITY} x230 \\
        ${SET_BOLD}--rom-factory${CLR_INTENSITY} ${FG_YELLOW}<path/to/factory.rom>${FG_DEFAULT} \\
        ${SET_BOLD}--ifd-lock-regions${CLR_INTENSITY} \\
        ${SET_BOLD}--ifd-altmedisable${CLR_INTENSITY} \\
        ${SET_BOLD}--ime${CLR_INTENSITY} ${FG_YELLOW}xtrunc${FG_DEFAULT} \\
        ${SET_BOLD}--gbe${CLR_INTENSITY} set_<macaddr-without-colons> \\
        ${SET_BOLD}${FG_YELLOW}--microcode${FG_DEFAULT}${CLR_INTENSITY} \\
        ${SET_BOLD}--payload-grub-dir${CLR_INTENSITY} <path/to/grub-payload-folder/>

    Generate a ROM Image with Zerocat’s Configuration and Coreboot Firmware for a ${SET_UNDERLINE}ThinkPad T430${CLR_UNDERLINE}:
    ${SET_BOLD}$BASH_SOURCE${CLR_INTENSITY} \\
        ${SET_BOLD}--toolbox${CLR_INTENSITY} <path/to/toolbox-folder> \\
        ${SET_BOLD}--target${CLR_INTENSITY} t430 \\
        ${SET_BOLD}--rom-factory${CLR_INTENSITY} ${FG_YELLOW}<path/to/factory.rom>${FG_DEFAULT} \\
        ${SET_BOLD}--ifd-lock-regions${CLR_INTENSITY} \\
        ${SET_BOLD}--ifd-altmedisable${CLR_INTENSITY} \\
        ${SET_BOLD}--ime${CLR_INTENSITY} ${FG_YELLOW}xtrunc${FG_DEFAULT} \\
        ${SET_BOLD}--gbe${CLR_INTENSITY} set_<macaddr-without-colons> \\
        ${SET_BOLD}${FG_YELLOW}--microcode${FG_DEFAULT}${CLR_INTENSITY} \\
        ${SET_BOLD}--payload-grub-dir${CLR_INTENSITY} <path/to/grub-payload-folder>

EOF
  _pass "... usage information has been provided."

  _funcstop "$FUNCNAME"
}

verify_ifd()
{
  _funcstart "$FUNCNAME"

  case "$arg__target" in
    ('t60'|'t60_ati_mobility_radeon_x1300'|'t60_ati_mobility_radeon_x1400')
      ;&

    ('x60_32bit'|'x60s_32bit'|'x60t_32bit')
      ;;

    ('x60'|'x60s'|'x60t')
      ;;

    (*)
      _info "Interactive verification of IFD dumps ..."

      declare -r dump1='ifd.factory'
      declare -r dump2='ifd.zerocat'

      pushd "$target_folder" &>/dev/null

      echo -e -n "${SET_DIM}" &&
        $path_to_coreboot/util/ifdtool/ifdtool -d \
          ${ROM_ZEROCAT} > "$dump2"
      _mesg "Created:${RTAB}$dump2"

      if [ -f "$arg__rom_factory" ]; then
        echo -e -n "${SET_DIM}" &&
          $path_to_coreboot/util/ifdtool/ifdtool -d \
            ${bin_folder##*/}/${ROM_FACTORY} > "$dump1"
        _mesg "Created:${RTAB}$dump1"
        _mesg "Now compare “$dump1” versus “$dump2”:"
        echo -e -n "${SET_DIM}" &&
          diff -y "$dump1" "$dump2"
        _mesg "Please scroll upwards. Do the dumps look like expected?"
      else
        _mesg "Now check “$dump2”:"
        echo -e -n "${SET_DIM}" &&
          cat "$dump2"
        _mesg "Please scroll upwards. Does the dump look like expected?"
      fi

      popd &>/dev/null

      hit_enter
      ;;
  esac

  _funcstop "$FUNCNAME"
}

print_nvram()
{
  _funcstart "$FUNCNAME"

  _info "Print NVRAM settings ..."

  echo -e -n "${SET_DIM}" &&
    $target_folder/build/util/nvramtool/nvramtool \
      -C $target_folder/${ROM_ZEROCAT} \
      -a \
      1>"${opt__mute:-/dev/stdout}" ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  _pass "... NVRAM settings printed."

  _funcstop "$FUNCNAME"
}

# $1: case target, i.e.: 'set-gfx'
# $2: memory size for option ‘set-gfx’, i.e. '256M'
tweak_nvram()
{
  _funcstart "$FUNCNAME"

  declare clop

  case "$1" in
    'set-gfx')
      case "$2" in
        '64M'|'128M'|'224M'|'256M')
          clop="-w gfx_uma_size=$2"
          ;;

        *)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "‘set-gfx’: unknown case: $2"
          ;;
      esac
      ;;

    'no-bluetooth')
      clop="-w bluetooth=Disable";
      ;;

    'no-wwan')
      clop="-w wwan=Disable";
      ;;

    'info')
      clop="-w debug_level=Info";
      ;;

    *)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: $1"
      ;;
  esac

  echo -e -n "${SET_DIM}" &&
    $target_folder/build/util/nvramtool/nvramtool -C \
      $target_folder/${ROM_ZEROCAT} \
      $clop \
      1>"${opt__mute:-/dev/stdout}" ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  _info "NVRAM Settings have been modified: ${clop#-w }"

  _funcstop "$FUNCNAME"
}

cbfs_add_seabios()
{
  _funcstart "$FUNCNAME"

  _info "Add SeaBIOS Payload to CBFS ..."

  echo -e -n "${SET_DIM}" &&
    $target_folder/build/cbfstool $target_folder/${ROM_ZEROCAT} \
      add-payload -n seabios.elf -f ${SEABIOS_PAYLOAD/\$\{path_to_seabios\}/$path_to_seabios} \
      1>"${opt__mute:-/dev/stdout}" ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  [ -z "$arg__rom_vga" ] && cbfs_add_file "${SEABIOS_VGABIOS/\$\{path_to_seabios\}/$path_to_seabios}" "vgaroms/vgabios.bin"
  cbfs_add_file "${TEMPLATE_SEABIOS_S3_RESUME_VGA_INIT/\$\{version_seabios\}/$version_seabios}" "etc/s3-resume-vga-init"
  cbfs_add_file "${TEMPLATE_SEABIOS_BOOT_MENU_MESSAGE/\$\{version_seabios\}/$version_seabios}" "etc/boot-menu-message"
  cbfs_add_file "${SEABIOS_CONFIG/\$\{path_to_seabios\}/$path_to_seabios}" "seabios.config"

  _pass "... SeaBIOS Payload added."

  _funcstop "$FUNCNAME"
}

cbfs_move_payloads()
{
  # $1: space separated list of payloads to move, i.e.: "nvramcui coreinfo"
  _funcstart "$FUNCNAME"

  for i in $1;
  do
    $target_folder/build/cbfstool $target_folder/${ROM_ZEROCAT} \
      extract -m x86 -n img/$i -f $i.extracted \
      &>/dev/null ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
    $target_folder/build/cbfstool $target_folder/${ROM_ZEROCAT} \
      remove -n img/$i \
      &>/dev/null ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
    $target_folder/build/cbfstool $target_folder/${ROM_ZEROCAT} \
      add-payload -c lzma -n $i -f $i.extracted \
      &>/dev/null ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
    rm $i.extracted ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
    _pass "Secondary payload $i has been moved within CBFS."
  done

  _funcstop "$FUNCNAME"
}

cbfs_add_background()
{
  _funcstart "$FUNCNAME"

  local -i i

  for (( i=0 ; i<${#BACKGROUND_CBFS[@]} ; i++ )) ; do
    [ "${grub_background[$i]}" ] ||
      break
    cbfs_add_file "${grub_background[$i]}" "${grub_background[$i]##*/}"
  done

  _funcstop "$FUNCNAME"
}

# $1: source file, full path
# $2: destination file, full path
copy_file()
{
  _funcstart "$FUNCNAME"

  declare srcfile=$1
  declare newfile=$2

  _info "Copy file ..."
  [ -f "${srcfile}" ] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: ${srcfile}"

  # copy file
  cp \
    "${srcfile}" \
    "${newfile}" ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  _pass "... file has been copied to:"
  _mesg "${INDENT}${newfile}"

  _funcstop "$FUNCNAME"
}

# $1: file to add to CBFS, full path
# $2: name to use within CBFS
cbfs_add_file()
{
  _funcstart "$FUNCNAME"

  declare newfile="${1}"
  declare newname="${2#\/}"

  _info "Add file to CBFS ..."
  [ -f "${newfile}" ] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: ${newfile}"

  # Add file to CBFS
  echo -e -n "${SET_DIM}"
  $target_folder/build/cbfstool \
    "$target_folder/${ROM_ZEROCAT}" \
    add \
    -t raw \
    -n "${newname}" \
    -f "${newfile}" \
    1>"${opt__mute:-/dev/stdout}" ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  _pass "... file has been added to CBFS:"
  _mesg "${newname}:${RTAB}${newfile}"

  _funcstop "$FUNCNAME"
}

print_cbfs()
{
  _funcstart "$FUNCNAME"

  _info "Print CBFS content ..."

  echo -e -n "${SET_DIM}" &&
    $target_folder/build/cbfstool \
      $target_folder/${ROM_ZEROCAT} \
      print \
      1>"${opt__mute:-/dev/stdout}" ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  _pass "... CBFS content printed."

  _funcstop "$FUNCNAME"
}

populate_target()
{
  _funcstart "$FUNCNAME"

  declare -r file_host_info="host-cpu-info.txt"
  declare -r file_cb_git_rev="coreboot-git-revision.txt"
  declare -r file_cb_config="config"
  declare desc=

  # create target folder
  _info "Create target folder ..."
  target_folder=$(mktemp -d ${template_target_folder}) ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
  _pass "... target folder created:"
  _mesg "${INDENT}${target_folder}"

  # write specfile
  _info "Write specfile ..."
  write_specfile "${target_folder}/specfile.md"
  _pass "... specfile written:"
  _mesg "${INDENT}${target_folder}/specfile.md"

  # backup revision coreboot
  pushd $path_to_coreboot &>/dev/null
  desc=$(git describe) || desc=$(git describe --tags)
  popd &>/dev/null
  echo $desc > $target_folder/${file_cb_git_rev}
  _info "File ${SET_BOLD}${file_cb_git_rev}${CLR_INTENSITY} has been created."

  # backup revision zerocat coreboot-machines
  echo "LABEL:     Zerocat (http://www.zerocat.org/)" > ${target_folder}/${REV_ZEROCAT}
  echo "PROJECT:   Coreboot Machines" >> ${target_folder}/${REV_ZEROCAT}
  echo "URL:       git://zerocat.org/zerocat/projects/coreboot-machines.git" >> ${target_folder}/${REV_ZEROCAT}
  desc=$(git describe | sed -r -e 's/(.*)(-g)([0-9a-f]*)/\1-\3/;' -) || desc=$(git describe --tags | sed -r -e 's/(.*)(-g)([0-9a-f]*)/\1-\3/;' -)
  echo "VERSION:   ${desc}" >> ${target_folder}/${REV_ZEROCAT}
  desc=$(git branch | sed -r -e '/^\*/!d; s/^\* //;' -)
  echo "BRANCH:    ${desc}" >> ${target_folder}/${REV_ZEROCAT}
  echo "BUILD:     ${target_folder##*\.}" >> ${target_folder}/${REV_ZEROCAT}

  _info "File ${SET_BOLD}${REV_ZEROCAT}${CLR_INTENSITY} has been written."

  # backup coreboot build
  cp -rf $path_to_coreboot/build $target_folder/
  _info "The coreboot build has been copied."

  # save temporary folder
  cp -rf \
    $bin_folder \
    $target_folder/
  _info "The temporary folder has been saved."

  # backup coreboot .config
  cp -f \
    $path_to_coreboot/.config \
    $target_folder/${file_cb_config}
  _info "File ${SET_BOLD}${file_cb_config}${CLR_INTENSITY} has been saved."

  # backup host cpu infos
  lscpu > $target_folder/${file_host_info}
  _info "File ${SET_BOLD}${file_host_info}${CLR_INTENSITY} has been created."

  # duplicate final coreboot ROM
  cp -rf \
    $target_folder/build/coreboot.rom \
    $target_folder/${ROM_ZEROCAT}
  _pass "Coreboot’s final ROM has been duplicated for further processing."

  # clean up after backup, remove strayed folders as well
  _info "Clean up coreboot folder and remove temporary files and folders ..."
  pushd $path_to_coreboot &>/dev/null
  declare i   # loop variable
  for i in build ${bin_folder##*\/} .config; do
    _mesg "${LIITEM}$i"
    echo -e -n "${SET_DIM}" &&
      rm -rf \
        $i \
        1>"${opt__mute:-/dev/stdout}" ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
  done
  for i in ${template_bin_folder//X/?}; do
    [ -d "$i" ] && {
      _warn "Obsolete folder detected, please remove:"
      _mesg "${INDENT}$i"
    }
  done
  popd &>/dev/null
  unset i
  _pass "... coreboot folder has been cleaned."

  _funcstop "$FUNCNAME"
}

# $1: ifd (name reference)
# $2: size_me_new
# $3: destination file
ifd_layout_file()
{
  _funcstart "$FUNCNAME"

  # create new layout file,
  #   target order of regions:
  #   fd, gbe, me, pd, bios

  declare -n p=$1

  _info "Create a new ifd layout file ..."

  # flashregion_0_flashdescriptor
  printf "%08x:%08x fd\n" "$((0x00))" "$((p[size_fd]-1))" > $3

  # flashregion_3_gbe
  printf "%08x:%08x gbe\n" "$((p[size_fd]))" "$((p[size_fd]+p[size_gbe]-1))" >> $3

  # flashregion_2_intel_me
  [ $(($2)) -eq 0 ] ||
    printf "%08x:%08x me\n" "$((p[size_fd]+p[size_gbe]))" "$((p[size_fd]+p[size_gbe]+$2-1))" >> $3

  # flashregion_3_platform_data is zero

  # flashregion_1_bios
  printf "%08x:%08x bios\n" "$((p[size_fd]+p[size_gbe]+$2))" "$((p[size_rom]-1))" >> $3

  _pass "... file ${SET_BOLD}${5/*\//}${CLR_INTENSITY} has been written:"
  echo -e -n "${SET_DIM}" &&
    cat $3 ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  _funcstop "$FUNCNAME"
}

#$1: step
coreboot_binaries()
{
  _funcstart "$FUNCNAME"

  # create temporary folder
  [ -d "$bin_folder" ] || {
    _info "Creating temporary folder to hold binaries and configurations ..."
    echo -e -n "${SET_DIM}" &&
      bin_folder=$(mktemp -d --tmpdir=${path_to_coreboot} ${template_bin_folder}) ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "failed to create temporary folder"
    _pass "... temporary folder created:"
    _mesg "${INDENT}$bin_folder"
  }

  case $1 in
    'populate-temporary-folder')
      # populate temporary folder
      [ -f "$arg__rom_factory" ] && {
        _info "Copy factory ROM ..."
        cp \
          $arg__rom_factory \
          "$bin_folder/${ROM_FACTORY}" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
        _pass "... factory ROM copied."
      }
      [ -f "$arg__rom_vga" ] && {
        _info "Copy external VGA Option ROM ..."
        cp \
          ${arg__rom_vga} \
          ${bin_folder}/${arg__rom_vga##*/} ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
        _pass "... external VGA Option ROM copied."
      }
      [ -f "${arg__payload_grub_dir}/${arg__payload_grub}" ] && {
        _info "Copy GRUB payload file ..."
        cp \
          ${arg__payload_grub_dir}/${arg__payload_grub} \
          ${bin_folder} ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
        _pass "... GRUB payload file copied."
      }
      ;;

    'me_cleaner-keep')
      [ -f "$bin_folder/${ROM_FACTORY}" ] && {
        coreboot_util_me_cleaner 'apply-but-keep' \
          "$bin_folder/${ROM_FACTORY}" \
          "$bin_folder/${ROM_FACTORY}.me_cleaner" \
          "$bin_folder/flashregion_0_flashdescriptor.bin.me_cleaner" \
          "$bin_folder/flashregion_2_intel_me.bin.me_cleaner" \
          "$bin_folder/me_cleaner.log"
      }
      ;;

    'me_cleaner')
      [ -f "$bin_folder/${ROM_FACTORY}" ] && {
        coreboot_util_me_cleaner 'apply' \
          "$bin_folder/${ROM_FACTORY}" \
          "$bin_folder/${ROM_FACTORY}.me_cleaner" \
          "$bin_folder/flashregion_0_flashdescriptor.bin.me_cleaner" \
          "$bin_folder/flashregion_2_intel_me.bin.me_cleaner" \
          "$bin_folder/me_cleaner.log"
      }
      ;;

    'compile-coreboot-utilities')
      # compile ifdtool
      coreboot_util_ifdtool make-clean
      coreboot_util_ifdtool make

      # compile bincfg
      coreboot_util_bincfg make-clean
      coreboot_util_bincfg make
      ;;

    'extract-factory-regions')
      # pushd
      #
      # The purpose of this statement is to execute the next ifdtool command within the
      # temporary folder for binaries, as ifdtool unfortunately misses an output option.
      # However, if $path_to_coreboot/util/ifdtool is a relative path, the invocation
      # of ifdtool will fail!
      #
      pushd $bin_folder &>/dev/null

      # extract regions from factory ROM
      coreboot_util_ifdtool 'extract-regions' \
        "${ROM_FACTORY}"

      # extract original chip layout
      coreboot_util_ifdtool 'extract-layout' \
        "${ROM_FACTORY}" \
        "layout.txt" && {
          _info "See original chip layout for reference:"
          echo -e -n "${SET_DIM}" &&
            cat layout.txt
        }

      # popd
      popd &>/dev/null
      ;;

    'GbE-binary')
      # pushd
      pushd $bin_folder &>/dev/null

      case "${arg__gbe,,}" in
        'keep')
          # use original firmware dump
          ;;

        set_[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])
          # create new gbe binary using new MAC address, clear bit l1_gbedis
          case "$arg__target" in
            ('x200'|'x200s'|'x200t'|'t400'|'t400s'|'t500')
              coreboot_util_bincfg 'compile-gbe-ich9m' "${arg__gbe##*_}" "0"
              ;;
            ('x230'|'x230t'|'x230s'|'t430'|'t430s'|'t530'|'w530'|'x220'|'x220i'|'t420'|'t420s'|'t520'|'t520i')
              coreboot_util_bincfg 'compile-gbe-6series' "${arg__gbe##*_}" "0"
              ;;
            (*)
              # unsupported target, internal script error
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
              ;;
          esac

          # replace gbe binary
          mv \
            "$path_to_coreboot/util/bincfg/flashregion_3_gbe.bin" \
            "flashregion_3_gbe.bin${gbebin_postfix}"
          ;;

        'disable')
          # create new gbe binary, use empty MAC address ff:ff:ff:ff:ff:ff, set bit l1_gbedis.
          case "$arg__target" in
            ('x200'|'x200s'|'x200t'|'t400'|'t400s'|'t500')
              coreboot_util_bincfg 'compile-gbe-ich9m' "ffffffffffff" "1"
              ;;
            ('x230'|'x230t'|'x230s'|'t430'|'t430s'|'t530'|'w530'|'x220'|'x220i'|'t420'|'t420s'|'t520'|'t520i')
              coreboot_util_bincfg 'compile-gbe-6series' "ffffffffffff" "1"
              ;;
            (*)
              # unsupported target, internal script error
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
              ;;
          esac

          # replace gbe binary
          mv \
            "$path_to_coreboot/util/bincfg/flashregion_3_gbe.bin" \
            "flashregion_3_gbe.bin${gbebin_postfix}"
          ;;

        *)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;
      esac

      # popd
      popd &>/dev/null
      ;;

    'size-IME-binary')
      # get size of truncated IME binary
      size_me_new=$((0x$(xxd $bin_folder/flashregion_2_intel_me.bin.me_cleaner | sed -r -e '$!d;' - | cut -f1 -d':' - ) + 0x10))
      ;;

    'size-IME-binary-extra')
      # get size of extra truncated IME binary
      size_me_new=$(((0x$(xxd $bin_folder/flashregion_2_intel_me.bin.me_cleaner | sed -r -e '$d;/.*  [.]*$/d;' - | sed -r -e '$!d;' - | cut -f1 -d':' -) / 0x1000 + 1) * 0x1000))
      ;;

    'truncated-IME-binary')
      _info "Write truncated IME binary ..."
      # create truncated region IME
      # note: 0x197000 = 0x197 * 0x1000 = 407 * 4096 = 407 * 4K
      # note: 0x194000 = 0x194 * 0x1000 = 404 * 4096 = 404 * 4K
      # note: select 4K granularity for size_me_new
      dd \
        if="$bin_folder/flashregion_2_intel_me.bin.me_cleaner" \
        of="$bin_folder/flashregion_2_intel_me.bin.new" \
        bs=$((0x1000)) count=$((size_me_new / 0x1000)) \
        &>/dev/null ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      _pass "... successfully written."
      ;;

    'descriptor-for-truncated-IME')
      # create new layout file
      ifd_layout_file \
        "ifd" \
        "$size_me_new" \
        "$bin_folder/layout.txt.new"

      # create new ROM with modified flashdescriptor,
      #  new file comes with ‘.new’ suffix
      coreboot_util_ifdtool \
        'apply-new-layout' \
        "$bin_folder/layout.txt.new" \
        "$bin_folder/${ROM_FACTORY}.me_cleaner"

      # extract and back up modified flashdescriptor
      declare newrom="$bin_folder/${ROM_FACTORY}.me_cleaner.new"
      _info "Extract and back up modified flashdescriptor ..."
      [ -f $newrom ] ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $newrom"
      coreboot_util_ifdtool 'extract-regions' "$newrom"
      unset newrom
      mv \
        "flashregion_0_flashdescriptor.bin" \
        "$bin_folder/flashregion_0_flashdescriptor.bin.new"
      _pass "... the modified flashdescriptor has been saved."

      # fix byte Nº81
      _info "Restore byte Nº81 with original value ..."
      dd \
        if="$bin_folder/flashregion_0_flashdescriptor.bin" \
        of="$bin_folder/flashregion_0_flashdescriptor.bin.new" \
        skip=81 seek=81 bs=1 count=1 conv=notrunc &>/dev/null ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      rm -f flashregion_?_*.bin
      _pass "... byte Nº81 has been restored."
      ;;

    *)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${1}"
      ;;
  esac

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
X230_config_VGA_BIOS()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"

  case "$version_coreboot" in
    ('4.14')
      _info "Patching configuration ..."
      echo -e -n "${SET_DIM}" &&
        patch -s --forward \
          "$1" \
          "coreboot@4.14_x230-vgarom.patch" \
            1>"${opt__mute:-/dev/stdout}";
      _pass "... configuration patched."
      ;;

    ('4.8.1')
      sed -r -i --file=cb481-x230-config-vga-bios.sedscr $1 ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Settings have been modified to support VGA Option ROM for X230."

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
T520_config_VGA_BIOS()
{
  _funcstart "$FUNCNAME"

  [ -f "$1" ] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"

  case "$version_coreboot" in
    ('4.14')
      _info "Patching configuration ..."
      echo -e -n "${SET_DIM}" &&
        patch -s --forward \
          "$1" \
          "coreboot@4.14_t520-vgarom.patch" \
            1>"${opt__mute:-/dev/stdout}";
      _pass "... configuration patched."
      ;;

    ('4.8.1')
      sed -r -i --file=cb481-t520-config-vga-bios.sedscr $1 ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Settings have been modified to support VGA Option ROM for T520."

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
config_VGA_BIOS_FILE()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"

  case "$version_coreboot" in
    ('4.14')
      ;&

    ('4.8.1')
      sed -r -i \
        -e '/CONFIG_VGA_BIOS_FILE/cCONFIG_VGA_BIOS_FILE=\"'"${bin_folder/#*\//}"'\/'"${arg__rom_vga##*/}"'\"' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_VGA_BIOS_FILE has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_VGA_BIOS_FILE/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
config_PAYLOAD_FILE()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"

  case "$version_coreboot" in
    ('4.14')
      ;&

    ('4.8.1')
      sed -r -i \
        -e '/CONFIG_PAYLOAD_FILE/cCONFIG_PAYLOAD_FILE=\"'"${bin_folder/#*\//}"'\/'"${arg__payload_grub/#*\//}"'\"' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_PAYLOAD_FILE has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_PAYLOAD_FILE/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: size of ROM
config_ROM_SIZE()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')
      sed -r -i \
        -e 's/(CONFIG_COREBOOT_ROMSIZE_KB_.*)(=y)/# \1 is not set/g;' \
        -e 's/(# )(CONFIG_COREBOOT_ROMSIZE_KB_'"$(printf "%d" "$(($2/0x400))")"')( is not set)/\2=y/g;' \
        -e 's/(CONFIG_COREBOOT_ROMSIZE_KB=)(.*)/\1'"$(printf "%d" "$(($2/0x400))")"'/g;' \
        -e 's/(CONFIG_ROM_SIZE=)(.*)/\1'"$(printf "0x%08x" "$2")"'/g;' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    ('4.8.1')
      sed -r -i \
        -e 's/(CONFIG_COREBOOT_ROMSIZE_KB_)(.*)(=y)/# \1\2 is not set/g;' \
        -e 's/(# )(CONFIG_COREBOOT_ROMSIZE_KB_'"$(printf "%d" "$(($2/0x400))")"')( is not set)/\2=y/g;' \
        -e 's/(CONFIG_COREBOOT_ROMSIZE_KB=)(.*)/\1'"$(printf "%d" "$(($2/0x400))")"'/g;' \
        -e 's/(CONFIG_ROM_SIZE=)(.*)/\1'"$(printf "0x%06x" "$2")"'/g;' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_ROM_SIZE has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_ROM_SIZE/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: new status: 'disable'
config_NVRAMCUI_SECONDARY_PAYLOAD()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')
      ;&

    ('4.8.1')
      case "$2" in
        ('disable')
          sed -r -i \
            -e '/# CONFIG_BOARD_EMULATION_/d;' \
            -e '/# CONFIG_CONSOLE_SERIAL_/d;' \
            -e '/# CONFIG_SEABIOS_/d;' \
            -e '/CONFIG_NVRAMCUI_SECONDARY_PAYLOAD/c# CONFIG_NVRAMCUI_SECONDARY_PAYLOAD is not set' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_NVRAMCUI_SECONDARY_PAYLOAD has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_NVRAMCUI_SECONDARY_PAYLOAD/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: new status: 'disable'
config_MEMTEST86_SECONDARY_PAYLOAD()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')
      case "$2" in
        ('disable')
          _info "Patching configuration ..."
          echo -e -n "${SET_DIM}" &&
            patch -s --forward \
              "$1" \
              "coreboot@4.14_x60_32bit-no-memtest86+.patch" \
                1>"${opt__mute:-/dev/stdout}";
          _pass "... configuration patched."
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    ('4.8.1')
      case "$2" in
        ('disable')
          sed -r -i \
            -e '/CONFIG_MEMTEST86_SECONDARY_PAYLOAD/c# CONFIG_MEMTEST86_SECONDARY_PAYLOAD is not set' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_MEMTEST86_SECONDARY_PAYLOAD has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_MEMTEST_SECONDARY_PAYLOAD/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: new status: 'disable'
config_TINT_SECONDARY_PAYLOAD()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')
      case "$2" in
        ('disable')
          _info "Patching configuration ..."
          echo -e -n "${SET_DIM}" &&
            patch -s --forward \
              "$1" \
              "coreboot@4.14_x60_32bit-no-tint.patch" \
                1>"${opt__mute:-/dev/stdout}";
          _pass "... configuration patched."
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    ('4.8.1')
      case "$2" in
        ('disable')
          sed -r -i \
            -e '/CONFIG_TINT_SECONDARY_PAYLOAD/c# CONFIG_TINT_SECONDARY_PAYLOAD is not set' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_TINT_SECONDARY_PAYLOAD has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_TINT_SECONDARY_PAYLOAD/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: new status: 'disable'
config_COREINFO_SECONDARY_PAYLOAD()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')
      ;&

    ('4.8.1')
      case "$2" in
        ('disable')
          sed -r -i \
            -e '/# CONFIG_BOARD_EMULATION_/d;' \
            -e '/# CONFIG_CONSOLE_SERIAL_/d;' \
            -e '/# CONFIG_SEABIOS_/d;' \
            -e '/CONFIG_COREINFO_SECONDARY_PAYLOAD/c# CONFIG_COREINFO_SECONDARY_PAYLOAD is not set' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_COREINFO_SECONDARY_PAYLOAD has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_COREINFO_SECONDARY_PAYLOAD/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: size of CBFS
config_CBFS_SIZE()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')
      # i.e.: t60
      sed -r -i \
        -e '/CONFIG_CBFS_SIZE/cCONFIG_CBFS_SIZE='"$(printf "0x%08x" "$2")" \
        -e '/# CONFIG_BOARD_EMULATION_QEMU_AARCH64/,/# CONFIG_BOARD_EMULATION_SPIKE_RISCV/d;' \
        -e '/# CONFIG_CONSOLE_SERIAL_921600/,/# CONFIG_CONSOLE_SERIAL_9600/d;' \
        -e '/# CONFIG_SEABIOS_STABLE/,/# CONFIG_SEABIOS_REVISION/d;' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    ('4.8.1')
      # i.e.: t60
      sed -r -i \
        -e '/CONFIG_CBFS_SIZE/cCONFIG_CBFS_SIZE='"$(printf "0x%06x" "$2")" \
        -e '/# CONFIG_BOARD_EMULATION_QEMU_ARMV7/,/# CONFIG_BOARD_EMULATION_SPIKE_UCB_RISCV/d;' \
        -e '/# CONFIG_CONSOLE_SERIAL_921600/,/# CONFIG_CONSOLE_SERIAL_9600/d;' \
        -e '/# CONFIG_SEABIOS_STABLE/,/# CONFIG_SEABIOS_REVISION/d;' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_CBFS_SIZE has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_CBFS_SIZE/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
config_LOCK_MANAGEMENT_ENGINE()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"

  case "$version_coreboot" in
    ('4.14')
      sed -r -i \
        -e '/# CONFIG_LOCK_MANAGEMENT_ENGINE/cCONFIG_LOCK_MANAGEMENT_ENGINE=y' \
        -e '/CONFIG_UNLOCK_FLASH_REGIONS=/c# CONFIG_UNLOCK_FLASH_REGIONS is not set' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    ('4.8.1')
      sed -r -i \
        -e '/# CONFIG_LOCK_MANAGEMENT_ENGINE/cCONFIG_LOCK_MANAGEMENT_ENGINE=y' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_LOCK_MANAGEMENT_ENGINE has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_LOCK_MANAGEMENT_ENGINE/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: 'enable'=yes=don't use microcode
config_CPU_MICROCODE_CBFS_NONE()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')
      case "$2" in
        ('enable')
          # i.e.: t400
          sed -r -i \
            -e '/CONFIG_USE_CPU_MICROCODE_CBFS_BINS=/c# CONFIG_CPU_MICROCODE_CBFS_DEFAULT_BINS is not set' \
            -e '/CONFIG_CPU_MICROCODE_CBFS_DEFAULT_BINS=/d;' \
            -e '/# CONFIG_CPU_MICROCODE_CBFS_NONE is not set/cCONFIG_CPU_MICROCODE_CBFS_NONE=y' \
              $1 ||
                go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    ('4.8.1')
      case "$2" in
        ('enable')
          # i.e.: x200
          sed -r -i \
            -e '/# CONFIG_BOARD_EMULATION_QEMU_ARMV7/,/# CONFIG_BOARD_EMULATION_SPIKE_UCB_RISCV/d;' \
            -e '/CONFIG_CPU_MICROCODE_CBFS_GENERATE=/c# CONFIG_CPU_MICROCODE_CBFS_GENERATE is not set' \
            -e '/# CONFIG_CPU_MICROCODE_CBFS_NONE/cCONFIG_CPU_MICROCODE_CBFS_NONE=y' \
            -e '/# CONFIG_CPU_MICROCODE_MULTIPLE_FILES/d;' \
            -e '/CONFIG_CPU_UCODE_BINARIES=/d;' \
            -e '/# CONFIG_CONSOLE_SERIAL_/d;' \
            -e '/# CONFIG_SEABIOS_/d;' \
              $1 ||
                go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac
  _mesg "Option CONFIG_CPU_MICROCODE_CBFS_NONE has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_CPU_MICROCODE_CBFS_NONE/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: 'enable'=yes, 'disable'=no
config_USE_ME_CLEANER()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')

      # FIXME: config template file already comes with USE_ME_CLEANER
      # disabled. Otherwise, what sed scripts are required here??

      case "$2" in
        ('disable')
          sed -r -i \
            -e '/CONFIG_ME_CLEANER_ARGS/d;' \
            -e '/CONFIG_USE_ME_CLEANER=y/,+4c# CONFIG_USE_ME_CLEANER is not set' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        ('enable')
          sed -r -i \
            -e '/CONFIG_OVERRIDE_DEVICETREE/aCONFIG_ME_CLEANER_ARGS=\"-S\"' \
            -e '/# CONFIG_USE_ME_CLEANER/cCONFIG_USE_ME_CLEANER=y\
\
#\
# Please test the modified ME/TXE firmware and coreboot in two steps\
#' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;
      esac
      ;;

    ('4.8.1')
      case "$2" in
        ('disable')
          sed -r -i \
            -e '/CONFIG_USE_ME_CLEANER=y/,+4c# CONFIG_USE_ME_CLEANER is not set' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        ('enable')
          sed -r -i \
            -e '/# CONFIG_USE_ME_CLEANER/cCONFIG_USE_ME_CLEANER=y\
\
#\
# Please test the modified ME/TXE firmware and coreboot in two steps\
#' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_USE_ME_CLEANER has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_USE_ME_CLEANER/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: 'disable'=no
config_CHECK_ME()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')
      ;&

    ('4.8.1')
      case "$2" in
        ('disable')
          sed -r -i \
            -e '/CONFIG_CHECK_ME=/c# CONFIG_CHECK_ME is not set' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_CHECK_ME has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_CHECK_ME/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: 'enable'=yes, 'disable'=no
config_HAVE_GBE_BIN()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')
      ;&

    ('4.8.1')
      case "$2" in
        ('disable')
          # i.e.: x200, x230; (merged script list)
          sed -r -i \
            -e '/CONFIG_HAVE_GBE_BIN/c# CONFIG_HAVE_GBE_BIN is not set' \
            -e '/CONFIG_GBE_BIN_PATH/d;' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        *)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_HAVE_GBE_BIN has been modified along with related options:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_HAVE_GBE_BIN/!d;' $1)"

  _funcstop "$FUNCNAME"
}


# $1: config file to be modified
# $2: 'enable'=yes, 'disable'=no
config_HAVE_ME_BIN()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"
  [[ "$2" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  case "$version_coreboot" in
    ('4.14')
      ;&

    ('4.8.1')
      case "$2" in
        ('disable')
          # i.e.: x200, x230; (merged script list)
          sed -r -i \
            -e '/CONFIG_HAVE_ME_BIN/c# CONFIG_HAVE_ME_BIN is not set' \
            -e '/CONFIG_ME_BIN_PATH/d;' \
            -e '/CONFIG_CHECK_ME=/d;' \
            -e '/CONFIG_USE_ME_CLEANER/d;' \
            $1 ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
          ;;

        *)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${2}"
          ;;
      esac
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_HAVE_ME_BIN has been modified along with related options:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_HAVE_ME_BIN/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: filename postfix
config_IFD_BIN_PATH()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"

  case "$version_coreboot" in
    ('4.14')
      ;&

    ('4.8.1')
      sed -r -i \
        -e 's|(CONFIG_IFD_BIN_PATH=\")(.*)(\")|\1'"${bin_folder/#*\//}"'\/\2'"$2"'\3|;' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_IFD_BIN_PATH has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_IFD_BIN_PATH/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: filename postfix
config_ME_BIN_PATH()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"

  case "$version_coreboot" in
    ('4.14')
      ;&

    ('4.8.1')
      sed -r -i \
        -e 's|(CONFIG_ME_BIN_PATH=\")(.*)(\")|\1'"${bin_folder/#*\//}"'\/\2'"$2"'\3|;' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_ME_BIN_PATH has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_ME_BIN_PATH/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: config file to be modified
# $2: filename postfix
config_GBE_BIN_PATH()
{
  _funcstart "$FUNCNAME"

  [[ -f "$1" ]] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $1"

  case "$version_coreboot" in
    ('4.14')
      ;&

    ('4.8.1')
      # note the different pattern:
      sed -r -i \
        -e 's|(CONFIG_GBE_BIN_PATH=\")(.*)(\.bin)(\")|\1'"${bin_folder/#*\//}"'\/\2\3'"$2"'\4|;' \
        $1 ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown coreboot version"
      ;;
  esac

  _mesg "Option CONFIG_GBE_BIN_PATH has been modified:"
  _mesg "${INDENT}$(sed -r -e '/CONFIG_GBE_BIN_PATH/!d;' $1)"

  _funcstop "$FUNCNAME"
}

# $1: target
# $2: coreboot version
# $3: par__tpm
# $4: delimiter
# $5: variable by name
name_config()
{
  _funcstart "$FUNCNAME"

  declare -n vref=${5:?${FG_RED}is not set${FG_DEFAULT}}

  [ "$1" ] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
  case $1 in
    'x60_32bit'|'x60s_32bit'|'x60t_32bit')
      vref=../templates/cb@${2}_config_${1/[st]_/_}${4}*?mb*.template
      ;;

    'x60'|'x60s'|'x60t')
      vref=../templates/cb@${2}_config_${1%[st]}${4}*?mb*.template
      ;;

    't60'|'t60_ati_mobility_radeon_x1300'|'t60_ati_mobility_radeon_x1400')
      vref=../templates/cb@${2}_config_${1}${4}*?mb*.template
      ;;

    'x1_carbon_gen1')
      vref=../templates/cb@${2}_config_${1}${4}*?mb${4}ime${3:+${4}tpm}*.template
      ;;

    'w530')   ;&
    [xt][245][023][01]|[xt][245][023][01][sti])
      vref=../templates/cb@${2}_config_${1}${4}*?mb${4}ime${4}gbe${3:+${4}tpm}*.template
      ;;

    *)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "template target mismatch"
      ;;
  esac

  _funcstop "$FUNCNAME"
}

# $1:
#   "machine-without-ifd"
#   "default-layout-with-ime-optionally-cleaned"
#   "new-layout-with-imetrunc"
#   "new-layout-without-ime"
coreboot_config()
{
  _funcstart "$FUNCNAME"

  local cbconfig="$path_to_coreboot/.config"

  _info "Apply configuration scheme for coreboot ..."

  case "$1" in
    'init-configfile')
      echo -e -n "${SET_DIM}" &&
        cp $template_config "$cbconfig" \
          1>"${opt__mute:-/dev/stdout}" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      config_ROM_SIZE "$cbconfig" "${ifd[size_rom]}"
      [ "$opt__microcode" ] || config_CPU_MICROCODE_CBFS_NONE "$cbconfig" 'enable'
      config_PAYLOAD_FILE "$cbconfig"
      [ "$par__coreinfo" ] || config_COREINFO_SECONDARY_PAYLOAD "$cbconfig" 'disable'
      [ "$par__nvramcui" ] || config_NVRAMCUI_SECONDARY_PAYLOAD "$cbconfig" 'disable'
      [ "$par__memtest86" ] || config_MEMTEST86_SECONDARY_PAYLOAD "$cbconfig" 'disable'
      [ "$par__tint" ] || config_TINT_SECONDARY_PAYLOAD "$cbconfig" 'disable'
      [ "$arg__rom_vga" ] && {
        [ "$arg__target" = 'x230' ] && X230_config_VGA_BIOS "$cbconfig"
        [ "$arg__target" = 't520' ] && T520_config_VGA_BIOS "$cbconfig"
        config_VGA_BIOS_FILE "$cbconfig"
      }
      ;;

    'monolithic-firmware-layout')
      config_CBFS_SIZE "$cbconfig" "$((ifd[size_rom]))"
      ;;

    'xx0-firmware-layout-with-IME')
      config_CBFS_SIZE "$cbconfig" "$((ifd[size_rom]-ifd[size_fd]-ifd[size_gbe]-ifd[size_me]))"
      config_CHECK_ME "$cbconfig" 'disable'
      config_USE_ME_CLEANER "$cbconfig" 'disable'
      config_IFD_BIN_PATH "$cbconfig" '.me_cleaner'
      config_GBE_BIN_PATH "$cbconfig" "$gbebin_postfix"
      config_ME_BIN_PATH "$cbconfig" '.me_cleaner'
      ;;

    'xx0-firmware-layout-with-truncated-IME')
      config_CBFS_SIZE "$cbconfig" "$((ifd[size_rom]-ifd[size_fd]-ifd[size_gbe]-size_me_new))"
      config_CHECK_ME "$cbconfig" 'disable'
      config_USE_ME_CLEANER "$cbconfig" 'disable'
      config_IFD_BIN_PATH "$cbconfig" '.new'
      config_GBE_BIN_PATH "$cbconfig" "$gbebin_postfix"
      config_ME_BIN_PATH "$cbconfig" '.new'
      ;;

    'x00-firmware-layout-with-IME')
      config_CBFS_SIZE "$cbconfig" "$((ifd[size_rom]-ifd[size_fd]-ifd[size_gbe]-ifd[size_me]))"
      config_IFD_BIN_PATH "$cbconfig" '.new'
      config_GBE_BIN_PATH "$cbconfig" "$gbebin_postfix"
      config_ME_BIN_PATH "$cbconfig"
      ;;

    'x00-firmware-layout-without-IME')
      config_CBFS_SIZE "$cbconfig" "$((ifd[size_rom]-ifd[size_fd]-ifd[size_gbe]))"
      config_IFD_BIN_PATH "$cbconfig" '.new'
      config_GBE_BIN_PATH "$cbconfig" "$gbebin_postfix"
      config_HAVE_ME_BIN "$cbconfig" 'disable'
      ;;

    *)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${1}"
      ;;
  esac

  _pass "... scheme applied:${RTAB}${FG_BLUE}‘${1:?is not set}’${FG_DEFAULT}"

  _funcstop "$FUNCNAME"
}


# $1: case target
# $2: source file / macaddress
# $3: destination file / l1_gbedis (0|1)
coreboot_util_bincfg()
{
  _funcstart "$FUNCNAME"

  case "$1" in
    'make-clean')
      _info "Coreboot: util/bincfg/: Run “make clean” ..."
      echo \
        -e \
        -n \
          "${SET_DIM}" &&
      make \
        -C "$path_to_coreboot/util/bincfg" \
          "clean" \
            1>"${opt__mute:-/dev/stdout}" ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      _pass "... “make clean” finished successfully."
      ;;

    'make')
      _info "Coreboot: util/bincfg/: Run “make” ..."

      # Workaround for coreboot@4.14: Disable -Werror compiler option
      local gofixup='WERROR=-Werror'
      local tmpfile='Makefile.fixed.mk'

      echo \
        -e \
        -n \
          "${SET_DIM}" &&
      sed \
        -r \
        -e "/^${gofixup}/s/^/#/;" \
          "$path_to_coreboot/util/bincfg/Makefile" \
            > "${path_to_coreboot}/util/bincfg/${tmpfile}" &&
      make \
        -C "$path_to_coreboot/util/bincfg" \
        -f "${tmpfile}" \
          1>"${opt__mute:-/dev/stdout}" &&
      rm \
        -f \
          "${path_to_coreboot}/util/bincfg/${tmpfile}" ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      unset tmpfile
      unset gofixup

      _pass "... “make” finished successfully."
      ;;

    'decompile-gbe-6series')
      _info "Coreboot: util/bincfg/: Decompile GbE binary ..."
      echo -e -n "${SET_DIM}" &&
        "$path_to_coreboot/util/bincfg/bincfg" -d \
          "$(dirs -l +1)/../templates/i82579lmv-gbe-6series.spec" \
          "$2" \
          "$3" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      _pass "... binary decompiled, ${SET_BOLD}${3}${CLR_INTENSITY} written."
      _info "Display MAC Address ..."
      echo -e -n "${SET_DIM}" &&
        cat "$3" | sed -r -e '/macaddress/!d;' -
      _pass "... MAC Address displayed."
      ;;

    'decompile-gbe-ich9m')
      _info "Coreboot: util/bincfg/: Decompile GbE binary ..."
      echo -e -n "${SET_DIM}" &&
        "$path_to_coreboot/util/bincfg/bincfg" -d \
          "$path_to_coreboot/util/bincfg/gbe-ich9m.spec" \
          "$2" \
          "$3" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      _pass "... binary decompiled, ${SET_BOLD}${3}${CLR_INTENSITY} written."
      _info "Display MAC Address ..."
      echo -e -n "${SET_DIM}" &&
        cat "$3" | sed -r -e '/macaddress/!d;' -
      _pass "... MAC Address displayed."
      ;;

    'decompile-ifd-x200')
      _info "Coreboot: util/bincfg/: Decompile X200 IFD binary ..."
      echo -e -n "${SET_DIM}" &&
        "$path_to_coreboot/util/bincfg/bincfg" -d \
          "$path_to_coreboot/util/bincfg/ifd-x200.spec" \
          "$2" \
          "$3" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      _pass "... binary decompiled, ${SET_BOLD}${3}${CLR_INTENSITY} written."
      ;;

    'compile-gbe-6series')
      _info "Coreboot: util/bincfg/: Compile GbE-6Series binary from settings ..."

      # create mac address setter file
      echo -e -n "${SET_DIM}" &&
        echo "$2" |
          sed -r \
            -e "s/(..)(..)(..)(..)(..)(..)/\n  \"macaddress0\" = 0x\1,\n  \"macaddress1\" = 0x\2,\n  \"macaddress2\" = 0x\3,\n  \"macaddress3\" = 0x\4,\n  \"macaddress4\" = 0x\5,\n  \"macaddress5\" = 0x\6,\n/;" \
              - > "$path_to_coreboot/util/bincfg/gbe-6series-macaddress.set" ||
                go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # create new setter file (with mac address settings)
      echo -e -n "${SET_DIM}" &&
        cp \
          "$(dirs -l +1)/../templates/i82579lmv-gbe-6series.set" \
          "$path_to_coreboot/util/bincfg/gbe-6series.set.new" &&
            sed -r -i \
              -e "s/(.*\"l1_gbedis\" = )(.*)(,)/\10x${3}\3/;" \
              -e "/.*\"macaddress5\" = .*,/r $path_to_coreboot/util/bincfg/gbe-6series-macaddress.set" \
                "$path_to_coreboot/util/bincfg/gbe-6series.set.new" \
                  1>"${opt__mute:-/dev/stdout}" ||
                    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # compile gbe
      echo -e -n "${SET_DIM}" &&
        "$path_to_coreboot/util/bincfg/bincfg" \
          "$(dirs -l +1)/../templates/i82579lmv-gbe-6series.spec" \
          "$path_to_coreboot/util/bincfg/gbe-6series.set.new" \
          "$path_to_coreboot/util/bincfg/flashregion_3_gbe.bin" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # clean up
      echo -e -n "${SET_DIM}" &&
        rm -f \
          "$path_to_coreboot/util/bincfg/gbe-6series.set.new" \
          "$path_to_coreboot/util/bincfg/gbe-6series-macaddress.set" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # file created:
      #   $path_to_coreboot/util/bincfg/flashregion_3_gbe.bin

      _pass "... GbE-6Series binary compiled."
      ;;

    'compile-gbe-ich9m')
      _info "Coreboot: util/bincfg/: Compile GbE-ICH9m binary from settings ..."

      # create mac address setter file
      echo -e -n "${SET_DIM}" &&
        echo "$2" |
          sed -r \
            -e "s/(..)(..)(..)(..)(..)(..)/\n  \"macaddress0\" = 0x\1,\n  \"macaddress1\" = 0x\2,\n  \"macaddress2\" = 0x\3,\n  \"macaddress3\" = 0x\4,\n  \"macaddress4\" = 0x\5,\n  \"macaddress5\" = 0x\6,\n/;" \
              - > "$path_to_coreboot/util/bincfg/gbe-ich9m-macaddress.set" ||
                go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # create new setter file (with mac address settings)
      echo -e -n "${SET_DIM}" &&
        cp \
          "$path_to_coreboot/util/bincfg/gbe-ich9m.set" \
          "$path_to_coreboot/util/bincfg/gbe-ich9m.set.new" &&
            sed -r -i \
              -e "s/.*\{.*/\{\n\t\"l1_gbedis\" = 0x${3},\n/;" \
              -e "/\{/r $path_to_coreboot/util/bincfg/gbe-ich9m-macaddress.set" \
                "$path_to_coreboot/util/bincfg/gbe-ich9m.set.new" \
                  1>"${opt__mute:-/dev/stdout}" ||
                    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # compile gbe
      echo -e -n "${SET_DIM}" &&
        "$path_to_coreboot/util/bincfg/bincfg" \
          "$path_to_coreboot/util/bincfg/gbe-ich9m.spec" \
          "$path_to_coreboot/util/bincfg/gbe-ich9m.set.new" \
          "$path_to_coreboot/util/bincfg/flashregion_3_gbe.bin" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # clean up
      echo -e -n "${SET_DIM}" &&
        rm -f \
          "$path_to_coreboot/util/bincfg/gbe-ich9m.set.new" \
          "$path_to_coreboot/util/bincfg/gbe-ich9m-macaddress.set" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # file created:
      #   $path_to_coreboot/util/bincfg/flashregion_3_gbe.bin

      _pass "... GbE-ICH9m binary compiled."
      ;;

    'compile-ifd-x200')
      _info "Coreboot: util/bincfg/: Compile X200 IFD binary from settings ..."

      # set locals
      local -i regions=3   # default for gbe, me, bios
      local density1=2
      local density2=2

      # set up setter file
      echo -e -n "${SET_DIM}" &&
        cp \
          "$path_to_coreboot/util/bincfg/ifd-x200.set" \
          "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      ## set chip densities
      case ${ifd[size_rom]} in
        (0x00400000)
          density1=3
          ;;

        (0x00800000)
          density1=4
          ;;

        (0x00c00000)
          density1=4
          density2=3
          ;;

        (0x01000000)
          density1=5
          ;;

        (*)
          ;;
      esac
      echo -e -n "${SET_DIM}" &&
        sed -r -i \
          -e "s/(.*flcomp_density1.*= )(.*)/\10x${density1},/;" \
          -e "s/(.*flcomp_density2.*= )(.*)/\10x${density2},/;" \
          "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      ## set/remove access permissions in BIOS and IME sections
      if [ "$opt__ifd_lock_regions" ]; then
        echo -e -n "${SET_DIM}" &&
          sed -r -i \
            -e "s/(.*flmstr1_w_fd.*= )(.*)/\1$(printf '0x%x' 0),/;" \
            -e "s/(.*flmstr1_r_me.*= )(.*)/\1$(printf '0x%x' 0),/;" \
            -e "s/(.*flmstr1_w_me.*= )(.*)/\1$(printf '0x%x' 0),/;" \
            -e "s/(.*flmstr2_w_fd.*= )(.*)/\1$(printf '0x%x' 0),/;" \
            -e "s/(.*flmstr2_r_bios.*= )(.*)/\1$(printf '0x%x' 0),/;" \
            -e "s/(.*flmstr2_w_bios.*= )(.*)/\1$(printf '0x%x' 0),/;" \
              "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
                1>"${opt__mute:-/dev/stdout}" ||
                  go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      else  # unlock regions
        echo -e -n "${SET_DIM}" &&
          sed -r -i \
            -e "s/(.*flmstr1_w_fd.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*flmstr1_r_me.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*flmstr1_w_me.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*flmstr2_w_fd.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*flmstr2_r_bios.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*flmstr2_w_bios.*= )(.*)/\1$(printf '0x%x' 1),/;" \
              "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
                1>"${opt__mute:-/dev/stdout}" ||
                  go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      fi

      ## IME and GbE section
      if [ "$arg__ime" = 'keep' ]; then
        echo -e -n "${SET_DIM}" &&
          sed -r -i \
            -e "s/(.*flreg2_base.*= )(.*)/\1$(printf '0x%x' $(((ifd[size_fd]+ifd[size_gbe])/0x1000))),/;" \
            -e "s/(.*flreg2_limit.*= )(.*)/\1$(printf '0x%x' $(((ifd[size_fd]+ifd[size_gbe]+ifd[size_me])/0x1000-0x01))),/;" \
            -e "s/(.*flmstr2_r_fd.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*flmstr2_r_me.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*flmstr2_w_me.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*flmstr2_r_gbe.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*flmstr2_w_gbe.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*flreg1_base.*= )(.*)/\1$(printf '0x%x' $(((ifd[size_fd]+ifd[size_gbe]+ifd[size_me])/0x1000))),/;" \
            -e "s/(.*flreg1_limit.*= )(.*)/\1$(printf '0x%x' $((ifd[size_rom]/0x1000-0x01))),/;" \
              "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
                1>"${opt__mute:-/dev/stdout}" ||
                  go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      else  # $arg__ime = 'none'
        echo -e -n "${SET_DIM}" &&
          sed -r -i \
            -e "s/(.*flreg1_limit.*= )(.*)/\1$(printf '0x%x' $((ifd[size_rom]/0x1000-0x01))),/;" \
              "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
                1>"${opt__mute:-/dev/stdout}" ||
                  go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      fi

      ## remove access permissions to me region (if unused)
      if [ "$arg__ime" = 'none' ]; then
        regions=$regions-1
        echo -e -n "${SET_DIM}" &&
          sed -r -i \
            -e "s/(.*flmstr2_r_.*= )(.*)/\1$(printf '0x%x' 0),/;" \
            -e "s/(.*flmstr2_w_.*= )(.*)/\1$(printf '0x%x' 0),/;" \
            -e "s/(.*_r_me.*= )(.*)/\1$(printf '0x%x' 0),/;" \
            -e "s/(.*_w_me.*= )(.*)/\1$(printf '0x%x' 0),/;" \
              "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
                1>"${opt__mute:-/dev/stdout}" ||
                  go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      fi

      ## remove access permissions to platform data region (unused)
      echo -e -n "${SET_DIM}" &&
        sed -r -i \
          -e "s/(.*_r_pd.*= )(.*)/\1$(printf '0x%x' 0),/;" \
          -e "s/(.*_w_pd.*= )(.*)/\1$(printf '0x%x' 0),/;" \
            "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
              1>"${opt__mute:-/dev/stdout}" ||
                go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      ## set/clear bit medisable
      if [ "$opt__ifd_medisable" ]; then
        echo -e -n "${SET_DIM}" &&
          sed -r -i \
            -e "s/(.*ich0_medisable.*= )(.*)/\1$(printf '0x%x' 1),/;" \
            -e "s/(.*mch0_medisable.*= )(.*)/\1$(printf '0x%x' 1),/;" \
              "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
                1>"${opt__mute:-/dev/stdout}" ||
                  go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      else
        echo -e -n "${SET_DIM}" &&
          sed -r -i \
            -e "s/(.*ich0_medisable.*= )(.*)/\1$(printf '0x%x' 0),/;" \
            -e "s/(.*mch0_medisable.*= )(.*)/\1$(printf '0x%x' 0),/;" \
              "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
                1>"${opt__mute:-/dev/stdout}" ||
                  go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      fi

      ## set/clear bit altmedisable
      if [ "$opt__ifd_altmedisable" ]; then
        echo -e -n "${SET_DIM}" &&
          sed -r -i \
            -e "s/(.*mch0_mealtdisable.*= )(.*)/\1$(printf '0x%x' 1),/;" \
              "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
                1>"${opt__mute:-/dev/stdout}" ||
                  go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      else
        echo -e -n "${SET_DIM}" &&
          sed -r -i \
            -e "s/(.*mch0_mealtdisable.*= )(.*)/\1$(printf '0x%x' 0),/;" \
              "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
                1>"${opt__mute:-/dev/stdout}" ||
                  go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      fi

      ## set regions
      echo -e -n "${SET_DIM}" &&
        sed -r -i \
          -e "s/(.*flmap0_nr.*= )(.*)/\1$(printf '0x%x' $regions),/;" \
            "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
              1>"${opt__mute:-/dev/stdout}" ||
                go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # unset locals
      unset density2
      unset density1
      unset regions

      # compile new ifd
      echo -e -n "${SET_DIM}" &&
        "$path_to_coreboot/util/bincfg/bincfg" \
          "$path_to_coreboot/util/bincfg/ifd-x200.spec" \
          "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
          "$path_to_coreboot/util/bincfg/flashregion_0_fd.bin" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # clean up
      echo -e -n "${SET_DIM}" &&
        rm -f \
          "$path_to_coreboot/util/bincfg/ifd-x200.set.new" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"

      # file created:
      #   $path_to_coreboot/util/bincfg/flashregion_0_fd.bin

      _pass "... X200 IFD binary compiled."
      ;;

    *)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${1}"
      ;;
  esac

  _funcstop "$FUNCNAME"
}


# $1: case target
# $2: source rom
# $3: modified source rom
# $4: modified descriptor binary
# $5: stripped_me binary
# $6: log file
coreboot_util_me_cleaner()
{
  _funcstart "$FUNCNAME"

  case $1 in
    ('apply-but-keep')
      _info "Coreboot: util/me_cleaner/: Run “me_cleaner.py”, but keep modules ..."
      echo -e -n "${SET_DIM}" &&
        "$path_to_coreboot/util/me_cleaner/me_cleaner.py" \
          ${opt__ifd_altmedisable:+--soft-disable-only} \
          ${opt__ifd_lock_regions:+--descriptor} \
          --keep-modules \
          --extract-me "$5" \
          --extract-descriptor "$4" \
          --output "$3" \
          "$2" \
            > "$6" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error"
      _pass "... “me_cleaner.py” successfully finished."
      ;;

    ('apply')
      _info "Coreboot: util/me_cleaner/: Run “me_cleaner.py” ..."
      echo -e -n "${SET_DIM}" &&
        "$path_to_coreboot/util/me_cleaner/me_cleaner.py" \
          ${opt__ifd_altmedisable:+--soft-disable} \
          ${opt__ifd_lock_regions:+--descriptor} \
          --relocate \
          --truncate \
          --extract-me "$5" \
          --extract-descriptor "$4" \
          --output "$3" \
          "$2" \
            > "$6" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error"
      _pass "... “me_cleaner.py” successfully finished."
      ;;

    ('check')
      _info "Coreboot: util/me_cleaner/: Run “me_cleaner.py” to check ME Firmware ..."
      echo -e -n "${SET_DIM}" &&
        "$path_to_coreboot/util/me_cleaner/me_cleaner.py" \
          --check \
          "$2" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error"
      _pass "... “me_cleaner.py” successfully finished."
      ;;

    (*)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "internal error"
      ;;
  esac

  _funcstop "$FUNCNAME"
}


# $1: case target
# $2: source file
# $3: destination file
coreboot_util_ifdtool()
{
  _funcstart "$FUNCNAME"

  case $1 in
    'make-clean')
      _info "Coreboot: util/ifdtool/: Run “make clean” ..."
      echo -e -n "${SET_DIM}" &&
        make -C $path_to_coreboot/util/ifdtool "clean" 1>"${opt__mute:-/dev/stdout}" ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      _pass "... “make clean” successfully finished."
      ;;

    'make')
      _info "Coreboot: util/ifdtool/: Run “make” ..."
      echo -e -n "${SET_DIM}" &&
        make -C $path_to_coreboot/util/ifdtool \
          1>"${opt__mute:-/dev/stdout}" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      _pass "... “make” successfully finished."
      ;;

    'extract-regions')
      _info "Coreboot: util/ifdtool/: Extract regions ..."
      [ -f $2 ] ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $2"
      echo -e -n "${SET_DIM}" &&
        $path_to_coreboot/util/ifdtool/ifdtool -x \
          $2 \
          1>"${opt__mute:-/dev/stdout}" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: ${1}"
      _pass "... regions extracted."
      ;;

    'extract-layout')
      _info "Coreboot: util/ifdtool/: Extract chip layout file ..."
      echo -e -n "${SET_DIM}" &&
        $path_to_coreboot/util/ifdtool/ifdtool -f \
          $3 \
          $2 \
          1>"${opt__mute:-/dev/stdout}" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: $1"
      _pass "... the chip layout file has been written."
      ;;

    'apply-new-layout')
      _info "Coreboot: util/ifdtool/: Create new ROM with modified flashdescriptor ..."
      echo -e -n "${SET_DIM}" &&
        $path_to_coreboot/util/ifdtool/ifdtool -n \
          $2 \
          $3 \
          1>"${opt__mute:-/dev/stdout}" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: $1"
      _pass "... a new ROM with modified flashdescriptor has been created."
      ;;

    'inject-descriptor')
      _mesg "Coreboot: util/ifdtool/: Inject Descriptor dump ..."
      echo -e -n "${SET_DIM}" &&
        $path_to_coreboot/util/ifdtool/ifdtool -i Descriptor:$2 \
          $3 \
          1>"${opt__mute:-/dev/stdout}" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: $1"
      _mesg "... the dumped Descriptor has been injected."
      ;;

    'inject-bios')
      _mesg "Coreboot: util/ifdtool/: Inject BIOS dump ..."
      echo -e -n "${SET_DIM}" &&
        $path_to_coreboot/util/ifdtool/ifdtool -i BIOS:$2 \
          $3 \
          1>"${opt__mute:-/dev/stdout}" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: $1"
      _mesg "... the dumped BIOS has been injected."
      ;;

    'apply-lock')
      _info "Coreboot: util/ifdtool/: Apply lock ..."
      echo -e -n "${SET_DIM}" &&
        $path_to_coreboot/util/ifdtool/ifdtool --lock \
          "$2" \
          1>"${opt__mute:-/dev/stdout}" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: $1"
      echo -e -n "${SET_DIM}" &&
        mv -v "$2.new" "$2" ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: $1"
      _pass "... lock applied."
      ;;

    'apply-unlock')
      _info "Coreboot: util/ifdtool/: Apply unlock ..."
      echo -e -n "${SET_DIM}" &&
        $path_to_coreboot/util/ifdtool/ifdtool --unlock \
          "$2" \
          1>"${opt__mute:-/dev/stdout}" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: $1"
      echo -e -n "${SET_DIM}" &&
        mv -v "$2.new" "$2" ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: $1"
      _pass "...un lock applied."
      ;;

    'set-AltMeDisable')  # Available with coreboot >= 4.12
      [ "$version_coreboot" != '4.8.1' ] && {
        _info "Coreboot: util/ifdtool/: Set bit AltMeDisable ..."
        echo -e -n "${SET_DIM}" &&
          $path_to_coreboot/util/ifdtool/ifdtool --altmedisable 1 \
            "$2" \
            1>"${opt__mute:-/dev/stdout}" ||
              go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: $1"
        echo -e -n "${SET_DIM}" &&
          mv -v "$2.new" "$2" ||
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "error: $1"
        _pass "... AltMeDisable bit has been set."
      }
      ;;

    *)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${1}"
      ;;
  esac

  _funcstop "$FUNCNAME"
}

# $1: target
# return 1: wrong parameter
# return 0: success
coreboot_make()
{
  _funcstart "$FUNCNAME"

  if [ "${path_to_coreboot//[^ ]}" != '' ]; then
    _warn "The Coreboot Makefile is likely to fail with paths containing white space."
    _mesg "Check messages!"
  fi
  case $1 in
    '')
      _info "Coreboot: Run “make”. This may take a while ..."
      echo -e -n "${SET_DIM}" &&
        make -C "$path_to_coreboot" 1>"${opt__mute:-/dev/stdout}" ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      _pass "... Coreboot “make” successfully finished."
      ;;

    'clean')
      _info "Coreboot: Run “make clean” ..."
      echo -e -n "${SET_DIM}" &&
        make -C "$path_to_coreboot" $1 1>"${opt__mute:-/dev/stdout}" ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      _pass "... Coreboot “make clean” successfully finished."
      ;;

    'distclean')
      _info "Coreboot: Run “make distclean” ..."
      echo -e -n "${SET_DIM}" &&
        make -C "$path_to_coreboot" $1 1>"${opt__mute:-/dev/stdout}" ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
      _pass "... Coreboot “make distclean” successfully finished."
      ;;

    *)
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown case: ${1}"
      ;;
  esac

  _funcstop "$FUNCNAME"
}

check_settings()
{
  _funcstart "$FUNCNAME"

  _info "Check settings ..."

  # Output
  [ "$DEBUG" -eq 1 ] || [ "$opt__mute" ] && {
    _dbug "${FG_MAGENTA}Output Settings ...${FG_DEFAULT}"
    [ "$DEBUG" -eq 0 ] ||
      _dbug "Debug output is activated."
    [ "$opt__mute" ] &&
      _mesg "Standard output of external processes is muted."
  }

  # Toolbox and Projects
  [ "$arg__toolbox" ] && {
    # display settings, exit if required but not set
    _dbug "${FG_MAGENTA}Toolbox, Projects and Versions ...${FG_DEFAULT}"
    # display toolbox folder
    _mesg "Toolbox Folder:${RTAB}${arg__toolbox:?${FG_RED}is not set${FG_DEFAULT}}"

    # display coreboot settings
    _mesg "${LIITEM}Path to Coreboot:${RTAB}${path_to_coreboot:?${FG_RED}is not set${FG_DEFAULT}}"
    _dbug "${LIITEM}Coreboot Version:${RTAB}${version_coreboot:?${FG_RED}is not set${FG_DEFAULT}}"

    # display seabios folder and version
    # FIXME: Test GRUB2 Configuration and decide whether SeaBIOS is required.
    _mesg "${LIITEM}Path to SeaBIOS:${RTAB}${path_to_seabios:?${FG_RED}is not set${FG_DEFAULT}}"
    _dbug "${LIITEM}SeaBIOS Version:${RTAB}${version_seabios:?${FG_RED}is not set${FG_DEFAULT}}"
  }

  # Factory
  [ "$opt__target" ] && {
    _dbug "${FG_MAGENTA}Factory Settings ...${FG_DEFAULT}"

    ## check arg__rom_factory
    if [ "$arg__rom_factory" ]; then
      case "$arg__target" in
        't500')
          ;&

        't400'|'t400s')
          ;&

        'x200'|'x200s'|'x200t')
          if [ "$arg__ime" = 'keep' -o "$arg__gbe" = 'keep' ]; then
            _mesg "Factory ROM, provided for backup and usage of extracted blobs:"
          else
            _mesg "Factory ROM, provided for backup usage only:"
          fi
          ;;

        'x201')
          ;&

        'x220'|'x220i'|'t420'|'t420s'|'t520'|'t520i')
          ;&

        'x1_carbon_gen1'|'x230'|'x230t'|'t430'|'t530'|'w530')
          ;&

        'x230s'|'t430s')
          _mesg "Factory ROM, provided for backup and usage of extracted blobs:"
          ;;

        *)
          _mesg "Factory ROM, provided for backup usage only:"
          ;;
      esac
      _mesg "${INDENT}${FG_YELLOW}$arg__rom_factory${FG_DEFAULT}"
    else
      case "$arg__target" in
        't500')
          ;&

        't400'|'t400s')
          ;&

        'x200'|'x200s'|'x200t')
          [ "$arg__ime" = 'keep' ] &&
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" " missing option: --rom-factory"
          ;;

        'x201')
          ;&

        'x220'|'x220i'|'t420'|'t420s'|'t520'|'t520i')
          ;&

        'x1_carbon_gen1'|'x230'|'x230t'|'t430'|'t530'|'w530')
          ;&

        'x230s'|'t430s')
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "missing option: --rom-factory"
          ;;

        *)
          _mesg "Factory ROM:${RTAB}not provided"
          ;;
      esac
    fi

    ## check arg__rom_vga
    [ "$arg__rom_vga" ] && {
      case "$arg__target" in
        't60_ati_mobility_radeon_x1300')
          ;&

        't60_ati_mobility_radeon_x1400')
          ;&

        't520')
          ;&

        'x230')
          _mesg "VGA Option ROM, provided for backup and blob usage:"
          ;;

        *)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-vga: option not yet supported for ${arg__target}"
          ;;
      esac
      _mesg "${INDENT}${FG_YELLOW}$arg__rom_vga${FG_DEFAULT}"
    }
  }

  # Configuration
  [ "$opt__target" ] && {
    ## Target
    _dbug "${FG_MAGENTA}Target Settings ...${FG_DEFAULT}"

    ### check target (target, chipsize, ime)
    case "$arg__target" in
      't60_ati_mobility_radeon_x1300'|'t60_ati_mobility_radeon_x1400')
        [ "$arg__rom_vga" ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "VGA ROM not specified."
        ;&

      't60')
        ;&

      'x60_32bit'|'x60s_32bit'|'x60t_32bit')
        ;&

      'x60'|'x60s'|'x60t')
        arg__chipsize="${arg__chipsize:=2mb}"
        [ "$arg__chipsize" = '2mb' ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "chipsize mismatch: $arg__chipsize"
        ifd=ifd_none_2mb
        [ "$arg__ime" != '' ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ime: not applicable"
        ;;

      't500')
        ;&

      't400'|'t400s')
        ;&

      'x200'|'x200s'|'x200t')
        [ "$arg__chipsize" ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--chipsize: not specified"
        case "$arg__chipsize" in
          '4mb')
            ifd=ifd_x00_4mb
            ;;

          '8mb')
            ifd=ifd_x00_8mb
            ;;

          '16mb')
            ifd=ifd_x00_16mb
            ;;

          *)
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "chipsize mismatch: $arg__chipsize"
            ;;
        esac
        arg__ime="${arg__ime:=none}"
        case "$arg__ime" in
          'keep')
            ;;

          'none')
            ;;

          *)
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ime: wrong option $arg__ime"
            ;;
        esac
        ;;

      'x201')
        ;&

      'x220'|'x220i'|'t420'|'t420s'|'t520'|'t520i')
        arg__chipsize="${arg__chipsize:=8mb}"
        [ "$arg__chipsize" = '8mb' ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "chipsize mismatch: $arg__chipsize"
        ifd=ifd_x20_8mb
        arg__ime="${arg__ime:=trunc}"
        case "$arg__ime" in
          'keep'|'trunc'|'xtrunc')
            ;;

          *)
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ime: wrong option $arg__ime"
            ;;
        esac
        ;;

      'x1_carbon_gen1'|'x230'|'x230t'|'t430'|'t530'|'w530')
        arg__chipsize="${arg__chipsize:=12mb}"
        [ "$arg__chipsize" = '12mb' ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "chipsize mismatch: $arg__chipsize"
        ifd=ifd_x30_12mb
        arg__ime="${arg__ime:=trunc}"
        case "$arg__ime" in
          'keep'|'trunc'|'xtrunc')
            ;;

          *)
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ime: wrong option $arg__ime"
            ;;
        esac
        ;;

      'x230s'|'t430s')
        arg__chipsize="${arg__chipsize:=16mb}"
        [ "$arg__chipsize" = '16mb' ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "chipsize mismatch: $arg__chipsize"
        ifd=ifd_x30_16mb
        arg__ime="${arg__ime:=trunc}"
        case "$arg__ime" in
          'keep'|'trunc'|'xtrunc')
            ;;

          *)
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ime: wrong option $arg__ime"
            ;;
        esac
        ;;
    esac
    _mesg "Target:${RTAB}${arg__target:?${FG_RED}is not set${FG_DEFAULT}}"
    _mesg "${LIITEM}SPI Chip Size:${RTAB}${arg__chipsize:?${FG_RED}is not set${FG_DEFAULT}}"

    ## Firmware
    _dbug "${FG_MAGENTA}Firmware Settings ...${FG_DEFAULT}"
    _mesg "Firmware:"

    ### check opt__ifd_lock_regions
    [ "$opt__ifd_lock_regions" ] && {
      case "$arg__ime" in
        'keep'|'trunc'|'xtrunc'|'none')
          ;;

        *)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ifd-lock-regions: incompatible option"
          ;;
      esac
      _mesg "${LIITEM}IFD:${RTAB}remove selected region access permissions"
    }

    ### check opt__ifd_medisable
    [ "$opt__ifd_medisable" ] && {
      case "$arg__target" in
        ('x200'|'x200s'|'x200t'|'t400'|'t400s'|'t500')
          ;;

        (*)
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ifd-medisable: wrong target"
          ;;
      esac
      _mesg "${LIITEM}IFD:${RTAB}set bit MeDisable"
    }

    ### check opt__ifd_altmedisable
    [ "$opt__ifd_altmedisable" ] && {
      _mesg "${LIITEM}IFD:${RTAB}set bit AltMeDisable"
    }

    ### report ime
    [ "$arg__ime" ] && {
      if [ "$arg__ime" = 'keep' -o "$arg__ime" = 'trunc' -o "$arg__ime" = 'xtrunc' ]; then
        _mesg "${LIITEM}IME:${RTAB}${FG_YELLOW}${arg__ime}${FG_DEFAULT}"
      else
        _mesg "${LIITEM}IME:${RTAB}${arg__ime}"
      fi
    }

    ### check gbe option
    case "${arg__target}" in
      'x220'|'x220i')           ;&
      't420'|'t420s')           ;&
      't520')                   ;&
      't520i')                  ;&
      'w530')                   ;&
      't530')                   ;&
      't430')                   ;&
      'x230s'|'t430s')          ;&
      'x230'|'x230t')           ;&
      't500')                   ;&
      't400'|'t400s')           ;&
      'x200'|'x200s'|'x200t')
        case "${arg__gbe,,}" in
          'keep') ;;
          'disable') ;;
          'set_000000000000') go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "MAC Address 00:00:00:00:00:00 shall not be used." ;;
          set_[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]) ;;
          *) go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "wrong or missing GbE option" ;;
        esac
        ;;

      'x201')
        case "$arg__gbe" in
          'keep') ;;
          *) go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "wrong or missing GbE option" ;;
        esac
        ;;

      *)
        [ "$arg__gbe" ] && go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--gbe: incompatible option"
        ;;
    esac
    [ "$arg__gbe" ] && _mesg "${LIITEM}GbE:${RTAB}${arg__gbe}"

    ## Coreboot
    _dbug "${FG_MAGENTA}Coreboot Settings ...${FG_DEFAULT}"
    _mesg "Coreboot:"

    ### check --microcode
    if [ "$opt__microcode" ]; then
      _mesg "${LIITEM}CPU Microcode Update:${RTAB}${FG_YELLOW}yes${FG_DEFAULT}"
    else
      case "$arg__target" in
        't60'|'t60_ati_mobility_radeon_x1300'|'t60_ati_mobility_radeon_x1400')
          ;&

        'x60_32bit'|'x60s_32bit'|'x60t_32bit')
          ;&

        'x60'|'x60s'|'x60t')
          ;&

        'x200'|'x200s'|'x200t')
          ;&

        't400'|'t400s')
          ;&

        't500')
          ;&

        't420')
          _mesg "${LIITEM}CPU Microcode Update:${RTAB}none"
          ;;

        *)
          _warn "${LIITEM}CPU Microcode Update:${RTAB}none, be aware!"
          _warn "${RTAB}Your machine might freeze."
          _mesg "${RTAB}Please consider to abort and reconfigure."
          _mesg "${RTAB}Alternatively, load updates via Operating System."
          ;;
      esac
    fi

    ### report tpm
    [ "$par__tpm" ] &&
      _mesg "${LIITEM}TPM:${RTAB}basic support"

    ## GRUB2 Payload
    _dbug "${FG_MAGENTA}GRUB2 Payload Settings ...${FG_DEFAULT}"
    _mesg "GRUB2 Payload:"

    ### check and display grub payload folder, files and version
    _mesg "${LIITEM}Payload Dir:${RTAB}${arg__payload_grub_dir:?${FG_RED}is not set${FG_DEFAULT}}"
    _mesg "${LIITEM}Payload ELF:${RTAB}${arg__payload_grub:?${FG_RED}is not set${FG_DEFAULT}}"
    _dbug "${LIITEM}Version:${RTAB}${version_grub:?${FG_RED}is not set${FG_DEFAULT}}"
    grub_config="${GRUB_CONFIG/\$\{version_grub\}/${version_grub}}"
    [ -f "${arg__payload_grub_dir}/${grub_config}" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: ${arg__payload_grub_dir}/${grub_config}"
    _mesg "${LIITEM}Config File:${RTAB}${grub_config}"

    #### report GRUB keymap
    grub_keymap="$(sed -r -e '/^\tkeymap/!d;' -e 's/^\tkeymap.* //;' ${arg__payload_grub_dir}/${grub_config})"
    _mesg "${INDENT}keymap:${RTAB}${grub_keymap}"

    #### report GRUB antifreeze
    if [ -n "$(sed -r -e '/intel_idle.max_cstate=?/!d;' ${arg__payload_grub_dir}/${grub_config})" ]; then
      _mesg "${INDENT}Antifreeze:${RTAB}enabled"
    else
      if [ "$arg__target" = 't520' -o "$arg__target" = 't520i' ]; then
        _warn "${INDENT}Antifreeze should be enabled for ${arg_target}!"
      fi
    fi

    #### report GRUB authorization
    if [ "$(sed -r -e '/^\tset superusers=/!d;' ${arg__payload_grub_dir}/${grub_config})" ]; then
      grub_auth=1
      _mesg "${INDENT}authorization:${RTAB}configured"
    else
      _mesg "${INDENT}authorization:${RTAB}not configured"
    fi

    #### set/report GRUB background images
    declare bg
    declare -i i=0
    while [ $i -lt ${#BACKGROUND_CBFS[@]} ];
    do
      bg="$(echo ${arg__payload_grub_dir}/${GRUB_BG/\$\{ibg\}/$i}.*)"
      if [ -f "$bg" ]; then
        grub_background[$i]="$bg"
        _mesg "${INDENT}${bg##*/}:${RTAB}${SET_BOLD}`ls -l $bg | sed -r -e 's/(^.* )(.* -> )(.*)/\3/;' -`${CLR_INTENSITY}"
        i+=1
      else
        break 1
      fi
    done
    unset i
    unset bg

    #### check GRUB Morse Feedback configuration
    declare test_config=
    test_config="$(sed -r -e '/Morse/,/\}/!d;' ${arg__payload_grub_dir}/${grub_config})"
    if [ "$test_config" != '' ]; then
      grub_config_morse="${GRUB_CONFIG_MORSE/\$\{version_grub\}/${version_grub}}"
      [ -f "${arg__payload_grub_dir}/${grub_config_morse}" ] ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "GRUB Morse Feedback: no such file: ${arg__payload_grub_dir}/${grub_config_morse}"
      _mesg "${INDENT}menu entry Morse:${RTAB}configured"
      case "$arg__target" in
        'x1_carbon_gen1'|'x230'|'x230t'|'x230s'|'t430'|'t530'|'w530'|'t430s')  # Hmm, GRUB2 has no audio. Why??
          _warn "GRUB2’s access to audio on $arg__target will likely fail, please check!"
          ;;
      esac
      _mesg "${INDENT}Morse Config File:${RTAB}${grub_config_morse}"
    else
      _mesg "${INDENT}menu entry Morse:${RTAB}not configured"
    fi
    unset test_config

    #### check/set SeaBIOS configuration
    declare test_config=
    test_config="$(sed -r -e '/[sS]ea[bB][iI][oO][sS]/,/\}/!d;' ${arg__payload_grub_dir}/${grub_config})"
    if [ "$test_config" ]; then
      par__seabios=1
      _mesg "${INDENT}menu entry SeaBIOS:${RTAB}configured"

      ## SeaBIOS
      _dbug "${INDENT}${FG_MAGENTA}SeaBIOS Settings ...${FG_DEFAULT}"
      [ -f "${SEABIOS_CONFIG/\$\{path_to_seabios\}/$path_to_seabios}" ] ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "file not found: SeaBIOS configuration"
      [ "$arg__rom_vga" ] &&
        [ -f "${SEABIOS_VGABIOS/\$\{path_to_seabios\}/$path_to_seabios}" ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-vga: SeaBIOS configuration mismatch"
      _mesg "${INDENT}${LIITEM}Config File:${RTAB}${SEABIOS_CONFIG/\$\{path_to_seabios\}/$path_to_seabios}"
      [ -f "${SEABIOS_PAYLOAD/\$\{path_to_seabios\}/$path_to_seabios}" ] ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "file not found: SeaBIOS payload"
      _mesg "${INDENT}${LIITEM}Payload File:${RTAB}${SEABIOS_PAYLOAD/\$\{path_to_seabios\}/$path_to_seabios}"
      [ "$arg__rom_vga" ] || {
        [ -f "${SEABIOS_VGABIOS/\$\{path_to_seabios\}/$path_to_seabios}" ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "file not found: SeaBIOS VGA BIOS"
        _mesg "${INDENT}${LIITEM}VGA-ROM:${RTAB}${SEABIOS_VGABIOS/\$\{path_to_seabios\}/$path_to_seabios}"
      }

    else
      par__seabios=''
      _mesg "${INDENT}menu entry SeaBIOS:${RTAB}not configured"
    fi
    unset test_config

    #### check/set Coreinfo configuration
    declare test_config=
    test_config="$(sed -r -e '/Coreinfo/,/\}/!d;' ${arg__payload_grub_dir}/${grub_config})"
    if [ "$test_config" ]; then
      par__coreinfo=1
      _mesg "${INDENT}menu entry Coreinfo:${RTAB}configured"
    else
      par__coreinfo=''
      _mesg "${INDENT}menu entry Coreinfo:${RTAB}not configured"
    fi
    unset test_config

    #### check/set NVRAMCUI configuration
    declare test_config=
    test_config="$(sed -r -e '/NVRAMCUI/,/\}/!d;' ${arg__payload_grub_dir}/${grub_config})"
    if [ "$test_config" ]; then
      par__nvramcui=1
      _mesg "${INDENT}menu entry NVRAMCUI:${RTAB}configured"
    else
      par__nvramcui=''
      _mesg "${INDENT}menu entry NVRAMCUI:${RTAB}not configured"
    fi
    unset test_config

    #### check/set Memtest86 configuration
    declare test_config=
    test_config="$(sed -r -e '/Memtest86/,/\}/!d;' ${arg__payload_grub_dir}/${grub_config})"
    if [ "$test_config" ]; then
      par__memtest86=1
      _mesg "${INDENT}menu entry Memtest86+:${RTAB}configured"
    else
      par__memtest86=''
      _mesg "${INDENT}menu entry Memtest86+:${RTAB}not configured"
    fi
    unset test_config

    #### check/set Tint configuration
    declare test_config=
    test_config="$(sed -r -e '/Tint/,/\}/!d;' ${arg__payload_grub_dir}/${grub_config})"
    if [ "$test_config" ]; then
      par__tint=1
      _mesg "${INDENT}menu entry Tint:${RTAB}configured"
    else
      par__tint=''
      _mesg "${INDENT}menu entry Tint:${RTAB}not configured"
    fi
    unset test_config

    ## Templates
    _dbug "${FG_MAGENTA}Template Files and Folders ...${FG_DEFAULT}"
    _mesg "Templates:"

    ### config file
    name_config "$arg__target" "$version_coreboot" "${par__tpm:+tpm}" '-' template_config
    _dbug "${LIITEM}Config File:${RTAB}${FG_BLUE}${template_config}${FG_DEFAULT}"
    [ -f $template_config ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $template_config"

    ### target folder
    set_template_target_folder 'template_target_folder'
    _mesg "${LIITEM}Target Folder:${RTAB}${FG_BLUE}$template_target_folder${FG_DEFAULT}"
    _mesg "\
Upon creation of the target folder,
the “${TEMP_SUFFIX}” suffix will be replaced by a random, unique pattern of digits,
and your final ${ROM_ZEROCAT} will be located within that folder."
  }
  _pass "... settings checked."

  _funcstop "$FUNCNAME"
}

# $1: specfile variable, name reference
write_specfile()
{
  _funcstart "$FUNCNAME"

  declare bullet='* '
  declare specfile="${1}"
  declare -a speclist=()

  # start speclist
  speclist+="# ROM Configuration Details\n\n\n"
  speclist+="${bullet}File ${specfile%\/*}/${ROM_ZEROCAT}\n"

  # list intel firmare specific markers
  speclist+="\n\n## Intel Flash Descriptor\n\n\n"
  if [ "$opt__ifd_lock_regions" -o "$opt__ifd_altmedisable" -o "$opt__ifd_medisable" ]; then
    speclist+="${bullet}ifd"
    speclist+="${opt__ifd_lock_regions:+${c}${opt__ifd_lock_regions}}"
    speclist+="${opt__ifd_medisable:+${c}medisable}"
    speclist+="${opt__ifd_altmedisable:+${c}altmedisable}"
    speclist+="\n"
  fi
  speclist+="\n\n## Intel Firmware\n\n\n"
  speclist+="${arg__ime:+${bullet}ime${c}${arg__ime}\n}"
  speclist+="${arg__gbe:+${bullet}gbe${c}${arg__gbe}\n}"

  # add coreboot specs
  speclist+="\n\n## Coreboot File System\n\n\n"
  speclist+="${bullet}coreboot@${version_coreboot}\n"
  speclist+="${opt__microcode:+${bullet}CPU microcode binary blob\n}"

  ## add tpm configuration
  speclist+="${par__tpm:+${bullet}TPM not disabled\n}"

  ## add vgarom configuration
  speclist+="${arg__rom_vga:+${bullet}VGAROM included\n}"

  ## add payload configuration: primary payload
  speclist+="\n\n### Primary Payload\n\n\n"
  speclist+="${bullet}grub@${version_grub}\n"
  speclist+="${grub_keymap:+${bullet}keymap ${grub_keymap}\n}"
  for i in ${!grub_background[@]}; do
    speclist+="${grub_background[$i]:+${bullet}background${i}\n}"
  done
  speclist+="${grub_auth:+${bullet}authorization scheme enabled\n}"
  speclist+="${grub_config_morse:+${bullet}morse feature\n}"

  ## add payload configuration: secondary payloads
  speclist+="\n\n### Secondary Payloads\n\n\n"
  [ "$par__seabios" ] && {
    speclist+="${bullet}SeaBIOS@${version_seabios}"
    speclist+="${arg__rom_vga:+${c}novgabios}"
    speclist+="\n"
  }
  speclist+="${par__coreinfo:+${bullet}Coreinfo\n}"
  speclist+="${par__nvramcui:+${bullet}NVRAMCUI\n}"
  speclist+="${par__memtest86:+${bullet}Memtest86\+\n}"
  speclist+="${par__tint:+${bullet}Tint Game\n}"

  echo -e \
    "${speclist}" \
      > "${specfile}" ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  _funcstop "$FUNCNAME"
}

# $1: template_target_folder variable, name reference
set_template_target_folder()
{
  _funcstart "$FUNCNAME"

  declare -r c='_'    # spec combinator level1
  declare -i i        # loop variable
  declare -a fname=()
  declare -n destdir=${1}
  # declared in main():
  #   version_coreboot
  #   version_seabios
  #   version_grub

  # set template_target_folder
  fname+="${arg__target}"
  fname+="${arg__chipsize:+${c}${arg__chipsize}}"

  ## add temporary suffix
  destdir="${fname[*]}.${TEMP_SUFFIX}"

  _funcstop "$FUNCNAME"
}

# $1: path to project
# $2: project version to match
check_version()
{
  _funcstart "$FUNCNAME"

  [ -d $1 ] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such directory: $1"
  local cwd=$(pwd)
  cd $1
  cver=$(git describe --tags)
  cd "$cwd"
  [ "$cver" != "$2" ] &&
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "$cver does not match $2"
  _pass "Version $cver matches $2."

  _funcstop "$FUNCNAME"
}

fallback_ROM()
{
  _funcstart "$FUNCNAME"

  _info "Create Fallback ROM ... "
  pushd $path_to_coreboot &>/dev/null

  coreboot_util_ifdtool 'inject-bios' \
    "${bin_folder##*/}/flashregion_1_bios.bin" \
    "build/coreboot.rom"

  echo -e -n "${SET_DIM}" &&
    mv -v build/coreboot.rom.new ${bin_folder##*/}/fallback.rom ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  popd &>/dev/null
  _pass "... Fallback ROM created."

  _funcstop "$FUNCNAME"
}

rom_split()
{
  _funcstart "$FUNCNAME"

  [ -f $target_folder/${ROM_ZEROCAT} ] ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "no such file: $target_folder/${ROM_ZEROCAT}"

  dd \
    if=$target_folder/${ROM_ZEROCAT} \
    of=$target_folder/${ROM_ZEROCAT/%/.bottom} \
    bs=1M count=8 &>/dev/null ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
  dd \
    if=$target_folder/${ROM_ZEROCAT} \
    of=$target_folder/${ROM_ZEROCAT/%/.top} \
    bs=1M skip=8 &>/dev/null ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"

  _pass "The ROM has successfully been split into top (4MB) and bottom (8MB) ROM."

  _funcstop "$FUNCNAME"
}

checksum_create()
{
  _funcstart "$FUNCNAME"

  declare files=
  declare i=

  _info "Create checksum files ..."
  pushd $target_folder &>/dev/null
  for i in ./*; do
    [ -f $i ] &&
      files+=" $i"
  done
  sha512sum $files > SHA512SUM.txt ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
  pushd ${bin_folder/*\//} &>/dev/null
  sha512sum ./* > SHA512SUM.txt ||
    go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO"
  popd &>/dev/null
  popd &>/dev/null
  _pass "... checksum files have been created."

  _funcstop "$FUNCNAME"
}

congratulations()
{
  _funcstart "$FUNCNAME"

  _pass "Your ${ROM_ZEROCAT} has been built."
  _mesg "Check the folder and keep it in a safe place:"
  _mesg "${INDENT}$target_folder"
  if [ -f "$target_folder/${bin_folder##*/}/fallback.rom" ]; then
    _mesg "In case your ${arg__target^^} crashes, you might want to try the fallback:"
    _mesg "${INDENT}${bin_folder##*/}/fallback.rom"
  fi

  _funcstop "$FUNCNAME"
}

# $1: arg__target
generate_rom()
{
  _funcstart "$FUNCNAME"

  declare -r template_bin_folder="binaries.${TEMP_SUFFIX}"
  declare bin_folder=

  # first step to do for all targets
  # targets have been checked to be valid in parse_cmdline()
  coreboot_make 'distclean'
  coreboot_binaries 'populate-temporary-folder'   # defines value of $bin_folder

  # next steps to do depend on target
  case $1 in
    'x60_32bit'|'x60s_32bit'|'x60t_32bit')
      ;&

    'x60'|'x60s'|'x60t')
      ;&

    't60'|'t60_ati_mobility_radeon_x1300'|'t60_ati_mobility_radeon_x1400')
      # coreboot config
      coreboot_config 'init-configfile'
      coreboot_config 'monolithic-firmware-layout'

      # coreboot build
      coreboot_make 'clean'
      coreboot_make ''

      # populate target folder
      populate_target
      copy_file "${arg__payload_grub_dir}/${grub_config}" "${target_folder}/${grub_config}"
      [ "$grub_config_morse" ] && copy_file "${arg__payload_grub_dir}/${grub_config_morse}" "${target_folder}/${grub_config_morse}"

      # edit cbfs content
      cbfs_add_file "${target_folder}/${REV_ZEROCAT}" "${REV_ZEROCAT}"
      cbfs_add_file "${arg__payload_grub_dir}/${grub_config}" "etc/${grub_config##*_}"
      [ "$grub_config_morse" ] && cbfs_add_file "${arg__payload_grub_dir}/${grub_config_morse}" "etc/${grub_config_morse##*_}"
      [ "$par__coreinfo" ] && cbfs_move_payloads "coreinfo"
      [ "$par__nvramcui" ] && cbfs_move_payloads "nvramcui"
      [ "$par__memtest86" ] && cbfs_move_payloads 'memtest86+'
      [ "$par__tint" ] && cbfs_move_payloads 'tint'
      [ "$par__seabios" ] && cbfs_add_seabios
      cbfs_add_background
      tweak_nvram 'set-gfx' '64M'
      tweak_nvram 'no-bluetooth'
      tweak_nvram 'no-wwan'
      tweak_nvram 'info'

      # display cbfs content
      [ "$opt__mute" ] || {
        print_cbfs
        print_nvram
      }
      ;;

    't500')
      ;&

    't400'|'t400s')
      ;&

    'x200'|'x200s'|'x200t')
      # prepare binaries
      coreboot_binaries 'compile-coreboot-utilities'
      coreboot_binaries 'GbE-binary'
      [ "$arg__ime" = 'keep' -o "$arg__gbe" = 'keep' ] &&
        coreboot_binaries 'extract-factory-regions'
      coreboot_util_bincfg 'compile-ifd-x200'
      mv \
        "${path_to_coreboot}/util/bincfg/flashregion_0_fd.bin" \
        "${bin_folder}/flashregion_0_flashdescriptor.bin.new"

      # coreboot configure
      coreboot_config 'init-configfile'
      case "$arg__ime" in
        ('keep')  coreboot_config 'x00-firmware-layout-with-IME'      ;;
        ('none')  coreboot_config 'x00-firmware-layout-without-IME'   ;;
      esac

      # coreboot build
      coreboot_make 'clean'
      coreboot_make ''

      # hmm, descriptor seems to have been touched by coreboot@4.8.1, re-inject
      if [ "$version_coreboot" = '4.8.1' ]; then
        dd \
          if="${bin_folder}/flashregion_0_flashdescriptor.bin.new" \
          of="${path_to_coreboot}/build/coreboot.rom" \
          bs=4K \
          count=1 \
          seek=0 \
          skip=0 \
          conv=nocreat,notrunc,sync
      fi

      # populate target folder
      populate_target
      copy_file "${arg__payload_grub_dir}/${grub_config}" "${target_folder}/${grub_config}"
      [ "$grub_config_morse" ] && copy_file "${arg__payload_grub_dir}/${grub_config_morse}" "${target_folder}/${grub_config_morse}"

      # edit cbfs content
      cbfs_add_file "${target_folder}/${REV_ZEROCAT}" "${REV_ZEROCAT}"
      cbfs_add_file "${arg__payload_grub_dir}/${grub_config}" "etc/${grub_config##*_}"
      [ "$grub_config_morse" ] && cbfs_add_file "${arg__payload_grub_dir}/${grub_config_morse}" "etc/${grub_config_morse##*_}"
      [ "$par__coreinfo" ] && cbfs_move_payloads "coreinfo"
      [ "$par__nvramcui" ] && cbfs_move_payloads "nvramcui"
      [ "$par__seabios" ] && cbfs_add_seabios
      cbfs_add_background
      tweak_nvram 'set-gfx' '256M'
      tweak_nvram 'no-bluetooth'
      tweak_nvram 'no-wwan'
      tweak_nvram 'info'

      # display cbfs content
      [ "$opt__mute" ] || {
        print_cbfs
        print_nvram
      }
      ;;

    'x201')
      ;&

    'x220'|'x220i'|'t420'|'t420s')
      ;&

    't520')   # T520: coreboot bios crashes sometimes, fallback ROM needed
      ;&

    't520i')
      ;&

    'x1_carbon_gen1')
      ;&

    'x230'|'x230t'|'t430'|'t530'|'w530')
      ;&

    'x230s'|'t430s')
      # prepare binaries
      coreboot_binaries 'compile-coreboot-utilities'
      coreboot_binaries 'extract-factory-regions'
      [ "$1" != 'x1_carbon_gen1' ] && coreboot_binaries 'GbE-binary'
      case "$arg__ime" in
        ('keep')
          coreboot_binaries 'me_cleaner-keep'
          ;;

        ('trunc')
          coreboot_binaries 'me_cleaner'
          coreboot_binaries 'size-IME-binary'
          coreboot_binaries 'truncated-IME-binary'
          coreboot_binaries 'descriptor-for-truncated-IME'
          ;;

        ('xtrunc')
          coreboot_binaries 'me_cleaner'
          coreboot_binaries 'size-IME-binary-extra'
          coreboot_binaries 'truncated-IME-binary'
          coreboot_binaries 'descriptor-for-truncated-IME'
          ;;
      esac

      # coreboot configure
      coreboot_config 'init-configfile'
      case "$arg__ime" in
        ('keep')    coreboot_config 'xx0-firmware-layout-with-IME' ;;
        ('trunc')   ;&
        ('xtrunc')  coreboot_config 'xx0-firmware-layout-with-truncated-IME' ;;
      esac

      # coreboot build
      coreboot_make 'clean'
      coreboot_make ''

      # apply options
      if [ "$opt__ifd_lock_regions" ]; then
        if [ "$version_coreboot" = '4.8.1' ]; then
          coreboot_util_ifdtool \
            'apply-lock' \
            "$path_to_coreboot/build/coreboot.rom"
        fi
      else
        coreboot_util_ifdtool \
          'apply-unlock' \
          "$path_to_coreboot/build/coreboot.rom"
      fi

      # final check
      coreboot_util_me_cleaner \
        'check' \
        "$path_to_coreboot/build/coreboot.rom"

      # fallback ROM?
      if [ "$1" = 't520' -o "$1" = 't520i' ]; then    # T520: inject vendor’s bios and create a fallback ROM
        fallback_ROM
      fi

      # populate target folder
      populate_target
      copy_file "${arg__payload_grub_dir}/${grub_config}" "${target_folder}/${grub_config}"
      [ "$grub_config_morse" ] && copy_file "${arg__payload_grub_dir}/${grub_config_morse}" "${target_folder}/${grub_config_morse}"

      # edit cbfs content
      cbfs_add_file "${target_folder}/${REV_ZEROCAT}" "${REV_ZEROCAT}"
      cbfs_add_file "${arg__payload_grub_dir}/${grub_config}" "etc/${grub_config##*_}"
      [ "$grub_config_morse" ] && cbfs_add_file "${arg__payload_grub_dir}/${grub_config_morse}" "etc/${grub_config_morse##*_}"
      [ "$par__coreinfo" ] && cbfs_move_payloads "coreinfo"
      [ "$par__nvramcui" ] && cbfs_move_payloads "nvramcui"
      [ "$par__memtest86" ] && cbfs_move_payloads "memtest86"
      [ "$par__tint" ] && cbfs_move_payloads "tint"
      [ "$par__seabios" ] && cbfs_add_seabios
      cbfs_add_background
      if [ "$1" = 'x201' ]; then
        tweak_nvram 'set-gfx' '128M'
      else
        tweak_nvram 'set-gfx' '224M'
      fi
      tweak_nvram 'no-bluetooth'
      tweak_nvram 'no-wwan'
      tweak_nvram 'info'

      # display cbfs content
      [ "$opt__mute" ] || {
        print_cbfs
        print_nvram
      }

      # split rom
      case $1 in
        'x1_carbon_gen1'|'x230'|'x230t'|'t430'|'t530'|'w530')
          rom_split
          ;;
      esac
      ;;
  esac

  verify_ifd
  checksum_create
  congratulations

  _funcstop "$FUNCNAME"
}

check_options()
{
  _funcstart "$FUNCNAME"

  _info "Check options ..."

  # --debug

  # --mute

  # --microcode
  [ "$opt__microcode" ] && {
    [ "$opt__target" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--microcode: incomplete set of command line options"
  }

  # --chipsize
  [ "$arg__chipsize" ] && {
    [ "$opt__target" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--chipsize: incomplete set of command line options"
  }

  # --ime
  [ "$arg__ime" ] && {
    [ "$opt__target" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ime: incomplete set of command line options"
  }

  # --gbe
  [ "$arg__gbe" ] && {
    [ "$opt__target" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--gbe: incomplete set of command line options"
  }

  # --rom-vga
  [ "$arg__rom_vga" ] && {
    [ "$opt__target" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-vga: incomplete set of command line options"
  }

  # --ifd-lock-regions
  [ "$opt__ifd_lock_regions" ] && {
    [ "$opt__target" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ifd-lock-regions: incomplete set of command line options"
  }

  # --rom-factory
  [ "$arg__rom_factory" ] && {
    [ "$opt__target" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-factory: incomplete set of command line options"
  }

  # --payload-grub-dir
  [ "$arg__payload_grub_dir" ] && {
    [ "$opt__target" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--payload-grub-dir: incomplete set of command line options"
  }

  # --toolbox
  [ "$arg__toolbox" ] && {
    [ "$opt__target" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--toolbox: incomplete set of command line options"
  }

  # --usage | --help

  # --clean

  # --remove-all

  # --target
  [ "$opt__target" ] && {
    [ "$arg__toolbox" ] && [ "$arg__payload_grub_dir" ] ||
      go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--target: incomplete set of command line options"
    [ "$arg__target" = 't60_ati_mobility_radeon_x1300' -o "$arg__target" = 't60_ati_mobility_radeon_x1400' ] && {
      [ "$arg__rom_vga" ] ||
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--target: incomplete set of command line options"
    }
  }

  _pass "... options checked."

  _funcstop "$FUNCNAME"
}

parse_cmdline()
{
  _funcstart "$FUNCNAME"

  declare -i n=
  declare opt=

  _info "Parse command line ..."
  while [ $# -gt 0 ]; do
    opt=${1:?${FG_RED}missing parameter${FG_DEFAULT}}
    n=1
    opt=${opt,,}
    case $opt in
      # parameters
      '--debug')
        # no action here, see bottom of script
        ;;

      '--mute')
        opt__mute="/dev/null"
        ;;

      '--toolbox')
        [ "$arg__toolbox" ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--toolbox: duplicate option"
        [ "${2:0:2}" = '--' ] || [ "${2}" = '' ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--toolbox: missing argument"
        opt="$2"
        n+=1
        pushd "$opt" &>/dev/null ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--toolbox: no such directory: ${opt}"
        arg__toolbox=$(dirs -l +0)
        popd &>/dev/null

        path_to_coreboot=$(echo "${arg__toolbox}"/coreboot[-@${FVS}]*/)
        select_option path_to_coreboot
        if [ -d "$path_to_coreboot" ]; then
          version_coreboot="${path_to_coreboot##*\/coreboot[-@${FVS}]}"
          version_coreboot="${version_coreboot%\/}"
        else
          path_to_coreboot=''
          version_coreboot=''
        fi

        path_to_seabios=$(echo "${arg__toolbox}"/seabios[-@${FVS}]*/)
        select_option path_to_seabios
        if [ -d "$path_to_seabios" ]; then
          version_seabios="${path_to_seabios##*\/seabios[-@${FVS}]}"
          version_seabios="${version_seabios%\/}"
        else
          path_to_seabios=''
          version_seabios=''
        fi
        ;;

      '--microcode')
        [ "$opt__microcode" ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--microcode: duplicate option"
          opt__microcode=1
        ;;

      '--chipsize')
        [ "$arg__chipsize" ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--chipsize: duplicate option"
        opt=${2,,}
        n+=1
        case "${opt%mb}" in
          '2'|'4'|'8'|'12'|'16')
            arg__chipsize="${opt}"
            ;;

          *)
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--chipsize: missing or wrong argument"
            ;;
        esac
        ;;

      '--ime')
        [ "$arg__ime" ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ime: duplicate option"
        opt=${2,,}
        n+=1
        case "${opt}" in
          'keep')
            ;&

          'trunc'|'xtrunc')
            ;&

          'none')
            arg__ime="$opt"
            ;;

          *)
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--ime: missing or wrong argument"
            ;;
        esac
        ;;

      '--gbe')
        [ "$arg__gbe" ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--gbe: duplicate option"
        opt=${2,,}
        n+=1
        case "${opt}" in
          'keep')
            arg__gbe=$opt
            ;;

          'set_'[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f])
            arg__gbe=$opt
            gbebin_postfix="${arg__gbe/#/.}"
            ;;

          'disable')
            arg__gbe=$opt
            gbebin_postfix="${arg__gbe/#/.}"
            ;;

          *)
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--gbe: missing or wrong argument"
            ;;
        esac
        ;;

      '--rom-vga')
        [ "$arg__rom_vga" ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-vga: duplicate option"
        [ "${2:0:2}" = '--' ] || [ "${2}" = '' ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-vga: missing argument"
        [ -f "$2" ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-vga: no such file: $2"
        case "${2##*/}" in
          (pci[0-9][0-9][0-9][0-9],[0-9][0-9][0-9][0-9].rom)
            ;;

          (*) go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-vga: invalid file name pattern: ${2##*/}"
            ;;
        esac
        opt="$2"
        n+=1
        pushd ${opt%/*} &>/dev/null
        arg__rom_vga="$(dirs -l +0)/${opt##*/}"
        popd &>/dev/null
        ;;

      '--rom-factory')
        [ "$arg__rom_factory" ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-factory: duplicate option"
        [ "${2:0:2}" = '--' ] || [ "${2}" = '' ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-factory: missing argument"
        [ -f "$2" ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--rom-factory: no such file: $2"
        opt="$2"
        n+=1
        pushd ${opt%/*} &>/dev/null
        arg__rom_factory="$(dirs -l +0)/${opt##*/}"
        popd &>/dev/null
        ;;

      '--ifd-lock-regions')
        opt__ifd_lock_regions='lock'
        ;;

      '--ifd-medisable')
        opt__ifd_medisable='1'
        ;;

      '--ifd-altmedisable')
        opt__ifd_altmedisable='1'
        ;;

      '--payload-grub-dir')
        [ "$arg__payload_grub_dir" ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--payload-grub-dir: duplicate option"
        [ "${2:0:2}" = '--' ] || [ "${2}" = '' ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--payload-grub-dir: missing argument"
        [ -d "$2" ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--payload-grub-dir: no such directory: $2"
        opt="$2"
        n+=1
        pushd ${opt} &>/dev/null
        arg__payload_grub_dir="$(dirs -l +0)"
        popd &>/dev/null
        # catch any first payload file
        arg__payload_grub=$(echo $arg__payload_grub_dir/${GRUB_PAYLOAD/\$\{version_grub\}/*})
        arg__payload_grub=${arg__payload_grub%% *}
        arg__payload_grub=${arg__payload_grub##*/}
        [ -e "$arg__payload_grub_dir/$arg__payload_grub" ] ||
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--payload-grub-dir: no payload file"
        # get version
        version_grub=${arg__payload_grub##*@}
        version_grub=${version_grub%%_*}
        ;;

      # jobs
      '--help')
        ;&

      '--usage')
        opt__usage=1
        ;;

      '--clean')
        opt__clean=1
        ;;

      '--remove-all')
        opt__remove_all=1
        ;;

      '--target')
        [ "$opt__target" ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--target: duplicate option"
        [ "${2:0:2}" = '--' ] || [ "${2}" = '' ] &&
          go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--target: missing argument"
        opt=${2,,}
        n+=1
        case "${opt}" in
          # Use templates with TPM options, accessible via SeaBIOS...
          'x201')                                             ;&
          'x220'|'x220i')                                     ;&
          't420'|'t420s')                                     ;&
          't520'|'t520i')                                     ;&
          'x1_carbon_gen1')                                   ;&
          'x230'|'x230t')                                     ;&
          't430')                                             ;&
          't430s')                                            ;&
          't530')                                             ;&
          'w530')            par__tpm=1                       ;&

          # Use templates with TPM disabled.
          'x230s')                                            ;&
          'x60_32bit'|'x60s_32bit'|'x60t_32bit')              ;&
          'x60'|'x60s'|'x60t')                                ;&
          't60')                                              ;&
          't60_ati_mobility_radeon_x1300')                    ;&
          't60_ati_mobility_radeon_x1400')                    ;&
          'x200'|'x200s'|'x200t')                             ;&
          't400'|'t400s')                                     ;&
          't500')            arg__target="${opt}"             ;;

          *)
            go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "--target: unknown argument"
            ;;
        esac
        opt__target=1
        ;;

      *)
        go_exit "$BASH_SOURCE" "$FUNCNAME" "$LINENO" "unknown option: $opt"
        ;;
    esac
    shift $n
  done
  if [ $# -ne 0 ]; then
    _warn "... $# parameters were skipped."
  else
    _pass "... command line parsed."
  fi

  _funcstop "$FUNCNAME"
}

job_list()
{
  _funcstart "$FUNCNAME"

  declare retval=1

  # jobs
  _dbug "${FG_MAGENTA}Jobs ...${FG_DEFAULT}"
  _info "Requested jobs are:"
  [ "$opt__usage" ] && {
    _mesg "${LIITEM}display usage information"
    retval=0
  }
  [ "$opt__clean" ] && {
    _mesg "${LIITEM}clean up temporary files"
    retval=0
  }
  [ "$opt__remove_all" ] && {
    _mesg "${LIITEM}clean build folders"
    retval=0
  }
  [ "$opt__target" ] && {
    _mesg "${LIITEM}set up target folder with $ROM_ZEROCAT"
    retval=0
  }
  [ "$retval" -eq 0 ] || {
    _mesg "${INDENT}none"
  }

  _funcstop "$FUNCNAME" $retval
}

clean()
{
  _funcstart "$FUNCNAME"

  _info "Remove generated files ..."
  declare pattern1=*gbe{_,-}*.bin
  declare pattern2=flashregion_?_*.bin
  declare no_files=0
  for i in $pattern1; do
    [ -f "$i" ] && {
      _mesg "${LIITEM}$i"
      no_files=1
    }
  done
  for i in $pattern2; do
    [ -f "$i" ] && {
      _mesg "${LIITEM}$i"
      no_files=1
    }
  done
  if [ "$no_files" -eq 0 ]; then
    _pass "... no files to remove."
  else
    yes_no_abort && {
      rm -f $pattern1 $pattern2
      _pass "... generated files have been removed."
    }
  fi
  unset pattern1
  unset pattern2
  unset no_files

  _funcstop "$FUNCNAME"
}

remove_all()
{
  _funcstart "$FUNCNAME"

  declare pattern=*-*.??????????
  declare no_folders=0

  _info "Start batch removal of generated folders ..."
  for i in $pattern; do
    [ -d "$i" ] && {
      no_folders=1
      _warn "Remove:${RTAB}$SET_BOLD$i$CLR_INTENSITY"
      yes_no_abort && {
        rm -rf "$i"
        _pass "... removed."
      }
    }
  done
  if [ "$no_folders" -eq 0 ]; then
    _pass "... no folders to remove."
  else
    _pass "... batch removal executed."
  fi
  unset pattern
  unset no_folders

  _funcstop "$FUNCNAME"
}

parse_debug()
{
  declare i=

  DEBUG=0
  for i in "$@"; do
    [ "$i" = '--debug' ] && DEBUG=1
  done

  true
}

main()
{
  trap '
    echo
    go_exit "$BASH_SOURCE" "$FUNCNAME" "" "$BASH_COMMAND"
    ' SIGINT ERR   # what sigspec is related to ERR??

  _funcstart "$FUNCNAME"

  # Pattern of declarations
  #
  # 1) command line options refer to $opt__<option>, i.e.:
  #   --mute -> $opt__mute
  # 2) arguments of command line options refer to $arg__<option>, i.e.:
  #   --target x230 -> $opt__target (=1) and $arg__target (=x230)
  # 3) variables related to 1) and 2) are prefixed with ‘par__’, i.e.:
  #

  declare -r scriptname="${TOOLCHAIN_SCRIPT[4]}"
  declare osid=
  declare -r -a commands_script=(
    'source'
    'echo'
    'printf'
    'cat'
    'xxd'
    'sed'
    'rm'
    'mv'
    'cd'
    'sleep'
    'exit'
    'git'
    'make'
  )
  declare -r ROM_FACTORY='factory.rom'
  declare -r ROM_ZEROCAT='zerocat.rom'
  declare -r REV_ZEROCAT='zerocat.revision'
  declare -r -A  ifd_none_2mb=([size_rom]=0x00200000 [size_fd]=0x0000 [size_gbe]=0x0000 [size_me]=0x000000 [size_bios]=0x200000 [size_pd]=0x0000)
  declare -r -A   ifd_x00_4mb=([size_rom]=0x00400000 [size_fd]=0x1000 [size_gbe]=0x2000 [size_me]=0x1f5000 [size_bios]=0x200000 [size_pd]=0x8000)
  declare -r -A   ifd_x00_8mb=([size_rom]=0x00800000 [size_fd]=0x1000 [size_gbe]=0x2000 [size_me]=0x5f5000 [size_bios]=0x200000 [size_pd]=0x8000)
  declare -r -A  ifd_x00_16mb=([size_rom]=0x01000000 [size_fd]=0x1000 [size_gbe]=0x2000 [size_me]=0x5f5000 [size_bios]=0xa00000 [size_pd]=0x8000)
  declare -r -A   ifd_x20_8mb=([size_rom]=0x00800000 [size_fd]=0x1000 [size_gbe]=0x2000 [size_me]=0x4fd000 [size_bios]=0x300000 [size_pd]=0x0000)
  declare -r -A  ifd_x30_12mb=([size_rom]=0x00c00000 [size_fd]=0x1000 [size_gbe]=0x2000 [size_me]=0x4fd000 [size_bios]=0x700000 [size_pd]=0x0000)
  declare -r -A  ifd_x30_16mb=([size_rom]=0x01000000 [size_fd]=0x1000 [size_gbe]=0x2000 [size_me]=0x4fd000 [size_bios]=0xb00000 [size_pd]=0x0000)

  declare opt__mute=
  declare opt__usage=
  declare opt__clean=
  declare opt__remove_all=
  declare opt__target=
  declare opt__microcode=
  declare opt__ifd_lock_regions=
  declare opt__ifd_medisable=
  declare opt__ifd_altmedisable=

  declare arg__toolbox=
  declare arg__target=
  declare arg__rom_factory=
  declare arg__rom_vga=
  declare arg__ime=                 # will be set with default values if unset
  declare arg__chipsize=            # will be set with default values if unset
  declare arg__gbe=                 # will be modified in case it contains a new gbe macaddress

  declare arg__payload_grub_dir=
  declare arg__payload_grub=        # directly related to $arg__payload_grub_dir
  declare version_grub=             # directly related to $arg__payload_grub_dir

  declare par__tpm=                 # will be set according to $arg__target
  declare par__seabios=             # will be set according to settings in $grub_config
  declare par__coreinfo=            # will be set according to settings in $grub_config
  declare par__nvramcui=            # will be set according to settings in $grub_config
  declare par__memtest86=           # will be set according to settings in $grub_config
  declare par__tint=                # will be set according to settings in $grub_config

  declare path_to_seabios=          # directly related to $arg__toolbox
  declare path_to_coreboot=         # directly related to $arg__toolbox
  declare version_seabios=          # directly related to $arg__toolbox
  declare version_coreboot=         # directly related to $arg__toolbox

  declare grub_config=              # GRUB configuration file for the GRUB payload
  declare grub_config_morse=        # GRUB configuration file, optional addon
  declare grub_keymap=              # GRUB keymap setting
  declare grub_auth=                # GRUB authorization setting
  declare -a grub_background        # array of background images for GRUB

  declare gbebin_postfix=
  declare size_me_new=              # temporary helper variable
  declare template_config=          # name of the coreboot configuration file template
  declare template_target_folder=   # name of the target folder template
  declare target_folder=            # name of the target folder with specific suffix
  declare -n ifd                    # pointer to specific ifd database

  _head "Zerocat Coreboot Machines ${PROJECT_NUMBER}”"
  _head "$scriptname – generate your Zerocat ROM"
  print_licheader
  print_logo
  test_scriptname "$BASH_SOURCE" "$scriptname" && {
    get_OSID 'osid'
    check_commands 'commands_script'
    _info "$(date), ready to start."
    hit_enter
    parse_cmdline "$@"
    check_options
    check_settings
    job_list && {
      yes_no_abort && {
        [ "$opt__usage" ] && {
          usage
        }
        [ "$opt__clean" ] && {
          clean
        }
        [ "$opt__remove_all" ] && {
          remove_all
        }
        [ "$opt__target" ] && {
          generate_rom "${arg__target}"
        }
      }
    }
  }
  _info "Good Bye."

  _funcstop "$FUNCNAME"

  trap - ERR SIGINT
}

# script
parse_debug "$@"
main "$@"
