blob: 21d2d62709cc79f0d99fb0a1460745dc0ce2a3c4 [file] [log] [blame]
extern "C" {
#include <libpdbg.h>
}
#include "phalerror/phal_error.hpp"
#include <libekb.H>
#include <libipl.H>
#include <ext_interface.hpp>
#include <phosphor-logging/log.hpp>
#include <registration.hpp>
#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<level::ERR>("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<level::INFO>("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<level::INFO>("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<level::ERR>(
"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<level::ERR>(
"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<level::ERR>("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<level::ERR>("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<level::ERR>("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<level::ERR>("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<level::ERR>("SEEPROM selection failed", entry("ERR=%s", ex.what()));
throw ex;
}
startHost();
}
REGISTER_PROCEDURE("startHost", startHostNormal)
REGISTER_PROCEDURE("startHostMpReboot", startHostMpReboot)
} // namespace phal
} // namespace openpower