summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.sh6
-rwxr-xr-xkflash.sh322
2 files changed, 328 insertions, 0 deletions
diff --git a/config.sh b/config.sh
index d6b6db8..d11551e 100644
--- a/config.sh
+++ b/config.sh
@@ -9,6 +9,12 @@ cross_compile[arm64]=aarch64-buildroot-linux-gnu-
#
# Directories
#
+# Variable name: flash_mount_point
+#
+# Path to a directory where the target disk can be mounted.
+#
+flash_mount_point=/mnt/disk
+#
# Variable name: target_root[]
#
# Path to the root directory of the target file system for each architecture.
diff --git a/kflash.sh b/kflash.sh
new file mode 100755
index 0000000..92ca9dd
--- /dev/null
+++ b/kflash.sh
@@ -0,0 +1,322 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0+
+
+set -e
+
+kbuild_root=$(dirname $(readlink -f "$0"))
+
+declare -A cross_compile
+declare -A extra_kcflags
+declare -A target_root
+
+if [[ -r $kbuild_root/config.sh ]] ; then
+ source $kbuild_root/config.sh || exit 1
+fi
+
+#
+# Options parsing
+#
+
+dry_run=0
+silent=0
+sudo=sudo
+
+while [[ $# != 0 ]] ; do
+ option=$1
+ shift
+
+ case $option in
+ --dry-run)
+ dry_run=1
+ sudo=echo
+ ;;
+ --silent)
+ silent=1
+ ;;
+ --*|-*)
+ echo "Unrecognized option $option"
+ exit 1
+ ;;
+ *)
+ platform=$option
+ ;;
+ esac
+done
+
+#
+# Platform
+#
+
+if [[ -z "$platform" ]] ; then
+ for f in $kbuild_root/platforms/*.sh ; do
+ pattern=$(cat $f | grep "dir_pattern=" | head -1)
+ pattern=${pattern/#dir_pattern=/}
+ if [[ -n "$pattern" ]] ; then
+ echo $PWD | grep -q "$pattern" || continue
+ platform=$(basename -s .sh $f)
+ break
+ fi
+ done
+fi
+
+if [[ ! -r "$kbuild_root/platforms/$platform.sh" ]] ; then
+ echo "Unknown platform '$platform'. Supported platforms are"
+ for f in $kbuild_root/platforms/*.sh ; do
+ echo "- $(basename -s .sh $f)"
+ done
+ exit 1
+fi
+
+source "${kbuild_root}/platforms/$platform.sh" || exit 1
+
+if [[ "${#flash_parts[@]}" -lt 1 ]] ; then
+ echo "Platform '$platform' doesn't declare flash_parts, can't flash"
+ exit 1
+fi
+
+#
+# Architecture
+#
+
+if [[ ! -r "$kbuild_root/arch/$arch.sh" ]] ; then
+ echo "Unknown architecture '$arch'. Supported architectures are"
+ for f in $kbuild_root/arch/*.sh ; do
+ echo "- $(basename -s .sh $f)"
+ done
+ exit 1
+fi
+
+source "${kbuild_root}/arch/$arch.sh" || exit 1
+
+# Override the output directory for ARM for historical reasons
+case $arch in
+ arm)
+ output_dir=$PWD/output/arm32
+ ;;
+ *)
+ output_dir=$PWD/output/$arch
+ ;;
+esac
+
+target_dir=${target_dir:-${target_root[$arch]}}
+tftp_dir=${tftp_dir:-$tftp_root/$platform}
+
+if [[ -r "$kbuild_root/images/$image.sh" ]] ; then
+ source "${kbuild_root}/images/$image.sh" || exit 1
+ eval make_${image}_image
+else
+ image_file=$output_dir/arch/$arch/boot/$image
+fi
+
+#
+# Validate the partition names and paths
+#
+
+for part_name in ${!flash_parts[@]} ; do
+ case $part_name in
+ dt|kernel|modules)
+ ;;
+ *)
+ echo "Unknown partition name '$part_name'"
+ exit 1
+ ;;
+ esac
+
+ ifs="$IFS"; IFS=";" read -ra flash_part <<< "${flash_parts[$part_name]}"; IFS="$ifs"
+ part_path=${flash_part[2]}
+
+ case $part_path in
+ RAW|/*)
+ ;;
+ *)
+ echo "Unknown partition path '$part_path'"
+ exit 1
+ ;;
+ esac
+done
+
+#
+# Locate the flash device
+#
+
+probe_device() {
+ local dev=$1
+
+ # Skip devices that don't exist.
+ if [[ ! -b /dev/$dev ]] ; then
+ return
+ fi
+
+ # Add the 'p' suffix for MMC devices.
+ local partdev=$dev
+ echo $dev | grep -q mmcblk && partdev=${partdev}p
+
+ #
+ # Safety check: make sure the number and name of the partitions we will
+ # flash match the expectations.
+ #
+ local part_count=$(ls -1 /dev/ | grep "${partdev}[0-9]" | wc -l)
+ if [[ $part_count != $flash_parts_num ]] ; then
+ echo "Device /dev/$dev has $part_count partitions, $flash_parts_num expected" >&2
+ return
+ fi
+
+ local part_name
+ for part_name in ${!flash_parts[@]} ; do
+ local flash_part
+ IFS=";" read -ra flash_part <<< "${flash_parts[$part_name]}"
+
+ local part_idx=${flash_part[0]}
+ local part_label=${flash_part[1]}
+ local part_dev=/dev/${partdev}${i}
+
+ local label=$(blkid ${part_dev} -s PARTLABEL | sed 's/.*PARTLABEL="\([^"]*\)"$/\1/')
+ if [[ $label != ${part_label} ]] ; then
+ echo "Partition ${part_dev} has label '$label', expected '${part_label}'" >&2
+ return
+ fi
+ done
+
+ echo /dev/$partdev
+}
+
+disks="mmcblk0 sda"
+dev=
+
+for disk in $disks ; do
+ dev=$(probe_device "$disk")
+ if [[ -n "$dev" ]] ; then
+ break
+ fi
+done
+
+if [[ -z "$dev" ]] ; then
+ echo "No flash device found"
+ exit 1
+fi
+
+echo "Found flash device ${dev}"
+
+#
+# Safety check: make sure nothing is mounted on $flash_mount_point, and no
+# partition from the device is mounted.
+#
+
+if mount | grep -q " on $flash_mount_point " ; then
+ echo "File system already mounted on $flash_mount_point."
+ exit 1
+fi
+
+if mount | grep -q "$dev" ; then
+ echo "Please unmount partitions $dev* before proceeding."
+ exit 1
+fi
+
+#
+# Safety check: make sure the kernel modules are installed.
+#
+
+version=$(cat $output_dir/include/generated/utsrelease.h | cut -d '"' -f 2)
+mod_path="$target_dir/lib/modules/$version"
+
+if [[ ! -d "$mod_path" ]] ; then
+ echo "Modules not installed in $mod_path"
+ exit 1
+fi
+
+#
+# Flash
+#
+
+for part_name in ${!flash_parts[@]} ; do
+ IFS=";" read -ra flash_part <<< "${flash_parts[$part_name]}"
+ part_idx=${flash_part[0]}
+
+ if [[ -z "$flash_msg" ]] ; then
+ flash_msg="Will flash $part_name to ${dev}${part_idx}"
+ else
+ flash_msg="${flash_msg}, $part_name to ${dev}${part_idx}"
+ fi
+done
+
+if [[ ${dry_run} == 1 ]] ; then
+ flash_msg="${flash_msg} (dry-run)"
+fi
+
+echo "${flash_msg}."
+echo -n "Proceed? [y/N] "
+
+read answer
+
+if [[ x$answer != xy ]] ; then
+ echo "Aborted"
+ exit 1
+fi
+
+flash_raw() {
+ local dst="$1"
+ local src="$3"
+
+ ${sudo} dd if="$src" of="$dst" bs=64k
+}
+
+flash_fs() {
+ local dev="$1"
+ local dst="${flash_mount_point}$2"
+ local src="$3"
+
+ ${sudo} mount "$dev" "$flash_mount_point"
+ trap "${sudo} umount $flash_mount_point" EXIT
+
+ if [[ -f "$src" ]] ; then
+ ${sudo} cp "$src" "$dst"
+ else
+ ${sudo} rsync -av --delete "$src" "$dst"
+ fi
+
+ trap - EXIT
+ ${sudo} umount "$flash_mount_point"
+}
+
+for part_name in ${!flash_parts[@]} ; do
+ IFS=";" read -ra flash_part <<< "${flash_parts[$part_name]}"
+ part_idx=${flash_part[0]}
+ part_path=${flash_part[2]}
+
+ echo "Flashing ${part_name} (${part_path})"
+
+ case $part_path in
+ RAW)
+ flash_cmd="flash_raw"
+ ;;
+ /*)
+ flash_cmd="flash_fs"
+ ;;
+ esac
+
+ case $part_name in
+ dt)
+ # For DT, only flash the first entry. This can be improved later if
+ # needed.
+ read -ra _dtbs <<< "$dtbs"
+ _dtb=${_dtbs[0]}
+ _dtb_src="$output_dir/arch/${arch}/boot/dts/${_dtb/:*/}"
+ _dtb_dst=${_dtb/*:/}
+ _dtb_dst=${_dtb_dst/*\//}
+
+ $flash_cmd "${dev}${part_idx}" "${part_path}/${_dtb_dst}" "${_dtb_src}"
+ ;;
+ kernel)
+ $flash_cmd "${dev}${part_idx}" "${part_path}/" "${image_file}"
+ ;;
+ modules)
+ $flash_cmd "${dev}${part_idx}" "${part_path}/" "${mod_path}"
+ ;;
+ esac
+done
+
+echo "Files copied, syncing"
+${sudo} sync
+echo "Done"
+
+[[ $silent == 0 ]] && play -q -n synth 0.1 sin 880