Martin Roth has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/56644 )
Change subject: util/amdtools: Add script to update the SPI speed in the EFS header ......................................................................
util/amdtools: Add script to update the SPI speed in the EFS header
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 update 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.
Updated documentation to go along with new script.
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 --- M util/amdtools/README M util/amdtools/description.md A util/amdtools/update_efs_spi_speed 3 files changed, 157 insertions(+), 25 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/44/56644/1
diff --git a/util/amdtools/README b/util/amdtools/README index 06e6910..3984114 100644 --- a/util/amdtools/README +++ b/util/amdtools/README @@ -1,31 +1,32 @@ +# amdtools +Various tools for AMD platforms
+## A tool to update the SPI speed set in the EFS table + This works for Stoney Ridge and Zen class AMD processors. + - update_efs_spi_speed
-This is a set of tools to compare (extended) K8 memory settings. +## A set of tools to compare (extended) K8 memory settings. + - k8-compare-pci-space.pl + - k8-interpret-extended-memory-settings.pl + - k8-read-mem-settings.sh + - parse-bkdg.pl
-Before you can use them, you need to massage the relevant BKDG sections into -useable data. Here's how. + Before you can use them, you need to massage the relevant BKDG + sections into useable data. Here's how.
-First, you need to acquire a copy of the K8 BKDG. Go here: + 1. First, you need to acquire a copy of the K8 BKDG. Go here: + Rev F: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/3255... + 2. Make sure pdftotext is installed (it's in the poppler-utils + package on Debian/Ubuntu). + 3. Run the bkdg through pdftotext: + `pdftotext -layout 32559.pdf 32559.txt` + 4. Extract sections 4.5.15 - 4.5.19 from the file, and save it + separately, say as bkdg-raw.data.
- Rev F: http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/3255... + 5. Finally run the txt file through the parse-bkdg.pl script like so: + `parse-bkdg.pl < bkdg-raw.data > bkdg.data`
-Then make sure pdftotext is installed (it's in the poppler-utils package on Debian/Ubuntu). + Now we have the bkdg.data file that is used by the other scripts.
-Now run the bkdg through pdftotext: - - pdftotext -layout 32559.pdf 32559.txt - -Now extract sections 4.5.15 - 4.5.19 from the file, and save it separately, say as bkdg-raw.data. - -Finally run the txt file through the parse-bkdg.pl script like so: - - parse-bkdg.pl < bkdg-raw.data > bkdg.data - -Now we have the bkdg.data file that is used by the other scripts. - -If you want to test the scripts without doing all this work, you can use some -sample input files from the 'example_input/' directory. - --- -Ward Vandewege, 2009-10-28. -ward@jhvc.com + If you want to test the scripts without doing all this work, you + can use some sample input files from the 'example_input/' directory. diff --git a/util/amdtools/description.md b/util/amdtools/description.md index 17642ab..1faac5b 100644 --- a/util/amdtools/description.md +++ b/util/amdtools/description.md @@ -1 +1,11 @@ -A set of tools to compare extended) K8 memory settings. `Perl` +Various tools for AMD processors +* update_efs_spi_speed - Change SPI speed in binary. `Bash` +* A set of tools to compare extended K8 memory settings. `Perl` + * k8-compare-pci-space.pl - Shows differences between values + in PCI space and the default value. `Perl` + * k8-interpret-extended-memory-settings.pl - Shows differences + between memory controller values and the default value. `Perl` + * k8-read-mem-settings.sh - Makes data files understood by the + k8-interpret-extended-memory-settings script. `Perl` + * parse-bkdg.pl - Make bkdg.data file used by above scripts. `Perl` + * example_input - Sample input for the above scripts. `Text` diff --git a/util/amdtools/update_efs_spi_speed b/util/amdtools/update_efs_spi_speed new file mode 100755 index 0000000..d1e436f --- /dev/null +++ b/util/amdtools/update_efs_spi_speed @@ -0,0 +1,121 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: BSD-3-Clause + +ROM=$1 +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 2>/dev/null; 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