@ -17,7 +17,8 @@ QEMU_OPTIONS ?= -enable-kvm
GITVERSION = $( shell git describe --dirty --abbrev= 6 ) ( $( shell date +%Y%m%d) )
BUILDINFO = $( GITVERSION) $( MAKECMDGOALS)
LIST_PATCHED = $( basename $( shell grep ^patched Descriptions.txt | cut -d" " -f1) )
LIST_PATCHED = $( basename $( shell grep ^patched Descriptions.txt | grep -v Battery | cut -d" " -f1) )
LIST_PATCHED_BO = $( basename $( shell grep ^patched Descriptions.txt | grep Battery | cut -d" " -f1) )
list_laptops :
$( info )
@ -34,6 +35,7 @@ DEPSDIR := .d
$( shell mkdir -p $ ( DEPSDIR ) )
test : $( addsuffix .iso ,$ ( LIST_PATCHED ) ) $( addsuffix .img ,$ ( LIST_PATCHED ) )
test.batteryonly : $( addsuffix .iso ,$ ( LIST_PATCHED_BO ) ) $( addsuffix .img ,$ ( LIST_PATCHED_BO ) )
ALL_IMG_ORIG := $( addsuffix .orig,$( shell grep rule:IMG Descriptions.txt | cut -d" " -f1) )
test.img.orig : $( ALL_IMG_ORIG )
@ -63,7 +65,7 @@ test.report:
# images) and any small downloads
clean :
rm -f $( CLEAN_FILES) \
patched.*.iso patched.*.img *.FL2 *.FL2 .orig *.img.enc \
patched.*.iso patched.*.img *.FL? *.FL? .orig *.img.enc \
*.img.enc.orig *.img.orig *.bat *.report \
*.img \
*.txt.orig
@ -100,15 +102,6 @@ list_images:
.PHONY : list_images
# All the bios update iso images I have checked have had a fat16 filesystem
# embedded in a dos mbr image as the el-torito ISO payload. Most of them
# had the same offset to this fat filesystem, so hardcode that offset here.
# FIXME:
# - checking the E330 image showed a different FAT_OFFSET, need to handle that
# The offset value is bytes in decimal.
FAT_OFFSET := 71680
# Some versions of mtools need this flag set to allow them to work with the
# dosfs images used by Lenovo - from my tests, it may be that Debian has
# applied some patch
@ -119,7 +112,14 @@ export MTOOLS_SKIP_CHECK=1
export MTOOLS_LOWER_CASE = 0
build-deps :
apt -y install git mtools libssl-dev build-essential xorriso
apt -y install \
git \
mtools \
libssl-dev \
build-essential \
xorriso \
unzip \
innoextract \
#
# Radare didnt seem to let me specify the directory to store the project file,
@ -175,7 +175,9 @@ patch_disable_keyboard:
# Download any ISO image that we have a checksum for
# NOTE: makes an assumption about the Lenovo URL not changing
.PRECIOUS : %.iso .orig
%.iso.orig :
.PRECIOUS : %.exe .orig
.PRECIOUS : %.zip .orig
%.iso.orig %.exe.orig %.zip.orig :
@echo -n "Downloading "
@scripts/describe $( basename $@ )
@wget -nv -O $@ https://download.lenovo.com/pccbbs/mobiles/$( basename $@ )
@ -210,9 +212,28 @@ patch_disable_keyboard:
# my mind to it..
#
%.iso.bat : %.iso .orig autoexec .bat .template
$( eval FAT_OFFSET := $( shell scripts/geteltorito -c $< 2>/dev/null) )
@sed -e " s%__DIR%`mdir -/ -b -i $<@@ $( FAT_OFFSET) |grep FL2 |head -1|cut -d/ -f3`%; s%__FL2%`mdir -/ -b -i $<@@ $( FAT_OFFSET) |grep FL2 |head -1|cut -d/ -f4`% " autoexec.bat.template >$@ .tmp
@mv $@ .tmp $@
# FIXME:
# - the following bat file generators are all basically duplicates of the
# above original one. They should be deduplicated
# - the "bat1" construct is ugly. Find a nicer way to do this.
%.iso.bat1 : %.iso .orig autoexec .bat .template
$( eval FAT_OFFSET := $( shell scripts/geteltorito -c $< 2>/dev/null) )
@sed -e " s%__DIR%`mdir -/ -b -i $<@@ $( FAT_OFFSET) |grep FL1 |head -1|cut -d/ -f3`%; s%__FL2%`mdir -/ -b -i $<@@ $( FAT_OFFSET) |grep FL1 |head -1|cut -d/ -f4`% " autoexec.bat.template >$@ .tmp
@mv $@ .tmp $( subst .bat1,.bat,$@ )
%.exe.bat : %.exe .orig autoexec .bat .template
@sed -e " s%__DIR%.%; s%__FL2%`basename \`innoextract -l $< | grep -i .CAP | cut -d' " ' -f2\` ` %" autoexec.bat.template > $@ .tmp
@mv $@ .tmp $@
%.exe.bat1 : %.exe .orig autoexec .bat .template
@sed -e " s%__DIR%.%; s%__FL2%`basename \`innoextract -l $< | grep -i .FL1 | cut -d' " ' -f2\` ` %" autoexec.bat.template > $@ .tmp
@mv $@ .tmp $@
# helper to write the ISO onto a cdrw
%.iso.blank_burn : %.iso
wodim -eject -v speed = 40 -tao gracetime = 0 blank = fast $<
@ -233,14 +254,26 @@ patch_disable_keyboard:
# If we ever want a copy of the dosflash.exe, just get it from the iso image
%.dosflash.exe.orig : %.iso .orig
$( eval FAT_OFFSET := $( shell scripts/geteltorito -c $^ 2>/dev/null) )
mcopy -m -i $^@@$( FAT_OFFSET) ::FLASH/DOSFLASH.EXE $@
# Extract the "embedded" fat file system from a given iso.
%.iso.extract : %.iso
$( eval FAT_OFFSET := $( shell scripts/geteltorito -c $^ 2>/dev/null) )
mcopy -n -s -i $^@@$( FAT_OFFSET) :: $@
%.iso.orig.extract : %.iso .orig
$( eval FAT_OFFSET := $( shell scripts/geteltorito -c $^ 2>/dev/null) )
mcopy -n -s -i $^@@$( FAT_OFFSET) :: $@
%.zip.extract : %.zip
unzip $^ -d $@
%.zip.orig.extract : %.zip
unzip $^ -d $@
%.exe.extract : %.exe
innoextract $^ -d $@
%.exe.orig.extract : %.exe .orig
innoextract $^ -d $@
## Use the system provided geteltorito script, if there is one
#GETELTORITO := $(shell if type geteltorito >/dev/null; then echo geteltorito; else echo ./geteltorito; fi)
@ -299,6 +332,14 @@ mec-tools/mec_encrypt: mec-tools/Makefile
git submodule update
make -C mec-tools
# FIXME:
# - There is no version tracking in this wget, so it is basically an untrusted
# execution vector. Either import this file to this repo or use a submodule.
nuvoton-tools/npce885crc :
-mkdir nuvoton-tools
wget -O nuvoton-tools/npce885crc.c https://raw.githubusercontent.com/leecher1337/thinkpad-Lx30-ec/main/fwpat/util/npce885crc.c
gcc -o nuvoton-tools/npce885crc nuvoton-tools/npce885crc.c
# Simple Visualisation
%.pgm : %
( echo " P5 256 $$ (( $( shell stat -c %s $<) /265)) 255 " ; cat $< ) > $@
@ -333,15 +374,48 @@ define rule_IMG_extract
e n d e f
rule_IMG_extract_DEPS = scripts/FL2_copyIMG mec-tools/mec_encrypt mec-tools/mec_csum_flasher mec-tools/mec_csum_boot
# TODO:
# - the prepare_iso_from_tpl looks like it is entirely needed due to some
# Lenovo images being broken. Look into what is broken and see if it is
# patchable without a template.
# $@ is the ISO to create
# $< is the FL2
# $1 is the pattern to match FL2 file in ISO image
# $2 FAT offset in ISO image
d e f i n e p r e p a r e _ i s o _ f r o m _ t p l
$( eval FAT_OFFSET_FL1SRC := $( shell scripts/geteltorito -c $@ .orig 2>/dev/null) )
$( eval FLASH_FILE := $( subst $$ ,\$ $$ $,$( shell mdir -/ -b -i $@ .orig@@$( FAT_OFFSET_FL1SRC) | grep -i $( 1) | head -1) ) )
$( eval DOSFLASH := $( shell mdir -/ -b -i $@ .orig@@$( FAT_OFFSET_FL1SRC) | grep DOSFLASH | head -1) )
$( eval FILE_DIR := $( shell basename $( dir $( FLASH_FILE:::%= %) ) ) )
mdeltree -i $@ .tmp@@$( 2) FLASH/
mmd -i $@ .tmp@@$( 2) FLASH FLASH/$( FILE_DIR)
-mkdir -p $@ .orig.extract.tmp
mcopy -n -s -m -i $@ .orig@@$( FAT_OFFSET_FL1SRC) $( FLASH_FILE) $( DOSFLASH) $@ .orig.extract.tmp
mcopy -o -s -m -i $@ .tmp@@$( 2) $@ .orig.extract.tmp/DOSFLASH.EXE ::/FLASH/
mcopy -o -s -m -i $@ .tmp@@$( 2) $@ .orig.extract.tmp/$( subst $$ ,\$ $,$( shell basename $( FLASH_FILE:::%= %) ) ) ::/FLASH/$( FILE_DIR) /
rm -r $@ .orig.extract.tmp
e n d e f
# FIXME:
# - the logic using the optional $2 below feels really clunky, try and
# improve it. See above for a related TODO for prepare_iso_from_tpl
# Create a new ISO image with patches applied
#
# $@ is the ISO to create
# $< is the FL2
# $1 is the pattern to match FL2 file in ISO image
# $2 optional: Name of other ISO that should be taken as a template with a working DOS on it
d e f i n e r u l e _ F L 2 _ i n s e r t
$( call buildinfo_ISO)
@cp --reflink= auto $@ .orig $@ .tmp
$( eval SRC := $( or $( 2) ,$@ ) )
@cp --reflink= auto $( SRC) .orig $@ .tmp
$( eval FAT_OFFSET := $( shell scripts/geteltorito -c $( SRC) .orig 2>/dev/null) )
$( if $( 2) ,$( call prepare_iso_from_tpl,$( 1) ,$( FAT_OFFSET) ) )
@cp --reflink= auto $< $<.tmp
@cp --reflink= auto $@ .report $@ .report.tmp
@ -351,6 +425,7 @@ define rule_FL2_insert
./scripts/ISO_copyFL2 to_iso $@ .tmp $<.tmp $( 1)
mcopy -t -m -o -i $@ .tmp@@$( FAT_OFFSET) $@ .report.tmp ::report.txt
-mattrib -i $@ .tmp@@$( FAT_OFFSET) -r -s -h ::AUTOEXEC.BAT
mcopy -t -m -o -i $@ .tmp@@$( FAT_OFFSET) $@ .bat.tmp ::AUTOEXEC.BAT
-mdel -i $@ .tmp@@$( FAT_OFFSET) ::EFI/Boot/BootX64.efi
-mattrib -i $@ .tmp@@$( FAT_OFFSET) -r ::FLASH/README.TXT
@ -369,6 +444,117 @@ rule_FL2_insert_DEPS = scripts/ISO_copyFL2 # TODO - bat file
# - provide a simple mechanism for selecting the flash command to run, to
# allow for autoexec bat files that do not use dosflash
# Extract the CAP file from an EXE image
#
# $@ is the CAP file to create
# $< is the EXE file
# $1 is the pattern to match CAP file in EXE file
d e f i n e r u l e _ C A P _ e x t r a c t
innoextract $< -I $( 1) -d tmp.inno
mv ` find tmp.inno -type f` $@
touch $@
rm -rf tmp.inno
e n d e f
rule_CAP_extract_DEPS = # no extra local dependancies
d e f i n e r u l e _ E X E _ e x t r a c t
$( call rule_CAP_extract,$1 )
e n d e f
rule_EXE_extract_DEPS = # no extra local dependancies
# TODO:
# - the following two rule_CAP_insert and rule_EXE_insert replicate a lot of
# logic included in rule_FL2_insert. See if we can refactor to share logic.
# Create a new CAP image with patches applied
# This is specifically for B590 firmware where we have to combine a bootable DOS
# ISO with the Flash-updater tool from an older .ZIP archive and a new capsule
# from an Innosetup .EXE and combine it together into an ISO image
#
# $@ is the CAP to create
# $< is the CAP
# $1 is the pattern to match CAP file in EXE file
# $2 Name of other ISO that should be taken as a template with a working DOS on it
# $3 ZIP file where to take the DOS flash updater program from
d e f i n e r u l e _ C A P _ i n s e r t
$( call buildinfo_ISO)
@cp --reflink= auto $( 2) .orig $@ .tmp
$( eval FAT_OFFSET := $( shell scripts/geteltorito -c $( 2) .orig 2>/dev/null) )
-mkdir -p $@ .orig.extract.tmp
unzip -o $( 3) .orig DOS/\* -x \* .cap \* .IMC \* .BAT -d $@ .orig.extract.tmp/
-mattrib -i $@ .tmp@@$( FAT_OFFSET) -r -/ ::FLASH/
mdeltree -i $@ .tmp@@$( FAT_OFFSET) FLASH/
mmd -i $@ .tmp@@$( FAT_OFFSET) FLASH
mcopy -o -s -m -i $@ .tmp@@$( FAT_OFFSET) $@ .orig.extract.tmp/DOS/* ::/FLASH/
@rm -r $@ .orig.extract.tmp
@cp --reflink= auto $< $<.tmp
@cp --reflink= auto $@ .report $@ .report.tmp
@cp --reflink= auto $@ .bat $@ .bat.tmp
@touch --date= "1980-01-01 00:00:01Z" $<.tmp $@ .report.tmp $@ .bat.tmp
@# TODO - datestamp here could be the lastcommitdatestamp
mcopy -t -m -o -i $@ .tmp@@$( FAT_OFFSET) $<.tmp ::/FLASH/$<
mcopy -t -m -o -i $@ .tmp@@$( FAT_OFFSET) $@ .report.tmp ::report.txt
-mattrib -i $@ .tmp@@$( FAT_OFFSET) -r -s -h ::AUTOEXEC.BAT
mcopy -t -m -o -i $@ .tmp@@$( FAT_OFFSET) $@ .bat.tmp ::AUTOEXEC.BAT
@rm $<.tmp $@ .report.tmp $@ .bat.tmp
@mv $@ .tmp $@
e n d e f
rule_CAP_insert_DEPS =
# TODO:
# - it is unclear if the dependancies for the $2 ISO image used below are
# handled
# - Similar to the prepare_iso_from_tpl, this looks like it has a bunch of
# logic due to some Lenovo images being broken. Look into what is broken
# and see if it is patchable without a template.
# Create a new EXE image with patches applied
# This is specifically for B580 firmware where we have to combine a bootable DOS
# ISO with a patched FL2 together into an ISO image
#
# $@ is the EXE to create
# $< is the CAP
# $1 is the pattern to match FL1 file in EXE file
# $2 Name of other ISO that should be taken as a template with DOS and DOSFLASH
d e f i n e r u l e _ E X E _ i n s e r t
$( call buildinfo_ISO)
@cp -f --reflink= auto $( 2) .orig $@ .tmp
$( eval FAT_OFFSET := $( shell scripts/geteltorito -c $( 2) .orig 2>/dev/null) )
$( eval DOSFLASH := $( shell mdir -/ -b -i $( 2) .orig@@$( FAT_OFFSET) | grep -i DOSFLASH | head -1) )
-rm -rf $@ .orig.extract.tmp
mkdir $@ .orig.extract.tmp
mcopy -n -s -m -i $@ .tmp@@$( FAT_OFFSET) $( DOSFLASH) $@ .orig.extract.tmp/
-mattrib -i $@ .tmp@@$( FAT_OFFSET) -r -/ ::FLASH/
mdeltree -i $@ .tmp@@$( FAT_OFFSET) FLASH/
mmd -i $@ .tmp@@$( FAT_OFFSET) FLASH
mcopy -o -s -m -i $@ .tmp@@$( FAT_OFFSET) $@ .orig.extract.tmp/DOSFLASH.EXE ::/FLASH/
mcopy -o -s -m -i $@ .tmp@@$( FAT_OFFSET) $< ::/FLASH/$( 1)
rm -r $@ .orig.extract.tmp
cp --reflink= auto $< $<.tmp
cp --reflink= auto $@ .report $@ .report.tmp
cp --reflink= auto $@ .bat1 $@ .bat.tmp
touch --date= "1980-01-01 00:00:01Z" $<.tmp $@ .report.tmp $@ .bat.tmp
@# TODO - datestamp here could be the lastcommitdatestamp
./scripts/ISO_copyFL2 to_iso $@ .tmp $<.tmp $( 1)
-mdel -i $@ .tmp@@$( FAT_OFFSET) ::EFI/Boot/BootX64.efi
mcopy -t -m -o -i $@ .tmp@@$( FAT_OFFSET) $@ .report.tmp ::report.txt
-mattrib -i $@ .tmp@@$( FAT_OFFSET) -r -s -h ::AUTOEXEC.BAT
mcopy -t -m -o -i $@ .tmp@@$( FAT_OFFSET) $@ .bat.tmp ::AUTOEXEC.BAT
@rm $<.tmp $@ .report.tmp $@ .bat.tmp
@mv $@ .tmp $@
e n d e f
rule_EXE_insert_DEPS =
# Insert the new firmware into the FL2 file
#
# $@ is the FL2 to create
@ -406,6 +592,10 @@ define rule_IMGnoenc_extract
e n d e f
rule_IMGnoenc_extract_DEPS = scripts/FL2_copyIMG
# TODO:
# - the rule_IMGnoenc_insert and rule_IMGnuvoton_insert share much of their
# logic. See if we can refactor them to remove duplication.
# Insert the new firmware into the FL2 file - special case, without encryption
#
# $@ is the FL2 to create
@ -418,6 +608,29 @@ define rule_IMGnoenc_insert
e n d e f
rule_IMGnoenc_insert_DEPS = scripts/FL2_copyIMG
# Extract the IMG file from an FL1 file - special case, for NUVOTON controllers
#
# $@ is the IMG to create
# $< is the FL2
d e f i n e r u l e _ I M G n u v o t o n _ e x t r a c t
./scripts/FL2_copyIMG from_fl2 $< $@
e n d e f
rule_IMGnuvoton_extract_DEPS = scripts/FL2_copyIMG
# Insert the new firmware into the FL2 file - special case, for NUVOTON controllers
#
# $@ is the FL1 to create
# $< is the IMG
d e f i n e r u l e _ I M G n u v o t o n _ i n s e r t
./nuvoton-tools/npce885crc -o 0x8000 -u $<
cp --reflink= auto $@ .orig $@ .tmp
./scripts/FL2_copyIMG to_fl2 $@ .tmp $<
mv $@ .tmp $@
$( call buildinfo_FL2)
e n d e f
rule_IMGnuvoton_insert_DEPS = scripts/FL2_copyIMG nuvoton-tools/npce885crc
# Extract the FL2 file from an ISO image with two FL2 files
#