mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-07-11 14:02:52 +02:00
a4ea286731
The primary purpose of my intense auditing has been to improve lbmk's coding style and fix bugs but there is a secondary purpose: know precisely who owns what, because I want to re-license as much as possible of lbmk under *MIT*, instead of the current GNU licensing. MIT is vastly superior, because it grants *actual* freedom to the user, permits *sublicensing* and it is vastly more compatible with other GPL combinations; for example, MIT license is compatible with GPL2-only whereas lbmk's current mix of GPLv3-or-later and GPLv3-only is legally incompatible with GPLv2-only. Re-licensing under MIT will most likely result in more contributions to Libreboot's build system in the future, especially as it will attract a lot more commercial interest. Contrary to the popular arguments, copyleft is a liability to the free software movement and results in less code being written; in practise, permissively licensed code gets more public contributions, including from commercial entities, even if companies can theoretically make something proprietary out of it (in practise, anyone inclined can just use the upstream and proprietary forks almost always die). Copyleft propaganda is fundamentally flawed. See: <https://unixsheikh.com/articles/the-problems-with-the-gpl.html> Anyway, I've been doing a combination of: * Seeking permission from other copyright holders, for re-licensing * Deleting, or moving, other contributions; for example, splitting certain contributions into separate files so that originally modified files become unencumbered. This latter solution is a result of *code cleanup* arising from the audit. For Ferass's contributions, I opted to seek *permission*, and permission was denied. In full compliance with this legal imperative, I'm acting accordingly; this commit removes all of Ferass's changes that converted lbmk to posix shell scripts, thus removing his copyright on the affected files, bypassing his authority entirely. Therefore, lbmk is largely now bash-dependent. In practise, nobody is going to use anything other than a GNU system to build Libreboot, because many projects that Libreboot makes use of rely heavily on GNU; for example, coreboot's build system makes heavy use of GNU-specific extensions in *GNU Make*, and likely contains many bashisms. Of course, Libreboot also compiles GNU GRUB. I would much rather have MIT-licensed Bash scripts than GPL-licensed posix SCL scripts. This reverts the changes from Ferass El Hafidi, for the following commits, with some exceptions: *7f5dfebf7d*f787044642Exception: download/mrc not reverted, because that was already a fork of an existing script under coreboot's build system, and their script was GPLv2. i cannot/will not re-license this file (ergo,7f5dfebf7dchange remains intact, on this file) resources/scripts/build/boot/roms_helper, these changes have been kept: *7e6691e9- Add ARMv7 and AArch64 support *dec2d720- add myself in the build/roms_helper script (added 2021 copyright for the change below) *b7405656- Workaround for grub's slow boot ^ these changes will be re-factored, splitting them out of the file into a new file. This will be done in a future lbmk revision. (in some cases, it makes sense to keep a change but split it, allowing the main file to be re-licensed without the change in it) This is part of a much larger series of licensing audits. It's likely that lbmk will be posix-compliant (in its shell scripts) again some day, because I'm planning to rewrite most of these scripts (the ones modified in this patch), and many of them (e.g. individual download scripts) are subject to future deletion in a planned overhaul of the download logic for third party projects. In addition: these changes are being kept (no attempt to re-license them will be made): *cff081c6- Fix grub's slow boot (1 year, 5 months ago) <Vitali64> *4c851889- Add macbook*1 16mb configs (1 year, 6 months ago) <Vitali64> Ferass's work that remains will be split into dedicated files containing them, where feasible. In the case of grub.cfg (for GNU GRUB), I don't care because it's a script for an engine (GRUB shell) that's under GPL anyway, so who really cares about MIT license. Signed-off-by: Leah Rowe <leah@libreboot.org>
456 lines
9.6 KiB
Bash
Executable File
456 lines
9.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# SPDX-FileCopyrightText: 2022 Caleb La Grange <thonkpeasant@protonmail.com>
|
|
# SPDX-FileCopyrightText: 2023 Leah Rowe <info@minifree.org>
|
|
# SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
ec_url=""
|
|
ec_url_bkup=""
|
|
ec_hash=""
|
|
dl_hash=""
|
|
dl_url=""
|
|
dl_url_bkup=""
|
|
e6400_vga_dl_hash=""
|
|
e6400_vga_dl_url=""
|
|
e6400_vga_dl_url_bkup=""
|
|
e6400_vga_offset=""
|
|
e6400_vga_romname=""
|
|
|
|
cbdir="coreboot/default"
|
|
cbcfgsdir="resources/coreboot"
|
|
boarddir=""
|
|
blobdir="blobs"
|
|
dl_path="${blobdir}/vendorupdate"
|
|
appdir="${blobdir}/app"
|
|
_7ztest="a"
|
|
mecleaner="$(pwd)/me_cleaner/me_cleaner.py"
|
|
e6400_unpack="$(pwd)/bios_extract/dell_inspiron_1100_unpacker.py"
|
|
me7updateparser="$(pwd)/resources/blobs/me7_update_parser.py"
|
|
kbc1126_ec_dump="$(pwd)/${cbdir}/util/kbc1126/kbc1126_ec_dump"
|
|
board=""
|
|
_b="" # board shorthand without e.g. _4mb (avoid duplication per flash size)
|
|
|
|
CONFIG_HAVE_MRC=""
|
|
CONFIG_HAVE_IFD_BIN=""
|
|
CONFIG_HAVE_ME_BIN=""
|
|
CONFIG_HAVE_GBE_BIN=""
|
|
CONFIG_KBC1126_FIRMWARE=""
|
|
CONFIG_BOARD_DELL_E6400=""
|
|
CONFIG_VGA_BIOS_FILE=""
|
|
|
|
main()
|
|
{
|
|
board="${1}"
|
|
boarddir="${cbcfgsdir}/${board}"
|
|
|
|
if [ ! -d "${boarddir}" ]; then
|
|
fail "Target not defined"
|
|
elif [ ! -f "${boarddir}/board.cfg" ]; then
|
|
fail "Target missing board.cfg"
|
|
fi
|
|
|
|
detect_firmware || exit 0
|
|
scan_sources_config
|
|
|
|
build_dependencies
|
|
download_blobs
|
|
}
|
|
|
|
detect_firmware()
|
|
{
|
|
set -- "${boarddir}/config/"*
|
|
. ${1} 2>/dev/null
|
|
. "${boarddir}/board.cfg"
|
|
|
|
if [ "${CONFIG_HAVE_MRC}" = "y" ]; then
|
|
needs+=" MRC"
|
|
fi
|
|
if [ "${CONFIG_HAVE_IFD_BIN}" = "y" ]; then
|
|
needs+=" IFD"
|
|
fi
|
|
if [ "${CONFIG_HAVE_ME_BIN}" = "y" ]; then
|
|
needs+=" ME"
|
|
fi
|
|
if [ "${CONFIG_HAVE_GBE_BIN}" = "y" ]; then
|
|
needs+=" GBE"
|
|
fi
|
|
if [ "${CONFIG_KBC1126_FIRMWARE}" = "y" ]; then
|
|
needs+=" EC"
|
|
fi
|
|
if [ "${CONFIG_BOARD_DELL_E6400}" = "y" ] \
|
|
&& [ "${CONFIG_VGA_BIOS_FILE}" != "" ]; then
|
|
needs+=" E6400VGA"
|
|
fi
|
|
if [ -z ${needs+x} ]; then
|
|
printf 'No binary blobs needed for this board\n'
|
|
return 1
|
|
fi
|
|
printf "Firmware needed for board %s: %s\n" ${board} ${needs}
|
|
}
|
|
|
|
scan_sources_config()
|
|
{
|
|
# Shorthand (avoid duplicating configs per flash size)
|
|
_b=${board%%_*mb}
|
|
|
|
awkstr=" /\{.*${_b}.*}{/ {flag=1;next} /\}/{flag=0} flag { print }"
|
|
|
|
while read -r line ; do
|
|
case ${line} in
|
|
EC_url*)
|
|
set ${line}
|
|
ec_url=${2}
|
|
;;
|
|
EC_url_bkup*)
|
|
set ${line}
|
|
ec_url_bkup=${2}
|
|
;;
|
|
EC_hash*)
|
|
set ${line}
|
|
ec_hash=${2}
|
|
;;
|
|
DL_hash*)
|
|
set ${line}
|
|
dl_hash=${2}
|
|
;;
|
|
DL_url*)
|
|
set ${line}
|
|
dl_url=${2}
|
|
;;
|
|
DL_url_bkup*)
|
|
set ${line}
|
|
dl_url_bkup=${2}
|
|
;;
|
|
E6400_VGA_DL_hash*)
|
|
set ${line}
|
|
e6400_vga_dl_hash=${2}
|
|
;;
|
|
E6400_VGA_DL_url*)
|
|
set ${line}
|
|
e6400_vga_dl_url=${2}
|
|
;;
|
|
E6400_VGA_DL_url_bkup*)
|
|
set ${line}
|
|
e6400_vga_dl_url_bkup=${2}
|
|
;;
|
|
E6400_VGA_offset*)
|
|
set ${line}
|
|
e6400_vga_offset=${2}
|
|
;;
|
|
E6400_VGA_romname*)
|
|
set ${line}
|
|
e6400_vga_romname=${2}
|
|
;;
|
|
esac
|
|
done <<< $(eval "awk '${awkstr}' resources/blobs/sources")
|
|
}
|
|
|
|
build_dependencies()
|
|
{
|
|
if [ ! -d me_cleaner ]; then
|
|
printf "downloading me_cleaner\n"
|
|
./download me_cleaner || fail "could not download me_cleaner"
|
|
fi
|
|
if [ ! -d ${cbdir} ]; then
|
|
printf "downloading coreboot\n"
|
|
./download coreboot default \
|
|
|| fail "could not download coreboot"
|
|
fi
|
|
if [ ! -d bios_extract ]; then
|
|
printf "downloading bios_extract\n"
|
|
./download bios_extract \
|
|
|| fail "could not download bios_extract"
|
|
fi
|
|
if [ ! -f ${cbdir}/util/kbc1126/kbc1126_ec_dump ]; then
|
|
printf "Building kbc1126_ec_dump from coreboot\n"
|
|
make -BC ${cbdir}/util/kbc1126 \
|
|
|| fail "could not build kbc1126_ec_dump"
|
|
fi
|
|
if [ ! -f "${cbdir}/util/ifdtool/ifdtool" ]; then
|
|
printf "building ifdtool from coreboot\n"
|
|
make -C ${cbdir}/util/ifdtool \
|
|
|| fail 'could not build ifdtool'
|
|
fi
|
|
}
|
|
|
|
download_blobs()
|
|
{
|
|
for need in ${needs}; do
|
|
case ${need} in
|
|
*ME*)
|
|
download_blob_intel_me || _failed+=" me"
|
|
;;
|
|
*EC*)
|
|
download_ec || _failed+=" ec"
|
|
;;
|
|
*E6400VGA*)
|
|
download_e6400vga || _failed+=" e6400vga"
|
|
;;
|
|
*MRC*)
|
|
./download mrc || _failed+=" mrc"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [ ! -z ${_failed+x} ]; then
|
|
fail "failed to obtain ${_failed}\nTry manual extraction?"
|
|
fi
|
|
}
|
|
|
|
download_blob_intel_me()
|
|
{
|
|
printf "Downloading neutered ME for board: %s\n" ${board}
|
|
|
|
fetch_update me || return 1
|
|
extract_blob_intel_me || return 1
|
|
}
|
|
|
|
extract_blob_intel_me()
|
|
{
|
|
printf "Extracting neutered ME for ${board}\n"
|
|
|
|
_me_destination=${CONFIG_ME_BIN_PATH#../../}
|
|
|
|
if [ ! -d "${_me_destination%/*}" ]; then
|
|
mkdir -p ${_me_destination%/*}
|
|
fi
|
|
if [ -d "${appdir}" ]; then
|
|
rm -r ${appdir}
|
|
fi
|
|
if [ -f "${_me_destination}" ]; then
|
|
printf 'me already downloaded\n'
|
|
return 0
|
|
fi
|
|
|
|
printf "Extracting and stripping Intel ME firmware\n"
|
|
|
|
innoextract ${dl_path} -d ${blobdir} \
|
|
|| 7z x ${dl_path} -o${appdir} \
|
|
|| fail 'Could not extract vendor update'
|
|
|
|
bruteforce_extract_blob_intel_me "$(pwd)/${_me_destination}" \
|
|
"$(pwd)/${appdir}" \
|
|
|| fail "Could not extract Intel ME firmware"
|
|
|
|
printf "Truncated and cleaned me output to ${_me_destination}\n"
|
|
}
|
|
|
|
# cursed, carcinogenic code. TODO rewrite it better
|
|
bruteforce_extract_blob_intel_me()
|
|
{
|
|
_me_destination="${1}"
|
|
cdir="${2}" # must be an absolute path, not relative
|
|
|
|
if [ -f "${_me_destination}" ]; then
|
|
return 0
|
|
fi
|
|
|
|
sdir="$(mktemp -d)"
|
|
mkdir -p "${sdir}" || return 1
|
|
|
|
(
|
|
printf "Entering %s\n" "${cdir}"
|
|
cd "${cdir}" || exit 1
|
|
for i in *; do
|
|
if [ -f "${_me_destination}" ]; then
|
|
# me.bin found, so avoid needless further traversal
|
|
break
|
|
elif [ -L "${i}" ]; then
|
|
# symlinks are a security risk, in this context
|
|
continue
|
|
elif [ -f "${i}" ]; then
|
|
"${mecleaner}" -r -t -O "${sdir}/vendorfile" \
|
|
-M "${_me_destination}" "${i}" \
|
|
&& break # (we found me.bin)
|
|
"${mecleaner}" -r -t -O "${_me_destination}" "${i}" \
|
|
&& break # (we found me.bin)
|
|
"${me7updateparser}" -O ${_me_destination} "${i}" \
|
|
&& break # (we found me.bin)
|
|
_7ztest="${_7ztest}a"
|
|
7z x "${i}" -o${_7ztest} || continue
|
|
bruteforce_extract_blob_intel_me "${_me_destination}" \
|
|
"${cdir}/${_7ztest}"
|
|
cdir="${1}"
|
|
cd "${cdir}"
|
|
elif [ -d "$i" ]; then
|
|
bruteforce_extract_blob_intel_me "${_me_destination}" \
|
|
"${cdir}/${i}"
|
|
cdir="${1}"
|
|
cd "${cdir}"
|
|
else
|
|
printf "SKIPPING: %s\n" "${i}"
|
|
fi
|
|
done
|
|
)
|
|
|
|
rm -Rf "${sdir}"
|
|
|
|
if [ ! -f "${_me_destination}" ]; then
|
|
printf "me.bin not found in vendor update for: %s\n" ${board}
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
download_ec()
|
|
{
|
|
printf "Downloading KBC1126 EC firmware for HP laptop\n"
|
|
|
|
fetch_update ec || return 1
|
|
extract_ec || return 1
|
|
}
|
|
|
|
extract_ec()
|
|
{
|
|
printf "Extracting KBC1126 EC firmware for board: %s\n" ${board}
|
|
|
|
_ec_destination=${CONFIG_KBC1126_FW1#../../}
|
|
|
|
if [ ! -d "${_ec_destination%/*}" ]; then
|
|
mkdir -p "${_ec_destination%/*}"
|
|
fi
|
|
if [ -d "${appdir}" ]; then
|
|
rm -Rf "${appdir}"
|
|
fi
|
|
if [ -f "${_ec_destination}" ]; then
|
|
printf "ec already downloaded\n"
|
|
return 0
|
|
fi
|
|
|
|
unar "${dl_path}" -o "${appdir}"
|
|
|
|
(
|
|
cd "${appdir}/${dl_path##*/}"
|
|
|
|
mv Rompaq/68*.BIN ec.bin
|
|
if [ ! -f ec.bin ]; then
|
|
unar -D ROM.CAB Rom.bin
|
|
mv Rom.bin ec.bin
|
|
fi
|
|
|
|
"${kbc1126_ec_dump}" ec.bin
|
|
)
|
|
|
|
for i in 1 2; do
|
|
if [ -f "${appdir}/${dl_path##*/}/ec.bin.fw${i}" ]; then
|
|
continue
|
|
fi
|
|
printf "Not found: %s/%s/ec.bin.fw%s\n" \
|
|
${appdir} ${dl_path##*/} ${i}
|
|
printf "Could not extract EC firmware for: %s\n" \
|
|
${board}
|
|
return 1
|
|
done
|
|
|
|
cp "${appdir}/${dl_path##*/}"/ec.bin.fw* "${_ec_destination%/*}/"
|
|
}
|
|
|
|
download_e6400vga()
|
|
{
|
|
printf "Downloading Nvidia VGA ROM for Dell Latitude E6400\n"
|
|
|
|
fetch_update e6400vga || return 1
|
|
extract_e6400vga || return 1
|
|
}
|
|
|
|
extract_e6400vga()
|
|
{
|
|
printf "Extracting Nvidia VGA ROM for ${board}\n"
|
|
|
|
_vga_destination=${CONFIG_VGA_BIOS_FILE#../../}
|
|
|
|
if [ -f "${_vga_destination}" ]; then
|
|
printf 'vga rom already downloaded\n'
|
|
return 0
|
|
fi
|
|
if [ ! -d "${_vga_destination%/*}" ]; then
|
|
mkdir -p ${_vga_destination%/*}
|
|
fi
|
|
if [ -d "${appdir}" ]; then
|
|
rm -r ${appdir}
|
|
fi
|
|
|
|
mkdir -p "${appdir}"
|
|
mv "${dl_path}" "${appdir}"
|
|
|
|
if [ "${e6400_vga_offset}" = "" ]; then
|
|
printf "E6400 VGA offset not defined\n"
|
|
return 1
|
|
elif [ "${e6400_vga_romname}" = "" ]; then
|
|
printf "E6400 VGA ROM name not defined\n"
|
|
return 1
|
|
fi
|
|
|
|
(
|
|
cd "${appdir}"
|
|
tail -c +${e6400_vga_offset} "${dl_path##*/}" \
|
|
| gunzip > bios.bin
|
|
if [ ! -f "bios.bin" ]; then
|
|
fail 'Could not extract bios.bin from Dell E6400 update'
|
|
fi
|
|
"${e6400_unpack}" bios.bin || printf "TODO: fix dell extract util\n"
|
|
if [ ! -f "${e6400_vga_romname}" ]; then
|
|
fail 'Could not extract VGA ROM from Dell E6400 BIOS update'
|
|
fi
|
|
)
|
|
|
|
cp "${appdir}"/"${e6400_vga_romname}" "${_vga_destination}"
|
|
|
|
printf "E6400 Nvidia ROM saved to: %s\n" "${_vga_destination}"
|
|
}
|
|
|
|
fetch_update()
|
|
{
|
|
printf "Fetching vendor update for board: %s\n" ${board}
|
|
|
|
fw_type="${1}"
|
|
dl=""
|
|
dl_bkup=""
|
|
dlsum=""
|
|
if [ "${fw_type}" = "me" ]; then
|
|
dl=${dl_url}
|
|
dl_bkup=${dl_url_bkup}
|
|
dlsum=${dl_hash}
|
|
elif [ "${fw_type}" = "ec" ]; then
|
|
dl=${ec_url}
|
|
dl_bkup=${ec_url_bkup}
|
|
dlsum=${ec_hash}
|
|
elif [ "${fw_type}" = "e6400vga" ]; then
|
|
dl=${e6400_vga_dl_url}
|
|
dl_bkup=${e6400_vga_dl_url_bkup}
|
|
dlsum=${e6400_vga_dl_hash}
|
|
else
|
|
printf "Unsupported download type: %s\n" ${fw_type}
|
|
return 1
|
|
fi
|
|
|
|
if [ -z "${dl_url+x}" ] && [ "${fw_type}" != "e6400vga" ]; then
|
|
printf "No vendor update specified for board: %s\n" ${board}
|
|
return 1
|
|
fi
|
|
|
|
vendor_checksum ${dlsum} || \
|
|
wget ${dl} -O ${dl_path} || wget ${dl_bkup} -O ${dl_path}
|
|
|
|
vendor_checksum ${dlsum} || fail \
|
|
"Cannot guarantee intergity of vendor update for: ${board}"
|
|
}
|
|
|
|
vendor_checksum()
|
|
{
|
|
if [ ! -f "${dl_path}" ]; then
|
|
printf "Vendor update not found on disk for: %s\n" ${board}
|
|
return 1
|
|
elif [ "$(sha1sum ${dl_path} | awk '{print $1}')" != "${1}" ]; then
|
|
printf "Bad checksum on vendor update for: %s\n" ${board}
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
fail()
|
|
{
|
|
printf "\nERROR: $@\n"
|
|
exit 1
|
|
}
|
|
|
|
main $@
|