blob: 1b642951895b361beb01f4193702a7efa20772fb [file] [log] [blame]
Brad Bishop5e5d4452020-10-27 19:46:13 -04001extern "C"
2{
Ramesh Iyyarc98bab52020-04-16 04:04:29 -05003#include <libpdbg.h>
4}
5
Brad Bishop5e5d4452020-10-27 19:46:13 -04006#include "attributes_info.H"
7
Marri Devender Rao78479602020-01-06 03:45:11 -06008#include "phalerror/phal_error.hpp"
Chirag Sharmaa2576932020-12-05 23:17:41 -06009#include "procedures/phal/common_utils.hpp"
Jayanth Othayothe22e8232021-06-08 03:34:34 -050010#include "util.hpp"
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050011
Jayanth Othayothe22e8232021-06-08 03:34:34 -050012#include <fmt/format.h>
Ramesh Iyyarc98bab52020-04-16 04:04:29 -050013#include <libekb.H>
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050014
Lakshminarayana R. Kammath75912e82020-04-28 07:37:17 -050015#include <ext_interface.hpp>
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050016#include <phosphor-logging/log.hpp>
17#include <registration.hpp>
Jayanth Othayothe22e8232021-06-08 03:34:34 -050018
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050019namespace openpower
20{
21namespace phal
22{
23
24using namespace phosphor::logging;
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050025
26/**
Lakshminarayana R. Kammath75912e82020-04-28 07:37:17 -050027 * @brief Check if master processor or not
28 *
29 * @return True/False
30 */
31bool isMasterProc(struct pdbg_target* procTarget)
32{
33 ATTR_PROC_MASTER_TYPE_Type type;
34
35 // Get processor type (Master or Alt-master)
36 if (DT_GET_PROP(ATTR_PROC_MASTER_TYPE, procTarget, type))
37 {
38 log<level::ERR>("Attribute [ATTR_PROC_MASTER_TYPE] get failed");
39 throw std::runtime_error(
40 "Attribute [ATTR_PROC_MASTER_TYPE] get failed");
41 }
42
43 /* Attribute value 0 corresponds to master processor */
44 if (type == 0)
45 {
46 return true;
47 }
48 else
49 {
50 return false;
51 }
52}
53
54/**
55 * @brief Select BOOT SEEPROM and Measurement SEEPROM(PRIMARY/BACKUP) on POWER
56 * processor position 0/1 depending on boot count before kicking off
57 * the boot.
58 *
59 * @return void
60 */
61void selectBootSeeprom()
62{
63 struct pdbg_target* procTarget;
64 ATTR_BACKUP_SEEPROM_SELECT_Enum bkpSeePromSelect;
65 ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_Enum bkpMeaSeePromSelect;
66
67 pdbg_for_each_class_target("proc", procTarget)
68 {
69 if (!isMasterProc(procTarget))
70 {
71 continue;
72 }
73
74 // Choose seeprom side to boot from based on boot count
75 if (getBootCount() > 0)
76 {
77 log<level::INFO>("Setting SBE seeprom side to 0",
78 entry("SBE_SIDE_SELECT=%d",
79 ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY));
80
81 bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY;
82 bkpMeaSeePromSelect =
83 ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_PRIMARY;
84 }
85 else
86 {
87 log<level::INFO>("Setting SBE seeprom side to 1",
88 entry("SBE_SIDE_SELECT=%d",
89 ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY));
90 bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY;
91 bkpMeaSeePromSelect =
92 ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_SECONDARY;
93 }
94
95 // Set the Attribute as per bootcount policy for boot seeprom
96 if (DT_SET_PROP(ATTR_BACKUP_SEEPROM_SELECT, procTarget,
97 bkpSeePromSelect))
98 {
99 log<level::ERR>(
100 "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed");
101 throw std::runtime_error(
102 "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed");
103 }
104
105 // Set the Attribute as per bootcount policy for measurement seeprom
106 if (DT_SET_PROP(ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT, procTarget,
107 bkpMeaSeePromSelect))
108 {
109 log<level::ERR>(
110 "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set "
111 "failed");
112 throw std::runtime_error(
113 "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set "
114 "failed");
115 }
116 }
117}
118
119/**
Jayanth Othayothe22e8232021-06-08 03:34:34 -0500120 * @brief Read the HW Level from VPD and set CLK NE termination site
121 * Note any failure in this function will result startHost failure.
122 */
123void setClkNETerminationSite()
124{
125 // Get Motherborad VINI Recored "HW" keyword
126 constexpr auto objPath =
127 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
128 constexpr auto kwdVpdInf = "com.ibm.ipzvpd.VINI";
129 constexpr auto hwKwd = "HW";
130
131 auto bus = sdbusplus::bus::new_default();
132
133 std::string service = util::getService(bus, objPath, kwdVpdInf);
134
135 auto properties = bus.new_method_call(
136 service.c_str(), objPath, "org.freedesktop.DBus.Properties", "Get");
137 properties.append(kwdVpdInf);
138 properties.append(hwKwd);
139
140 // Store "HW" Keyword data.
141 std::variant<std::vector<uint8_t>> val;
142 try
143 {
144 auto result = bus.call(properties);
145 result.read(val);
146 }
147 catch (const sdbusplus::exception::SdBusError& e)
148 {
149 log<level::ERR>("Get HW Keyword read from VINI Failed");
150 throw std::runtime_error("Get HW Keyword read from VINI Failed");
151 }
152
153 auto hwData = std::get<std::vector<uint8_t>>(val);
154
155 //"HW" Keyword size is 2 as per VPD spec.
156 constexpr auto hwKwdSize = 2;
157 if (hwKwdSize != hwData.size())
158 {
159 log<level::ERR>(
160 fmt::format("Incorrect VINI records HW Keyword data size({})",
161 hwData.size())
162 .c_str());
163 throw std::runtime_error("Incorrect VINI records HW Keyword data size");
164 }
165
166 log<level::DEBUG>(fmt::format("VINI Records HW[0]:{} HW[1]:{}",
167 hwData.at(0), hwData.at(1))
168 .c_str());
169
170 // VINI Record "HW" keyword's Byte 0's MSB bit indicates
171 // proc or planar type need to choose.
172 constexpr uint8_t SYS_CLK_NE_TERMINATION_ON_MASK = 0x80;
173
174 ATTR_SYS_CLK_NE_TERMINATION_SITE_Type clockTerm =
175 ENUM_ATTR_SYS_CLK_NE_TERMINATION_SITE_PLANAR;
176
177 if (SYS_CLK_NE_TERMINATION_ON_MASK & hwData.at(0))
178 {
179 clockTerm = ENUM_ATTR_SYS_CLK_NE_TERMINATION_SITE_PROC;
180 }
181
182 // update all the processor attributes
183 struct pdbg_target* procTarget;
184 pdbg_for_each_class_target("proc", procTarget)
185 {
186
187 if (DT_SET_PROP(ATTR_SYS_CLK_NE_TERMINATION_SITE, procTarget,
188 clockTerm))
189 {
190 log<level::ERR>(
191 "Attribute ATTR_SYS_CLK_NE_TERMINATION_SITE set failed");
192 throw std::runtime_error(
193 "Attribute ATTR_SYS_CLK_NE_TERMINATION_SITE set failed");
194 }
195 }
196}
197
198/**
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500199 * @brief Starts the self boot engine on POWER processor position 0
200 * to kick off a boot.
201 * @return void
202 */
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500203void startHost(enum ipl_type iplType = IPL_TYPE_NORMAL)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500204{
Chirag Sharmaa2576932020-12-05 23:17:41 -0600205 try
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500206 {
Chirag Sharmaa2576932020-12-05 23:17:41 -0600207 phal_init();
208 ipl_set_type(iplType);
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500209 }
Chirag Sharmaa2576932020-12-05 23:17:41 -0600210 catch (std::exception& ex)
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500211 {
Chirag Sharmaa2576932020-12-05 23:17:41 -0600212 log<level::ERR>("Exception raised during init PHAL",
213 entry("EXCEPTION=%s", ex.what()));
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500214 openpower::pel::detail::processBootErrorCallback(false);
Chirag Sharmaa2576932020-12-05 23:17:41 -0600215 throw std::runtime_error("PHAL initialization failed");
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500216 }
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500217
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500218 // To clear trace if success
219 openpower::pel::detail::processBootErrorCallback(true);
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500220
Jayanth Othayothe22e8232021-06-08 03:34:34 -0500221 setClkNETerminationSite();
222
Marri Devender Rao78479602020-01-06 03:45:11 -0600223 // callback method will be called upon failure which will create the PEL
224 int rc = ipl_run_major(0);
225 if (rc > 0)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500226 {
227 log<level::ERR>("step 0 failed to start the host");
Marri Devender Rao78479602020-01-06 03:45:11 -0600228 throw std::runtime_error("Failed to execute host start boot step");
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500229 }
230}
231
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500232/**
233 * @brief Starts the reboot with type memory preserving reboot.
234 * @return void
235 */
236void startHostMpReboot()
237{
238 // set ipl type as mpipl
239 startHost(IPL_TYPE_MPIPL);
240}
241
242/**
243 * @brief Starts the normal boot type.
244 * @return void
245 */
246void startHostNormal()
247{
Dhruvaraj Subhashchandran3ae7ed42020-06-16 12:48:14 -0500248 // Run select seeprom before poweron
249 try
250 {
251 selectBootSeeprom();
252
253 // To clear trace as it is success
254 openpower::pel::detail::processBootErrorCallback(true);
255 }
256 catch (const std::exception& ex)
257 {
258 // create PEL in failure
259 openpower::pel::detail::processBootErrorCallback(false);
260 log<level::ERR>("SEEPROM selection failed", entry("ERR=%s", ex.what()));
261 throw ex;
262 }
263
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500264 startHost();
265}
266
Brad Bishop63508a72020-10-27 18:55:01 -0400267REGISTER_PROCEDURE("startHost", startHostNormal)
268REGISTER_PROCEDURE("startHostMpReboot", startHostMpReboot)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500269
270} // namespace phal
271} // namespace openpower