summaryrefslogtreecommitdiff
path: root/meta-google
diff options
context:
space:
mode:
authorWilliam A. Kennington III <wak@google.com>2021-10-16 01:55:39 +0300
committerWilliam A. Kennington III <wak@google.com>2021-10-20 02:35:08 +0300
commita7532a6b3629e7b8e1690769f70d4d9dcc3f7056 (patch)
tree4f00ddab52eb4cc9aa56d6435a8dbae47439e83a /meta-google
parentdc7e42efcf59bc5b0afbdc09465247a2877661bd (diff)
downloadopenbmc-a7532a6b3629e7b8e1690769f70d4d9dcc3f7056.tar.xz
meta-google: ipmi-fru: Direct read support
We can't dynamically bind to the at24 driver if the eeprom is not in the kernel's device tree. Since this support was intended to be used for dynamic FRUs, it is broken when the kernel has the entries removed. Change-Id: I99c774191c22d67e518fe9435b1446b80efb5600 Signed-off-by: William A. Kennington III <wak@google.com>
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() {