122 lines
3.3 KiB
Bash
Executable File
122 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
ROM="$1"
|
|
declare -i NEW_SPEED="$2"
|
|
|
|
readonly EFS_SIG_DWORD="55aa55aa"
|
|
readonly FAST_SPEED_NEW_F15_MOD_60_6F_OFFSET=0x41
|
|
readonly SPI_FASTSPEED_F17_MOD_00_2F_OFFSET=0x44
|
|
readonly SPI_FASTSPEED_F17_MOD_30_3F_OFFSET=0x48
|
|
|
|
# print out the very simple usage
|
|
usage() {
|
|
echo "Usage: $0 <ROM> <Speed>"
|
|
echo " Speed must be between 0 & 5"
|
|
echo " 0: 66.66Mhz"
|
|
echo " 1: 33.33MHz"
|
|
echo " 2: 22.22MHz"
|
|
echo " 3: 16.66MHz"
|
|
echo " 4: 100MHz"
|
|
echo " 5: 800KHz"
|
|
}
|
|
|
|
# Validate the input parameters
|
|
if [[ $# -ne 2 || ! -f "${ROM}" || "${NEW_SPEED}" -lt 0 || "${NEW_SPEED}" -gt 5 ]]; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
# Read a 32, 16, or 8 bit value from a location in a binary file
|
|
getval() {
|
|
local location=$1
|
|
local length=$2
|
|
|
|
if [[ ${length} -eq 1 ]]; then
|
|
dd "if=${ROM}" bs=1 "skip=${location}" "count=${length}" 2>/dev/null | hexdump -v -e '1/1 "%02x\n"'
|
|
elif [[ ${length} -eq 2 ]]; then
|
|
dd "if=${ROM}" bs=1 "skip=${location}" "count=${length}" 2>/dev/null | hexdump -v -e '1/2 "%04x\n"'
|
|
elif [[ ${length} -eq 4 ]]; then
|
|
dd "if=${ROM}" bs=1 "skip=${location}" "count=${length}" 2>/dev/null | hexdump -v -e '1/4 "%08x\n"'
|
|
else
|
|
echo "Error: invalid value"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Update a location in a binary
|
|
# Note that the passed in value must be formatted correctly:
|
|
# Each byte needs to be specified as "\\xXX" where X is a hex digit
|
|
setval() {
|
|
local location=$1
|
|
local length=$2
|
|
local hexval=$3
|
|
|
|
# shellcheck disable=SC2059
|
|
if ! printf "$hexval" | dd "of=${ROM}" bs=1 "seek=${location}" "count=${length}" conv=notrunc status=none; then
|
|
echo "Error: Could not write to ${ROM}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Print the speed associated with the passed-in value
|
|
showspeed() {
|
|
local speedval=$1
|
|
case ${speedval} in
|
|
0 | 00) echo "0: 66.66Mhz" ;;
|
|
1 | 01) echo "1: 33.33MHz" ;;
|
|
2 | 02) echo "2: 22.22MHz" ;;
|
|
3 | 03) echo "3: 16.66MHz" ;;
|
|
4 | 04) echo "4: 100MHz" ;;
|
|
5 | 05) echo "5: 800KHz" ;;
|
|
ff) echo "Error: Speed not set" ;;
|
|
*) echo "Error: Unknown speed (${speedval})" ;;
|
|
esac
|
|
}
|
|
|
|
# Locate the SPI speed data and update it to the new speed
|
|
update_efs() {
|
|
local location=$1
|
|
local updated_speed=0
|
|
|
|
for speed_offset in FAST_SPEED_NEW_F15_MOD_60_6F_OFFSET SPI_FASTSPEED_F17_MOD_00_2F_OFFSET SPI_FASTSPEED_F17_MOD_30_3F_OFFSET; do
|
|
local speed_val
|
|
local speed_loc=$((location + speed_offset))
|
|
speed_val=$(getval "${speed_loc}" "1")
|
|
|
|
if [[ "${speed_val}" != "ff" ]]; then
|
|
printf "Found speed value of %s at %#06x\n" "$(showspeed "${speed_val}")" "${speed_loc}"
|
|
updated_speed=1
|
|
setval "${speed_loc}" "1" "\\x0${NEW_SPEED}"
|
|
speed_val=$(getval "${speed_loc}" "1")
|
|
printf "New speed value: %s\n" "$(showspeed "${speed_val}")"
|
|
fi
|
|
|
|
done
|
|
if [[ ${updated_speed} -eq 0 ]]; then
|
|
echo "Error: Could not find speed value to update."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Find the EFS location and update the speed
|
|
main() {
|
|
local location
|
|
local val
|
|
|
|
for i in {0..5}; do
|
|
location="$((0xffffff - (0x80000 << i) + 0x20000 + 1))"
|
|
val="$(getval "${location}" 4 )"
|
|
if [[ "${val}" == "${EFS_SIG_DWORD}" ]]; then
|
|
printf "EFS found at %#06x\n" "${location}"
|
|
update_efs "${location}"
|
|
exit 0
|
|
fi
|
|
done
|
|
|
|
echo "Error: EFS not found in ${ROM}."
|
|
exit 1
|
|
}
|
|
|
|
main
|