#!/bin/bash # called from build.sh (kernel-kit) # download & process linux-firmware git source ./build.conf || exit 1 export LANG=C #faster setglobal DEBUG = '0' #0=disabled, 1=enabled rm -f ./fw-*.log test $DEBUG -ne 1 -a -d zfirmware_workdir && rm -r zfirmware_workdir setglobal CWD = $[pwd] # busybox stat faster? busybox|grep -qow 'stat' && setglobal STAT = ''busybox stat'' || setglobal STAT = 'stat' # vars setglobal SRC_FW_DIR = ''../linux-firmware'' setglobal DEST_FW_DIR = ''zfirmware_workdir/lib'' setglobal SRC_FILE_FW = "$(SRC_FW_DIR)/WHENCE" setglobal dotconfig = $[find output -maxdepth 1 -type f -name 'DOTconfig*' | head -1] if test -f $dotconfig { setglobal DOTCONFIG_str = $[grep -v -E '^#|is not set$' $dotconfig] } else { echo "WARNING: No DOTconfig file in output/" echo "Put a DOTconfig file there..." #exit 1 } setglobal FIRMWARE_SFS = ""sources/fdrv_$(kernel_version)_$(package_name_suffix).sfs"" setglobal FIRMWARE_RESULT_DIR = ''zfirmware_workdir/lib/firmware'' setglobal FIRMWARE_EXTRA_DIR = ''zfirmware_workdir/lib/linux-firmware'' setglobal kernel_package = $[find output -type d -name 'linux_kernel*' | head -1] if test ! -d $(kernel_package) { setglobal kernel_package = $[find $CWD -type d -name 'linux_kernel*' | head -1] } #if [ ! -d "${kernel_package}" ] ; then # echo "WARNING: No kernel package..." # #exit 1 #else setglobal dest_kernel_package = "$(kernel_package)/lib/firmware" test ! -d $(dest_kernel_package) && mkdir -p $dest_kernel_package #fi ################################################################# # FUNCTIONS ################################################################# proc func_git { if test -d $SRC_FW_DIR{ cd $SRC_FW_DIR echo "Updating the git firmware repo" git pull test $Status -ne 0 && echo "Failed to update git firmware" # non fatal return 0 # precaution } else { cd .. echo "Cloning the firmware repo may take a long time" git clone git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git if test $Status -ne 0{ echo "Failed to clone the git firmware repo" return 1 } return 0 } } proc process_driver { local driver=$1 local DRIVER=$(driver^^) setglobal DRIVER = $(DRIVER//-/_) match $DRIVER { # try to avoid dups with RADEON setglobal DRIVER = ''DRM_RADEON='' with NOUVEAU setglobal DRIVER = ''DRM_NOUVEAU='' with AMDGPU setglobal DRIVER = ''DRM_AMDGPU='' with I915 setglobal DRIVER = ''DRM_I915='' with KEYSPAN setglobal DRIVER = ''SERIAL_KEYSPAN='' with LIBERTAS setglobal DRIVER = 'LIBERTAS_USB' with RTL8821AEsetglobal DRIVER = '8821AE' with MWIFIEX setglobal DRIVER = 'MWIFIEX_USB' with MWLWIFI setglobal DRIVER = ''CONFIG_MAC80211'' #see WHENCE, .config } echo -n "$driver " setglobal D = $[echo $DOTCONFIG_str | grep $DRIVER | head -n1] if test -z $D { echo return 1 } else { echo -- $D -- return 0 } } proc get_func { local file=$(1) local source_path=$(SRC_FW_DIR)/$(file) local target_dir=$(CWD)/$(FIRMWARE_EXTRA_DIR)/$(file) setglobal target_dir = $(target_dir%/*) # strip off file if test ! -d $(target_dir) { # manufacture dest subdirs before move mkdir -p $(target_dir) } cp -d $(source_path) $(target_dir) !2 >/dev/null if test $Status -eq 0{ echo "$file $[$STAT -c %s $SRC_FW_DIR/$file]" >> fw-1.log } else { echo "FAILURE: $file" >> fw-1.log } } proc extract_firmware { shell { while read -r field value etc { match $field { with "Driver:" setglobal driver = $value # select firmware according based on DOTconfig... process_driver $driver || continue echo -n "$driver " > !2 while test 1 { read -r field value etc match $field { with "File:" setglobal file = $value ; get_func $file with "License:"|"Licence:" break } } } } < ${SRC_FILE_FW} } > fw-2.log } proc fw_filter{ setglobal list = $1 test -z $2 && setglobal B = '10000000' || setglobal B = $2 #~10MB (salesmen MB ;-) test $B -eq 0 && setglobal B = '10000000' echo "Filtering with $list" shell { echo ; echo ; echo "Filtering with $list" echo 'FILTERED FIRMWARE LIST IN ZDRV' echo '==============================' mkdir -p $(FIRMWARE_RESULT_DIR) setglobal filelist = $[find $(FIRMWARE_EXTRA_DIR) | sed "s%$(FIRMWARE_EXTRA_DIR)\/%%] # strip leading crap setglobal filelist2 = $[find $(SRC_FW_DIR) | sed -e "s%$(SRC_FW_DIR)\/%%" -e 's|\.git/||] # strip leading crap #echo "$filelist" while read line { setglobal file = $(line##*/) setglobal file2 = $(line) setglobal action = 'mv' #move echo -n "$file " > !2 setglobal file_path = $[echo $filelist | grep "^$(file2)$" | head -n1] if test ! $file_path { setglobal file_path = $[echo $filelist | grep "\/$(file)$" | head -n1] test -z $file_path && continue } setglobal source_path = "$(FIRMWARE_EXTRA_DIR)/$(file_path)" test -f $(source_path) -o -h $(source_path) || continue setglobal target_dir = "$(FIRMWARE_RESULT_DIR)/$(file_path)" setglobal target_dir = $(target_dir%/*) # strip off file if test ! -d $(target_dir) { # manufacture dest subdirs before move mkdir -p $(target_dir) } # make sure links follow targets test -h $(source_path) -a -e $(source_path) && setglobal SSIZE = $[$STAT -L -c %s $(source_path)] || setglobal SSIZE = $[stat -c %s $(source_path)] test -z $SSIZE && continue #precaution test $SSIZE -gt $B && continue ##discard bigguns # do links first? setglobal ret = '0' test -h $(source_path) && $(action) -f $(source_path) $(target_dir)/ #2>>fw-2.log setglobal ret = $Status test -e $(source_path) && $(action) -f $(source_path) $(target_dir)/ setglobal ret = $shExpr('$ret + $?') test $ret -le 1 && echo "$(file) SUCCESS" || echo "$(file) FAIL" } < $list } >> fw-2.log } proc licence_func { echo "Extracting licences" mkdir -p $(FIRMWARE_RESULT_DIR)/licences find $(SRC_FW_DIR) -type f -iname 'licen?e*' -exec cp '{}' $(FIRMWARE_RESULT_DIR)/licences ';' } ################################################################# # MAIN ################################################################# # update or clone git firmware if test $GIT_ALREADY_DOWNLOADED != "yes" { func_git || do { echo "ERROR" ; exit 1 ; } } cd $(CWD) test -d $DEST_FW_DIR && rm -rf $DEST_FW_DIR mkdir -p $DEST_FW_DIR test -f $(FIRMWARE_SFS) && rm -f $(FIRMWARE_SFS) # cut down firmware .. or not setglobal FW_FLAG = $1; if test ! $FW_FLAG -a -z $CUTBYTES { echo -n " Cut down firmware? 1. Cut down according to firmware.lst [default] 2. Cut down according to built modules (needs work) 3. Don't cut down Choose option: " ; read cdf match $cdf { with 2 setglobal FW_FLAG = '"big'" with 3 setglobal FW_FLAG = '"complete'" with * setglobal FW_FLAG = ''"" } } match $FW_FLAG { with complete mkdir -p $(FIRMWARE_RESULT_DIR) echo "Copy all firmware" cp -an $(SRC_FW_DIR)/* $(FIRMWARE_RESULT_DIR)/ rm -rf $(FIRMWARE_RESULT_DIR)/.git $(FIRMWARE_RESULT_DIR)/LICEN* licence_func if test -d $(dest_kernel_package) { cp -an $(FIRMWARE_RESULT_DIR)/* $(dest_kernel_package)/ rm -r $(FIRMWARE_RESULT_DIR) } else { mksquashfs zfirmware_workdir $(FIRMWARE_SFS##*/) -comp xz md5sum $(FIRMWARE_SFS##*/) > $(FIRMWARE_SFS##*/).md5.txt } with big echo "Extracting firmware" extract_firmware # process entries in WHENCE echo #main_proc setglobal echo = '"Not filtering'" mv $(FIRMWARE_EXTRA_DIR) $(FIRMWARE_RESULT_DIR) licence_func if test -d $(dest_kernel_package) { cp -n -r $(FIRMWARE_RESULT_DIR)/* $(dest_kernel_package)/ } with * # create new list.. now gets filtered by size and obscure (= big ones deleted) # obscure fw are liquidio, phanfw.bin (netxen_nic) and cxgb{3,4} (chelsio) - mainly in servers grep '^File' $SRC_FILE_FW |grep -oE '\: [a-zA-Z].*|\: L.*|\: [0-9].*'|sed 's/^\: //'|grep -vE 'liquidio|cxgb[34]|phanfw.bin' > firmware.lst # choose if test ! $CUTBYTES{ echo -n " Cut down firmware more? 1. Cut down with some big, mostly obscure firmware removed (default) 2. Cut down eliminating fw bigger than 1.5MB - usually safe 3. Cut down eliminating fw bigger than 1MB - may cut wifi support 4. Cut down eliminating fw bigger than 500KB - use at own risk 5. Cut down eliminating fw bigger than 250KB - are you insane? Choose option: " ; read cdfplus match $cdfplus { with 2 setglobal CUTBYTES = '1500000' with 3 setglobal CUTBYTES = '1000000' with 4 setglobal CUTBYTES = '500000' with 5 setglobal CUTBYTES = '250000' with * setglobal CUTBYTES = '0' } } echo "Extracting firmware" extract_firmware # process entries in WHENCE echo fw_filter firmware.lst $CUTBYTES find $(FIRMWARE_EXTRA_DIR) -type d -empty -delete licence_func # copy final fw to kernel if test -d $(dest_kernel_package) { cp -n -r $(FIRMWARE_RESULT_DIR)/* $(dest_kernel_package)/ } rm -r $(FIRMWARE_RESULT_DIR) # now move the extras to / lib/firmware & make sfs mv $(FIRMWARE_EXTRA_DIR) $(FIRMWARE_RESULT_DIR) mksquashfs zfirmware_workdir $(FIRMWARE_SFS) -comp xz md5sum $(FIRMWARE_SFS) > $(FIRMWARE_SFS).md5.txt } shell { echo '================' echo "FIRMWARE IN FDRV" echo '================' cat fw-1.log echo '==============================' test -f $(list).log && cat $(list).log && rm $(list).log } &>> build.log # cleanup if test $DEBUG -ne 1 { rm -f fw-*.log rm -rf zfirmware_workdir } echo "Firmware script complete." ### END ###