Martin Roth | a95cd26 | 2021-07-27 14:56:11 -0600 | [diff] [blame] | 1 | #!/usr/bin/env bash |
| 2 | # SPDX-License-Identifier: BSD-3-Clause |
| 3 | |
| 4 | ROM="$1" |
| 5 | declare -i NEW_SPEED="$2" |
| 6 | |
| 7 | readonly EFS_SIG_DWORD="55aa55aa" |
| 8 | readonly FAST_SPEED_NEW_F15_MOD_60_6F_OFFSET=0x41 |
| 9 | readonly SPI_FASTSPEED_F17_MOD_00_2F_OFFSET=0x44 |
| 10 | readonly SPI_FASTSPEED_F17_MOD_30_3F_OFFSET=0x48 |
| 11 | |
| 12 | # print out the very simple usage |
| 13 | usage() { |
| 14 | echo "Usage: $0 <ROM> <Speed>" |
| 15 | echo " Speed must be between 0 & 5" |
| 16 | echo " 0: 66.66Mhz" |
| 17 | echo " 1: 33.33MHz" |
| 18 | echo " 2: 22.22MHz" |
| 19 | echo " 3: 16.66MHz" |
| 20 | echo " 4: 100MHz" |
| 21 | echo " 5: 800KHz" |
| 22 | } |
| 23 | |
| 24 | # Validate the input parameters |
| 25 | if [[ $# -ne 2 || ! -f "${ROM}" || "${NEW_SPEED}" -lt 0 || "${NEW_SPEED}" -gt 5 ]]; then |
| 26 | usage |
| 27 | exit 1 |
| 28 | fi |
| 29 | |
| 30 | # Read a 32, 16, or 8 bit value from a location in a binary file |
| 31 | getval() { |
| 32 | local location=$1 |
| 33 | local length=$2 |
| 34 | |
| 35 | if [[ ${length} -eq 1 ]]; then |
| 36 | dd "if=${ROM}" bs=1 "skip=${location}" "count=${length}" 2>/dev/null | hexdump -v -e '1/1 "%02x\n"' |
| 37 | elif [[ ${length} -eq 2 ]]; then |
| 38 | dd "if=${ROM}" bs=1 "skip=${location}" "count=${length}" 2>/dev/null | hexdump -v -e '1/2 "%04x\n"' |
| 39 | elif [[ ${length} -eq 4 ]]; then |
| 40 | dd "if=${ROM}" bs=1 "skip=${location}" "count=${length}" 2>/dev/null | hexdump -v -e '1/4 "%08x\n"' |
| 41 | else |
| 42 | echo "Error: invalid value" |
| 43 | exit 1 |
| 44 | fi |
| 45 | } |
| 46 | |
| 47 | # Update a location in a binary |
| 48 | # Note that the passed in value must be formatted correctly: |
| 49 | # Each byte needs to be specified as "\\xXX" where X is a hex digit |
| 50 | setval() { |
| 51 | local location=$1 |
| 52 | local length=$2 |
| 53 | local hexval=$3 |
| 54 | |
| 55 | # shellcheck disable=SC2059 |
| 56 | if ! printf "$hexval" | dd "of=${ROM}" bs=1 "seek=${location}" "count=${length}" conv=notrunc status=none; then |
| 57 | echo "Error: Could not write to ${ROM}" |
| 58 | exit 1 |
| 59 | fi |
| 60 | } |
| 61 | |
| 62 | # Print the speed associated with the passed-in value |
| 63 | showspeed() { |
| 64 | local speedval=$1 |
| 65 | case ${speedval} in |
| 66 | 0 | 00) echo "0: 66.66Mhz" ;; |
| 67 | 1 | 01) echo "1: 33.33MHz" ;; |
| 68 | 2 | 02) echo "2: 22.22MHz" ;; |
| 69 | 3 | 03) echo "3: 16.66MHz" ;; |
| 70 | 4 | 04) echo "4: 100MHz" ;; |
| 71 | 5 | 05) echo "5: 800KHz" ;; |
| 72 | ff) echo "Error: Speed not set" ;; |
| 73 | *) echo "Error: Unknown speed (${speedval})" ;; |
| 74 | esac |
| 75 | } |
| 76 | |
| 77 | # Locate the SPI speed data and update it to the new speed |
| 78 | update_efs() { |
| 79 | local location=$1 |
| 80 | local updated_speed=0 |
| 81 | |
| 82 | 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 |
| 83 | local speed_val |
| 84 | local speed_loc=$((location + speed_offset)) |
| 85 | speed_val=$(getval "${speed_loc}" "1") |
| 86 | |
| 87 | if [[ "${speed_val}" != "ff" ]]; then |
| 88 | printf "Found speed value of %s at %#06x\n" "$(showspeed "${speed_val}")" "${speed_loc}" |
| 89 | updated_speed=1 |
| 90 | setval "${speed_loc}" "1" "\\x0${NEW_SPEED}" |
| 91 | speed_val=$(getval "${speed_loc}" "1") |
| 92 | printf "New speed value: %s\n" "$(showspeed "${speed_val}")" |
| 93 | fi |
| 94 | |
| 95 | done |
| 96 | if [[ ${updated_speed} -eq 0 ]]; then |
| 97 | echo "Error: Could not find speed value to update." |
| 98 | exit 1 |
| 99 | fi |
| 100 | } |
| 101 | |
| 102 | # Find the EFS location and update the speed |
| 103 | main() { |
| 104 | local location |
| 105 | local val |
| 106 | |
| 107 | for i in {0..5}; do |
| 108 | location="$((0xffffff - (0x80000 << i) + 0x20000 + 1))" |
| 109 | val="$(getval "${location}" 4 )" |
| 110 | if [[ "${val}" == "${EFS_SIG_DWORD}" ]]; then |
| 111 | printf "EFS found at %#06x\n" "${location}" |
| 112 | update_efs "${location}" |
| 113 | exit 0 |
| 114 | fi |
| 115 | done |
| 116 | |
| 117 | echo "Error: EFS not found in ${ROM}." |
| 118 | exit 1 |
| 119 | } |
| 120 | |
| 121 | main |