The update_efs_spi_speed allows changing the SPI speed manually in a binary that has already been built. This will allow binaries not built for the EM100 SPI ROM emulator to be updated so that they will work. There is a corresponding change that will check to see if the EFS value has been modified from the original speed and will prevent coreboot from updating the SPI speed and mode. BUG=b:177233017 TEST=Update SPI speed in existing binary. See that SPI speed has changed. Signed-off-by: Martin Roth <martin@coreboot.org> Change-Id: I905a9fd8bd93a28aab927dffecbbcf24934b9e03 Reviewed-on: https://review.coreboot.org/c/coreboot/+/56644 Reviewed-by: Raul Rangel <rrangel@chromium.org> Reviewed-by: Karthik Ramasubramanian <kramasub@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
		
			
				
	
	
		
			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
 |