blob: e6f01ec00087d84039b89dd5c793ee4801f785a3 [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
Jayanth Othayoth25e39c82021-07-12 01:00:17 -05008#include "extensions/phal/common_utils.hpp"
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -05009#include "extensions/phal/create_pel.hpp"
Jayanth Othayoth6552de02021-07-12 00:55:57 -050010#include "extensions/phal/phal_error.hpp"
Jayanth Othayothe22e8232021-06-08 03:34:34 -050011#include "util.hpp"
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050012
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 Iyyarf9152b92021-09-06 03:43:59 -050016#include <nlohmann/json.hpp>
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050017#include <phosphor-logging/log.hpp>
18#include <registration.hpp>
Jayanth Othayothe22e8232021-06-08 03:34:34 -050019
Jayanth Othayothe0dd7af2023-09-13 09:03:30 +000020#include <format>
21
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050022namespace openpower
23{
24namespace phal
25{
26
27using namespace phosphor::logging;
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050028
29/**
Lakshminarayana R. Kammath75912e82020-04-28 07:37:17 -050030 * @brief Select BOOT SEEPROM and Measurement SEEPROM(PRIMARY/BACKUP) on POWER
31 * processor position 0/1 depending on boot count before kicking off
32 * the boot.
33 *
34 * @return void
35 */
36void selectBootSeeprom()
37{
38 struct pdbg_target* procTarget;
39 ATTR_BACKUP_SEEPROM_SELECT_Enum bkpSeePromSelect;
40 ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_Enum bkpMeaSeePromSelect;
41
42 pdbg_for_each_class_target("proc", procTarget)
43 {
Andrew Geissler5c3f9252021-06-10 10:53:05 -050044 if (!isPrimaryProc(procTarget))
Lakshminarayana R. Kammath75912e82020-04-28 07:37:17 -050045 {
46 continue;
47 }
48
49 // Choose seeprom side to boot from based on boot count
50 if (getBootCount() > 0)
51 {
52 log<level::INFO>("Setting SBE seeprom side to 0",
53 entry("SBE_SIDE_SELECT=%d",
54 ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY));
55
56 bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY;
57 bkpMeaSeePromSelect =
58 ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_PRIMARY;
59 }
60 else
61 {
62 log<level::INFO>("Setting SBE seeprom side to 1",
63 entry("SBE_SIDE_SELECT=%d",
64 ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY));
65 bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY;
66 bkpMeaSeePromSelect =
67 ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_SECONDARY;
68 }
69
70 // Set the Attribute as per bootcount policy for boot seeprom
71 if (DT_SET_PROP(ATTR_BACKUP_SEEPROM_SELECT, procTarget,
72 bkpSeePromSelect))
73 {
74 log<level::ERR>(
75 "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed");
76 throw std::runtime_error(
77 "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed");
78 }
79
80 // Set the Attribute as per bootcount policy for measurement seeprom
81 if (DT_SET_PROP(ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT, procTarget,
82 bkpMeaSeePromSelect))
83 {
84 log<level::ERR>(
85 "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set "
86 "failed");
87 throw std::runtime_error(
88 "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set "
89 "failed");
90 }
91 }
92}
93
94/**
Jayanth Othayothe22e8232021-06-08 03:34:34 -050095 * @brief Read the HW Level from VPD and set CLK NE termination site
96 * Note any failure in this function will result startHost failure.
97 */
98void setClkNETerminationSite()
99{
100 // Get Motherborad VINI Recored "HW" keyword
101 constexpr auto objPath =
102 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
103 constexpr auto kwdVpdInf = "com.ibm.ipzvpd.VINI";
104 constexpr auto hwKwd = "HW";
105
106 auto bus = sdbusplus::bus::new_default();
107
108 std::string service = util::getService(bus, objPath, kwdVpdInf);
109
110 auto properties = bus.new_method_call(
111 service.c_str(), objPath, "org.freedesktop.DBus.Properties", "Get");
112 properties.append(kwdVpdInf);
113 properties.append(hwKwd);
114
115 // Store "HW" Keyword data.
116 std::variant<std::vector<uint8_t>> val;
117 try
118 {
119 auto result = bus.call(properties);
120 result.read(val);
121 }
Patrick Williamsaaea6862022-07-22 19:26:54 -0500122 catch (const sdbusplus::exception_t& e)
Jayanth Othayothe22e8232021-06-08 03:34:34 -0500123 {
124 log<level::ERR>("Get HW Keyword read from VINI Failed");
125 throw std::runtime_error("Get HW Keyword read from VINI Failed");
126 }
127
128 auto hwData = std::get<std::vector<uint8_t>>(val);
129
130 //"HW" Keyword size is 2 as per VPD spec.
131 constexpr auto hwKwdSize = 2;
132 if (hwKwdSize != hwData.size())
133 {
134 log<level::ERR>(
Jayanth Othayothe0dd7af2023-09-13 09:03:30 +0000135 std::format("Incorrect VINI records HW Keyword data size({})",
Jayanth Othayothe22e8232021-06-08 03:34:34 -0500136 hwData.size())
137 .c_str());
138 throw std::runtime_error("Incorrect VINI records HW Keyword data size");
139 }
140
Jayanth Othayothe0dd7af2023-09-13 09:03:30 +0000141 log<level::DEBUG>(std::format("VINI Records HW[0]:{} HW[1]:{}",
Jayanth Othayothe22e8232021-06-08 03:34:34 -0500142 hwData.at(0), hwData.at(1))
143 .c_str());
144
145 // VINI Record "HW" keyword's Byte 0's MSB bit indicates
146 // proc or planar type need to choose.
147 constexpr uint8_t SYS_CLK_NE_TERMINATION_ON_MASK = 0x80;
148
149 ATTR_SYS_CLK_NE_TERMINATION_SITE_Type clockTerm =
150 ENUM_ATTR_SYS_CLK_NE_TERMINATION_SITE_PLANAR;
151
152 if (SYS_CLK_NE_TERMINATION_ON_MASK & hwData.at(0))
153 {
154 clockTerm = ENUM_ATTR_SYS_CLK_NE_TERMINATION_SITE_PROC;
155 }
156
157 // update all the processor attributes
158 struct pdbg_target* procTarget;
159 pdbg_for_each_class_target("proc", procTarget)
160 {
Jayanth Othayothe22e8232021-06-08 03:34:34 -0500161 if (DT_SET_PROP(ATTR_SYS_CLK_NE_TERMINATION_SITE, procTarget,
162 clockTerm))
163 {
164 log<level::ERR>(
165 "Attribute ATTR_SYS_CLK_NE_TERMINATION_SITE set failed");
166 throw std::runtime_error(
167 "Attribute ATTR_SYS_CLK_NE_TERMINATION_SITE set failed");
168 }
169 }
170}
171
172/**
Ramesh Iyyarf9152b92021-09-06 03:43:59 -0500173 * @brief Helper function to create error log (aka PEL) with
174 * procedure callout for the hardware isolation policy
175 * settings failures.
176 *
177 * @param[in] procedureCode - The procedure code to include in the callout
178 * @param[in] priority - The priority for the procedure callout
179 * @param[in] additionalData - The additional data to include in the error log
180 *
181 * @return void
182 */
183static void
184 createPELForHwIsolationSettingsErr(const std::string& procedureCode,
185 const std::string& priority,
186 const pel::FFDCData& additionalData)
187{
188 try
189 {
190 using json = nlohmann::json;
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500191 using Severity =
192 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level;
Ramesh Iyyarf9152b92021-09-06 03:43:59 -0500193
194 json jsonCalloutDataList;
195 jsonCalloutDataList = json::array();
196 json jsonCalloutData;
197 jsonCalloutData["Procedure"] = procedureCode;
198 jsonCalloutData["Priority"] = priority;
199 jsonCalloutDataList.emplace_back(jsonCalloutData);
200
201 openpower::pel::createErrorPEL("org.open_power.PHAL.Error.Boot",
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500202 jsonCalloutDataList, additionalData,
203 Severity::Error);
Ramesh Iyyarf9152b92021-09-06 03:43:59 -0500204 }
205 catch (const std::exception& e)
206 {
207 // Don't throw exception since the caller might call in the error path
208 // and even we should allow the hardware isolation by default.
209 log<level::ERR>(
Jayanth Othayothe0dd7af2023-09-13 09:03:30 +0000210 std::format("Exception [{}], failed to create the error log "
Ramesh Iyyarf9152b92021-09-06 03:43:59 -0500211 "for the hardware isolation policy settings failures.",
212 e.what())
213 .c_str());
214 }
215}
216
217/**
218 * @brief Helper function to decide the hardware isolation (aka guard)
219 *
220 * @return xyz.openbmc_project.Object.Enable::Enabled value on success
221 * true on failure since hardware isolation feature should be
222 * enabled by default.
223 */
224static bool allowHwIsolation()
225{
226 bool allowHwIsolation{true};
227
228 constexpr auto hwIsolationPolicyObjPath =
229 "/xyz/openbmc_project/hardware_isolation/allow_hw_isolation";
230 constexpr auto hwIsolationPolicyIface = "xyz.openbmc_project.Object.Enable";
231
232 try
233 {
234 auto bus = sdbusplus::bus::new_default();
235
236 std::string service = util::getService(bus, hwIsolationPolicyObjPath,
237 hwIsolationPolicyIface);
238
239 auto method =
240 bus.new_method_call(service.c_str(), hwIsolationPolicyObjPath,
241 "org.freedesktop.DBus.Properties", "Get");
242 method.append(hwIsolationPolicyIface, "Enabled");
243
244 auto reply = bus.call(method);
245
246 std::variant<bool> resp;
247
248 reply.read(resp);
249
250 if (const bool* enabledPropVal = std::get_if<bool>(&resp))
251 {
252 allowHwIsolation = *enabledPropVal;
253 }
254 else
255 {
Jayanth Othayothe0dd7af2023-09-13 09:03:30 +0000256 const auto trace{std::format(
Ramesh Iyyarf9152b92021-09-06 03:43:59 -0500257 "Failed to read the HardwareIsolation policy "
258 "from the path [{}] interface [{}]. Continuing with "
259 "default mode(allow_hw_isolation)",
260 hwIsolationPolicyObjPath, hwIsolationPolicyIface)};
261
262 log<level::ERR>(trace.c_str());
263 createPELForHwIsolationSettingsErr("BMC0001", "M",
264 {{"REASON_FOR_PEL", trace}});
265 }
266 }
Patrick Williamsaaea6862022-07-22 19:26:54 -0500267 catch (const sdbusplus::exception_t& e)
Ramesh Iyyarf9152b92021-09-06 03:43:59 -0500268 {
Jayanth Othayothe0dd7af2023-09-13 09:03:30 +0000269 const auto trace{std::format(
Ramesh Iyyarf9152b92021-09-06 03:43:59 -0500270 "Exception [{}] to get the HardwareIsolation policy "
271 "from the path [{}] interface [{}]. Continuing with "
272 "default mode (allow_hw_isolation)",
273 e.what(), hwIsolationPolicyObjPath, hwIsolationPolicyIface)};
274
275 log<level::ERR>(trace.c_str());
276 createPELForHwIsolationSettingsErr("BMC0001", "M",
277 {{"REASON_FOR_PEL", trace}});
278 }
279
280 return allowHwIsolation;
281}
282
283/**
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500284 * @brief Starts the self boot engine on POWER processor position 0
285 * to kick off a boot.
286 * @return void
287 */
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500288void startHost(enum ipl_type iplType = IPL_TYPE_NORMAL)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500289{
Chirag Sharmaa2576932020-12-05 23:17:41 -0600290 try
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500291 {
Chirag Sharmaa2576932020-12-05 23:17:41 -0600292 phal_init();
293 ipl_set_type(iplType);
Ramesh Iyyarf9152b92021-09-06 03:43:59 -0500294
295 /**
296 * Don't apply guard records if the HardwareIsolation (aka guard)
297 * the policy is disabled (false). By default, libipl will apply
298 * guard records.
299 */
300 if (!allowHwIsolation())
301 {
302 ipl_disable_guard();
303 }
304
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -0500305 if (iplType == IPL_TYPE_NORMAL)
306 {
307 // Update SEEPROM side only for NORMAL boot
308 selectBootSeeprom();
309 }
310 setClkNETerminationSite();
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500311 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500312 catch (const std::exception& ex)
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500313 {
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -0500314 log<level::ERR>("Exception raised during ipl initialisation",
Chirag Sharmaa2576932020-12-05 23:17:41 -0600315 entry("EXCEPTION=%s", ex.what()));
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -0500316 openpower::pel::createPEL("org.open_power.PHAL.Error.Boot");
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500317 openpower::pel::detail::processBootError(false);
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -0500318 throw std::runtime_error("IPL initialization failed");
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500319 }
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500320
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500321 // To clear trace if success
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500322 openpower::pel::detail::processBootError(true);
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500323
Marri Devender Rao78479602020-01-06 03:45:11 -0600324 // callback method will be called upon failure which will create the PEL
325 int rc = ipl_run_major(0);
326 if (rc > 0)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500327 {
328 log<level::ERR>("step 0 failed to start the host");
Marri Devender Rao78479602020-01-06 03:45:11 -0600329 throw std::runtime_error("Failed to execute host start boot step");
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500330 }
331}
332
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500333/**
334 * @brief Starts the reboot with type memory preserving reboot.
335 * @return void
336 */
337void startHostMpReboot()
338{
339 // set ipl type as mpipl
340 startHost(IPL_TYPE_MPIPL);
341}
342
343/**
344 * @brief Starts the normal boot type.
345 * @return void
346 */
347void startHostNormal()
348{
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -0500349 startHost(IPL_TYPE_NORMAL);
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500350}
351
Brad Bishop63508a72020-10-27 18:55:01 -0400352REGISTER_PROCEDURE("startHost", startHostNormal)
353REGISTER_PROCEDURE("startHostMpReboot", startHostMpReboot)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500354
355} // namespace phal
356} // namespace openpower