#!/bin/bash # Purpose {{{ # This script will build a new initrd with some extra firmwares. # 1. Download Debian initrd (Bookworm, Bullseye and Sid) # 2. Download firmwares # * bnx2 # * all non-free (for tigon) # * Myricom for IBM # * qlogic # * iwlwifi (Intel WiFi for user's laptop) # 3. Extract everything # 4. Build a new initrd with everything and compress with XZ # }}} # Vars {{{ readonly PROGNAME=$(basename "${0}") readonly NBARGS="${#}" [ -z "${DEBUG}" ] && DEBUG=1 ## Export DEBUG for sub-script export DEBUG # Default value for TFTP's directory if command -v in.tftpd > /dev/null; then source /etc/default/tftpd-hpa else TFTP_DIRECTORY="/srv/tftp" fi FIRM_BNX2_DEB_URL_DEFAULT="http://deb.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-bnx2_20210315-3_all.deb" FIRM_NONFREE_DEB_URL_DEFAULT="http://deb.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-linux-nonfree_20210315-3_all.deb" FIRM_MYRICOM_DEB_URL_DEFAULT="http://deb.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-myricom_20210315-3_all.deb" FIRM_QLOGIC_DEB_URL_DEFAULT="http://deb.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-qlogic_20230210-5~bpo11+1_all.deb" FIRM_IWLWIFI_DEB_URL_DEFAULT="http://deb.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-iwlwifi_20210315-3_all.deb" ## Colors readonly PURPLE='\033[1;35m' readonly RED='\033[0;31m' readonly RESET='\033[0m' readonly COLOR_DEBUG="${PURPLE}" # }}} usage() { # {{{ cat <<- EOF usage: $PROGNAME [-d|-h] This script will build a new Debian initrd with extra firmwares for "all" Debian's releases. EXAMPLES : - Build Debian's initrd to default place (${TFTP_DIRECTORY}) ${PROGNAME} OPTIONS : -d,--debug Enable debug messages. -h,--help Print this help message. EOF } # }}} debug_message() { # {{{ local_message="${1}" ## Print message if DEBUG is enable (=0) [ "${DEBUG}" -eq "0" ] && printf '\e[1;35m%-6b\e[m\n' "DEBUG − ${PROGNAME} : ${local_message}" return 0 } # }}} error_message() { # {{{ local_error_message="${1}" local_error_code="${2}" ## Print message printf '%b\n' "ERROR − ${PROGNAME} : ${RED}${local_error_message}${RESET}" exit "${local_error_code:=66}" } # }}} define_vars() { # {{{ # If firm_bnx2_deb_url wasn't defined (argument) {{{ if [ -z "${firm_bnx2_deb_url}" ]; then ## Use default value firm_bnx2_deb_url="${FIRM_BNX2_DEB_URL_DEFAULT}" fi # }}} # If firm_nonfree_deb_url wasn't defined (argument) {{{ if [ -z "${firm_nonfree_deb_url}" ]; then ## Use default value firm_nonfree_deb_url="${FIRM_NONFREE_DEB_URL_DEFAULT}" fi # }}} # If firm_myricom_deb_url wasn't defined (argument) {{{ if [ -z "${firm_myricom_deb_url}" ]; then ## Use default value firm_myricom_deb_url="${FIRM_MYRICOM_DEB_URL_DEFAULT}" fi # }}} # If firm_qlogic_deb_url wasn't defined (argument) {{{ if [ -z "${firm_qlogic_deb_url}" ]; then ## Use default value firm_qlogic_deb_url="${FIRM_QLOGIC_DEB_URL_DEFAULT}" fi # }}} # If firm_iwlwifi_deb_url wasn't defined (argument) {{{ if [ -z "${firm_iwlwifi_deb_url}" ]; then ## Use default value firm_iwlwifi_deb_url="${FIRM_IWLWIFI_DEB_URL_DEFAULT}" fi # }}} } # }}} download_file() { # {{{ local_url="${1}" local_dest_file="${2}" ## If the destination file is empty if [ -z "${local_dest_file}" ]; then debug_message "download_file − \ Download ${local_url} in the current directory." wget --quiet "${local_url}" else debug_message "download_file − \ Download ${local_url} to ${RED}${local_dest_file}${COLOR_DEBUG} ." wget --quiet "${local_url}" --output-document="${local_dest_file}" fi ## Unset variables unset local_url unset local_dest_file } # }}} is_file_empty() { # {{{ local_file="${1}" ## File is empty by default return_is_file_empty="0" ### Check if the file is empty if [ ! -s "${local_file}" ]; then return_is_file_empty="0" debug_message "is_file_empty − \ The file ${RED}${local_file}${COLOR_DEBUG} is empty or doesn't exists." else return_is_file_empty="1" debug_message "is_file_empty − \ The file ${RED}${local_file}${COLOR_DEBUG} exists and has a size greater than zero." fi ## Unset variables unset local_file return "${return_is_file_empty}" } # }}} main() { # {{{ if ! [ $(id -u) = 0 ]; then # To allow creation of temp file (mknod,…) error_message "Please run this script as root" 1 fi define_vars for DISTRO in bookworm bullseye sid; do # For ALL Debian's version debug_message "Main FOR loop − \ Manage initrd and firmwares for ${RED}${DISTRO}${COLOR_DEBUG} release." ## Temp directory TEMP_DIR=$(mktemp -d) pushd "${TEMP_DIR}" > /dev/null \ || error_message "Can't move to ${TEMP_DIR}/ temp directory." 2 initrd_file="${TEMP_DIR}/initrd.gz" ## Download original initrd {{{ download_file "http://deb.debian.org/debian/dists/${DISTRO}/main/installer-amd64/current/images/netboot/debian-installer/amd64/initrd.gz" "${initrd_file}" is_file_empty "${initrd_file}" \ && error_message "${initrd_file} file for ${DISTRO} is empty !" 3 ## }}} ## Uncompress initrd {{{ mkdir -- "${TEMP_DIR}"/mkinitrd pushd "${TEMP_DIR}"/mkinitrd/ > /dev/null \ || error_message "Can't move to ${TEMP_DIR}/mkinitrd/ directory." 2 zcat "${initrd_file}" | cpio --extract --quiet --preserve-modification-time 1>/dev/null 2>&1 popd > /dev/null \ || error_message "Can't move back from ${TEMP_DIR}/mkinitrd/ directory." 2 ## }}} ## Download bnx2's firmware and uncompress it {{{ firm_bnx2_deb_file="${TEMP_DIR}/firmware-bnx2.deb" #wget http://deb.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-bnx2_0.43_all.deb download_file "${firm_bnx2_deb_url}" "${firm_bnx2_deb_file}" is_file_empty "${firm_bnx2_deb_file}" \ && error_message "${firm_bnx2_deb_file} file for ${DISTRO} is empty !" 3 dpkg-deb --extract "${firm_bnx2_deb_file}" "${TEMP_DIR}"/mkinitrd \ || error_message "Can't extract ${firm_bnx2_deb_file} file for ${DISTRO}." 3 ## }}} ## Download nonfree firmwares (for Tigon…) and uncompress it {{{ firm_nonfree_deb_file="${TEMP_DIR}/firmware-nonfree.deb" download_file "${firm_nonfree_deb_url}" "${firm_nonfree_deb_file}" is_file_empty "${firm_nonfree_deb_file}" \ && error_message "${firm_nonfree_deb_file} file for ${DISTRO} is empty !" 3 dpkg-deb --extract "${firm_nonfree_deb_file}" "${TEMP_DIR}"/mkinitrd \ || error_message "Can't extract ${firm_nonfree_deb_file} file for ${DISTRO}." 3 ## }}} ## Download myricom's firmware (for IBM) and uncompress it {{{ firm_myricom_deb_file="${TEMP_DIR}/firmware-myricom.deb" download_file "${firm_myricom_deb_url}" "${firm_myricom_deb_file}" is_file_empty "${firm_myricom_deb_file}" \ && error_message "${firm_myricom_deb_file} file for ${DISTRO} is empty !" 3 dpkg-deb --extract "${firm_myricom_deb_file}" "${TEMP_DIR}"/mkinitrd \ || error_message "Can't extract ${firm_myricom_deb_file} file for ${DISTRO}." 3 ## }}} ## Download qlogic's firmware and uncompress it {{{ firm_qlogic_deb_file="${TEMP_DIR}/firmware-qlogic.deb" download_file "${firm_qlogic_deb_url}" "${firm_qlogic_deb_file}" is_file_empty "${firm_qlogic_deb_file}" \ && error_message "${firm_qlogic_deb_file} file for ${DISTRO} is empty !" 3 dpkg-deb --extract "${firm_qlogic_deb_file}" "${TEMP_DIR}"/mkinitrd \ || error_message "Can't extract ${firm_qlogic_deb_file} file for ${DISTRO}." 3 ## }}} ## Download iwlwifi's firmware (for user's laptop) and uncompress it {{{ firm_iwlwifi_deb_file="${TEMP_DIR}/firmware-iwlwifi.deb" #wget http://deb.debian.org/debian/pool/non-free/f/firmware-nonfree/firmware-iwlwifi_0.43_all.deb download_file "${firm_iwlwifi_deb_url}" "${firm_iwlwifi_deb_file}" is_file_empty "${firm_iwlwifi_deb_file}" \ && error_message "${firm_iwlwifi_deb_file} file for ${DISTRO} is empty !" 3 dpkg-deb --extract "${firm_iwlwifi_deb_file}" "${TEMP_DIR}"/mkinitrd \ || error_message "Can't extract ${firm_iwlwifi_deb_file} file for ${DISTRO}." 3 ## }}} ## Make a new initrd {{{ new_initrd_file="${TEMP_DIR}/initrd.xz" mv "${initrd_file}" initrd_orig.gz pushd "${TEMP_DIR}"/mkinitrd/ > /dev/null \ || error_message "Can't move to ${TEMP_DIR}/mkinitrd/ temp directory." 2 ### With a very good compression rate find . | cpio --quiet --create --format=newc | xz --stdout -9 --check=crc32 > "${new_initrd_file}" is_file_empty "${new_initrd_file}" \ && error_message "New initrd ${new_initrd_file} file for ${DISTRO} is empty !" 3 popd > /dev/null \ || error_message "Can't move back from ${TEMP_DIR}/mkinitrd/ directory." 2 ## }}} ## Move new initrd to TFTP tree {{{ mkdir --parents -- "${TFTP_DIRECTORY}/installer/debian/${DISTRO}/amd64/" mv -- "${new_initrd_file}" "${TFTP_DIRECTORY}/installer/debian/${DISTRO}/amd64/initrd_firm.xz" ## }}} ## Leave temp directory and clean it {{{ popd > /dev/null \ || error_message "Can't move back from ${TEMP_DIR}/ directory." 2 rm --recursive --force -- "${TEMP_DIR}" ## }}} done } # }}} # Manage arguments # {{{ # This code can't be in a function due to argument management if [ ! "${NBARGS}" -eq "0" ]; then manage_arg="0" ## If the first argument is not an option if ! printf -- '%s' "${1}" | grep -q -E -- "^-+"; then ## Print help message and exit printf '%b\n' "${RED}Invalid option: ${1}${RESET}" printf '%b\n' "---" usage exit 1 fi # Parse all options (start with a "-") one by one while printf -- '%s' "${1}" | grep -q -E -- "^-+"; do case "${1}" in -d|--debug ) ## debug DEBUG=0 ;; -h|--help ) ## help usage ## Exit after help informations exit 0 ;; * ) ## unknow option printf '%b\n' "${RED}Invalid option: ${1}${RESET}" printf '%b\n' "---" usage exit 1 ;; esac debug_message "Arguments management − \ ${RED}${1}${COLOR_DEBUG} option managed." ## Move to the next argument shift manage_arg=$((manage_arg+1)) done debug_message "Arguments management − \ ${RED}${manage_arg}${COLOR_DEBUG} argument(s) successfully managed." else debug_message "Arguments management − \ No arguments/options to manage." fi # }}} main exit 0