redpill-load/build-loader.sh

292 lines
15 KiB
Bash
Raw Normal View History

1970-01-01 08:00:00 +08:00
#!/usr/bin/env bash
set -u
##### BASIC RUNTIME VALIDATION #########################################################################################
# shellcheck disable=SC2128
if [ -z "${BASH_SOURCE}" ] ; then
echo "You need to execute this script using bash v4+ without using pipes"
exit 1
fi
cd "${BASH_SOURCE%/*}/" || exit 1
########################################################################################################################
##### CONFIGURATION YOU CAN OVERRIDE USING ENVIRONMENT #################################################################
BRP_DEBUG=${BRP_DEBUG:-0} # whether you want to see debug messages
BRP_CACHE_DIR=${BRP_CACHE_DIR:-"$PWD/cache"} # cache directory where stuff is downloaded & unpacked
BRP_USER_CFG=${BRP_USER_CFG:-"$PWD/user_config.json"}
BRP_BUILD_DIR=${BRP_BUILD_DIR:-''} # makes sure attempts are unique; do not override this unless you're using repack
BRP_KEEP_BUILD=${BRP_KEEP_BUILD:-''} # will be set to 1 for repack method or 0 for direct
BRP_LINUX_PATCH_METHOD=${BRP_LINUX_PATCH_METHOD:-"direct"} # how to generate kernel image (direct bsp patch vs repack)
BRP_LINUX_SRC=${BRP_LINUX_SRC:-''} # used for repack method
BRP_BOOT_IMAGE=${BRP_BOOT_IMAGE:-"$PWD/ext/boot-image-template.img.gz"} # gz-ed "template" image to base final image on
# The options below are meant for debugging only. Setting them will create an image which is not normally usable
BRP_DEV_DISABLE_RP=${BRP_DEV_DISABLE_RP:-0} # when set to 1 the rp.ko will be renamed to rp-dis.ko
BRP_DEV_DISABLE_SB=${BRP_DEV_DISABLE_SB:-0} # when set to 1 the synobios.ko will be renamed to synobios-dis.ko
1970-01-01 08:00:00 +08:00
########################################################################################################################
##### INCLUDES #########################################################################################################
. include/log.sh # logging helpers
. include/text.sh # text manipulation
. include/runtime.sh # need to include this early so we can used date and such
. include/json.sh # json parsing routines
. include/config-manipulators.sh
. include/file.sh # file-related operations (copying/moving/unpacking etc)
. include/patch.sh # helpers for patching files using patch(1) and bspatch(1)
. include/boot-image.sh # helper functions for dealing with the boot image
########################################################################################################################
##### CONFIGURATION VALIDATION##########################################################################################
### Command line params handling
if [ $# -lt 2 ] || [ $# -gt 3 ]; then
echo "Usage: $0 platform version <output-file>"
exit 1
fi
BRP_HW_PLATFORM="$1"
BRP_SW_VERSION="$2"
BRP_OUTPUT_FILE="${3:-"$PWD/images/redpill-${BRP_HW_PLATFORM}_${BRP_SW_VERSION}_b$(date '+%s').img"}"
1970-01-01 08:00:00 +08:00
BRP_REL_CONFIG_BASE="$PWD/config/${BRP_HW_PLATFORM}/${BRP_SW_VERSION}"
BRP_REL_CONFIG_JSON="${BRP_REL_CONFIG_BASE}/config.json"
### Some config validation
if [ "${BRP_LINUX_PATCH_METHOD}" == "direct" ]; then
BRP_BUILD_DIR=${BRP_BUILD_DIR:-"$PWD/build/$(date '+%s')"}
1970-01-01 08:00:00 +08:00
BRP_KEEP_BUILD=${BRP_KEEP_BUILD:='0'}
1970-01-01 08:00:00 +08:00
elif [ "${BRP_LINUX_PATCH_METHOD}" == "repack" ]; then
if [ -z ${BRP_BUILD_DIR} ]; then
pr_crit "You've chosen \"%s\" method for patching - you must specify BRP_BUILD_DIR" "${BRP_LINUX_PATCH_METHOD}"
fi
1970-01-01 08:00:00 +08:00
BRP_KEEP_BUILD=${BRP_KEEP_BUILD:='1'}
1970-01-01 08:00:00 +08:00
if [ -z ${BRP_LINUX_SRC} ]; then
pr_crit "You've chosen \"repack\" method for patching - you must specify BRP_LINUX_SRC" "${BRP_LINUX_PATCH_METHOD}"
fi
if [ ! -f "${BRP_LINUX_SRC}/Kbuild" ]; then
pr_crit "BRP_LINUX_SRC=%s doesn't look like are valid Linux source tree (Kbuild not present)" "${BRP_LINUX_SRC}"
fi
if [ ! -f "${BRP_LINUX_SRC}/.config" ]; then
pr_crit "Kernel configuration file (%s/.config) doesn't exist - create one (or copy existing one)" "${BRP_LINUX_SRC}"
fi
else
pr_crit "BRP_LINUX_PATCH_METHOD=%s is not are valid value: {direct|repack}" "${BRP_LINUX_PATCH_METHOD}"
fi
if [ ! -f "${BRP_USER_CFG}" ]; then
pr_crit "User config (BRP_USER_CFG) \"%s\" doesn't exist" "${BRP_USER_CFG}"
fi
brp_json_validate "${BRP_USER_CFG}"
if [ ! -f "${BRP_REL_CONFIG_JSON}" ]; then
pr_crit "There doesn't seem to be a config for %s platform running %s (checked %s)" \
"${BRP_HW_PLATFORM}" "${BRP_SW_VERSION}" "${BRP_REL_CONFIG_JSON}"
fi
brp_json_validate "${BRP_REL_CONFIG_JSON}"
readonly BRP_REL_OS_ID=$(brp_json_get_field "${BRP_REL_CONFIG_JSON}" "os.id")
pr_dbg "******** Printing config variables ********"
pr_dbg "Cache dir: %s" "$BRP_CACHE_DIR"
pr_dbg "Build dir: %s" "$BRP_BUILD_DIR"
pr_dbg "User config: %s" "$BRP_USER_CFG"
pr_dbg "Keep build dir? %s" "$BRP_KEEP_BUILD"
pr_dbg "Linux patch method: %s" "$BRP_LINUX_PATCH_METHOD"
pr_dbg "Linux repack src: %s" "$BRP_LINUX_SRC"
pr_dbg "Hardware platform: %s" "$BRP_HW_PLATFORM"
pr_dbg "Software version: %s" "$BRP_SW_VERSION"
pr_dbg "Image template: %s" "$BRP_BOOT_IMAGE"
pr_dbg "Image destination: %s" "$BRP_OUTPUT_FILE"
pr_dbg "Release cfg base: %s" "$BRP_REL_CONFIG_BASE"
pr_dbg "Release cfg JSON: %s" "$BRP_REL_CONFIG_JSON"
pr_dbg "Release id: %s" "$BRP_REL_OS_ID"
pr_dbg "*******************************************"
##### SYSTEM IMAGE HANDLING ############################################################################################
readonly BRP_PAT_FILE="${BRP_CACHE_DIR}/${BRP_REL_OS_ID}.pat"
readonly BRP_UPAT_DIR="${BRP_BUILD_DIR}/pat-${BRP_REL_OS_ID}-unpacked"
if [ ! -d "${BRP_UPAT_DIR}" ]; then
pr_dbg "Unpacked PAT %s not found - preparing" "${BRP_UPAT_DIR}"
brp_mkdir "${BRP_UPAT_DIR}"
if [ ! -f "${BRP_PAT_FILE}" ]; then
readonly BRP_PAT_URL=$(brp_json_get_field "${BRP_REL_CONFIG_JSON}" "os.pat_url")
pr_info "PAT file %s not found - downloading from %s" "${BRP_PAT_FILE}" "${BRP_PAT_URL}"
"${CURL_PATH}" --output "${BRP_PAT_FILE}" "${BRP_PAT_URL}"
else
pr_dbg "Found existing PAT at %s - skipping download" "${BRP_PAT_FILE}"
fi
brp_verify_file_sha256 "${BRP_PAT_FILE}" "$(brp_json_get_field "${BRP_REL_CONFIG_JSON}" "os.sha256")"
brp_unpack_tar "${BRP_PAT_FILE}" "${BRP_UPAT_DIR}"
else
pr_info "Found unpacked PAT at \"%s\" - skipping unpacking" "${BRP_UPAT_DIR}"
fi
##### LINUX KERNEL MODIFICATIONS #######################################################################################
# Prepare Linux kernel image
readonly BRP_ZLINUX_FILE=${BRP_UPAT_DIR}/$(brp_json_get_field "${BRP_REL_CONFIG_JSON}" 'files.zlinux.name')
readonly BRP_ZLINUX_PATCHED_FILE="${BRP_BUILD_DIR}/zImage-patched"
if [ ! -f "${BRP_ZLINUX_PATCHED_FILE}" ]; then
# Using repack method to patch the kernel. This method assumes that it will be interrupted, someone will go and look
# at the unpacked file, patch it manually and re-run the process to continue packing
if [ "${BRP_LINUX_PATCH_METHOD}" == "repack" ]; then
readonly BRP_VMLINUX_FILE="${BRP_BUILD_DIR}/vmlinux.elf"
if [ ! -f "${BRP_VMLINUX_FILE}" ]; then
brp_unpack_zimage "${BRP_ZLINUX_FILE}" "${BRP_VMLINUX_FILE}"
else
pr_info "Found unpacked vmlinux at \"%s\" - skipping unpacking" "${BRP_VMLINUX_FILE}"
fi
brp_verify_file_sha256 "${BRP_VMLINUX_FILE}" "$(brp_json_get_field "${BRP_REL_CONFIG_JSON}" "files.vmlinux.sha256")"
readonly BRP_VMLINUX_PATCHED_FILE="${BRP_BUILD_DIR}/vmlinux-patched.elf"
if [ ! -f "${BRP_VMLINUX_PATCHED_FILE}" ]; then
pr_err "Patched unpacked Linux file \"%s\" doesn't exist. Create it based on \"%s\" and run the process again" \
"${BRP_VMLINUX_PATCHED_FILE}" "${BRP_VMLINUX_FILE}"
pr_warn "If you don't know what to do you picked A WRONG METHOD - read the README again. The method you used is for developers only!"
exit 1
else
pr_info "Found patched Linux kernel at \"%s\" - repacking" "${BRP_VMLINUX_PATCHED_FILE}"
brp_repack_zimage "${BRP_LINUX_SRC}" "${BRP_VMLINUX_PATCHED_FILE}" "${BRP_ZLINUX_PATCHED_FILE}"
fi
else # we can just "else" for "direct" creation method since it should be checked at the top
brp_verify_file_sha256 "${BRP_ZLINUX_FILE}" "$(brp_json_get_field "${BRP_REL_CONFIG_JSON}" "files.zlinux.sha256")"
brp_apply_binary_patches \
"${BRP_ZLINUX_FILE}" \
"${BRP_ZLINUX_PATCHED_FILE}" \
"$(brp_json_get_array_values "${BRP_REL_CONFIG_JSON}" 'patches.zlinux')" \
"${BRP_REL_CONFIG_BASE}"
fi
else
pr_info "Found patched zImage at \"%s\" - skipping patching & repacking" "${BRP_ZLINUX_PATCHED_FILE}"
fi
##### RAMDISK MODIFICATIONS ############################################################################################
# here we have a ready kernel in BRP_ZLINUX_PATCHED_FILE which makes the end of playing with the kernel
# Now we can begin to take care of the ramdisk
readonly BRP_RD_FILE=${BRP_UPAT_DIR}/$(brp_json_get_field "${BRP_REL_CONFIG_JSON}" 'files.ramdisk.name') # original ramdisk file
readonly BRP_URD_DIR="${BRP_BUILD_DIR}/rd-${BRP_REL_OS_ID}-unpacked" # folder with unpacked ramdisk contents
readonly BRP_RD_REPACK="${BRP_BUILD_DIR}/rd-patched-${BRP_REL_OS_ID}.gz" # repacked ramdisk file
#rm -rf build/testing/rd-* # for debugging ramdisk routines; also comment-out rm of BRP_URD_DIR
#rm "${BRP_RD_REPACK}" # for testing
if [ ! -f "${BRP_RD_REPACK}" ]; then # do we even need to unpack-modify-repack the ramdisk or was it already done?
if [ ! -d "${BRP_URD_DIR}" ]; then # do we need to unpack the ramdisk first?
pr_dbg "Unpacked ramdisk %s not found - preparing" "${BRP_URD_DIR}"
brp_mkdir "${BRP_URD_DIR}"
brp_verify_file_sha256 "${BRP_RD_FILE}" "$(brp_json_get_field "${BRP_REL_CONFIG_JSON}" "files.ramdisk.sha256")"
brp_unpack_zrd "${BRP_RD_FILE}" "${BRP_URD_DIR}"
else
pr_info "Found unpacked ramdisk at \"%s\" - skipping unpacking" "${BRP_URD_DIR}"
fi
# Applies all static .patch files to the ramdisk
brp_apply_text_patches \
"${BRP_URD_DIR}" \
"$(brp_json_get_array_values "${BRP_REL_CONFIG_JSON}" 'patches.ramdisk')" \
"${BRP_REL_CONFIG_BASE}"
# Now we apply dynamic patches for configs
# These paths look to be static throughout maaaaany years, so they're not in config file - if needed it's easy to move
# them to the JSON file
readonly BRP_POST_INIT_FILE="${BRP_URD_DIR}/sbin/init.post" # file with @@@CONFIG-MANIPULATORS-TOOLS@@@ and @@@CONFIG-GENERATED@@@
readonly BRP_RD_CONFS=("${BRP_URD_DIR}/etc/synoinfo.conf" "${BRP_URD_DIR}/etc.defaults/synoinfo.conf") # files to patch in the baked-in ramdisk
readonly BRP_OS_CONFS=("/tmpRoot/etc/synoinfo.conf" "/tmpRoot/etc.defaults/synoinfo.conf") # paths of files on the OS partition (valid after the RD boots)
# Patch preboot (statically)
pr_process "Patching config files in ramdisk"
brp_patch_config_files "${BRP_REL_CONFIG_JSON}" 'synoinfo' "${BRP_RD_CONFS[@]}" # first apply platform changes
brp_patch_config_files "${BRP_USER_CFG}" 'synoinfo' "${BRP_RD_CONFS[@]}" # then apply user changes
pr_process_ok
# Next we need to ensure the same patches are applied to post-boot environment too (dynamically)
pr_process "Adding OS config patching"
BRP_TEMP_ARRAY=(); brp_generate_set_confs_calls \
"${BRP_REL_CONFIG_JSON}" 'synoinfo' BRP_TEMP_ARRAY "${BRP_OS_CONFS[@]}" # platform configs
BRP_OS_CONFS_LINES="$(brp_array_to_text $'\n' "${BRP_TEMP_ARRAY[@]}")"
BRP_TEMP_ARRAY=(); brp_generate_set_confs_calls \
"${BRP_USER_CFG}" 'synoinfo' BRP_TEMP_ARRAY "${BRP_OS_CONFS[@]}" # user configs
BRP_OS_CONFS_LINES+=$'\n'"$(brp_array_to_text $'\n' "${BRP_TEMP_ARRAY[0]+"${BRP_TEMP_ARRAY[@]}"}")"
brp_replace_token_with_script "${BRP_POST_INIT_FILE}" '@@@CONFIG-MANIPULATORS-TOOLS@@@' "$PWD/include/config-manipulators.sh"
brp_replace_token_with_text "${BRP_POST_INIT_FILE}" '@@@CONFIG-GENERATED@@@' "${BRP_OS_CONFS_LINES}"
pr_process_ok
# Copy any extra files
brp_cp_from_list "${BRP_REL_CONFIG_JSON}" "extra.ramdisk_copy" "${BRP_REL_CONFIG_BASE}" "${BRP_URD_DIR}"
brp_cp_from_list "${BRP_USER_CFG}" "ramdisk_copy" '' "${BRP_URD_DIR}" # no src prefix => user can use absolute paths
# Handle debug flags
if [ "${BRP_DEV_DISABLE_RP}" -eq 1 ]; then
pr_warn "<DEV> Disabling RedPill LKM"
"${MV_PATH}" "${BRP_URD_DIR}/usr/lib/modules/rp.ko" "${BRP_URD_DIR}/usr/lib/modules/rp-dis.ko" \
|| pr_crit "Failed to move RedPill LKM"
fi
if [ "${BRP_DEV_DISABLE_SB}" -eq 1 ]; then
pr_warn "<DEV> Disabling mfgBIOS LKM"
"${MV_PATH}" "${BRP_URD_DIR}/usr/lib/modules/synobios.ko" "${BRP_URD_DIR}/usr/lib/modules/synobios-dis.ko" \
|| pr_crit "Failed to move mfgBIOS LKM"
fi
1970-01-01 08:00:00 +08:00
# Finally, we can finish ramdisk modifications with repacking it
readonly BRP_RD_COMPRESSED=$(brp_json_get_field "${BRP_REL_CONFIG_JSON}" "extra.compress_rd")
pr_process "Repacking ramdisk to %s" "${BRP_RD_REPACK}"
if [ "${BRP_RD_COMPRESSED}" == "true" ]; then
brp_pack_zrd "${BRP_RD_REPACK}" "${BRP_URD_DIR}"
elif [ "${BRP_RD_COMPRESSED}" == "false" ]; then
brp_pack_cpiord "${BRP_RD_REPACK}" "${BRP_URD_DIR}"
else
pr_crit "Invalid value for platform extra.compress_rd (expected bool, got \"%s\")" "${BRP_RD_COMPRESSED}"
fi
pr_process_ok
# remove unpacked ramdisk in case the script is run again (to prevent stacking changes); this should happen even if
# BRP_KEEP_BUILD is set!
pr_dbg "Removing old unpacked RD files"
"${RM_PATH}" -rf "${BRP_URD_DIR}" || pr_warn "Failed to remove unpacked ramdisk %s" "${BRP_URD_DIR}"
else
pr_info "Found repacked ramdisk at \"%s\" - skipping patching & repacking" "${BRP_URD_DIR}"
fi
##### PREPARE GRUB CONFIG ##############################################################################################
readonly BRP_TMP_GRUB_CONF="${BRP_BUILD_DIR}/grub.cfg"
pr_process "Generating GRUB config"
brp_generate_grub_conf "${BRP_REL_CONFIG_JSON}" "${BRP_USER_CFG}" "${BRP_REL_CONFIG_BASE}" "${BRP_TMP_GRUB_CONF}"
pr_process_ok
##### CREATE FINAL LOADER IMAGE ########################################################################################
pr_process "Creating loader image at %s" "${BRP_OUTPUT_FILE}"
brp_unpack_single_gz "${BRP_BOOT_IMAGE}" "${BRP_OUTPUT_FILE}"
readonly BRP_OUT_P1="$(brp_mount_img_partitions "${BRP_OUTPUT_FILE}" 1 "${BRP_BUILD_DIR}/img-mnt")" # partition 1 of img
readonly BRP_OUT_P2="$(brp_mount_img_partitions "${BRP_OUTPUT_FILE}" 2 "${BRP_BUILD_DIR}/img-mnt")" # partition 2 of img
readonly BRP_ZLINMOD_NAME="zImage" # name of the linux kernel in the final image
readonly BRP_RDMOD_NAME="rd.gz" # name of the ramdisk in the final image
brp_cp_flat "${BRP_ZLINUX_PATCHED_FILE}" "${BRP_OUT_P1}/${BRP_ZLINMOD_NAME}"
brp_cp_flat "${BRP_RD_REPACK}" "${BRP_OUT_P1}/${BRP_RDMOD_NAME}"
brp_cp_flat "${BRP_TMP_GRUB_CONF}" "${BRP_OUT_P1}/boot/grub/grub.cfg"
pr_process_ok
##### CLEANUP ##########################################################################################################
pr_process "Cleaning up"
brp_detach_image "${BRP_OUTPUT_FILE}"
1970-01-01 08:00:00 +08:00
if [ "${BRP_KEEP_BUILD}" -eq 0 ]; then
"${RM_PATH}" -rf "${BRP_BUILD_DIR}"
fi
1970-01-01 08:00:00 +08:00
pr_process_ok