1#!/bin/bash
2smpro_path() {
3	if [ "$1" == 0 ]; then
4		echo "/sys/bus/i2c/drivers/smpro-core/2-004f"
5	else
6		echo "/sys/bus/i2c/drivers/smpro-core/2-004e"
7	fi
8}
9
10function log_ampere_oem_redfish_event()
11{
12	msg=$1
13	priority=$2
14	severity=$3
15	msgID=$4
16	msgArgs1=$5
17	msgArgs2=$6
18
19logger --journald << EOF
20MESSAGE=${msg}
21PRIORITY=${priority}
22SEVERITY=${severity}
23REDFISH_MESSAGE_ID=${msgID}
24REDFISH_MESSAGE_ARGS=${msgArgs1},${msgArgs2}
25EOF
26}
27
28parse_phy_syndrome_s1_type() {
29	s1=$1
30	slice=$((s1 & 0xf))
31	ubit=$(((s1 & 0x10) >> 4))
32	lbit=$(((s1 & 0x20) >> 5))
33	uMsg="Upper Nibble: No Error"
34	lMsg="Lower Nibble: No Error"
35	if [ $ubit == 1 ]; then
36		uMsg="Upper Nibble: No rising edge error"
37	fi
38	if [ $lbit == 1 ]; then
39		lMsg="Lower Nibble: No rising edge error"
40	fi
41	echo "Slice $slice: $uMsg, $lMsg"
42}
43
44parse_phy_syndrome() {
45	s0=$1
46	s1=$2
47	case $s0 in
48		1)
49			echo "PHY Training Setup failure"
50			;;
51		2)
52			s1Msg=$(parse_phy_syndrome_s1_type "$s1")
53			echo "PHY Write Leveling failure: $s1Msg"
54			;;
55		3)
56			echo "PHY Read Gate Leveling failure"
57			;;
58		4)
59			echo "PHY Read Leveling failure"
60			;;
61		5)
62			echo "PHY Software Training failure"
63			;;
64		*)
65			echo "N/A"
66			;;
67	esac
68}
69
70parse_dimm_syndrome() {
71	s0=$1
72	case $s0 in
73		1)
74			echo "DRAM VREFDQ Training failure"
75			;;
76		2)
77			echo "LRDIMM DB Training failure"
78			;;
79		3)
80			echo "LRDIMM DB Software Training failure"
81			;;
82		*)
83			echo "N/A"
84			;;
85	esac
86}
87
88log_err_to_redfish_err() {
89	channel="$(printf '%d' "0x$1" 2>/dev/null)"
90	data="$(printf '%d' "0x$2" 2>/dev/null)"
91	trErrType=$((data & 0x03))
92	rank=$(((data & 0x1C) >> 2))
93	syndrome0=$(((data & 0xE0) >> 5))
94	syndrome1=$(((data & 0xFF00) >> 8))
95
96	# PHY sysdrom errors
97	fType=""
98	redfisComp="DIMM"
99	redfisMsg=""
100	if [ $trErrType == 1 ]; then
101		fType="PHY training failure"
102		redfisMsg=$(parse_phy_syndrome $syndrome0 $syndrome1)
103	# DIMM traning errors
104	elif [ $trErrType == 2 ]; then
105		fType="DIMM training failure"
106		redfisMsg=$(parse_dimm_syndrome $syndrome0)
107	else
108		fType="Invalid DIMM Syndrome error type"
109		redfisMsg="NA"
110	fi
111
112	#smg=$("DDR training: MCU rank $rank: $fType: $redfisMsg")
113	log_ampere_oem_redfish_event \
114		"" 2 "" "OpenBMC.0.1.AmpereCritical.Critical" \
115		$redfisComp "Slot $channel MCU rank $rank: $fType: $redfisMsg"
116}
117
118log_err_to_sel_err() {
119	channel="$(printf '%d' "0x$1" 2>/dev/null)"
120	data="$(printf '%d' "0x$2" 2>/dev/null)"
121	byte0=$(((data & 0xff00) >> 8))
122	byte1=$((data & 0xff))
123	evtdata0=$((EVENT_DIR_ASSERTION | OEM_SENSOR_SPECIFIC))
124	evtdata1=$(((channel << 4) | BOOT_SYNDROME_DATA | (socket << 3)))
125
126	# phy sysdrom errors
127	# OEM data bytes
128	#   oem id: 3 bytes [0x3a 0xcd 0x00]
129	#   sensor num: 1 bytes
130	#   sensor type: 1 bytes
131	#   data bytes: 4 bytes
132	#   sel type: 4 byte [0x00 0x00 0x00 0xC0]
133	busctl call xyz.openbmc_project.Logging.IPMI \
134		/xyz/openbmc_project/Logging/IPMI \
135		xyz.openbmc_project.Logging.IPMI IpmiSelAddOem \
136		sayy "" 12 \
137		0x3a 0xcd 0x00 \
138		"$SENSOR_TYPE_SYSTEM_FW_PROGRESS" "$SENSOR_BOOT_PROGRESS" \
139		"$evtdata0" "$evtdata1" "$byte0" "$byte1" \
140		0x00 0x00 0x00 0xC0
141}
142
143BOOT_SYNDROME_DATA=4
144SENSOR_BOOT_PROGRESS=235
145EVENT_DIR_ASSERTION=0x00
146OEM_SENSOR_SPECIFIC=0x70
147SENSOR_TYPE_SYSTEM_FW_PROGRESS=0x0F
148
149socket=$1
150base="$(smpro_path "$socket")"
151
152# For the second socket, it is required to read out to
153# clear all old boot progress before query the dimm
154# training fail info.
155# Normally, it would take up to 12 times to read them all
156# Make the value to 16 to make sure it always works.
157if [ "$socket" == "1" ]; then
158	path=("$base"/smpro-misc.*.auto/boot_progress)
159	filename="${path[0]}"
160	if [ ! -f "$filename" ];
161	then
162		echo "Error: $filename not found"
163	else
164		for ((i=0; i<16; i++))
165		do
166			cat "$filename" > /dev/null 2>&1
167		done
168	fi
169fi
170
171# Checking for DIMM slot 0-15
172for ((i=0; i<16; i++))
173do
174	path=("$base"/smpro-errmon.*.auto/event_dimm"${i}"_syndrome)
175	filename="${path[0]}"
176	if [ ! -f "$filename" ];
177	then
178		echo "Error: $filename not found"
179		continue
180	fi
181
182	line=$(cat "$filename")
183	if [ -n "$line" ];
184	then
185		log_err_to_redfish_err "$i" "$line"
186		log_err_to_sel_err "$i" "$line"
187	fi
188done
189
190exit 0;
191