mctp-i2c: support recovery of MCTP endpoint

Effort: go/cx7-mctp-link-recover
Add recoverEndponit function to detect removed MCTP endpoints and try
to re-assign the same EID to the device.

Tested:
https://paste.googleplex.com/4685089171308544

Google-Bug-Id: 383145677
Change-Id: Ia465131969dfc11a7ea6cbf3fba0b87456df27c6
Signed-off-by: Jinliang Wang <jinliangw@google.com>
diff --git a/recipes-connectivity/mctp/mctp/init-mctp-i2c-endpoint.sh b/recipes-connectivity/mctp/mctp/init-mctp-i2c-endpoint.sh
index 989574d..00c1bd6 100644
--- a/recipes-connectivity/mctp/mctp/init-mctp-i2c-endpoint.sh
+++ b/recipes-connectivity/mctp/mctp/init-mctp-i2c-endpoint.sh
@@ -22,6 +22,9 @@
         au.com.CodeConstruct.MCTP.Endpoint Remove
 done
 
+# allow old MCTP endpoints resource being freed
+sleep 1
+
 echo "# object_path i2c_bus address mctp_net mctp_eid" >$conf_file
 
 EID_BASE=60
@@ -47,6 +50,52 @@
     exit 1
 }
 
+recoverEndpoint()
+{
+    existing_eids=$(busctl tree xyz.openbmc_project.MCTP |
+        grep -Eo 'mctp/[0-9]+/[0-9]+')
+
+    while read -r line; do
+        if [[ $line =~ ^#.* ]] || [[ -z "$line" ]]; then
+            continue
+        fi
+
+        bus=$(echo "$line" | awk '{print $2}')
+        addr=$(echo "$line" | awk '{print $3}')
+        net=$(echo "$line" | awk '{print $4}')
+        eid=$(echo "$line" | awk '{print $5}')
+
+        if [ -z "$bus" ] || [ -z "$addr" ] || [ -z "$net" ] || [ -z "$eid" ]; then
+            echo "Warning: one of $bus,$addr,$net,$eid is empty"
+            continue
+        fi
+
+        if echo $existing_eids | grep "mctp/$net/$eid" >/dev/null; then
+            continue
+        fi
+
+        if [[ "$net" != "1" ]]; then
+            echo "Error: we don't support net $net yet"
+        fi
+
+        echo "Trying to re-assign mctpi2c$bus $addr with mctp/1/$eid"
+        output=$(busctl call xyz.openbmc_project.MCTP \
+            /xyz/openbmc_project/mctp \
+            au.com.CodeConstruct.MCTP AssignEndpointStatic \
+            sayy "mctpi2c$bus" 1 "$addr" "$eid" 2>&1)
+
+        # Example output: yisb 8 1 "/xyz/openbmc_project/mctp/1/8" true
+        if [[ "$output" =~ ^yisb[[:space:]]+([0-9]+)[[:space:]]+([0-9]+) ]]; then
+            echo "Recovered mctpi2c$bus $addr with mctp/1/$eid"
+            continue
+        fi
+
+        echo "Failed to re-assign mctpi2c$bus $addr with mctp/1/$eid"
+        echo "Error: $output"
+
+    done < "$conf_file"
+}
+
 while true; do
     # Query MctpI2cBinding configuration
     output=$(dbus-send --system --print-reply \
@@ -60,9 +109,15 @@
     object_paths=$(echo "$output" | grep -Eo '/xyz.*[^"]')
 
     # Populate i2c bus and address info
+
+    # associative array
     declare -A buses
+    # indexed array
     declare -a table
+
+    buses=()
     table=()
+
     for object_path in $object_paths; do
         if grep -F "$object_path" "$conf_file" >/dev/null; then
             # skip if already exist in the conf_file
@@ -155,4 +210,6 @@
     # MCTP EID(either newly populated or failed to setup MCTP endpoint
     # before).
     sleep 60
+
+    recoverEndpoint
 done