blob: d9749dbb342d8028f19f8df280d17076257f3d47 [file] [log] [blame]
extern "C"
{
#include <libpdbg.h>
}
#include "attributes_info.H"
#include "extensions/phal/common_utils.hpp"
#include "extensions/phal/phal_error.hpp"
#include <fmt/format.h>
#include <libekb.H>
#include <phosphor-logging/log.hpp>
namespace openpower
{
namespace phal
{
using namespace phosphor::logging;
void phal_init(enum ipl_mode mode)
{
// TODO: Setting boot error callback should not be in common code
// because, we wont get proper reason in PEL for failure.
// So, need to make code like caller of this function pass error
// handling callback.
// add callback methods for debug traces and for boot failures
openpower::pel::addBootErrorCallbacks();
// PDBG_DTB environment variable set to CEC device tree path
setDevtreeEnv();
if (!pdbg_targets_init(NULL))
{
log<level::ERR>("pdbg_targets_init failed");
throw std::runtime_error("pdbg target initialization failed");
}
if (libekb_init())
{
log<level::ERR>("libekb_init failed");
throw std::runtime_error("libekb initialization failed");
}
if (ipl_init(mode) != 0)
{
log<level::ERR>("ipl_init failed");
throw std::runtime_error("libipl initialization failed");
}
}
bool isPrimaryProc(struct pdbg_target* procTarget)
{
ATTR_PROC_MASTER_TYPE_Type type;
// Get processor type (Primary or Secondary)
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 primary processor */
if (type == ENUM_ATTR_PROC_MASTER_TYPE_ACTING_MASTER)
{
return true;
}
else
{
return false;
}
}
pdbg_target* getFsiTarget(struct pdbg_target* procTarget)
{
struct pdbg_target* fsiTarget = nullptr;
pdbg_for_each_target("fsi", procTarget, fsiTarget)
{
// grab first one we find
break;
}
if (!fsiTarget)
{
log<level::ERR>(
"fsi path of target not found",
entry("PROC_TARGET_PATH=%s", pdbg_target_path(procTarget)));
return nullptr;
}
return fsiTarget;
}
uint32_t probeTarget(struct pdbg_target* procTarget)
{
struct pdbg_target* pibTarget = nullptr;
pdbg_for_each_target("pib", procTarget, pibTarget)
{
// grab first one we find
break;
}
if (!pibTarget)
{
log<level::ERR>(
"pib path of target not found",
entry("PROC_TARGET_PATH=%s", pdbg_target_path(procTarget)));
return -1;
}
// probe PIB and ensure it's enabled
if (PDBG_TARGET_ENABLED != pdbg_target_probe(pibTarget))
{
log<level::ERR>(
"probe on pib target failed",
entry("PIB_TARGET_PATH=%s", pdbg_target_path(pibTarget)));
return -1;
}
return 0;
}
uint32_t getCFAM(struct pdbg_target* procTarget, const uint32_t reg,
uint32_t& val)
{
pdbg_target* fsiTarget = getFsiTarget(procTarget);
if (nullptr == fsiTarget)
{
log<level::ERR>("getCFAM: fsi path or target not found");
return -1;
}
auto rc = probeTarget(procTarget);
if (rc)
{
// probe function logged details to journal
return rc;
}
rc = fsi_read(fsiTarget, reg, &val);
if (rc)
{
log<level::ERR>(
"failed to read input cfam", entry("RC=%u", rc),
entry("CFAM=0x%X", reg),
entry("FSI_TARGET_PATH=%s", pdbg_target_path(fsiTarget)));
return rc;
}
return 0;
}
uint32_t putCFAM(struct pdbg_target* procTarget, const uint32_t reg,
const uint32_t val)
{
pdbg_target* fsiTarget = getFsiTarget(procTarget);
if (nullptr == fsiTarget)
{
log<level::ERR>("putCFAM: fsi path or target not found");
return -1;
}
auto rc = probeTarget(procTarget);
if (rc)
{
// probe function logged details to journal
return rc;
}
rc = fsi_write(fsiTarget, reg, val);
if (rc)
{
log<level::ERR>(
"failed to write input cfam", entry("RC=%u", rc),
entry("CFAM=0x%X", reg),
entry("FSI_TARGET_PATH=%s", pdbg_target_path(fsiTarget)));
return rc;
}
return 0;
}
void setDevtreeEnv()
{
// PDBG_DTB environment variable set to CEC device tree path
static constexpr auto PDBG_DTB_PATH =
"/var/lib/phosphor-software-manager/pnor/rw/DEVTREE";
if (setenv("PDBG_DTB", PDBG_DTB_PATH, 1))
{
log<level::ERR>(
fmt::format("Failed to set PDBG_DTB: ({})", strerror(errno))
.c_str());
throw std::runtime_error("Failed to set PDBG_DTB");
}
}
} // namespace phal
} // namespace openpower