blob: 01cada9a029dcf0c0ab356baa6a5bc79a2f5e3ed [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
Jayanth Othayothe22e8232021-06-08 03:34:34 -050013#include <fmt/format.h>
Ramesh Iyyarc98bab52020-04-16 04:04:29 -050014#include <libekb.H>
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050015
Lakshminarayana R. Kammath75912e82020-04-28 07:37:17 -050016#include <ext_interface.hpp>
Ramesh Iyyarf9152b92021-09-06 03:43:59 -050017#include <nlohmann/json.hpp>
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050018#include <phosphor-logging/log.hpp>
19#include <registration.hpp>
Jayanth Othayothe22e8232021-06-08 03:34:34 -050020
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050021namespace openpower
22{
23namespace phal
24{
25
26using namespace phosphor::logging;
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -050027
28/**
Lakshminarayana R. Kammath75912e82020-04-28 07:37:17 -050029 * @brief Select BOOT SEEPROM and Measurement SEEPROM(PRIMARY/BACKUP) on POWER
30 * processor position 0/1 depending on boot count before kicking off
31 * the boot.
32 *
33 * @return void
34 */
35void selectBootSeeprom()
36{
37 struct pdbg_target* procTarget;
38 ATTR_BACKUP_SEEPROM_SELECT_Enum bkpSeePromSelect;
39 ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_Enum bkpMeaSeePromSelect;
40
41 pdbg_for_each_class_target("proc", procTarget)
42 {
Andrew Geissler5c3f9252021-06-10 10:53:05 -050043 if (!isPrimaryProc(procTarget))
Lakshminarayana R. Kammath75912e82020-04-28 07:37:17 -050044 {
45 continue;
46 }
47
48 // Choose seeprom side to boot from based on boot count
49 if (getBootCount() > 0)
50 {
51 log<level::INFO>("Setting SBE seeprom side to 0",
52 entry("SBE_SIDE_SELECT=%d",
53 ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY));
54
55 bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY;
56 bkpMeaSeePromSelect =
57 ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_PRIMARY;
58 }
59 else
60 {
61 log<level::INFO>("Setting SBE seeprom side to 1",
62 entry("SBE_SIDE_SELECT=%d",
63 ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY));
64 bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY;
65 bkpMeaSeePromSelect =
66 ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_SECONDARY;
67 }
68
69 // Set the Attribute as per bootcount policy for boot seeprom
70 if (DT_SET_PROP(ATTR_BACKUP_SEEPROM_SELECT, procTarget,
71 bkpSeePromSelect))
72 {
73 log<level::ERR>(
74 "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed");
75 throw std::runtime_error(
76 "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed");
77 }
78
79 // Set the Attribute as per bootcount policy for measurement seeprom
80 if (DT_SET_PROP(ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT, procTarget,
81 bkpMeaSeePromSelect))
82 {
83 log<level::ERR>(
84 "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set "
85 "failed");
86 throw std::runtime_error(
87 "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set "
88 "failed");
89 }
90 }
91}
92
93/**
Jayanth Othayothe22e8232021-06-08 03:34:34 -050094 * @brief Read the HW Level from VPD and set CLK NE termination site
95 * Note any failure in this function will result startHost failure.
96 */
97void setClkNETerminationSite()
98{
99 // Get Motherborad VINI Recored "HW" keyword
100 constexpr auto objPath =
101 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
102 constexpr auto kwdVpdInf = "com.ibm.ipzvpd.VINI";
103 constexpr auto hwKwd = "HW";
104
105 auto bus = sdbusplus::bus::new_default();
106
107 std::string service = util::getService(bus, objPath, kwdVpdInf);
108
109 auto properties = bus.new_method_call(
110 service.c_str(), objPath, "org.freedesktop.DBus.Properties", "Get");
111 properties.append(kwdVpdInf);
112 properties.append(hwKwd);
113
114 // Store "HW" Keyword data.
115 std::variant<std::vector<uint8_t>> val;
116 try
117 {
118 auto result = bus.call(properties);
119 result.read(val);
120 }
Patrick Williams2246cca2021-09-02 09:32:52 -0500121 catch (const sdbusplus::exception::exception& e)
Jayanth Othayothe22e8232021-06-08 03:34:34 -0500122 {
123 log<level::ERR>("Get HW Keyword read from VINI Failed");
124 throw std::runtime_error("Get HW Keyword read from VINI Failed");
125 }
126
127 auto hwData = std::get<std::vector<uint8_t>>(val);
128
129 //"HW" Keyword size is 2 as per VPD spec.
130 constexpr auto hwKwdSize = 2;
131 if (hwKwdSize != hwData.size())
132 {
133 log<level::ERR>(
134 fmt::format("Incorrect VINI records HW Keyword data size({})",
135 hwData.size())
136 .c_str());
137 throw std::runtime_error("Incorrect VINI records HW Keyword data size");
138 }
139
140 log<level::DEBUG>(fmt::format("VINI Records HW[0]:{} HW[1]:{}",
141 hwData.at(0), hwData.at(1))
142 .c_str());
143
144 // VINI Record "HW" keyword's Byte 0's MSB bit indicates
145 // proc or planar type need to choose.
146 constexpr uint8_t SYS_CLK_NE_TERMINATION_ON_MASK = 0x80;
147
148 ATTR_SYS_CLK_NE_TERMINATION_SITE_Type clockTerm =
149 ENUM_ATTR_SYS_CLK_NE_TERMINATION_SITE_PLANAR;
150
151 if (SYS_CLK_NE_TERMINATION_ON_MASK & hwData.at(0))
152 {
153 clockTerm = ENUM_ATTR_SYS_CLK_NE_TERMINATION_SITE_PROC;
154 }
155
156 // update all the processor attributes
157 struct pdbg_target* procTarget;
158 pdbg_for_each_class_target("proc", procTarget)
159 {
160
161 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;
191
192 json jsonCalloutDataList;
193 jsonCalloutDataList = json::array();
194 json jsonCalloutData;
195 jsonCalloutData["Procedure"] = procedureCode;
196 jsonCalloutData["Priority"] = priority;
197 jsonCalloutDataList.emplace_back(jsonCalloutData);
198
199 openpower::pel::createErrorPEL("org.open_power.PHAL.Error.Boot",
200 jsonCalloutDataList, additionalData);
201 }
202 catch (const std::exception& e)
203 {
204 // Don't throw exception since the caller might call in the error path
205 // and even we should allow the hardware isolation by default.
206 log<level::ERR>(
207 fmt::format("Exception [{}], failed to create the error log "
208 "for the hardware isolation policy settings failures.",
209 e.what())
210 .c_str());
211 }
212}
213
214/**
215 * @brief Helper function to decide the hardware isolation (aka guard)
216 *
217 * @return xyz.openbmc_project.Object.Enable::Enabled value on success
218 * true on failure since hardware isolation feature should be
219 * enabled by default.
220 */
221static bool allowHwIsolation()
222{
223 bool allowHwIsolation{true};
224
225 constexpr auto hwIsolationPolicyObjPath =
226 "/xyz/openbmc_project/hardware_isolation/allow_hw_isolation";
227 constexpr auto hwIsolationPolicyIface = "xyz.openbmc_project.Object.Enable";
228
229 try
230 {
231 auto bus = sdbusplus::bus::new_default();
232
233 std::string service = util::getService(bus, hwIsolationPolicyObjPath,
234 hwIsolationPolicyIface);
235
236 auto method =
237 bus.new_method_call(service.c_str(), hwIsolationPolicyObjPath,
238 "org.freedesktop.DBus.Properties", "Get");
239 method.append(hwIsolationPolicyIface, "Enabled");
240
241 auto reply = bus.call(method);
242
243 std::variant<bool> resp;
244
245 reply.read(resp);
246
247 if (const bool* enabledPropVal = std::get_if<bool>(&resp))
248 {
249 allowHwIsolation = *enabledPropVal;
250 }
251 else
252 {
253 const auto trace{fmt::format(
254 "Failed to read the HardwareIsolation policy "
255 "from the path [{}] interface [{}]. Continuing with "
256 "default mode(allow_hw_isolation)",
257 hwIsolationPolicyObjPath, hwIsolationPolicyIface)};
258
259 log<level::ERR>(trace.c_str());
260 createPELForHwIsolationSettingsErr("BMC0001", "M",
261 {{"REASON_FOR_PEL", trace}});
262 }
263 }
264 catch (const sdbusplus::exception::exception& e)
265 {
266 const auto trace{fmt::format(
267 "Exception [{}] to get the HardwareIsolation policy "
268 "from the path [{}] interface [{}]. Continuing with "
269 "default mode (allow_hw_isolation)",
270 e.what(), hwIsolationPolicyObjPath, hwIsolationPolicyIface)};
271
272 log<level::ERR>(trace.c_str());
273 createPELForHwIsolationSettingsErr("BMC0001", "M",
274 {{"REASON_FOR_PEL", trace}});
275 }
276
277 return allowHwIsolation;
278}
279
280/**
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500281 * @brief Starts the self boot engine on POWER processor position 0
282 * to kick off a boot.
283 * @return void
284 */
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500285void startHost(enum ipl_type iplType = IPL_TYPE_NORMAL)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500286{
Chirag Sharmaa2576932020-12-05 23:17:41 -0600287 try
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500288 {
Chirag Sharmaa2576932020-12-05 23:17:41 -0600289 phal_init();
290 ipl_set_type(iplType);
Ramesh Iyyarf9152b92021-09-06 03:43:59 -0500291
292 /**
293 * Don't apply guard records if the HardwareIsolation (aka guard)
294 * the policy is disabled (false). By default, libipl will apply
295 * guard records.
296 */
297 if (!allowHwIsolation())
298 {
299 ipl_disable_guard();
300 }
301
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -0500302 if (iplType == IPL_TYPE_NORMAL)
303 {
304 // Update SEEPROM side only for NORMAL boot
305 selectBootSeeprom();
306 }
307 setClkNETerminationSite();
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500308 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500309 catch (const std::exception& ex)
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500310 {
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -0500311 log<level::ERR>("Exception raised during ipl initialisation",
Chirag Sharmaa2576932020-12-05 23:17:41 -0600312 entry("EXCEPTION=%s", ex.what()));
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -0500313 openpower::pel::createPEL("org.open_power.PHAL.Error.Boot");
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500314 openpower::pel::detail::processBootError(false);
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -0500315 throw std::runtime_error("IPL initialization failed");
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500316 }
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500317
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500318 // To clear trace if success
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500319 openpower::pel::detail::processBootError(true);
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500320
Marri Devender Rao78479602020-01-06 03:45:11 -0600321 // callback method will be called upon failure which will create the PEL
322 int rc = ipl_run_major(0);
323 if (rc > 0)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500324 {
325 log<level::ERR>("step 0 failed to start the host");
Marri Devender Rao78479602020-01-06 03:45:11 -0600326 throw std::runtime_error("Failed to execute host start boot step");
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500327 }
328}
329
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500330/**
331 * @brief Starts the reboot with type memory preserving reboot.
332 * @return void
333 */
334void startHostMpReboot()
335{
336 // set ipl type as mpipl
337 startHost(IPL_TYPE_MPIPL);
338}
339
340/**
341 * @brief Starts the normal boot type.
342 * @return void
343 */
344void startHostNormal()
345{
Jayanth Othayothad3ff0f2021-11-01 06:35:17 -0500346 startHost(IPL_TYPE_NORMAL);
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500347}
348
Brad Bishop63508a72020-10-27 18:55:01 -0400349REGISTER_PROCEDURE("startHost", startHostNormal)
350REGISTER_PROCEDURE("startHostMpReboot", startHostMpReboot)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500351
352} // namespace phal
353} // namespace openpower