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,51 @@
SUMMARY = "OpenBMC for Ampere - Applications"
PR = "r1"
inherit packagegroup
inherit obmc-phosphor-utils
PROVIDES = "${PACKAGES}"
PACKAGES = " \
${PN}-chassis \
${PN}-flash \
${PN}-system \
${PN}-fans \
"
PROVIDES += "virtual/obmc-chassis-mgmt"
PROVIDES += "virtual/obmc-flash-mgmt"
PROVIDES += "virtual/obmc-system-mgmt"
PROVIDES += "virtual/obmc-fan-mgmt"
RPROVIDES:${PN}-chassis += "virtual-obmc-chassis-mgmt"
RPROVIDES:${PN}-flash += "virtual-obmc-flash-mgmt"
RPROVIDES:${PN}-system += "virtual-obmc-system-mgmt"
RPROVIDES:${PN}-fans += "virtual-obmc-fan-mgmt"
SUMMARY:${PN}-chassis = "Ampere Chassis"
RDEPENDS:${PN}-chassis = " \
obmc-phosphor-buttons-signals \
obmc-phosphor-buttons-handler \
phosphor-skeleton-control-power \
ampere-hostctrl \
phosphor-hostlogger \
phosphor-sel-logger \
phosphor-logging \
ac01-boot-progress \
phosphor-post-code-manager \
phosphor-host-postd \
"
SUMMARY:${PN}-system = "Ampere System"
RDEPENDS:${PN}-system = " \
smbios-mdr \
"
SUMMARY:${PN}-flash = "Ampere Flash"
RDEPENDS:${PN}-flash = " \
phosphor-software-manager \
"
SUMMARY:${PN}-fans = "Ampere Fans"
RDEPENDS:${PN}-fans = " \
"
@@ -0,0 +1,14 @@
FILESEXTRAPATHS:append := "${THISDIR}/${PN}:"
RDEPENDS:${PN} = "bash"
SRC_URI += " \
file://ampere_fault_monitor.sh \
file://ampere_check_gpio_fault.sh \
"
do_install() {
install -d ${D}/${sbindir}
install -m 755 ${WORKDIR}/ampere_fault_monitor.sh ${D}/${sbindir}/
install -m 755 ${WORKDIR}/ampere_check_gpio_fault.sh ${D}/${sbindir}/
}
@@ -0,0 +1,205 @@
#!/bin/bash
# This script monitors S0/S1 fault GPIO and detects errors or warnings from CPUs
#
# According to OpenBMC_Software_Funcional_Specification, section 3.16,
#
# When the BMC detects the GPIO_FAULT signal indicating an SCP booting failure:
# • If a non-critical error/warning from the SCP occurs, the BMC blinks the Fault LED once.
# • If a critical error from the SCP occurs, the BMC turns on the Fault LED.
# The BMC monitors the GPIO_FAULT signal from the SCP during SCP booting to determine whether
# the error is non-critical or critical. A fatal error is indicated when the signal is On and then Off
# continuously, followed by a “quiet” period of about three seconds, and this pattern repeats. If the “quiet”
# period is longer than three seconds, the error is non-fatal. The BMC must set up appropriate debounce
# times to detect such errors. The BMC is expected to turn on the Fault LED forever for fatal errors, or to
# turn on the Fault LED and turn it off when the fault clears for non-fatal errors.
#
# Usage: <app_name> <socket 0/1>
# shellcheck source=/dev/null
source /usr/sbin/gpio-lib.sh
# global variables
error_flag='/tmp/fault_err'
warning_flag='/tmp/fault_warning'
duty_cycle=250000
scan_pulse=100000
blank_num=8
curr_pattern=0
prev_pattern=0
gpio_status=0
repeat=0
socket=$1
socket1_present=15
socket1_status=1
S0_fault_gpio=73
S1_fault_gpio=201
map_event_name() {
case $curr_pattern in
1)
event_name="RAS_GPIO_INVALID_LCS"
;;
2)
event_name="RAS_GPIO_FILE_HDR_INVALID"
;;
3)
event_name="RAS_GPIO_FILE_INTEGRITY_INVALID"
;;
4)
event_name="RAS_GPIO_KEY_CERT_AUTH_ERR"
;;
5)
event_name="RAS_GPIO_CNT_CERT_AUTH_ERR"
;;
6)
event_name="RAS_GPIO_I2C_HARDWARE_ERR"
;;
7)
event_name="RAS_GPIO_CRYPTO_ENGINE_ERR"
;;
8)
event_name="RAS_GPIO_ROTPK_EFUSE_INVALID"
;;
9)
event_name="RAS_GPIO_SEED_EFUSE_INVALID"
;;
10)
event_name="RAS_GPIO_LCS_FROM_EFUSE_INVALID"
;;
11)
event_name="RAS_GPIO_PRIM_ROLLBACK_EFUSE_INVALID"
;;
12)
event_name="RAS_GPIO_SEC_ROLLBACK_EFUSE_INVALID"
;;
13)
event_name="RAS_GPIO_HUK_EFUSE_INVALID"
;;
14)
event_name="RAS_GPIO_CERT_DATA_INVALID"
;;
15)
event_name="RAS_GPIO_INTERNAL_HW_ERR"
;;
*)
event_name="NOT_SUPPORT"
;;
esac
}
detect_patern_repeat() {
local prev=0
local curr=0
local cnt=13
while true
do
usleep $scan_pulse
gpio_status=$(cat /sys/class/gpio/gpio"$gpio_Id"/value)
prev=$curr
curr=$gpio_status
if [ "$prev" == 0 ] && [ "$curr" == 1 ]; then
# patern start repeating, check if previous and current pattern are the same
repeat=1
break
fi
if [ "$cnt" == 0 ]; then
map_event_name
echo "detected a warning from fault GPIO #$fault_gpio $socket, event $event_name"
# pattern not repeat, this is a warning, turn on warning flag
touch $warning_flag
break
fi
cnt=$(( cnt - 1 ))
done
}
detect_pattern() {
local cnt_falling_edge=0
local cnt_blank=0
local prev=0
local curr=0
while true
do
prev=$curr
curr=$gpio_status
# count the falling edges, if they appear, just reset cnt_blank
if [ "$prev" == 1 ] && [ "$curr" == 0 ]; then
cnt_falling_edge=$(( cnt_falling_edge + 1 ))
cnt_blank=0
continue
# check if we are in the quite gap
elif [ "$prev" == 0 ] && [ "$curr" == 0 ]; then
cnt_blank=$(( cnt_blank + 1 ))
if [ "$cnt_blank" == "$blank_num" ]; then
# echo "pattern number falling_edge=$cnt_falling_edge blank=$cnt_blank"
curr_pattern=$cnt_falling_edge
# after count all falling edges, now check if patern repeat after 3s
detect_patern_repeat
break
fi
fi
usleep $scan_pulse
gpio_status=$(cat /sys/class/gpio/gpio"$gpio_Id"/value)
done
}
gpio_config_input() {
echo "$gpio_Id" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio"${gpio_Id}"/direction
}
init_sysfs_fault_gpio() {
gpio_Id=$(gpio_number "$fault_gpio")
if [ -d /sys/class/gpio/gpio"$gpio_Id" ]; then
return
fi
gpio_config_input "$fault_gpio"
}
# init
if [ "$socket" == "0" ]; then
fault_gpio=$S0_fault_gpio
else
socket1_status=$(gpioget 0 "$socket1_present")
if [ "$socket1_status" == 1 ]; then
echo "socket 1 not present"
exit 1
fi
fault_gpio=$S1_fault_gpio
fi
init_sysfs_fault_gpio
# daemon start
while true
do
# detect when pattern starts
if [ "$gpio_status" == 1 ]; then
# now, there is something on gpio, check if that is a pattern
detect_pattern
if [ "$repeat" == 1 ] && [ "$prev_pattern" == "$curr_pattern" ]; then
map_event_name
echo "detected an error from fault GPIO #$fault_gpio $socket, event#$curr_pattern $event_name"
touch $error_flag
repeat=0
fi
prev_pattern=$curr_pattern
curr_pattern=0
continue
fi
usleep $duty_cycle
gpio_status=$(cat /sys/class/gpio/gpio"$gpio_Id"/value)
done
exit 1
@@ -0,0 +1,180 @@
#!/bin/bash
# This script monitors fan, over-temperature, PSU, CPU/SCP failure and update fault LED status
# shellcheck disable=SC2004
# shellcheck disable=SC2046
# shellcheck source=/dev/null
# common variables
warning_fault_flag='/tmp/fault_warning'
error_fault_flag='/tmp/fault_err'
overtemp_fault_flag='/tmp/fault_overtemp'
fault_RAS_UE_flag='/tmp/fault_RAS_UE'
blink_rate=100000
fault="false"
on="true"
off="false"
gpio_fault="false"
# fan variables
fan_failed="false"
fan_failed_flag='/tmp/fan_failed'
# PSU variables
psu_failed="false"
psu_bus=6
psu0_addr=0x58
psu1_addr=0x59
status_word_cmd=0x79
# Following the PMBus Specification
# Bit[1]: CML faults
# Bit[2]: Over temperature faults
# Bit[3]: Under voltage faults
# Bit[4]: Over current faults
# Bit[5]: Over voltage fault
# Bit[10]: Fan faults
psu_fault_bitmask=0x43e
# led variables
led_service='xyz.openbmc_project.LED.GroupManager'
led_fault_path='/xyz/openbmc_project/led/groups/system_fault'
led_fault_interface='xyz.openbmc_project.Led.Group'
fault_led_status=$off
# functions declaration
check_fan_failed() {
if [[ -f $fan_failed_flag ]]; then
fan_failed="true"
else
fan_failed="false"
fi
}
turn_on_off_fault_led() {
busctl set-property $led_service $led_fault_path $led_fault_interface Asserted b "$1" >> /dev/null
}
check_psu_failed() {
local psu0_presence
local psu1_presence
local psu0_value
local psu1_value
psu0_presence=$(gpioget $(gpiofind PSU1_PRESENT))
psu0_failed="true"
if [ "$psu0_presence" == "0" ]; then
# PSU0 presence, monitor the PSUs using pmbus, check the STATUS_WORD
psu0_value=$(i2cget -f -y $psu_bus $psu0_addr $status_word_cmd w)
psu0_bit_fault=$(($psu0_value & $psu_fault_bitmask))
if [ "$psu0_bit_fault" == "0" ]; then
psu0_failed="false"
fi
fi
psu1_presence=$(gpioget $(gpiofind PSU2_PRESENT))
psu1_failed="true"
if [ "$psu1_presence" == "0" ]; then
# PSU1 presence, monitor the PSUs using pmbus, check the STATUS_WORD
psu1_value=$(i2cget -f -y $psu_bus $psu1_addr $status_word_cmd w)
psu1_bit_fault=$(($psu1_value & $psu_fault_bitmask))
if [ "$psu1_bit_fault" == "0" ]; then
psu1_failed="false"
fi
fi
if [ "$psu0_failed" == "true" ] || [ "$psu1_failed" == "true" ]; then
psu_failed="true"
else
psu_failed="false"
fi
}
check_fault() {
if [[ "$fan_failed" == "true" ]] || [[ "$psu_failed" == "true" ]] \
|| [[ "$gpio_fault" == "true" ]] \
|| [[ "$RAS_UE_occured" == "true" ]] \
|| [[ "$overtemp_occured" == "true" ]]; then
fault="true"
else
fault="false"
fi
}
control_fault_led() {
if [ "$fault" == "true" ]; then
if [ "$fault_led_status" == $off ]; then
turn_on_off_fault_led $on
fault_led_status=$on
fi
else
if [ "$fault_led_status" == $on ]; then
turn_on_off_fault_led $off
fault_led_status=$off
fi
fi
}
blink_fault_led() {
if [ "$fault_led_status" == $off ]; then
turn_on_off_fault_led $on
usleep $blink_rate
turn_on_off_fault_led $off
else
turn_on_off_fault_led $off
usleep $blink_rate
turn_on_off_fault_led $on
fi
}
check_gpio_fault() {
if [[ -f $error_fault_flag ]]; then
gpio_fault="true"
else
if [ -f $warning_fault_flag ]; then
blink_fault_led
rm $warning_fault_flag
fi
gpio_fault="false"
fi
}
check_RAS_UE_occured() {
if [[ -f $fault_RAS_UE_flag ]]; then
echo "RAS UE error occured, turn on fault LED"
RAS_UE_occured="true"
else
RAS_UE_occured="false"
fi
}
check_overtemp_occured() {
if [[ -f $overtemp_fault_flag ]]; then
echo "Over temperature occured, turn on fault LED"
overtemp_occured="true"
else
overtemp_occured="false"
fi
}
# daemon start
while true
do
check_gpio_fault
check_fan_failed
check_overtemp_occured
check_RAS_UE_occured
# Monitors PSU presence
check_psu_failed
check_fault
control_fault_led
sleep 2
done
exit 1
@@ -0,0 +1,18 @@
SUMMARY = "Ampere Computing LLC Update MAC Address from FRU Inventory Information"
DESCRIPTION = "Update MAC Address from FRU Inventory Information 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
DEPENDS = "systemd"
RDEPENDS:${PN} = "bash"
FILESEXTRAPATHS:append := "${THISDIR}/${PN}:"
SYSTEMD_SERVICE:${PN} = "ampere_update_mac.service"
@@ -0,0 +1,13 @@
[Unit]
Description=Updating MAC Address Service From FRU inventory
Requires=xyz.openbmc_project.EntityManager.service
After=xyz.openbmc_project.EntityManager.service
[Service]
ExecStart=/usr/sbin/ampere_update_mac.sh eth1 3 80
SyslogIdentifier=ampere_update_mac.sh
Type=oneshot
RemainAfterExit=yes
[Install]
WantedBy={SYSTEMD_DEFAULT_TARGET}
@@ -0,0 +1,32 @@
SUMMARY = "Phosphor OpenBMC Mt.Jade Platform Init Service"
DESCRIPTION = "Phosphor OpenBMC Mt.Jade Platform Init 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_platform_init.sh \
file://ampere_uart_console_setup.sh \
file://ampere_uartmux_ctrl.sh \
file://ampere-platform-init.service \
"
SYSTEMD_PACKAGES = "${PN}"
SYSTEMD_SERVICE:${PN} = "ampere-platform-init.service"
do_install () {
install -d ${D}${sbindir}
install -m 0755 ${WORKDIR}/ampere_platform_init.sh ${D}${sbindir}/
install -m 0755 ${WORKDIR}/ampere_uart_console_setup.sh ${D}${sbindir}/
install -m 0755 ${WORKDIR}/ampere_uartmux_ctrl.sh ${D}/${sbindir}/
install -d ${D}${systemd_unitdir}/system/
install -m 0644 ${WORKDIR}/ampere-platform-init.service ${D}${systemd_unitdir}/system
}
@@ -0,0 +1,11 @@
[Unit]
Description = Mt.Jade Platform Initialization
[Service]
Restart=no
RemainAfterExit=true
Type=oneshot
ExecStart=/usr/sbin/ampere_platform_init.sh
[Install]
WantedBy=sysinit.target
@@ -0,0 +1,51 @@
#!/bin/bash
# shellcheck source=meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-lib.sh
source /usr/sbin/gpio-lib.sh
# shellcheck source=meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-defs.sh
source /usr/sbin/gpio-defs.sh
source /usr/sbin/ampere_uart_console_setup.sh
# Configure to boot from MAIN SPI-HOST
gpio_configure_output "$SPI0_BACKUP_SEL" 0
gpio_configure_input "$S0_I2C9_ALERT_L"
gpio_configure_input "$S1_I2C9_ALERT_L"
gpio_configure_input "$GPIO_BMC_VGA_FRONT_PRES_L"
gpio_configure_input "$GPIO_S0_VRHOT_L"
gpio_configure_input "$GPIO_S1_VRHOT_L"
gpio_configure_output "$BMC_VGA_SEL" 1
# =======================================================
# Below GPIOs are controlled by other services so just
# initialize in A/C power only.
bootstatus=$(cat /sys/class/watchdog/watchdog0/bootstatus)
if [ "$bootstatus" == '32' ]; then
gpio_configure_output "$BMC_GPIOR2_EXT_HIGHTEMP_L" 1
gpio_configure_output "$GPIO_BMC_VR_PMBUS_SEL_L" 1
gpio_configure_output "$GPIO_BMC_I2C6_RESET_L" 1
# Initialize OCP register
gpio_configure_output "$OCP_MAIN_PWREN" 0
# Configure SPI-NOR/EEPROM switching
gpio_configure_output "$SPI0_PROGRAM_SEL" 0
gpio_configure_output "$BMC_I2C_BACKUP_SEL" 1
gpio_configure_output "$SPI0_BACKUP_SEL" 0
# Initialize BMC_SYS_PSON_L, SHD_REQ_L, BMC_SYSRESET_L
gpio_configure_output "$SYS_PSON_L" 1
gpio_configure_output "$S0_SHD_REQ_L" 1
gpio_configure_output "$S0_SYSRESET_L" 1
gpio_configure_output "$S1_SYSRESET_L" 1
# RTC Lock, SPECIAL_BOOT
gpio_configure_output "$RTC_LOCK" 0
gpio_configure_output "$S0_SPECIAL_BOOT" 0
gpio_configure_output "$S1_SPECIAL_BOOT" 0
fi
gpio_configure_output "$BMC_READY" 1
# =======================================================
# Setting uart muxes to BMC as default
uart_console_setup
@@ -0,0 +1,57 @@
#!/bin/sh -e
#
# Copyright (c) 2020 Ampere Computing LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# shellcheck disable=SC2039
# shellcheck disable=SC2112
# shellcheck disable=SC3010
# shellcheck disable=SC3030
# shellcheck disable=SC3054
export obmc_console_tty=("ttyS0" "ttyS1" "ttyS2" "ttyS3")
function get_uart_port()
{
tty=$1
case "${tty}" in
"ttyS0") uart=1
;;
"ttyS1") uart=2
;;
"ttyS2") uart=3
;;
"ttyS3") uart=4
;;
*) echo "Invalid tty passed to $0. Exiting!"
exit 1;
;;
esac
echo $uart
}
function uart_console_setup()
{
# Default the host routing through the mux to use the BMC (2)
# This allows the SoL console in webui, and the ssh port 2200, to work
# upon startup. If UART transcievers are installed on the header and required,
# this value should be set to 1
for tty in "${obmc_console_tty[@]}"; do
uart=$(get_uart_port "$tty")
if [ "${uart}" -ne 0 ]
then
/usr/sbin/ampere_uartmux_ctrl.sh "${uart}" 2
fi
done
}
@@ -0,0 +1,55 @@
#!/bin/bash
#
# Copyright (c) 2021 Ampere Computing LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Ampere Computing LLC: UART MUX/DEMUX for CPU0 UART0,1,4 and CPU1 UART1
# Usage: ampere_uartmux_ctrl.sh <CPU UART port number> <UARTx_MODE>
# <UARTx_MODE> of 1 sets CPU To HDR_CONN
# <UARTx_MODE> of 2 sets BMC to CPU (eg dropbear ssh server on port 2200)
# shellcheck source=meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-lib.sh
source /usr/sbin/gpio-lib.sh
if [ $# -lt 2 ]; then
exit 1
fi
case "$1" in
1) GPIO_UARTx_MODE0=56
;;
2) GPIO_UARTx_MODE0=57
;;
3) GPIO_UARTx_MODE0=58
;;
4) GPIO_UARTx_MODE0=59
;;
*) echo "Invalid UART port selection"
exit 1
;;
esac
echo "Ampere UART MUX CTRL UART port $1 to mode $2"
case "$2" in
1) gpio_configure_output "${GPIO_UARTx_MODE0}" 0
exit 0
;;
2) gpio_configure_output "${GPIO_UARTx_MODE0}" 1
exit 0
;;
*) echo "Invalid UART mode selection"
exit 1
;;
esac
@@ -0,0 +1,20 @@
FILESEXTRAPATHS:append := "${THISDIR}/${PN}:"
SRC_URI:append = " \
file://gpio-defs.sh \
file://gpio-lib.sh \
file://ampere_power_util.sh \
file://ampere_firmware_upgrade.sh \
file://ampere_flash_bios.sh \
file://ampere_driver_binder.sh \
"
do_install:append() {
install -d ${D}/usr/sbin
install -m 0755 ${WORKDIR}/gpio-lib.sh ${D}/${sbindir}/
install -m 0755 ${WORKDIR}/gpio-defs.sh ${D}/${sbindir}/
install -m 0755 ${WORKDIR}/ampere_power_util.sh ${D}/${sbindir}/
install -m 0755 ${WORKDIR}/ampere_firmware_upgrade.sh ${D}/${sbindir}/
install -m 0755 ${WORKDIR}/ampere_flash_bios.sh ${D}/${sbindir}/
install -m 0755 ${WORKDIR}/ampere_driver_binder.sh ${D}/${sbindir}/
}
@@ -0,0 +1,29 @@
#!/bin/bash
DELAY_BEFORE_BIND=5000000
# Each driver include driver name and driver path
declare -a DRIVER_NAMEs=("2-004f"
"2-004e"
)
# Driver path should include / at the end
declare -a DRIVER_PATHs=("/sys/bus/i2c/drivers/smpro-core/"
"/sys/bus/i2c/drivers/smpro-core/"
)
# get length of an array
arraylength=${#DRIVER_NAMEs[@]}
usleep $DELAY_BEFORE_BIND
# use for loop to read all values and indexes
for (( i=0; i<"${arraylength}"; i++ ));
do
bindFile="${DRIVER_PATHs[$i]}bind"
driverDir="${DRIVER_PATHs[$i]}${DRIVER_NAMEs[$i]}"
if [ -d "$driverDir" ]; then
echo "Driver ${DRIVER_NAMEs[$i]} is already bound."
continue;
fi
echo "${DRIVER_NAMEs[$i]}" > "$bindFile"
done
exit 0
@@ -0,0 +1,151 @@
#!/bin/bash
do_fru_upgrade() {
FRU_DEVICE="/sys/bus/i2c/devices/3-0050/eeprom"
if ! command -v ampere_fru_upgrade;
then
echo "Bypass fru update as no ampere_fru_upgrade available"
exit
fi
ampere_fru_upgrade -d $FRU_DEVICE -f "$IMAGE"
systemctl restart xyz.openbmc_project.FruDevice.service
systemctl restart phosphor-ipmi-host.service
}
do_smpmpro_upgrade() {
I2C_BUS_DEV="1"
EEPROM_ADDR="0x50"
if ! command -v ampere_eeprom_prog;
then
echo "Bypass SCP firmware update as no ampere_eeprom_prog available"
exit
fi
echo "SECPRO mode: $SECPRO"
# Turn off the Host if it is currently ON
chassisstate=$(obmcutil chassisstate | awk -F. '{print $NF}')
echo "Current Chassis State: $chassisstate"
if [ "$chassisstate" == 'On' ];
then
echo "Turning the Chassis off"
obmcutil chassisoff
# Wait 60s until Chassis is off
cnt=30
while [ "$cnt" -gt 0 ];
do
cnt=$((cnt - 1))
sleep 2
# Check if HOST was OFF
chassisstate_off=$(obmcutil chassisstate | awk -F. '{print $NF}')
if [ "$chassisstate_off" != 'On' ];
then
break
fi
if [ "$cnt" == "0" ];
then
echo "--- Error : Failed turning the Chassis off"
exit 1
fi
done
fi
if [[ $SECPRO == 1 ]]; then
# 3 is S0_SPECIAL_BOOT
gpioset 0 3=1
# 66 is S1_SPECIAL_BOOT
gpioset 0 66=1
fi
# Switch EEPROM control to BMC AST2500 I2C
# 226 is BMC_GPIOAC2_SPI0_PROGRAM_SEL
gpioset 0 226=0
# 08 is BMC_GPIOB0_I2C_BACKUP_SEL
if [[ $DEV_SEL == 1 ]]; then
echo "Run update primary Boot EEPROM"
gpioset 0 8=1 # Main EEPROM
elif [[ $DEV_SEL == 2 ]]; then
echo "Run update secondary Boot EEPROM"
gpioset 0 8=0 # Second EEPROM
else
echo "Please choose Main (1) or Second EEPROM (2)"
exit 0
fi
# Write Firmware to EEPROM and read back for validation
ampere_eeprom_prog -b $I2C_BUS_DEV -s $EEPROM_ADDR -p -f "$IMAGE"
# Switch EEPROM control to Host
# 08 is BMC_GPIOB0_I2C_BACKUP_SEL
gpioset 0 8=1
# 226 is BMC_GPIOAC2_SPI0_PROGRAM_SEL
gpioset 0 226=1
# Deassert SECPRO GPIO PINs
if [[ $SECPRO == 1 ]]; then
echo "De-asserting special GPIO PINs"
# 3 is S0_SPECIAL_BOOT
gpioset 0 3=0
# 66 is S1_SPECIAL_BOOT
gpioset 0 66=0
fi
if [ "$chassisstate" == 'On' ];
then
sleep 5
echo "Turn on the Host"
obmcutil poweron
fi
}
if [ $# -eq 0 ]; then
echo "Usage:"
echo " $(basename "$0") <Type> <Image file> <DEV_SEL> [SECPRO]"
echo "Where:"
echo " <Type>: smpmpro or fru"
echo " If Type is smpmpro, then DEV_SEL must is 1 (MAIN EEPROM), 2 (Failover)"
echo " SECPRO: Optional, input '1' to enter & flash secpro mode. Default: 0"
exit 0
fi
TYPE=$1
IMAGE=$2
if [ -z "$3" ]
then
DEV_SEL="1" # by default, select Main image
else
DEV_SEL=$3
fi
SECPRO=0
if [ -n "$4" ]; then
if [[ "$4" == "1" ]]; then
SECPRO=1
fi
fi
MANIFEST="$(echo "$IMAGE" | cut -d'/' -f-4)/MANIFEST"
if [ -f "$MANIFEST" ]; then
echo "MANIFEST: $MANIFEST"
if grep -qF "SECPRO" "$MANIFEST"; then
SECPRO=1
fi
fi
# Restrict to flash failover in case of SECPRO
if [ $SECPRO == 1 ] && [ "$DEV_SEL" == 2 ]; then
echo "Not allow to flash the failover with SECPRO image"
exit
fi
if [[ $TYPE == "smpmpro" ]]; then
do_smpmpro_upgrade
elif [[ $TYPE == "fru" ]]; then
do_fru_upgrade
fi
@@ -0,0 +1,129 @@
#!/bin/bash
#
# Copyright (c) 2021 Ampere Computing LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
do_flash () {
# Check the PNOR partition available
HOST_MTD=$(< /proc/mtd grep "pnor-uefi" | sed -n 's/^\(.*\):.*/\1/p')
if [ -z "$HOST_MTD" ];
then
# Check the ASpeed SMC driver bound before
HOST_SPI=/sys/bus/platform/drivers/spi-aspeed-smc/1e630000.spi
if [ -d "$HOST_SPI" ]; then
echo "Unbind the ASpeed SMC driver"
echo 1e630000.spi > /sys/bus/platform/drivers/spi-aspeed-smc/unbind
sleep 2
fi
# If the PNOR partition is not available, then bind again driver
echo "--- Bind the ASpeed SMC driver"
echo 1e630000.spi > /sys/bus/platform/drivers/spi-aspeed-smc/bind
sleep 2
HOST_MTD=$(< /proc/mtd grep "pnor-uefi" | sed -n 's/^\(.*\):.*/\1/p')
if [ -z "$HOST_MTD" ];
then
echo "Fail to probe Host SPI-NOR device"
exit 1
fi
fi
echo "--- Flashing firmware to @/dev/$HOST_MTD"
flashcp -v "$IMAGE" /dev/"$HOST_MTD"
}
if [ $# -eq 0 ]; then
echo "Usage: $(basename "$0") <BIOS image file>"
exit 0
fi
IMAGE="$1"
if [ ! -f "$IMAGE" ]; then
echo "The image file $IMAGE does not exist"
exit 1
fi
if [ -z "$2" ]; then
DEV_SEL="1" # by default, select primary device
else
DEV_SEL="$2"
fi
# Turn off the Host if it is currently ON
chassisstate=$(obmcutil chassisstate | awk -F. '{print $NF}')
echo "--- Current Chassis State: $chassisstate"
if [ "$chassisstate" == 'On' ];
then
echo "--- Turning the Chassis off"
obmcutil chassisoff
# Wait 60s until Chassis is off
cnt=30
while [ "$cnt" -gt 0 ];
do
cnt=$((cnt - 1))
sleep 2
# Check if HOST was OFF
chassisstate_off=$(obmcutil chassisstate | awk -F. '{print $NF}')
if [ "$chassisstate_off" != 'On' ];
then
break
fi
if [ "$cnt" == "0" ];
then
echo "--- Error : Failed turning the Chassis off"
exit 1
fi
done
fi
# Switch the host SPI bus to BMC"
echo "--- Switch the host SPI bus to BMC."
if ! gpioset 0 226=0; then
echo "ERROR: Switch the host SPI bus to BMC. Please check gpio state"
exit 1
fi
# Switch the host SPI bus (between primary and secondary)
# 227 is BMC_SPI0_BACKUP_SEL
if [[ $DEV_SEL == 1 ]]; then
echo "Run update primary Host SPI-NOR"
gpioset 0 227=0 # Primary SPI
elif [[ $DEV_SEL == 2 ]]; then
echo "Run update secondary Host SPI-NOR"
gpioset 0 227=1 # Second SPI
else
echo "Please choose primary SPI (1) or second SPI (2)"
exit 0
fi
# Flash the firmware
do_flash
# Switch the host SPI bus to HOST."
echo "--- Switch the host SPI bus to HOST."
if ! gpioset 0 226=1; then
echo "ERROR: Switch the host SPI bus to HOST. Please check gpio state"
exit 1
fi
if [ "$chassisstate" == 'On' ];
then
sleep 5
echo "Turn on the Host"
obmcutil poweron
fi
@@ -0,0 +1,120 @@
#!/bin/bash
# shellcheck source=meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-defs.sh
source /usr/sbin/gpio-defs.sh
# Usage of this utility
function usage() {
echo "Usage:"
echo " ampere_power_util.sh mb [status|shutdown_ack|force_reset|soft_off]";
}
power_status() {
st=$(busctl get-property xyz.openbmc_project.State.Chassis /xyz/openbmc_project/state/chassis0 xyz.openbmc_project.State.Chassis CurrentPowerState | cut -d"." -f6)
if [ "$st" == "On\"" ]; then
echo "on"
else
echo "off"
fi
}
shutdown_ack() {
if [ -f "/run/openbmc/host@0-softpoweroff" ]; then
echo "Receive shutdown ACK triggered after softportoff the host."
touch /run/openbmc/host@0-softpoweroff-shutdown-ack
else
echo "Receive shutdown ACK triggered"
sleep 3
systemctl start obmc-chassis-poweroff@0.target
fi
}
soft_off() {
# Trigger shutdown_req
touch /run/openbmc/host@0-softpoweroff
gpioset -l 0 "$S0_SHD_REQ_L"=1
sleep 1s
gpioset -l 0 "$S0_SHD_REQ_L"=0
# Wait for shutdown_ack from the host in 30 seconds
cnt=30
while [ $cnt -gt 0 ];
do
# Wait for SHUTDOWN_ACK and create the host@0-softpoweroff-shutdown-ack
if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then
break
fi
sleep 1
cnt=$((cnt - 1))
done
# Softpoweroff is successed
sleep 2
rm -rf /run/openbmc/host@0-softpoweroff
if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then
rm -rf /run/openbmc/host@0-softpoweroff-shutdown-ack
fi
echo 0
}
force_reset() {
if [ -f "/run/openbmc/host@0-softpoweroff" ]; then
# In graceful host reset, after trigger os shutdown,
# the phosphor-state-manager will call force-warm-reset
# in this case the force_reset should wait for shutdown_ack from host
cnt=30
while [ $cnt -gt 0 ];
do
if [ -f "/run/openbmc/host@0-softpoweroff-shutdown-ack" ]; then
break
fi
echo "Waiting for shutdown-ack count down $cnt"
sleep 1
cnt=$((cnt - 1))
done
# The host OS is failed to shutdown
if [ $cnt == 0 ]; then
echo "Shutdown-ack time out after 30s."
exit 0
fi
fi
echo "Triggering sysreset pin"
gpioset -l 0 "$S0_SYSRESET_L"=1
sleep 1
gpioset -l 0 "$S0_SYSRESET_L"=0
}
if [ $# -lt 2 ]; then
echo "Total number of parameter=$#"
echo "Insufficient parameter"
usage;
exit 0;
fi
if [ "$1" != "mb" ]; then
echo "Invalid parameter1=$1"
usage;
exit 0;
fi
mkdir -p /run/openbmc/
if [ "$2" == "shutdown_ack" ]; then
shutdown_ack
elif [ "$2" == "status" ]; then
power_status
elif [ "$2" == "force_reset" ]; then
force_reset
elif [ "$2" == "soft_off" ]; then
ret=$(soft_off)
if [ "$ret" == 0 ]; then
echo "The host is already softoff"
else
echo "Failed to softoff the host"
fi
exit "$ret";
else
echo "Invalid parameter2=$2"
usage;
fi
exit 0;
@@ -0,0 +1,59 @@
#!/bin/sh
# shellcheck disable=SC2034
# Index of GPIO device in gpioget/gpioset
GPIO_CHIP0_IDX=0
GPIO_CHIP1_IDX=1
# Base of GPIO chip in /sys/class/gpio
GPIO_CHIP0_BASE=792
GPIO_CHIP1_BASE=780
### Power control configuration
# Power control gpios
S0_SHD_REQ_L=49
S0_SHD_ACK_L=50
S0_REBOOT_ACK_L=75
S0_SYSRESET_L=91
S1_SYSRESET_L=92
### Table 1: GPIO Assignments
BMC_I2C_BACKUP_SEL=8
S0_CPU_FW_BOOT_OK=48
CPU_BMC_OVERTEMP_L=51
CPU_BMC_HIGHTEMP_L=72
CPU_FAULT_ALERT=73
S1_CPU_FW_BOOT_OK=202
S0_SPECIAL_BOOT=3
S1_SPECIAL_BOOT=66
RTC_LOCK=203
### Table 2: Alert and Additional Miscellaneous Signals
S0_SCP_AUTH_FAILURE=74
S1_SCP_AUTH_FAILURE=205
BMC_OK=228
SLAVE_PRESENT_L=230
### Common GPIOs
SYS_PSON_L=42
BMC_READY=229
### OCP power selection
OCP_AUX_PWREN=139
OCP_MAIN_PWREN=140
### SPI0 Mode selection
SPI0_PROGRAM_SEL=226
SPI0_BACKUP_SEL=227
### Mt.Jade specific GPIOs
S0_I2C9_ALERT_L=100
S1_I2C9_ALERT_L=101
GPIO_BMC_VGA_FRONT_PRES_L=135
GPIO_S0_VRHOT_L=144
GPIO_S1_VRHOT_L=145
BMC_VGA_SEL=195
BMC_GPIOR2_EXT_HIGHTEMP_L=138
GPIO_BMC_VR_PMBUS_SEL_L=149
GPIO_BMC_I2C6_RESET_L=63
@@ -0,0 +1,33 @@
#!/bin/bash
# shellcheck source=meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-defs.sh
source /usr/sbin/gpio-defs.sh
function gpio_number() {
GPIO_BASE=$(cat /sys/class/gpio/gpiochip"$GPIO_CHIP0_BASE"/base)
echo $((GPIO_BASE + $1))
}
# Configure GPIO as output and set its value
function gpio_configure_output() {
gpioId=$(gpio_number "$1")
echo "$gpioId" > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio"${gpioId}"/direction
echo "$2" > /sys/class/gpio/gpio"${gpioId}"/value
echo "$gpioId" > /sys/class/gpio/unexport
}
function gpio_get_val() {
gpioId=$(gpio_number "$1")
echo "$gpioId" > /sys/class/gpio/export
cat /sys/class/gpio/gpio"$gpioId"/value
echo "$gpioId" > /sys/class/gpio/unexport
}
# Configure GPIO as input
function gpio_configure_input() {
gpioId=$(gpio_number "$1")
echo "$gpioId" > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio"${gpioId}"/direction
echo "$gpioId" > /sys/class/gpio/unexport
}
@@ -0,0 +1,44 @@
SUMMARY = "Ampere Computing LLC Utilities"
DESCRIPTION = "Ampere Utilities for Mt.Jade 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
S = "${WORKDIR}"
SRC_URI = " \
file://ampere_gpio_utils.sh \
"
DEPENDS = "systemd"
RDEPENDS:${PN} = "bash"
SYSTEMD_PACKAGES = "${PN}"
SYSTEMD_SERVICE:${PN} = " \
ampere-gpio-poweroff@.service \
ampere-gpio-poweron@.service \
"
# chassis power on
CHASSIS_POWERON_SVC = "ampere-gpio-poweron@.service"
CHASSIS_POWERON_INSTMPL = "ampere-gpio-poweron@{0}.service"
CHASSIS_POWERON_TGTFMT = "obmc-chassis-poweron@{0}.target"
CHASSIS_POWERON_FMT = "../${CHASSIS_POWERON_SVC}:${CHASSIS_POWERON_TGTFMT}.requires/${CHASSIS_POWERON_INSTMPL}"
SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'CHASSIS_POWERON_FMT', 'OBMC_CHASSIS_INSTANCES')}"
# chassis power off
CHASSIS_POWEROFF_SVC = "ampere-gpio-poweroff@.service"
CHASSIS_POWEROFF_INSTMPL = "ampere-gpio-poweroff@{0}.service"
CHASSIS_POWEROFF_TGTFMT = "obmc-chassis-poweroff@{0}.target"
CHASSIS_POWEROFF_FMT = "../${CHASSIS_POWEROFF_SVC}:${CHASSIS_POWEROFF_TGTFMT}.requires/${CHASSIS_POWEROFF_INSTMPL}"
SYSTEMD_LINK:${PN} += "${@compose_list_zip(d, 'CHASSIS_POWEROFF_FMT', 'OBMC_CHASSIS_INSTANCES')}"
do_install() {
install -d ${D}/usr/sbin
install -m 0755 ${WORKDIR}/ampere_gpio_utils.sh ${D}/${sbindir}/
}
@@ -0,0 +1,9 @@
[Unit]
Description=Ampere set GPIOs before power off
Before=phosphor-wait-power-off@%i.service
Conflicts=obmc-chassis-poweron@%i.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/ampere_gpio_utils.sh power off
SyslogIdentifier=ampere_gpio_utils
@@ -0,0 +1,10 @@
[Unit]
Description=Ampere set GPIOs before power on
Before=phosphor-wait-power-on@%i.service
After=obmc-power-start-pre@%i.target
Conflicts=obmc-chassis-poweroff@%i.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/ampere_gpio_utils.sh power on
SyslogIdentifier=ampere_gpio_utils
@@ -0,0 +1,44 @@
#!/bin/bash
# shellcheck source=meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-lib.sh
source /usr/sbin/gpio-defs.sh
# shellcheck source=meta-ampere/meta-jade/recipes-ampere/platform/ampere-utils/gpio-defs.sh
source /usr/sbin/gpio-lib.sh
function usage() {
echo "usage: ampere_gpio_utils.sh [power] [on|off]";
}
set_gpio_power_off() {
echo "Setting GPIO before Power off"
}
set_gpio_power_on() {
echo "Setting GPIO before Power on"
val=$(gpio_get_val "$S0_CPU_FW_BOOT_OK")
if [ "$val" == 1 ]; then
exit
fi
gpio_configure_output "$SPI0_PROGRAM_SEL" 1
gpio_configure_output "$SPI0_BACKUP_SEL" 0
}
if [ $# -lt 2 ]; then
echo "Total number of parameter=$#"
echo "Insufficient parameter"
usage;
exit 0;
fi
if [ "$1" == "power" ]; then
if [ "$2" == "on" ]; then
set_gpio_power_on
elif [ "$2" == "off" ]; then
set_gpio_power_off
fi
exit 0;
else
echo "Invalid parameter1=$1"
usage;
exit 0;
fi