extern "C" { #include } #include "phalerror/phal_error.hpp" #include #include #include #include #include #include "attributes_info.H" namespace openpower { namespace phal { using namespace phosphor::logging; /** * @brief Check if master processor or not * * @return True/False */ bool isMasterProc(struct pdbg_target* procTarget) { ATTR_PROC_MASTER_TYPE_Type type; // Get processor type (Master or Alt-master) if (DT_GET_PROP(ATTR_PROC_MASTER_TYPE, procTarget, type)) { log("Attribute [ATTR_PROC_MASTER_TYPE] get failed"); throw std::runtime_error( "Attribute [ATTR_PROC_MASTER_TYPE] get failed"); } /* Attribute value 0 corresponds to master processor */ if (type == 0) { return true; } else { return false; } } /** * @brief Select BOOT SEEPROM and Measurement SEEPROM(PRIMARY/BACKUP) on POWER * processor position 0/1 depending on boot count before kicking off * the boot. * * @return void */ void selectBootSeeprom() { struct pdbg_target* procTarget; ATTR_BACKUP_SEEPROM_SELECT_Enum bkpSeePromSelect; ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_Enum bkpMeaSeePromSelect; pdbg_for_each_class_target("proc", procTarget) { if (!isMasterProc(procTarget)) { continue; } // Choose seeprom side to boot from based on boot count if (getBootCount() > 0) { log("Setting SBE seeprom side to 0", entry("SBE_SIDE_SELECT=%d", ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY)); bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY; bkpMeaSeePromSelect = ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_PRIMARY; } else { log("Setting SBE seeprom side to 1", entry("SBE_SIDE_SELECT=%d", ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY)); bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY; bkpMeaSeePromSelect = ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_SECONDARY; } // Set the Attribute as per bootcount policy for boot seeprom if (DT_SET_PROP(ATTR_BACKUP_SEEPROM_SELECT, procTarget, bkpSeePromSelect)) { log( "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed"); throw std::runtime_error( "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed"); } // Set the Attribute as per bootcount policy for measurement seeprom if (DT_SET_PROP(ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT, procTarget, bkpMeaSeePromSelect)) { log( "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set " "failed"); throw std::runtime_error( "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set " "failed"); } } } /** * @brief Starts the self boot engine on POWER processor position 0 * to kick off a boot. * @return void */ void startHost(enum ipl_type iplType = IPL_TYPE_NORMAL) { // add callback methods for debug traces and for boot failures openpower::pel::addBootErrorCallbacks(); if (!pdbg_targets_init(NULL)) { log("pdbg_targets_init failed"); openpower::pel::detail::processBootErrorCallback(false); throw std::runtime_error("pdbg target initialization failed"); } // To clear trace if success openpower::pel::detail::processBootErrorCallback(true); if (libekb_init()) { log("libekb_init failed"); openpower::pel::detail::processBootErrorCallback(false); throw std::runtime_error("libekb initialization failed"); } // To clear trace if success openpower::pel::detail::processBootErrorCallback(true); if (ipl_init(IPL_AUTOBOOT) != 0) { log("ipl_init failed"); openpower::pel::detail::processBootErrorCallback(false); throw std::runtime_error("Boot initialization failed"); } ipl_set_type(iplType); // To clear trace if success openpower::pel::detail::processBootErrorCallback(true); // callback method will be called upon failure which will create the PEL int rc = ipl_run_major(0); if (rc > 0) { log("step 0 failed to start the host"); throw std::runtime_error("Failed to execute host start boot step"); } } /** * @brief Starts the reboot with type memory preserving reboot. * @return void */ void startHostMpReboot() { // set ipl type as mpipl startHost(IPL_TYPE_MPIPL); } /** * @brief Starts the normal boot type. * @return void */ void startHostNormal() { // Run select seeprom before poweron try { selectBootSeeprom(); // To clear trace as it is success openpower::pel::detail::processBootErrorCallback(true); } catch (const std::exception& ex) { // create PEL in failure openpower::pel::detail::processBootErrorCallback(false); log("SEEPROM selection failed", entry("ERR=%s", ex.what())); throw ex; } startHost(); } REGISTER_PROCEDURE("startHost", startHostNormal); REGISTER_PROCEDURE("startHostMpReboot", startHostMpReboot); } // namespace phal } // namespace openpower