diff options
Diffstat (limited to 'meta-quanta/meta-gbs/recipes-gbs/gbs-sysinit/files/gbs-sysinit.sh')
-rw-r--r-- | meta-quanta/meta-gbs/recipes-gbs/gbs-sysinit/files/gbs-sysinit.sh | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/meta-quanta/meta-gbs/recipes-gbs/gbs-sysinit/files/gbs-sysinit.sh b/meta-quanta/meta-gbs/recipes-gbs/gbs-sysinit/files/gbs-sysinit.sh new file mode 100644 index 000000000..7b4571091 --- /dev/null +++ b/meta-quanta/meta-gbs/recipes-gbs/gbs-sysinit/files/gbs-sysinit.sh @@ -0,0 +1,297 @@ +#!/bin/bash +# Copyright 2020 Google LLC +# Copyright 2020 Quanta Computer Inc. +# +# 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. + + +source /usr/libexec/gbs-gpio-common.sh + +WD1RCR_ADDR=0xf080103c +CORSTC_ADDR=0xf080105c +BOARD_VER="" # Set by check_board_ver +pe_eeprom_addr=( 50 54 ) + +SERVICE_NAME="xyz.openbmc_project.Inventory.Manager" +INTERFACE_NAME="xyz.openbmc_project.Inventory.Item" + +PE_PRESENT_OBJPATH=("/xyz/openbmc_project/inventory/system/chassis/gpios/pe_slot0_prsnt" +"/xyz/openbmc_project/inventory/system/chassis/gpios/pe_slot1_prsnt") +HSBP_PRESENT_OBJPATH="/xyz/openbmc_project/inventory/system/chassis/gpios/hsbp_cab_prsnt" +FANBD_PRESENT_OBJPATH="/xyz/openbmc_project/inventory/system/chassis/gpios/fanbd_cab_prsnt" +BP12V_PRESENT_OBJPATH="/xyz/openbmc_project/inventory/system/chassis/gpios/bp12v_cab_prsnt" +SATA0_PRESENT_OBJPATH="/xyz/openbmc_project/inventory/system/chassis/gpios/sata0_prsnt" + +set_gpio_persistence() { + reg_val=$(devmem ${WD1RCR_ADDR} 32) + # Clear bit 16-23 to perserve all GPIO states across warm resets + reg_val=$(printf "0x%08x" $((reg_val & ~0xff0000))) + echo "Setting WD1RCR_ADDR to ${reg_val}" + devmem "${WD1RCR_ADDR}" 32 "${reg_val}" + + reg_val=$(devmem ${CORSTC_ADDR} 32) + # Clear bit 16-23 of CORSTC + reg_val=$(printf "0x%08x" $((reg_val & ~0xff0000))) + echo "Setting CORSTC_ADDR to ${reg_val}" + devmem "${CORSTC_ADDR}" 32 "${reg_val}" +} + +get_board_rev_id() { + echo $(get_gpio_value 'BMC_BRD_REV_ID7')\ + $(get_gpio_value 'BMC_BRD_REV_ID6')\ + $(get_gpio_value 'BMC_BRD_REV_ID5')\ + $(get_gpio_value 'BMC_BRD_REV_ID4')\ + $(get_gpio_value 'BMC_BRD_REV_ID3')\ + $(get_gpio_value 'BMC_BRD_REV_ID2')\ + $(get_gpio_value 'BMC_BRD_REV_ID1')\ + $(get_gpio_value 'BMC_BRD_REV_ID0')\ + | sed 's/ //g' > ~/board_rev_id.txt +} + +get_board_sku_id() { + echo $(get_gpio_value 'BMC_BRD_SKU_ID3')\ + $(get_gpio_value 'BMC_BRD_SKU_ID2')\ + $(get_gpio_value 'BMC_BRD_SKU_ID1')\ + $(get_gpio_value 'BMC_BRD_SKU_ID0')\ + | sed 's/ //g' > ~/board_sku_id.txt +} + +get_hsp_board_rev_id() { + echo $(get_gpio_value 'HSBP_BRD_REV_ID3')\ + $(get_gpio_value 'HSBP_BRD_REV_ID2')\ + $(get_gpio_value 'HSBP_BRD_REV_ID1')\ + $(get_gpio_value 'HSBP_BRD_REV_ID0')\ + | sed 's/ //g' > ~/hsp_board_rev_id.txt +} + +get_fan_board_rev_id() { + echo $(get_gpio_value 'FAN_BRD_REV_ID1')\ + $(get_gpio_value 'FAN_BRD_REV_ID0')\ + | sed 's/ //g' > ~/fan_board_rev_id.txt +} + +check_board_ver() { + # Sets BOARD_VER to either "PREPVT" or "PVT" + # + # BOARD_REV_ID[7:6] = + # 0x00 - EVT + # 0x01 - DVT + # 0x10 - PVT + # 0x11 - MP + + rev7_val=$(get_gpio_value 'BMC_BRD_REV_ID7') + if (( rev7_val == 0 )); then + echo "EVT/DVT rev!" + BOARD_VER="PREPVT" + else + echo "PVT/MP rev!" + BOARD_VER="PVT" + fi +} + +check_board_sku() { + sku1_val=$(get_gpio_value 'BMC_BRD_SKU_ID1') + if (( sku1_val == 1 )); then + echo "GBS SKU!" + BOARD_SKU="GBS" + else + echo "Other SKU!" + BOARD_SKU="TBD" + fi +} + +set_uart_en_low() { + # GPIO76 UART_EN polarity inverted between DVT/PVT + # Pin direction was set high in the kernel. + set_gpio_direction 'FM_BMC_CPU_UART_EN' low +} + +set_hdd_prsnt() { + # On PVT need to forward SATA0_PRSNT_N to HDD_PRSNT_N + # The signal is safe to set on DVT boards so just set universally. + sata_prsnt_n="$(busctl get-property $SERVICE_NAME ${SATA0_PRESENT_OBJPATH} \ + $INTERFACE_NAME Present | awk '{print $2}')" + if [[ ${sata_prsnt_n} != "true" ]]; then + return 1 + fi + # sata_prsnt_n is active low => value "true" means low + if [[ ${sata_prsnt_n} == "true" ]]; then + set_gpio_direction 'HDD_PRSNT_N' low + else + set_gpio_direction 'HDD_PRSNT_N' high + fi +} + +KERNEL_FIU_ID="c0000000.fiu" +KERNEL_SYSFS_FIU="/sys/bus/platform/drivers/NPCM-FIU" + +bind_host_mtd() { + set_gpio_direction 'SPI_SW_SELECT' high + if [[ -d ${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID} ]]; then + echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind + fi + echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/bind +} + +unbind_host_mtd() { + if [[ -d ${KERNEL_SYSFS_FIU}/${KERNEL_FIU_ID} ]]; then + echo "${KERNEL_FIU_ID}" > "${KERNEL_SYSFS_FIU}"/unbind + fi + set_gpio_direction 'SPI_SW_SELECT' low +} +trap unbind_host_mtd EXIT SIGHUP SIGINT SIGTERM + +# Taken from /run/initramfs/update +# Given label name, return mtd node. e.g. `findmtd bmc` returns 'mtd0' +findmtd() { + m=$(grep -xl "$1" /sys/class/mtd/*/name) + m=${m%/name} + m=${m##*/} + echo $m +} + +verify_host_bios() { + echo "BIOS verification start!" + + # placeholder for verifying host BIOS. For now time BIOS read + # with dd + bind_host_mtd || { echo "Failed to bind FIU driver for host MTD"; return 1; } + + pnor_mtd=$(findmtd pnor) + [[ -z "${pnor_mtd}" ]] && { echo "Failed to find host MTD partition!"; return 1; } + + # Test timing by computing SHA256SUM. + sha256sum /dev/${pnor_mtd}ro + + echo "BIOS verification complete!" + unbind_host_mtd +} + +reset_phy() { + ifconfig eth1 down + set_gpio_direction 'RST_BMC_PHY_N' low + set_gpio_direction 'RST_BMC_PHY_N' high + ifconfig eth1 up +} + +parse_pe_fru() { + pe_fruid=3 + for i in {1..2}; + do + pe_prsnt_n="$(busctl get-property $SERVICE_NAME ${PE_PRESENT_OBJPATH[$(($i-1))]} \ + $INTERFACE_NAME Present | awk '{print $2}')" + + if [[ ${pe_prsnt_n} != "true" ]]; then + pe_fruid=$(($pe_fruid+1)) + continue + fi + + # Output is the i2c bus number for the PCIE cards on PE0/PE1 + # i2c-0 -> i2c mux (addr: 0x71) -> PE0/PE1 + # PE0: channel 0 + # PE1: channel 1 + pe_fru_bus="$(ls -al /sys/bus/i2c/drivers/pca954x/0-0071/ | grep channel \ + | awk -F "/" '{print $(NF)}' | awk -F "-" '{print $2}' | sed -n "${i}p")" + + # If the PE FRU EEPROM syspath does not exist, create it ("24c02" is the + # EEPROM part number) and perform a phosphor-read-eeprom + for ((j=0; j < ${#pe_eeprom_addr[@]}; j++)); + do + i2cget -f -y $pe_fru_bus "0x${pe_eeprom_addr[$j]}" 0x01 > /dev/null 2>&1 + if [ $? -eq 0 ]; then + if [ ! -f "/sys/bus/i2c/devices/$pe_fru_bus-00${pe_eeprom_addr[$j]}/eeprom" ]; then + echo 24c02 "0x${pe_eeprom_addr[$j]}" > "/sys/bus/i2c/devices/i2c-$pe_fru_bus/new_device" + fi + pe_fru_bus="/sys/bus/i2c/devices/$pe_fru_bus-00${pe_eeprom_addr[$j]}/eeprom" + phosphor-read-eeprom --eeprom $pe_fru_bus --fruid $pe_fruid + break + fi + done + pe_fruid=$(($pe_fruid+1)) + done +} + +check_power_status() { + res0="$(busctl get-property -j xyz.openbmc_project.State.Chassis \ + /xyz/openbmc_project/state/chassis0 xyz.openbmc_project.State.Chassis \ + CurrentPowerState | jq -r '.["data"]')" + echo $res0 +} + +main() { + get_board_rev_id + get_board_sku_id + + check_board_ver + if [[ "${BOARD_VER}" == "PREPVT" ]]; then + set_uart_en_low + fi + + check_board_sku + + hsbp_prsnt="$(busctl get-property $SERVICE_NAME ${HSBP_PRESENT_OBJPATH} \ + $INTERFACE_NAME Present | awk '{print $2}')" + if [[ ${hsbp_prsnt} == "true" ]]; then + get_hsp_board_rev_id + hsbp_12v_prsnt="$(busctl get-property $SERVICE_NAME ${BP12V_PRESENT_OBJPATH} \ + $INTERFACE_NAME Present | awk '{print $2}')" + if [[ ${hsbp_12v_prsnt} != "true" ]]; then + echo "HSBP board power cable(12V) not present !!" + fi + else + echo "HSBP board sideband cable not present !!" + echo "Stop NVMe Power/LED control Service " + systemctl stop xyz.openbmc_project.Control.Nvme.Power + systemctl stop xyz.openbmc_project.nvme.manager + fi + + fan_prsnt="$(busctl get-property $SERVICE_NAME ${FANBD_PRESENT_OBJPATH} \ + $INTERFACE_NAME Present | awk '{print $2}')" + if [[ ${fan_prsnt} == "true" ]]; then + get_fan_board_rev_id + else + echo "Fan board sideband cable not present !!" + fi + + set_hdd_prsnt + + reset_phy + + if [[ $(check_power_status) != \ + 'xyz.openbmc_project.State.Chassis.PowerState.On' ]]; then + verify_host_bios + + echo "Release host from reset!" >&2 + set_gpio_direction 'RST_BMC_RSMRST_N' high + set_gpio_direction 'RST_KBRST_BMC_CPLD_N' high + # TODO: remove the hack once kernel driver is ready + # Set the GPIO states to preserve across reboots + set_gpio_persistence + + echo "Starting host power!" >&2 + busctl set-property xyz.openbmc_project.State.Host \ + /xyz/openbmc_project/state/host0 \ + xyz.openbmc_project.State.Host \ + RequestedHostTransition s \ + xyz.openbmc_project.State.Host.Transition.On + else + echo "Host is already running, doing nothing!" >&2 + fi + + parse_pe_fru +} + +# Exit without running main() if sourced +return 0 2>/dev/null + +main "$@" |