summaryrefslogtreecommitdiff
path: root/meta-google
diff options
context:
space:
mode:
Diffstat (limited to 'meta-google')
-rw-r--r--meta-google/recipes-google/ipmi/ipmi-fru-sh/lib.sh72
1 files changed, 52 insertions, 20 deletions
diff --git a/meta-google/recipes-google/ipmi/ipmi-fru-sh/lib.sh b/meta-google/recipes-google/ipmi/ipmi-fru-sh/lib.sh
index 940be7fb0..d02eeab47 100644
--- a/meta-google/recipes-google/ipmi/ipmi-fru-sh/lib.sh
+++ b/meta-google/recipes-google/ipmi/ipmi-fru-sh/lib.sh
@@ -23,6 +23,20 @@ IPMI_FRU_COMMON_HEADER_MULTI_RECORD_OFFSET_IDX=5
IPMI_FRU_AREA_HEADER_SIZE_IDX=1
IPMI_FRU_CHECKSUM_IDX=-1
+offset_1bw() {
+ local addr="$1"
+ local off="$2"
+ local extra="${3-0}"
+ echo w$((1+extra))@$addr $(( off & 0xff ))
+}
+
+offset_2bw() {
+ local addr="$1"
+ local off="$2"
+ local extra="${3-0}"
+ echo w$((2+extra))@$addr $(( (off >> 8) & 0xff )) $(( off & 0xff ))
+}
+
of_name_to_eeproms() {
local names
if ! names="$(grep -xl "$1" /sys/bus/i2c/devices/*/of_node/name)"; then
@@ -42,10 +56,14 @@ of_name_to_eeprom() {
echo "$eeproms"
}
+# Each element is a `filename`
declare -A IPMI_FRU_EEPROM_FILE=()
+# Each element is a `bus` + `addr` + `offset_bytes_func`
+declare -A IPMI_FRU_EEPROM_BUSADDR=()
-ipmi_fru_device_to_file() {
+ipmi_fru_device_alloc() {
local fdn="$1"
+ local idx="$2"
local json
json="$(busctl -j call xyz.openbmc_project.FruDevice \
@@ -54,20 +72,21 @@ ipmi_fru_device_to_file() {
local jqq='.data[0] | (.BUS.data | tostring) + " " + (.ADDRESS.data | tostring)'
local busaddr
- busaddr="$(echo "$json" | jq -r "$jqq")" || return
+ busaddr=($(echo "$json" | jq -r "$jqq")) || return
# FRU 0 is hardcoded and FruDevice does not report the correct bus for it
# Hardcode a workaround for this specifically known bus
- if [ "$busaddr" = '0 0' ]; then
- echo "/etc/fru/baseboard.fru.bin"
+ if (( busaddr[0] == 0 && busaddr[1] == 0 )); then
+ IPMI_FRU_EEPROM_FILE["$idx"]=/etc/fru/baseboard.fru.bin
else
- local dev="$(printf '%d-%04x' $busaddr)"
- local efile="/sys/bus/i2c/devices/$dev/eeprom"
- # The at24 eeprom driver is not guaranteed to be bound
- if [ ! -e "$efile" ]; then
- echo "$dev" >/sys/bus/i2c/drivers/at24/bind || return
+ local offset_bw=offset_2bw
+ local rsp
+ rsp=$(i2ctransfer -f -y ${busaddr[0]} $(offset_1bw ${busaddr[1]} 0) r1) || return
+ # FRUs never start with 0xff bytes, so we can figure out addressing mode
+ if (( rsp != 0xff )); then
+ offset_bw=offset_1bw
fi
- echo "$efile"
+ IPMI_FRU_EEPROM_BUSADDR["$idx"]="${busaddr[*]} $offset_bw"
fi
}
@@ -77,7 +96,8 @@ ipmi_fru_alloc() {
# Pick the first free index to return as the allocated entry
for (( ret = 0; ret < "${#IPMI_FRU_EEPROM_FILE[@]}"; ++ret )); do
- [ -n "${IPMI_FRU_EEPROM_FILE[@]+1}" ] || break
+ [ -n "${IPMI_FRU_EEPROM_FILE[@]+1}" ] || \
+ [ -n "${IPMI_FRU_EEPROM_BUSADDR[@]+1}" ]|| break
done
if [[ "$name" =~ ^of-name:(.*)$ || "$name" =~ ^([^:]*)$ ]]; then
@@ -91,13 +111,12 @@ ipmi_fru_alloc() {
local file
while (( SECONDS - start < 60 )); do
local rc=0
- file="$(ipmi_fru_device_to_file "$fdn")" || rc=$?
+ ipmi_fru_device_alloc "$fdn" "$ret" || rc=$?
(( rc == 0 )) && break
# Immediately return any errors, 80 is special to signify retry
(( rc != 80 )) && return $rc
sleep 1
done
- IPMI_FRU_EEPROM_FILE["$ret"]="$file"
else
echo "Invalid IPMI FRU eeprom specification: $name" >&2
return 1
@@ -106,6 +125,7 @@ ipmi_fru_alloc() {
ipmi_fru_free() {
unset 'IPMI_FRU_EEPROM_FILE[$1]'
+ unset 'IPMI_FRU_EEPROM_BUSADDR[$1]'
}
checksum() {
@@ -127,24 +147,36 @@ fix_checksum() {
}
read_bytes() {
+ local busaddr=(${IPMI_FRU_EEPROM_BUSADDR["$1"]-})
local file="${IPMI_FRU_EEPROM_FILE["$1"]-$1}"
local offset="$2"
local size="$3"
- echo "Reading $file at $offset for $size" >&2
- dd if="$file" bs=1 count="$size" skip="$offset" 2>/dev/null | \
- hexdump -v -e '1/1 "%d "'
+ if (( "${#busaddr[@]}" > 0)); then
+ echo "Reading ${busaddr[*]} at $offset for $size" >&2
+ i2ctransfer -f -y ${busaddr[0]} $(${busaddr[2]} ${busaddr[1]} $offset) r$size
+ else
+ echo "Reading $file at $offset for $size" >&2
+ dd if="$file" bs=1 count="$size" skip="$offset" 2>/dev/null | \
+ hexdump -v -e '1/1 "%d "'
+ fi
}
write_bytes() {
+ local busaddr=(${IPMI_FRU_EEPROM_BUSADDR["$1"]-})
local file="${IPMI_FRU_EEPROM_FILE["$1"]-$1}"
local offset="$2"
local -n bytes_arr="$3"
- local hexstr
- hexstr="$(printf '\\x%x' "${bytes_arr[@]}")" || return
- echo "Writing $file at $offset for ${#bytes_arr[@]}" >&2
- printf "$hexstr" | dd of="$file" bs=1 seek=$offset 2>/dev/null
+ if (( "${#busaddr[@]}" > 0)); then
+ echo "Writing ${busaddr[*]} at $offset for ${#bytes_arr[@]}" >&2
+ i2ctransfer -f -y ${busaddr[0]} $(${busaddr[2]} ${busaddr[1]} $offset ${#bytes_arr[@]}) ${bytes_arr[@]}
+ else
+ local hexstr
+ hexstr="$(printf '\\x%x' "${bytes_arr[@]}")" || return
+ echo "Writing $file at $offset for ${#bytes_arr[@]}" >&2
+ printf "$hexstr" | dd of="$file" bs=1 seek=$offset 2>/dev/null
+ fi
}
read_header() {