blob: 6e3f6833f185300fde123e2d35db1cf0a43da45d [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 Othayoth6552de02021-07-12 00:55:57 -05009#include "extensions/phal/phal_error.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 Select BOOT SEEPROM and Measurement SEEPROM(PRIMARY/BACKUP) on POWER
28 * processor position 0/1 depending on boot count before kicking off
29 * the boot.
30 *
31 * @return void
32 */
33void selectBootSeeprom()
34{
35 struct pdbg_target* procTarget;
36 ATTR_BACKUP_SEEPROM_SELECT_Enum bkpSeePromSelect;
37 ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_Enum bkpMeaSeePromSelect;
38
39 pdbg_for_each_class_target("proc", procTarget)
40 {
Andrew Geissler5c3f9252021-06-10 10:53:05 -050041 if (!isPrimaryProc(procTarget))
Lakshminarayana R. Kammath75912e82020-04-28 07:37:17 -050042 {
43 continue;
44 }
45
46 // Choose seeprom side to boot from based on boot count
47 if (getBootCount() > 0)
48 {
49 log<level::INFO>("Setting SBE seeprom side to 0",
50 entry("SBE_SIDE_SELECT=%d",
51 ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY));
52
53 bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY;
54 bkpMeaSeePromSelect =
55 ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_PRIMARY;
56 }
57 else
58 {
59 log<level::INFO>("Setting SBE seeprom side to 1",
60 entry("SBE_SIDE_SELECT=%d",
61 ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY));
62 bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY;
63 bkpMeaSeePromSelect =
64 ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_SECONDARY;
65 }
66
67 // Set the Attribute as per bootcount policy for boot seeprom
68 if (DT_SET_PROP(ATTR_BACKUP_SEEPROM_SELECT, procTarget,
69 bkpSeePromSelect))
70 {
71 log<level::ERR>(
72 "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed");
73 throw std::runtime_error(
74 "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed");
75 }
76
77 // Set the Attribute as per bootcount policy for measurement seeprom
78 if (DT_SET_PROP(ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT, procTarget,
79 bkpMeaSeePromSelect))
80 {
81 log<level::ERR>(
82 "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set "
83 "failed");
84 throw std::runtime_error(
85 "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set "
86 "failed");
87 }
88 }
89}
90
91/**
Jayanth Othayothe22e8232021-06-08 03:34:34 -050092 * @brief Read the HW Level from VPD and set CLK NE termination site
93 * Note any failure in this function will result startHost failure.
94 */
95void setClkNETerminationSite()
96{
97 // Get Motherborad VINI Recored "HW" keyword
98 constexpr auto objPath =
99 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
100 constexpr auto kwdVpdInf = "com.ibm.ipzvpd.VINI";
101 constexpr auto hwKwd = "HW";
102
103 auto bus = sdbusplus::bus::new_default();
104
105 std::string service = util::getService(bus, objPath, kwdVpdInf);
106
107 auto properties = bus.new_method_call(
108 service.c_str(), objPath, "org.freedesktop.DBus.Properties", "Get");
109 properties.append(kwdVpdInf);
110 properties.append(hwKwd);
111
112 // Store "HW" Keyword data.
113 std::variant<std::vector<uint8_t>> val;
114 try
115 {
116 auto result = bus.call(properties);
117 result.read(val);
118 }
119 catch (const sdbusplus::exception::SdBusError& e)
120 {
121 log<level::ERR>("Get HW Keyword read from VINI Failed");
122 throw std::runtime_error("Get HW Keyword read from VINI Failed");
123 }
124
125 auto hwData = std::get<std::vector<uint8_t>>(val);
126
127 //"HW" Keyword size is 2 as per VPD spec.
128 constexpr auto hwKwdSize = 2;
129 if (hwKwdSize != hwData.size())
130 {
131 log<level::ERR>(
132 fmt::format("Incorrect VINI records HW Keyword data size({})",
133 hwData.size())
134 .c_str());
135 throw std::runtime_error("Incorrect VINI records HW Keyword data size");
136 }
137
138 log<level::DEBUG>(fmt::format("VINI Records HW[0]:{} HW[1]:{}",
139 hwData.at(0), hwData.at(1))
140 .c_str());
141
142 // VINI Record "HW" keyword's Byte 0's MSB bit indicates
143 // proc or planar type need to choose.
144 constexpr uint8_t SYS_CLK_NE_TERMINATION_ON_MASK = 0x80;
145
146 ATTR_SYS_CLK_NE_TERMINATION_SITE_Type clockTerm =
147 ENUM_ATTR_SYS_CLK_NE_TERMINATION_SITE_PLANAR;
148
149 if (SYS_CLK_NE_TERMINATION_ON_MASK & hwData.at(0))
150 {
151 clockTerm = ENUM_ATTR_SYS_CLK_NE_TERMINATION_SITE_PROC;
152 }
153
154 // update all the processor attributes
155 struct pdbg_target* procTarget;
156 pdbg_for_each_class_target("proc", procTarget)
157 {
158
159 if (DT_SET_PROP(ATTR_SYS_CLK_NE_TERMINATION_SITE, procTarget,
160 clockTerm))
161 {
162 log<level::ERR>(
163 "Attribute ATTR_SYS_CLK_NE_TERMINATION_SITE set failed");
164 throw std::runtime_error(
165 "Attribute ATTR_SYS_CLK_NE_TERMINATION_SITE set failed");
166 }
167 }
168}
169
170/**
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500171 * @brief Starts the self boot engine on POWER processor position 0
172 * to kick off a boot.
173 * @return void
174 */
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500175void startHost(enum ipl_type iplType = IPL_TYPE_NORMAL)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500176{
Chirag Sharmaa2576932020-12-05 23:17:41 -0600177 try
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500178 {
Chirag Sharmaa2576932020-12-05 23:17:41 -0600179 phal_init();
180 ipl_set_type(iplType);
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500181 }
Chirag Sharmaa2576932020-12-05 23:17:41 -0600182 catch (std::exception& ex)
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500183 {
Chirag Sharmaa2576932020-12-05 23:17:41 -0600184 log<level::ERR>("Exception raised during init PHAL",
185 entry("EXCEPTION=%s", ex.what()));
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500186 openpower::pel::detail::processBootErrorCallback(false);
Chirag Sharmaa2576932020-12-05 23:17:41 -0600187 throw std::runtime_error("PHAL initialization failed");
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500188 }
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500189
Ramesh Iyyarc98bab52020-04-16 04:04:29 -0500190 // To clear trace if success
191 openpower::pel::detail::processBootErrorCallback(true);
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500192
Jayanth Othayothe22e8232021-06-08 03:34:34 -0500193 setClkNETerminationSite();
194
Marri Devender Rao78479602020-01-06 03:45:11 -0600195 // callback method will be called upon failure which will create the PEL
196 int rc = ipl_run_major(0);
197 if (rc > 0)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500198 {
199 log<level::ERR>("step 0 failed to start the host");
Marri Devender Rao78479602020-01-06 03:45:11 -0600200 throw std::runtime_error("Failed to execute host start boot step");
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500201 }
202}
203
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500204/**
205 * @brief Starts the reboot with type memory preserving reboot.
206 * @return void
207 */
208void startHostMpReboot()
209{
210 // set ipl type as mpipl
211 startHost(IPL_TYPE_MPIPL);
212}
213
214/**
215 * @brief Starts the normal boot type.
216 * @return void
217 */
218void startHostNormal()
219{
Dhruvaraj Subhashchandran3ae7ed42020-06-16 12:48:14 -0500220 // Run select seeprom before poweron
221 try
222 {
223 selectBootSeeprom();
224
225 // To clear trace as it is success
226 openpower::pel::detail::processBootErrorCallback(true);
227 }
228 catch (const std::exception& ex)
229 {
230 // create PEL in failure
231 openpower::pel::detail::processBootErrorCallback(false);
232 log<level::ERR>("SEEPROM selection failed", entry("ERR=%s", ex.what()));
233 throw ex;
234 }
235
Dhruvaraj Subhashchandranc2e42762020-06-17 00:30:12 -0500236 startHost();
237}
238
Brad Bishop63508a72020-10-27 18:55:01 -0400239REGISTER_PROCEDURE("startHost", startHostNormal)
240REGISTER_PROCEDURE("startHostMpReboot", startHostMpReboot)
Ramesh Iyyarb181d3b2019-10-17 13:39:10 -0500241
242} // namespace phal
243} // namespace openpower