Initial commit

This commit is contained in:
Your Name
2026-04-23 17:07:55 +08:00
commit b7e39e063b
16725 changed files with 1625565 additions and 0 deletions
@@ -0,0 +1,35 @@
SUMMARY = "Phosphor OpenBMC Boot Progress Handling Service"
DESCRIPTION = "Phosphor OpenBMC Altra Boot Progress Handling Daemon"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
inherit systemd
inherit obmc-phosphor-systemd
DEPENDS += "systemd"
RDEPENDS:${PN} += "libsystemd"
RDEPENDS:${PN} += "bash"
SRC_URI = " \
file://ampere_boot_progress.sh \
file://dimm_train_fail_log.sh \
"
SYSTEMD_PACKAGES = "${PN}"
HOST_ON_RESET_HOSTTMPL = "ampere-boot-progress.service"
HOST_ON_RESET_HOSTINSTMPL = "ampere-boot-progress.service"
HOST_ON_RESET_HOSTTGTFMT = "obmc-host-already-on@{0}.target"
HOST_ON_RESET_HOSTFMT = "../${HOST_ON_RESET_HOSTTMPL}:${HOST_ON_RESET_HOSTTGTFMT}.requires/${HOST_ON_RESET_HOSTINSTMPL}"
SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'HOST_ON_RESET_HOSTFMT', 'OBMC_HOST_INSTANCES')}"
SYSTEMD_SERVICE:${PN} += "${HOST_ON_RESET_HOSTTMPL}"
do_install () {
install -d ${D}${sbindir}
install -m 0755 ${WORKDIR}/ampere_boot_progress.sh ${D}${sbindir}/
install -m 0755 ${WORKDIR}/dimm_train_fail_log.sh ${D}${sbindir}/
}
@@ -0,0 +1,8 @@
[Unit]
Description=Ampere Altra Boot Progress Handling
After=obmc-host-already-on@0.target
BindTo=obmc-host-already-on@0.target
[Service]
ExecStart=/usr/sbin/ampere_boot_progress.sh
SyslogIdentifier=ampere-boot-progress
@@ -0,0 +1,206 @@
#!/bin/bash
# Initialize variables
boot_stage=00
boot_status=00
uefi_code=00000000
function set_postcode()
{
# shellcheck disable=SC2086
busctl set-property xyz.openbmc_project.State.Boot.Raw \
/xyz/openbmc_project/state/boot/raw0 \
xyz.openbmc_project.State.Boot.Raw Value \(tay\) "$1" 0
}
function update_boot_progress_last_state_time()
{
# Get BMC current time
bp_last_state_time=$(busctl get-property xyz.openbmc_project.Time.Manager \
/xyz/openbmc_project/time/bmc \
xyz.openbmc_project.Time.EpochTime \
Elapsed | cut -d' ' -f2)
# Update the Boot Progress LastStateTime
busctl set-property xyz.openbmc_project.State.Host \
/xyz/openbmc_project/state/host0 \
xyz.openbmc_project.State.Boot.Progress \
BootProgressLastUpdate t \
"$bp_last_state_time"
}
function update_boot_progress()
{
bootprog=$1
busctl set-property xyz.openbmc_project.State.Host \
/xyz/openbmc_project/state/host0 \
xyz.openbmc_project.State.Boot.Progress \
BootProgress s \
"xyz.openbmc_project.State.Boot.Progress.ProgressStages.$bootprog"
# Update Boot Progress LastStateTime
update_boot_progress_last_state_time
}
function get_boot_stage_string()
{
bootstage=$1
ueficode=$2
case $bootstage in
00)
boot_stage_str="SMpro"
;;
01)
boot_stage_str="PMpro"
;;
02)
boot_stage_str="ATF BL1 (Code=${ueficode})"
;;
03)
boot_stage_str="DDR initialization (Code=${ueficode})"
;;
04)
boot_stage_str="DDR training progress (Code=${ueficode})"
;;
05)
boot_stage_str="ATF BL2 (Code=${ueficode})"
;;
06)
boot_stage_str="ATF BL31 (Code=${ueficode})"
;;
07)
boot_stage_str="ATF BL32 (Code=${ueficode})"
;;
08)
boot_stage_str="UEFI booting (UEFI Code=${ueficode})"
;;
09)
boot_stage_str="OS booting"
;;
esac
echo "$boot_stage_str"
}
function set_boot_progress()
{
boot_stage=$1
uefi_code=$2
case $boot_stage in
02)
update_boot_progress "PrimaryProcInit"
;;
03)
update_boot_progress "MemoryInit"
;;
08)
if [[ "$uefi_code" =~ 0201* ]]; then
update_boot_progress "PCIInit"
fi
;;
09)
update_boot_progress "OSStart"
;;
esac
}
function log_redfish_biosboot_ok_event()
{
logger-systemd --journald << EOF
MESSAGE=
PRIORITY=2
SEVERITY=
REDFISH_MESSAGE_ID=OpenBMC.0.1.BIOSBoot.OK
REDFISH_MESSAGE_ARGS="UEFI firmware booting done"
EOF
}
function log_redfish_bios_panic_event()
{
boot_state_str=$(get_boot_stage_string "$1" "$2")
logger-systemd --journald << EOF
MESSAGE=
PRIORITY=2
SEVERITY=
REDFISH_MESSAGE_ID=OpenBMC.0.1.BIOSFirmwarePanicReason.Warning
REDFISH_MESSAGE_ARGS=${boot_state_str}
EOF
}
cnt=0
# If any reason makes SCP fail to access in 6s, break the service.
while [ $cnt -lt 30 ];
do
# Sleep 200ms
sleep 1s
if ! read -r bg <<< "$(cat /sys/bus/platform/devices/smpro-misc.2.auto/boot_progress)";
then
cnt=$((cnt + 1))
continue
fi
cnt=0
# Check if any update from previous check
if [ "$last_bg" == "$bg" ]; then
continue
fi
last_bg=$bg
# Check if the Host is already ON or not. If Host is already boot, update boot progress and break.
if [ "${boot_stage}" == "00" ] && [ "${bg[0]}" == "09" ];
then
update_boot_progress "OSRunning"
break
fi
# Update current boot progress
boot_stage=${bg:2:2}
boot_status=${bg:0:2}
uefi_code=${bg:4}
echo "Boot Progress = ${boot_stage} ${boot_status} ${uefi_code}"
# Log Boot Progress to dbus
if [ "${boot_status}" == "03" ]; then
# Log Redfish Event if failure.
log_redfish_bios_panic_event "$boot_stage" "$uefi_code"
# Dimm training failed, check errors
if [ "${boot_stage}" == "04" ]; then
/usr/sbin/dimm_train_fail_log.sh 0
/usr/sbin/dimm_train_fail_log.sh 1
fi
elif [ "${boot_status}" == "01" ]; then
# Check and set boot progress to dbus
set_boot_progress "$boot_stage" "$uefi_code"
fi
# Log POST Code to dbus.
set_postcode "0x$boot_stage$boot_status$uefi_code"
# Stop the service when booting to OS
if [ "${boot_stage}" == "08" ] && [ "${boot_status}" == "02" ]; then
update_boot_progress "SystemInitComplete"
log_redfish_biosboot_ok_event
elif [ "${boot_stage}" == "09" ] && [ "${boot_status}" == "02" ];
then
update_boot_progress "OSRunning"
break
fi
done
@@ -0,0 +1,190 @@
#!/bin/bash
smpro_path() {
if [ "$1" == 0 ]; then
echo "/sys/bus/i2c/drivers/smpro-core/2-004f"
else
echo "/sys/bus/i2c/drivers/smpro-core/2-004e"
fi
}
function log_ampere_oem_redfish_event()
{
msg=$1
priority=$2
severity=$3
msgID=$4
msgArgs1=$5
msgArgs2=$6
logger-systemd --journald << EOF
MESSAGE=${msg}
PRIORITY=${priority}
SEVERITY=${severity}
REDFISH_MESSAGE_ID=${msgID}
REDFISH_MESSAGE_ARGS=${msgArgs1},${msgArgs2}
EOF
}
parse_phy_syndrome_s1_type() {
s1=$1
slice=$((s1 & 0xf))
ubit=$(((s1 & 0x10) >> 4))
lbit=$(((s1 & 0x20) >> 5))
uMsg="Upper Nibble: No Error"
lMsg="Lower Nibble: No Error"
if [ $ubit == 1 ]; then
uMsg="Upper Nibble: No rising edge error"
fi
if [ $lbit == 1 ]; then
lMsg="Lower Nibble: No rising edge error"
fi
echo "Slice $slice: $uMsg, $lMsg"
}
parse_phy_syndrome() {
s0=$1
s1=$2
case $s0 in
1)
echo "PHY Training Setup failure"
;;
2)
s1Msg=$(parse_phy_syndrome_s1_type "$s1")
echo "PHY Write Leveling failure: $s1Msg"
;;
3)
echo "PHY Read Gate Leveling failure"
;;
4)
echo "PHY Read Leveling failure"
;;
5)
echo "PHY Software Training failure"
;;
*)
echo "N/A"
;;
esac
}
parse_dimm_syndrome() {
s0=$1
case $s0 in
1)
echo "DRAM VREFDQ Training failure"
;;
2)
echo "LRDIMM DB Training failure"
;;
3)
echo "LRDIMM DB Software Training failure"
;;
*)
echo "N/A"
;;
esac
}
log_err_to_redfish_err() {
channel="$(printf '%d' "0x$1" 2>/dev/null)"
data="$(printf '%d' "0x$2" 2>/dev/null)"
trErrType=$((data & 0x03))
rank=$(((data & 0x1C) >> 2))
syndrome0=$(((data & 0xE0) >> 5))
syndrome1=$(((data & 0xFF00) >> 8))
# PHY sysdrom errors
fType=""
redfisComp="DIMM"
redfisMsg=""
if [ $trErrType == 1 ]; then
fType="PHY training failure"
redfisMsg=$(parse_phy_syndrome $syndrome0 $syndrome1)
# DIMM traning errors
elif [ $trErrType == 2 ]; then
fType="DIMM training failure"
redfisMsg=$(parse_dimm_syndrome $syndrome0)
else
fType="Invalid DIMM Syndrome error type"
redfisMsg="NA"
fi
#smg=$("DDR training: MCU rank $rank: $fType: $redfisMsg")
log_ampere_oem_redfish_event \
"" 2 "" "OpenBMC.0.1.AmpereCritical.Critical" \
$redfisComp "Slot $channel MCU rank $rank: $fType: $redfisMsg"
}
log_err_to_sel_err() {
channel="$(printf '%d' "0x$1" 2>/dev/null)"
data="$(printf '%d' "0x$2" 2>/dev/null)"
byte0=$(((data & 0xff00) >> 8))
byte1=$((data & 0xff))
evtdata0=$((EVENT_DIR_ASSERTION | OEM_SENSOR_SPECIFIC))
evtdata1=$(((channel << 4) | BOOT_SYNDROME_DATA | (socket << 3)))
# phy sysdrom errors
# OEM data bytes
# oem id: 3 bytes [0x3a 0xcd 0x00]
# sensor num: 1 bytes
# sensor type: 1 bytes
# data bytes: 4 bytes
# sel type: 4 byte [0x00 0x00 0x00 0xC0]
busctl call xyz.openbmc_project.Logging.IPMI \
/xyz/openbmc_project/Logging/IPMI \
xyz.openbmc_project.Logging.IPMI IpmiSelAddOem \
sayy "" 12 \
0x3a 0xcd 0x00 \
"$SENSOR_TYPE_SYSTEM_FW_PROGRESS" "$SENSOR_BOOT_PROGRESS" \
"$evtdata0" "$evtdata1" "$byte0" "$byte1" \
0x00 0x00 0x00 0xC0
}
BOOT_SYNDROME_DATA=4
SENSOR_BOOT_PROGRESS=235
EVENT_DIR_ASSERTION=0x00
OEM_SENSOR_SPECIFIC=0x70
SENSOR_TYPE_SYSTEM_FW_PROGRESS=0x0F
socket=$1
base="$(smpro_path "$socket")"
# For the second socket, it is required to read out to
# clear all old boot progress before query the dimm
# training fail info.
# Normally, it would take up to 12 times to read them all
# Make the value to 16 to make sure it always works.
if [ "$socket" == "1" ]; then
path=("$base"/smpro-misc.*.auto/boot_progress)
filename="${path[0]}"
if [ ! -f "$filename" ];
then
echo "Error: $filename not found"
else
for ((i=0; i<16; i++))
do
cat "$filename" > /dev/null 2>&1
done
fi
fi
# Checking for DIMM slot 0-15
for ((i=0; i<16; i++))
do
path=("$base"/smpro-errmon.*.auto/event_dimm"${i}"_syndrome)
filename="${path[0]}"
if [ ! -f "$filename" ];
then
echo "Error: $filename not found"
continue
fi
line=$(cat "$filename")
if [ -n "$line" ];
then
log_err_to_redfish_err "$i" "$line"
log_err_to_sel_err "$i" "$line"
fi
done
exit 0;
@@ -0,0 +1,63 @@
SUMMARY = "Ampere Computing LLC Host Control Implementation"
DESCRIPTION = "A host control implementation suitable for Ampere Computing LLC's systems"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
inherit systemd
inherit obmc-phosphor-systemd
RDEPENDS:${PN} = "bash"
S = "${WORKDIR}"
SRC_URI = " \
file://ampere-host-force-reset@.service \
file://ampere-host-on-host-check@.service \
file://ampere_host_check.sh \
file://obmc-power-already-on@.target \
file://obmc-host-already-on@.target \
file://ampere-bmc-reboot-host-check@.service \
"
SYSTEMD_PACKAGES = "${PN}"
SYSTEMD_SERVICE:${PN} = " \
ampere-host-force-reset@.service \
obmc-power-already-on@.target \
obmc-host-already-on@.target \
ampere-bmc-reboot-host-check@.service \
"
# append force reboot
HOST_WARM_REBOOT_FORCE_TGT = "ampere-host-force-reset@.service"
HOST_WARM_REBOOT_FORCE_INSTMPL = "ampere-host-force-reset@{0}.service"
HOST_WARM_REBOOT_FORCE_TGTFMT = "obmc-host-force-warm-reboot@{0}.target"
HOST_WARM_REBOOT_FORCE_TARGET_FMT = "../${HOST_WARM_REBOOT_FORCE_TGT}:${HOST_WARM_REBOOT_FORCE_TGTFMT}.requires/${HOST_WARM_REBOOT_FORCE_INSTMPL}"
SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'HOST_WARM_REBOOT_FORCE_TARGET_FMT', 'OBMC_HOST_INSTANCES')}"
SYSTEMD_SERVICE:${PN} += "${HOST_WARM_REBOOT_FORCE_TGT}"
HOST_ON_RESET_HOSTTMPL = "ampere-host-on-host-check@.service"
HOST_ON_RESET_HOSTINSTMPL = "ampere-host-on-host-check@{0}.service"
HOST_ON_RESET_HOSTTGTFMT = "obmc-host-startmin@{0}.target"
HOST_ON_RESET_HOSTFMT = "../${HOST_ON_RESET_HOSTTMPL}:${HOST_ON_RESET_HOSTTGTFMT}.requires/${HOST_ON_RESET_HOSTINSTMPL}"
SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'HOST_ON_RESET_HOSTFMT', 'OBMC_HOST_INSTANCES')}"
SYSTEMD_SERVICE:${PN} += "${HOST_ON_RESET_HOSTTMPL}"
# append on phosphor-wait-power-on
AMPERE_POWER_ON_TGT = "obmc-power-already-on@.target"
AMPERE_POWER_ON_INSTMPL = "obmc-power-already-on@{0}.target"
OP_WAIT_POWER_ON = "phosphor-wait-power-on@{0}.service"
AMPERE_POWER_ON_TARGET_FMT = "../${AMPERE_POWER_ON_TGT}:${OP_WAIT_POWER_ON}.wants/${AMPERE_POWER_ON_INSTMPL}"
SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'AMPERE_POWER_ON_TARGET_FMT', 'OBMC_HOST_INSTANCES')}"
# append on obmc-chassis-poweron but will start after phosphor-state-manager init
# host state as running
HOST_CHECK_BMC_REBOOT_HOSTTMPL = "ampere-bmc-reboot-host-check@.service"
HOST_CHECK_BMC_REBOOT_HOSTINSTMPL = "ampere-bmc-reboot-host-check@{0}.service"
HOST_CHECK_BMC_REBOOT_HOSTTGTFMT = "obmc-chassis-poweron@{0}.target"
HOST_CHECK_BMC_REBOOT_HOSTFMT = "../${HOST_CHECK_BMC_REBOOT_HOSTTMPL}:${HOST_CHECK_BMC_REBOOT_HOSTTGTFMT}.requires/${HOST_CHECK_BMC_REBOOT_HOSTINSTMPL}"
SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'HOST_CHECK_BMC_REBOOT_HOSTFMT', 'OBMC_HOST_INSTANCES')}"
do_install() {
install -d ${D}/usr/sbin
install -m 0755 ${WORKDIR}/ampere_host_check.sh ${D}/${sbindir}/
}
@@ -0,0 +1,15 @@
[Unit]
Description=Check Host%i status after bmc reboot
After=obmc-host-reset@%i.target
After=obmc-host-reset-running@%i.target
After=mapper-wait@-xyz-openbmc_project-state-host%i.service
OnSuccess=obmc-host-already-on@%i.target
ConditionPathExists=/run/openbmc/chassis@%i-on
ConditionPathExists=/run/openbmc/host@%i-on
Conflicts=obmc-chassis-poweroff@%i.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c "if [ $(busctl get-property `mapper get-service /xyz/openbmc_project/state/host0` /xyz/openbmc_project/state/host0 xyz.openbmc_project.State.Host CurrentHostState | grep -i '\.Running' | wc -l) != 0 ]; then exit 0; fi"
@@ -0,0 +1,14 @@
[Unit]
Description=Ampere Computing LLC force reset host%i
Wants=phosphor-reboot-host@%i.service
Conflicts=obmc-chassis-poweroff@%i.target
OnFailure=obmc-chassis-powerreset@%i.target
[Service]
RemainAfterExit=no
Type=oneshot
ExecStart=/bin/sh -c "sleep 3 && /usr/bin/env ampere_power_util.sh mb force_reset"
SyslogIdentifier=ampere_power_util.sh
[Install]
WantedBy=obmc-host-force-warm-reboot@%i.target
@@ -0,0 +1,13 @@
[Unit]
Description=Check Host%i status before obmc-host-startmin
After=obmc-host-started@%i.target
After=obmc-power-start-pre@%i.target
Conflicts=obmc-host-stop@%i.target
Conflicts=phosphor-reset-host-check@%i.service
OnFailure=obmc-host-quiesce@%i.target
OnSuccess=obmc-host-already-on@%i.target
OnFailureJobMode=flush
[Service]
Type=oneshot
ExecStart=/usr/sbin/ampere_host_check.sh
@@ -0,0 +1,30 @@
#!/bin/bash
# Check current Host status. Do nothing when the Host is currently ON
st=$(busctl get-property xyz.openbmc_project.State.Host \
/xyz/openbmc_project/state/host0 xyz.openbmc_project.State.Host \
CurrentHostState | cut -d"." -f6)
if [ "$st" == "Running\"" ]; then
exit 0
fi
# Time out checking for Host ON is 60s
cnt=60
while [ "$cnt" -gt 0 ];
do
cnt=$((cnt - 1))
st=$(busctl call xyz.openbmc_project.State.HostCondition.Gpio \
/xyz/openbmc_project/Gpios/host0 org.freedesktop.DBus.Properties \
Get ss xyz.openbmc_project.Condition.HostFirmware \
CurrentFirmwareCondition | cut -d"." -f6)
if [ "$st" == "Running\"" ]; then
if command -v ampere_driver_binder.sh;
then
ampere_driver_binder.sh
fi
exit 0
fi
sleep 1
done
exit 1
@@ -0,0 +1,6 @@
[Unit]
Description=Ampere Host %i already on target
Conflicts=obmc-chassis-poweroff@%i.target
Conflicts=obmc-host-quiesce@%i.target
Conflicts=ampere-host-force-reset@%i.service
Conflicts=ampere-host-shutdown-ack@%i.service
@@ -0,0 +1,5 @@
[Unit]
Description=Ampere power %i already on target
After=phosphor-wait-power-on@%i.service
Conflicts=obmc-chassis-poweroff@%i.target
Conflicts=ampere-host-shutdown-ack@%i.service
@@ -0,0 +1,28 @@
SUMMARY = "Enable USB ethernet"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
DEPENDS += "systemd"
RDEPENDS:${PN} += "libsystemd bash"
inherit allarch systemd
SRC_URI += "file://ampere-usbnet.service \
file://ampere_usbnet.sh \
file://00-bmc-usb0.network"
do_install() {
install -d ${D}${systemd_unitdir}/system/
install -m 0644 ${WORKDIR}/ampere-usbnet.service ${D}${systemd_unitdir}/system
install -d ${D}${sysconfdir_native}/systemd/network/
install -m 0644 ${WORKDIR}/00-bmc-usb0.network ${D}${sysconfdir_native}/systemd/network
install -d ${D}/${sbindir}
install -m 755 ${WORKDIR}/ampere_usbnet.sh ${D}/${sbindir}
}
NATIVE_SYSTEMD_SUPPORT = "1"
SYSTEMD_PACKAGES = "${PN}"
SYSTEMD_SERVICE:${PN} = "ampere-usbnet.service"
@@ -0,0 +1,8 @@
[Match]
Name=usb0
[Address]
Address=192.168.0.10/16
[Network]
LinkLocalAddressing=no
IPv6AcceptRA=no
DHCP=no
@@ -0,0 +1,12 @@
[Unit]
Description=Ampere Ethernet over USB gadget device
After=phosphor-ipmi-host.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/sbin/ampere_usbnet.sh
ExecStop=/usr/bin/usb-ctrl ecm usbnet off
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,18 @@
#!/bin/bash
ENV_MAC_ADDR=$(fw_printenv bmc_macaddr)
MAC_ADDR=$(echo "$ENV_MAC_ADDR" | cut -d "=" -f 2)
if [ -n "$MAC_ADDR" ]; then
# Generate MAC Address from eth1addr using locally administered MAC
# https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local_(U/L_bit
SUBMAC=$(echo "$MAC_ADDR" | cut -d ":" -f 2-6)
/usr/bin/usb-ctrl ecm usbnet on "06:$SUBMAC" "02:$SUBMAC"
else
/usr/bin/usb-ctrl ecm usbnet on
fi
# Use NCM (Ethernet) Gadget instead of FunctionFS Gadget
echo 0x0103 > /sys/kernel/config/usb_gadget/usbnet/idProduct
echo "OpenBMC usbnet Device" > /sys/kernel/config/usb_gadget/usbnet/strings/0x409/product
@@ -0,0 +1,35 @@
SUMMARY = "Ampere Driver Binder Implementation"
DESCRIPTION = "The driver binder for Ampere Computing LLC's systems"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
inherit systemd
inherit obmc-phosphor-systemd
RDEPENDS:${PN} = "bash"
S = "${WORKDIR}"
SRC_URI = " \
file://ampere-power-on-driver-binder@.service \
file://ampere-host-on-driver-binder@.service \
"
SYSTEMD_PACKAGES = "${PN}"
SYSTEMD_SERVICE:${PN} = " \
ampere-power-on-driver-binder@.service \
ampere-host-on-driver-binder@.service \
"
# bind driver after the power is on
POWER_ON_DRIVER_BINDER_TGT = "ampere-power-on-driver-binder@.service"
POWER_ON_DRIVER_BINDER_INSTMPL = "ampere-power-on-driver-binder@{0}.service"
AMPER_POWER_ON = "obmc-power-already-on@{0}.target"
POWER_ON_DRIVER_BINDER_TARGET_FMT = "../${POWER_ON_DRIVER_BINDER_TGT}:${AMPER_POWER_ON}.wants/${POWER_ON_DRIVER_BINDER_INSTMPL}"
SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'POWER_ON_DRIVER_BINDER_TARGET_FMT', 'OBMC_HOST_INSTANCES')}"
# bind driver after the host is on
HOST_ON_DRIVER_BINDER_TGT = "ampere-host-on-driver-binder@.service"
HOST_ON_DRIVER_BINDER_INSTMPL = "ampere-host-on-driver-binder@{0}.service"
AMPER_HOST_RUNNING = "obmc-host-already-on@{0}.target"
HOST_ON_DRIVER_BINDER_TARGET_FMT = "../${HOST_ON_DRIVER_BINDER_TGT}:${AMPER_HOST_RUNNING}.wants/${HOST_ON_DRIVER_BINDER_INSTMPL}"
SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'HOST_ON_DRIVER_BINDER_TARGET_FMT', 'OBMC_HOST_INSTANCES')}"
@@ -0,0 +1,13 @@
[Unit]
Description=Ampere host on driver binder %i
After=obmc-host-already-on@%i.target
BindTo=obmc-host-already-on@%i.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c "if command -v ampere_host_on_driver_binder.sh; then echo 'Try to bind driver after host on if does not' && ampere_host_on_driver_binder.sh; fi && exit 0;"
SyslogIdentifier=host_on_binder
RemainAfterExit=no
[Install]
WantedBy=obmc-host-already-on@%i.target
@@ -0,0 +1,10 @@
[Unit]
Description=Ampere power on driver binder %i
After=obmc-power-already-on@%i.target
BindTo=obmc-power-already-on@%i.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c "if command -v ampere_power_on_driver_binder.sh; then echo 'Try to bind driver after power on if does not' && ampere_power_on_driver_binder.sh; fi && exit 0;"
SyslogIdentifier=power_on_binder
RemainAfterExit=no
@@ -0,0 +1,23 @@
SUMMARY = "Ampere Computing LLC Fault Monitor"
DESCRIPTION = "Monitor fault events and update fault led status for Ampere systems"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
inherit systemd
inherit obmc-phosphor-systemd
FILESEXTRAPATHS:append := "${THISDIR}/${PN}:"
SYSTEMD_SERVICE:${PN} = "ampere-fault-monitor.service"
GPIO_FAULT_START_TGT = "ampere-check-gpio-fault@.service"
GPIO_FAULT_START_S0_INSTMPL = "ampere-check-gpio-fault@{0}.service"
SYSTEMD_SERVICE:${PN} += "${GPIO_FAULT_START_TGT}"
HOST_ON_STARTMIN_TGTFMT = "obmc-host-startmin@{0}.target"
GPIO_FAULT_START_S0_STARTMIN_FMT = "../${GPIO_FAULT_START_TGT}:${HOST_ON_STARTMIN_TGTFMT}.wants/${GPIO_FAULT_START_S0_INSTMPL}"
SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'GPIO_FAULT_START_S0_STARTMIN_FMT', 'OBMC_HOST_INSTANCES')}"
@@ -0,0 +1,12 @@
[Unit]
Description=Monitor GPIO fault and updade fault LED status %i
Before=obmc-host-start-pre@0.target
After=obmc-host-already-on@0.target
Conflicts=obmc-host-stop@0.target
[Service]
Restart=no
ExecStart=/bin/sh -c "if [ -f /usr/sbin/ampere_check_gpio_fault.sh ]; then /usr/sbin/ampere_check_gpio_fault.sh %i; fi"
ExecStopPost=/bin/sh -c "if [ -f /tmp/gpio_fault ]; then sleep 5; rm /tmp/gpio_fault; fi"
SyslogIdentifier=ampere_check_fault_gpio
Type=simple
@@ -0,0 +1,12 @@
[Unit]
Description=Monitor fault events and updade fault LED status
After=xyz.openbmc_project.State.Host@0.service
[Service]
Restart=on-failure
ExecStart=/usr/sbin/ampere_fault_monitor.sh
SyslogIdentifier=ampere_fault_monitor.sh
Type=simple
[Install]
WantedBy={SYSTEMD_DEFAULT_TARGET}
@@ -0,0 +1,22 @@
SUMMARY = "Ampere Platform Environment Definitions"
DESCRIPTION = "Ampere Platform Environment Definitions"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
SRC_URI = " \
file://ampere_add_redfishevent.sh \
file://ampere_update_mac.sh \
file://ampere_spi_util.sh \
file://ampere_power_control_lock.sh \
"
RDEPENDS:${PN} = "bash"
do_install() {
install -d ${D}/usr/sbin
install -m 0755 ${WORKDIR}/ampere_add_redfishevent.sh ${D}/${sbindir}/
install -m 0755 ${WORKDIR}/ampere_update_mac.sh ${D}/${sbindir}/
install -m 0755 ${WORKDIR}/ampere_spi_util.sh ${D}/${sbindir}/
install -m 0755 ${WORKDIR}/ampere_power_control_lock.sh ${D}/${sbindir}/
}
@@ -0,0 +1,26 @@
#!/bin/bash
registry=$1
msgarg=$2
if [ -z "$registry" ]; then
echo "Usage:"
echo " $0 <redfish registry> <argument>"
exit
fi
# Check if logger-systemd exist. Do nothing if not exists
if ! command -v logger-systemd;
then
echo "logger-systemd does not exist. Skip log events for $registry $msgarg"
exit
fi
# Log events
logger-systemd --journald << EOF
MESSAGE=
PRIORITY=
SEVERITY=
REDFISH_MESSAGE_ID=$registry
REDFISH_MESSAGE_ARGS=$msgarg
EOF
@@ -0,0 +1,99 @@
#!/bin/bash
declare -a power_reboot_targets=(
obmc-host-reboot@0.target
obmc-host-warm-reboot@0.target
obmc-host-force-warm-reboot@0.target
)
declare -a power_off_targets=(
obmc-chassis-hard-poweroff@0.target
)
declare -a power_on_targets=(
obmc-host-start@0.target
)
systemd1_service="org.freedesktop.systemd1"
systemd1_object_path="/org/freedesktop/systemd1"
systemd1_manager_interface="org.freedesktop.systemd1.Manager"
mask_method="MaskUnitFiles"
unmask_method="UnmaskUnitFiles"
function mask_reboot_targets()
{
# To prevent reboot actions, this function will mask all reboot targets
for target in "${power_reboot_targets[@]}"
do
busctl call $systemd1_service $systemd1_object_path $systemd1_manager_interface \
$mask_method asbb 1 "$target" true true
done
}
function unmask_reboot_targets()
{
# Allow reboot targets work normal
for target in "${power_reboot_targets[@]}"
do
busctl call $systemd1_service $systemd1_object_path $systemd1_manager_interface \
$unmask_method asb 1 "$target" true
done
}
function mask_off_targets()
{
# To prevent off actions,this function will mask all off targets
for target in "${power_off_targets[@]}"
do
busctl call $systemd1_service $systemd1_object_path $systemd1_manager_interface \
$mask_method asbb 1 "$target" true true
done
}
function unmask_off_targets()
{
# Allow off targets work normal
for target in "${power_off_targets[@]}"
do
busctl call $systemd1_service $systemd1_object_path $systemd1_manager_interface \
$unmask_method asb 1 "$target" true
done
}
function mask_on_targets()
{
# To prevent on actions, this function will mask all on targets
systemctl mask "${power_on_targets[@]}" --runtime
}
function unmask_on_targets()
{
# Allow on targets work normal
systemctl unmask "${power_on_targets[@]}" --runtime
}
purpose=$1
allow=$2
if [ "$purpose" == "reboot" ]; then
if [ "$allow" == "false" ]
then
mask_reboot_targets
else
unmask_reboot_targets
fi
elif [ "$purpose" == "off" ]; then
if [ "$allow" == "false" ]
then
mask_off_targets
else
unmask_off_targets
fi
elif [ "$purpose" == "on" ]; then
if [ "$allow" == "false" ]
then
mask_on_targets
else
unmask_on_targets
fi
fi
@@ -0,0 +1,242 @@
#!/bin/bash
# shellcheck disable=SC2046
# shellcheck source=meta-ampere/meta-mitchell/recipes-ampere/platform/ampere-platform-init/gpio-lib.sh
source /usr/sbin/gpio-lib.sh
spi_address="1e630000.spi"
spi_bind="/sys/bus/platform/drivers/spi-aspeed-smc/bind"
spi_unbind="/sys/bus/platform/drivers/spi-aspeed-smc/unbind"
spi_lock="/run/platform/spi.lock"
spi_lock_dir="/run/platform"
bind_aspeed_smc_driver() {
if [ -f "${spi_lock}" ]; then
pid=$1
pid_lock=$(cat "${spi_lock}")
if [[ "${pid}" != "${pid_lock}" ]]; then
echo "SPI-NOR resoure is lock by process $pid_lock"
return 1
fi
fi
# BMC access SPI-NOR resource
gpio_name_set spi0-program-sel 1
sleep 0.1
echo "Bind the ASpeed SMC driver"
echo "${spi_address}" > "${spi_bind}" 2>/dev/null
# Check the HNOR partition available
HOST_MTD=$(< /proc/mtd grep "pnor" | sed -n 's/^\(.*\):.*/\1/p')
if [ -z "$HOST_MTD" ]; then
echo "${spi_address}" > "${spi_unbind}"
sleep 0.1
echo "${spi_address}" > "${spi_bind}"
fi
# BMC release SPI-NOR resource
gpio_name_set spi0-program-sel 0
return 0
}
unbind_aspeed_smc_driver() {
if [ -f "${spi_lock}" ]; then
pid=$1
pid_lock=$(cat "${spi_lock}")
if [[ "${pid}" != "${pid_lock}" ]]; then
echo "SPI-NOR resoure is lock by process $pid_lock . Wait 10s"
# Wait maximum 10 seconds for unlock SPI-NOR
cnt=10
while [ $cnt -gt 0 ]
do
if [ -f "${spi_lock}" ]; then
sleep 1
cnt=$((cnt - 1))
else
break
fi
done
if [ "$cnt" -eq "0" ]; then
echo "Timeout 10 seconds, SPI-NOR still busy. Force unlock to access SPI"
rm -f "${spi_lock}"
fi
fi
fi
HOST_MTD=$(< /proc/mtd grep "pnor" | sed -n 's/^\(.*\):.*/\1/p')
if [ -n "$HOST_MTD" ]; then
# If the HNOR partition is available, then unbind driver
# BMC access SPI-NOR resource
gpio_name_set spi0-program-sel 1
sleep 0.1
echo "Unbind the ASpeed SMC driver"
echo "${spi_address}" > "${spi_unbind}"
fi
# BMC release SPI-NOR resource
gpio_name_set spi0-program-sel 0
# Deassert BMC access SPI-NOR pin
gpio_name_set spi-nor-access 0
sleep 0.5
return 0
}
lock_spi_resource() {
# Wait maximum 10 seconds to lock SPI-NOR
cnt=10
while [ $cnt -gt 0 ]
do
if [ -f "${spi_lock}" ]; then
sleep 1
cnt=$((cnt - 1))
else
echo "$1" > "${spi_lock}"
break
fi
done
if [ "$cnt" -eq "0" ]; then
echo "Timeout 10 seconds, SPI-NOR is still locked by another process"
return 1
fi
return 0
}
unlock_spi_resource() {
if [ ! -f "${spi_lock}" ]; then
echo "SPI-NOR is already unlocked"
return 0
fi
pid=$1
pid_lock=$(cat "${spi_lock}")
if [[ "${pid}" == "${pid_lock}" ]]; then
rm -f "${spi_lock}"
else
echo "Cannot unlock, SPI-NOR is locked by another process"
return 1
fi
return 0
}
start_handshake_spi() {
if [ -f "${spi_lock}" ]; then
pid=$1
pid_lock=$(cat "${spi_lock}")
if [[ "${pid}" != "${pid_lock}" ]]; then
echo "SPI-NOR resoure is lock by process $pid_lock"
return 1
fi
fi
# Wait maximum 10 seconds to grant access SPI
cnt=10
while [ $cnt -gt 0 ]
do
spinor_access=$(gpio_name_get soc-spi-nor-access)
if [ "$spinor_access" == "1" ]; then
sleep 1
cnt=$((cnt - 1))
else
break
fi
done
if [ "$cnt" -eq "0" ]; then
echo "Timeout 10 seconds, host is still hold SPI-NOR."
return 1
fi
echo "Start handshake SPI-NOR"
# Grant BMC access SPI-NOR. The process call the scripts should only
# claim the bus for only maximum period 500ms.
gpio_name_set spi-nor-access 1
# Switch the Host SPI-NOR to BMC
gpio_name_set spi0-program-sel 1
}
stop_handshake_spi() {
if [ -f "${spi_lock}" ]; then
pid=$1
pid_lock=$(cat "${spi_lock}")
if [[ "${pid}" != "${pid_lock}" ]]; then
echo "SPI-NOR resoure is lock by process $pid_lock"
return 1
fi
fi
echo "Stop handshake SPI-NOR"
# Switch the Host SPI-NOR to HOST
gpio_name_set spi0-program-sel 0
# Deassert BMC access SPI-NOR pin
gpio_name_set spi-nor-access 0
}
if [ $# -eq 0 ]; then
echo "Usage:"
echo " - Handshake access SPI-NOR "
echo " $(basename "$0") cmd pid"
echo " <cmd>:"
echo " lock - lock the SPI-NOR resource"
echo " unlock - unlock the SPI-NOR resource"
echo " bind - bind the SPI-NOR resource"
echo " unbind - unbind the SPI-NOR resource"
echo " start_handshake - start handshake between BMC and Host"
echo " stop_handshake - release handshake between BMC and Host"
echo " <pid>: Optional - PID of the process call script"
exit 0
fi
CMD=$1
if [ ! -d "${spi_lock_dir}" ]; then
mkdir -p "${spi_lock_dir}"
fi
if [ -z "$2" ]; then
PID=$$
else
PID=$2
fi
if [[ "${CMD}" == "lock" ]]; then
lock_spi_resource "${PID}"
ret=$?
if [[ "${ret}" == "1" ]]; then
echo "Cannot lock SPI-NOR, the resource is busy"
exit 1
fi
elif [[ "${CMD}" == "unlock" ]]; then
unlock_spi_resource "${PID}"
ret=$?
if [[ "${ret}" == "1" ]]; then
echo "Cannot unlock SPI-NOR, the resource is busy"
exit 1
fi
elif [[ "${CMD}" == "bind" ]]; then
bind_aspeed_smc_driver "${PID}"
ret=$?
if [[ "${ret}" == "1" ]]; then
echo "Cannot bind SPI-NOR, the resource is busy"
exit 1
fi
elif [[ "${CMD}" == "unbind" ]]; then
unbind_aspeed_smc_driver "${PID}"
ret=$?
if [[ "${ret}" == "1" ]]; then
echo "Cannot unbind SPI-NOR, the resource is busy"
exit 1
fi
elif [[ "${CMD}" == "start_handshake" ]]; then
start_handshake_spi "${PID}"
ret=$?
if [[ "${ret}" == "1" ]]; then
echo "Cannot start handshake SPI-NOR"
exit 1
fi
elif [[ "${CMD}" == "stop_handshake" ]]; then
stop_handshake_spi "${PID}"
ret=$?
if [[ "${ret}" == "1" ]]; then
echo "Cannot stop handshake SPI-NOR"
exit 1
fi
fi
exit 0
@@ -0,0 +1,115 @@
#!/bin/bash
#
# This script is used to get the BMC MAC Address from FRU EEPROM at Board Extra.
# and if the eth address is not exist on U-boot Enviroment, this script will update it.
#
function Usage () {
echo "Usage:"
echo " ampere_update_mac.sh <ethX> <fru bus> <fru addr>"
echo "Example:"
echo " ampere_update_mac.sh eth1 3 80"
}
function read_mac_address () {
fruBus=$1
fruAddr=$2
if FRU_OBJECT_PATH=$(busctl tree xyz.openbmc_project.FruDevice | grep "/xyz/openbmc_project/FruDevice/" | tr -s '\n' ' ' | tr -d "|-" | tr -d '`')
then
IFS=' ' read -r -a FRU_OBJ_PATH_ARR <<< "$FRU_OBJECT_PATH"
for fruObj in "${FRU_OBJ_PATH_ARR[@]}"
do
BUS_IDX_RW=$(busctl get-property xyz.openbmc_project.FruDevice "$fruObj" xyz.openbmc_project.FruDevice BUS)
BUS_ADDR_RW=$(busctl get-property xyz.openbmc_project.FruDevice "$fruObj" xyz.openbmc_project.FruDevice ADDRESS)
if [ -z "$BUS_IDX_RW" ] || [ -z "$BUS_IDX_RW" ]; then
continue
else
BUS_IDX_CV=$(echo "$BUS_IDX_RW" | cut -d " " -f 2)
BUS_ADDR_CV=$(echo "$BUS_ADDR_RW" | cut -d " " -f 2)
if [ "$BUS_IDX_CV" != "$fruBus" ] || [ "$BUS_ADDR_CV" != "$fruAddr" ]; then
continue
fi
fi
MAC_ADDR_RAW=$(busctl get-property xyz.openbmc_project.FruDevice "$fruObj" xyz.openbmc_project.FruDevice BOARD_INFO_AM1)
MAC_ADDR=$(echo "$MAC_ADDR_RAW" | cut -d "\"" -f 2)
break
done
fi
echo "$MAC_ADDR"
}
ETHERNET_INTERFACE=$1
BMC_FRU_BUS=$2
BMC_FRU_ADDR=$3
if [ -z "$BMC_FRU_ADDR" ];
then
Usage
exit
fi
# Check eth port
case ${ETHERNET_INTERFACE} in
"eth0")
ENV_PORT="1"
;;
"eth1")
ENV_PORT="2"
;;
"eth2")
ENV_PORT="3"
;;
*)
Usage
exit
;;
esac
# Read FRU Board Custom Field 1 to get the MAC address
for i in {1..10}; do
MAC_ADDR=$(read_mac_address "$BMC_FRU_BUS" "$BMC_FRU_ADDR")
# Check if BMC MAC address is exported
if [ -z "${MAC_ADDR}" ]; then
sleep 2
continue
fi
if echo "$MAC_ADDR" | grep -q -vE "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$" ; then
echo "ERROR: No valid BMC MAC Address detected from BMC FRU! $MAC_ADDR"
exit 0
else
echo "mac-update: detect BMC MAC $MAC_ADDR at loop $i"
break
fi
done
# Check if the Ethernet port has correct MAC Address
ETH_INCLUDE_MAC=$(ifconfig "${ETHERNET_INTERFACE}" | grep -i "$MAC_ADDR")
if [ -n "$ETH_INCLUDE_MAC" ]; then
echo "BMC MAC Address is already configured"
exit 0
fi
# Request to restart the service
ifconfig "${ETHERNET_INTERFACE}" down
fw_setenv bmc_macaddr "${MAC_ADDR}"
ifconfig "${ETHERNET_INTERFACE}" hw ether "${MAC_ADDR}"
retval=$?
if [[ $retval -ne 0 ]]; then
echo "ERROR: Can not update MAC ADDR to ${ETHERNET_INTERFACE}"
exit 1
fi
# Setting LAN MAC Address to xx:xx:xx:xx:xx:xx
ipmitool lan set "${ENV_PORT}" macaddr "${ETHERNET_INTERFACE}"
# Enableing BMC-generated ARP responses & Setting SNMP Community String to public
ipmitool lan set "${ENV_PORT}" arp respond on
ipmitool lan set "${ENV_PORT}" snmp public
ifconfig "${ETHERNET_INTERFACE}" up
echo "Successfully update the MAC address ${MAC_ADDR} to ${ETHERNET_INTERFACE}"