| Brad Bishop | 5e5d445 | 2020-10-27 19:46:13 -0400 | [diff] [blame] | 1 | extern "C" | 
 | 2 | { | 
| Ramesh Iyyar | c98bab5 | 2020-04-16 04:04:29 -0500 | [diff] [blame] | 3 | #include <libpdbg.h> | 
 | 4 | } | 
 | 5 |  | 
| Brad Bishop | 5e5d445 | 2020-10-27 19:46:13 -0400 | [diff] [blame] | 6 | #include "attributes_info.H" | 
 | 7 |  | 
| Jayanth Othayoth | 25e39c8 | 2021-07-12 01:00:17 -0500 | [diff] [blame] | 8 | #include "extensions/phal/common_utils.hpp" | 
| Jayanth Othayoth | ad3ff0f | 2021-11-01 06:35:17 -0500 | [diff] [blame] | 9 | #include "extensions/phal/create_pel.hpp" | 
| Jayanth Othayoth | 6552de0 | 2021-07-12 00:55:57 -0500 | [diff] [blame] | 10 | #include "extensions/phal/phal_error.hpp" | 
| Jayanth Othayoth | e22e823 | 2021-06-08 03:34:34 -0500 | [diff] [blame] | 11 | #include "util.hpp" | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 12 |  | 
| Jayanth Othayoth | e22e823 | 2021-06-08 03:34:34 -0500 | [diff] [blame] | 13 | #include <fmt/format.h> | 
| Ramesh Iyyar | c98bab5 | 2020-04-16 04:04:29 -0500 | [diff] [blame] | 14 | #include <libekb.H> | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 15 |  | 
| Lakshminarayana R. Kammath | 75912e8 | 2020-04-28 07:37:17 -0500 | [diff] [blame] | 16 | #include <ext_interface.hpp> | 
| Ramesh Iyyar | f9152b9 | 2021-09-06 03:43:59 -0500 | [diff] [blame] | 17 | #include <nlohmann/json.hpp> | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 18 | #include <phosphor-logging/log.hpp> | 
 | 19 | #include <registration.hpp> | 
| Jayanth Othayoth | e22e823 | 2021-06-08 03:34:34 -0500 | [diff] [blame] | 20 |  | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 21 | namespace openpower | 
 | 22 | { | 
 | 23 | namespace phal | 
 | 24 | { | 
 | 25 |  | 
 | 26 | using namespace phosphor::logging; | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 27 |  | 
 | 28 | /** | 
| Lakshminarayana R. Kammath | 75912e8 | 2020-04-28 07:37:17 -0500 | [diff] [blame] | 29 |  *  @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 |  */ | 
 | 35 | void 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 Geissler | 5c3f925 | 2021-06-10 10:53:05 -0500 | [diff] [blame] | 43 |         if (!isPrimaryProc(procTarget)) | 
| Lakshminarayana R. Kammath | 75912e8 | 2020-04-28 07:37:17 -0500 | [diff] [blame] | 44 |         { | 
 | 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 Othayoth | e22e823 | 2021-06-08 03:34:34 -0500 | [diff] [blame] | 94 |  * @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 |  */ | 
 | 97 | void 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 Williams | aaea686 | 2022-07-22 19:26:54 -0500 | [diff] [blame] | 121 |     catch (const sdbusplus::exception_t& e) | 
| Jayanth Othayoth | e22e823 | 2021-06-08 03:34:34 -0500 | [diff] [blame] | 122 |     { | 
 | 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 |     { | 
| Jayanth Othayoth | e22e823 | 2021-06-08 03:34:34 -0500 | [diff] [blame] | 160 |         if (DT_SET_PROP(ATTR_SYS_CLK_NE_TERMINATION_SITE, procTarget, | 
 | 161 |                         clockTerm)) | 
 | 162 |         { | 
 | 163 |             log<level::ERR>( | 
 | 164 |                 "Attribute ATTR_SYS_CLK_NE_TERMINATION_SITE set failed"); | 
 | 165 |             throw std::runtime_error( | 
 | 166 |                 "Attribute ATTR_SYS_CLK_NE_TERMINATION_SITE set failed"); | 
 | 167 |         } | 
 | 168 |     } | 
 | 169 | } | 
 | 170 |  | 
 | 171 | /** | 
| Ramesh Iyyar | f9152b9 | 2021-09-06 03:43:59 -0500 | [diff] [blame] | 172 |  * @brief Helper function to create error log (aka PEL) with | 
 | 173 |  *        procedure callout for the hardware isolation policy | 
 | 174 |  *        settings failures. | 
 | 175 |  * | 
 | 176 |  * @param[in] procedureCode - The procedure code to include in the callout | 
 | 177 |  * @param[in] priority - The priority for the procedure callout | 
 | 178 |  * @param[in] additionalData - The additional data to include in the error log | 
 | 179 |  * | 
 | 180 |  * @return void | 
 | 181 |  */ | 
 | 182 | static void | 
 | 183 |     createPELForHwIsolationSettingsErr(const std::string& procedureCode, | 
 | 184 |                                        const std::string& priority, | 
 | 185 |                                        const pel::FFDCData& additionalData) | 
 | 186 | { | 
 | 187 |     try | 
 | 188 |     { | 
 | 189 |         using json = nlohmann::json; | 
| Marri Devender Rao | 4d5b5bf | 2022-05-23 09:23:31 -0500 | [diff] [blame] | 190 |         using Severity = | 
 | 191 |             sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level; | 
| Ramesh Iyyar | f9152b9 | 2021-09-06 03:43:59 -0500 | [diff] [blame] | 192 |  | 
 | 193 |         json jsonCalloutDataList; | 
 | 194 |         jsonCalloutDataList = json::array(); | 
 | 195 |         json jsonCalloutData; | 
 | 196 |         jsonCalloutData["Procedure"] = procedureCode; | 
 | 197 |         jsonCalloutData["Priority"] = priority; | 
 | 198 |         jsonCalloutDataList.emplace_back(jsonCalloutData); | 
 | 199 |  | 
 | 200 |         openpower::pel::createErrorPEL("org.open_power.PHAL.Error.Boot", | 
| Marri Devender Rao | 4d5b5bf | 2022-05-23 09:23:31 -0500 | [diff] [blame] | 201 |                                        jsonCalloutDataList, additionalData, | 
 | 202 |                                        Severity::Error); | 
| Ramesh Iyyar | f9152b9 | 2021-09-06 03:43:59 -0500 | [diff] [blame] | 203 |     } | 
 | 204 |     catch (const std::exception& e) | 
 | 205 |     { | 
 | 206 |         // Don't throw exception since the caller might call in the error path | 
 | 207 |         // and even we should allow the hardware isolation by default. | 
 | 208 |         log<level::ERR>( | 
 | 209 |             fmt::format("Exception [{}], failed to create the error log " | 
 | 210 |                         "for the hardware isolation policy settings failures.", | 
 | 211 |                         e.what()) | 
 | 212 |                 .c_str()); | 
 | 213 |     } | 
 | 214 | } | 
 | 215 |  | 
 | 216 | /** | 
 | 217 |  * @brief Helper function to decide the hardware isolation (aka guard) | 
 | 218 |  * | 
 | 219 |  * @return xyz.openbmc_project.Object.Enable::Enabled value on success | 
 | 220 |  *         true on failure since hardware isolation feature should be | 
 | 221 |  *         enabled by default. | 
 | 222 |  */ | 
 | 223 | static bool allowHwIsolation() | 
 | 224 | { | 
 | 225 |     bool allowHwIsolation{true}; | 
 | 226 |  | 
 | 227 |     constexpr auto hwIsolationPolicyObjPath = | 
 | 228 |         "/xyz/openbmc_project/hardware_isolation/allow_hw_isolation"; | 
 | 229 |     constexpr auto hwIsolationPolicyIface = "xyz.openbmc_project.Object.Enable"; | 
 | 230 |  | 
 | 231 |     try | 
 | 232 |     { | 
 | 233 |         auto bus = sdbusplus::bus::new_default(); | 
 | 234 |  | 
 | 235 |         std::string service = util::getService(bus, hwIsolationPolicyObjPath, | 
 | 236 |                                                hwIsolationPolicyIface); | 
 | 237 |  | 
 | 238 |         auto method = | 
 | 239 |             bus.new_method_call(service.c_str(), hwIsolationPolicyObjPath, | 
 | 240 |                                 "org.freedesktop.DBus.Properties", "Get"); | 
 | 241 |         method.append(hwIsolationPolicyIface, "Enabled"); | 
 | 242 |  | 
 | 243 |         auto reply = bus.call(method); | 
 | 244 |  | 
 | 245 |         std::variant<bool> resp; | 
 | 246 |  | 
 | 247 |         reply.read(resp); | 
 | 248 |  | 
 | 249 |         if (const bool* enabledPropVal = std::get_if<bool>(&resp)) | 
 | 250 |         { | 
 | 251 |             allowHwIsolation = *enabledPropVal; | 
 | 252 |         } | 
 | 253 |         else | 
 | 254 |         { | 
 | 255 |             const auto trace{fmt::format( | 
 | 256 |                 "Failed to read the HardwareIsolation policy " | 
 | 257 |                 "from the path [{}] interface [{}]. Continuing with " | 
 | 258 |                 "default mode(allow_hw_isolation)", | 
 | 259 |                 hwIsolationPolicyObjPath, hwIsolationPolicyIface)}; | 
 | 260 |  | 
 | 261 |             log<level::ERR>(trace.c_str()); | 
 | 262 |             createPELForHwIsolationSettingsErr("BMC0001", "M", | 
 | 263 |                                                {{"REASON_FOR_PEL", trace}}); | 
 | 264 |         } | 
 | 265 |     } | 
| Patrick Williams | aaea686 | 2022-07-22 19:26:54 -0500 | [diff] [blame] | 266 |     catch (const sdbusplus::exception_t& e) | 
| Ramesh Iyyar | f9152b9 | 2021-09-06 03:43:59 -0500 | [diff] [blame] | 267 |     { | 
 | 268 |         const auto trace{fmt::format( | 
 | 269 |             "Exception [{}] to get the HardwareIsolation policy " | 
 | 270 |             "from the path [{}] interface [{}]. Continuing with " | 
 | 271 |             "default mode (allow_hw_isolation)", | 
 | 272 |             e.what(), hwIsolationPolicyObjPath, hwIsolationPolicyIface)}; | 
 | 273 |  | 
 | 274 |         log<level::ERR>(trace.c_str()); | 
 | 275 |         createPELForHwIsolationSettingsErr("BMC0001", "M", | 
 | 276 |                                            {{"REASON_FOR_PEL", trace}}); | 
 | 277 |     } | 
 | 278 |  | 
 | 279 |     return allowHwIsolation; | 
 | 280 | } | 
 | 281 |  | 
 | 282 | /** | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 283 |  * @brief Starts the self boot engine on POWER processor position 0 | 
 | 284 |  *        to kick off a boot. | 
 | 285 |  * @return void | 
 | 286 |  */ | 
| Dhruvaraj Subhashchandran | c2e4276 | 2020-06-17 00:30:12 -0500 | [diff] [blame] | 287 | void startHost(enum ipl_type iplType = IPL_TYPE_NORMAL) | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 288 | { | 
| Chirag Sharma | a257693 | 2020-12-05 23:17:41 -0600 | [diff] [blame] | 289 |     try | 
| Ramesh Iyyar | c98bab5 | 2020-04-16 04:04:29 -0500 | [diff] [blame] | 290 |     { | 
| Chirag Sharma | a257693 | 2020-12-05 23:17:41 -0600 | [diff] [blame] | 291 |         phal_init(); | 
 | 292 |         ipl_set_type(iplType); | 
| Ramesh Iyyar | f9152b9 | 2021-09-06 03:43:59 -0500 | [diff] [blame] | 293 |  | 
 | 294 |         /** | 
 | 295 |          * Don't apply guard records if the HardwareIsolation (aka guard) | 
 | 296 |          * the policy is disabled (false). By default, libipl will apply | 
 | 297 |          * guard records. | 
 | 298 |          */ | 
 | 299 |         if (!allowHwIsolation()) | 
 | 300 |         { | 
 | 301 |             ipl_disable_guard(); | 
 | 302 |         } | 
 | 303 |  | 
| Jayanth Othayoth | ad3ff0f | 2021-11-01 06:35:17 -0500 | [diff] [blame] | 304 |         if (iplType == IPL_TYPE_NORMAL) | 
 | 305 |         { | 
 | 306 |             // Update SEEPROM side only for NORMAL boot | 
 | 307 |             selectBootSeeprom(); | 
 | 308 |         } | 
 | 309 |         setClkNETerminationSite(); | 
| Ramesh Iyyar | c98bab5 | 2020-04-16 04:04:29 -0500 | [diff] [blame] | 310 |     } | 
| Patrick Williams | 1a9a5a6 | 2021-10-06 13:05:06 -0500 | [diff] [blame] | 311 |     catch (const std::exception& ex) | 
| Ramesh Iyyar | c98bab5 | 2020-04-16 04:04:29 -0500 | [diff] [blame] | 312 |     { | 
| Jayanth Othayoth | ad3ff0f | 2021-11-01 06:35:17 -0500 | [diff] [blame] | 313 |         log<level::ERR>("Exception raised during ipl initialisation", | 
| Chirag Sharma | a257693 | 2020-12-05 23:17:41 -0600 | [diff] [blame] | 314 |                         entry("EXCEPTION=%s", ex.what())); | 
| Jayanth Othayoth | ad3ff0f | 2021-11-01 06:35:17 -0500 | [diff] [blame] | 315 |         openpower::pel::createPEL("org.open_power.PHAL.Error.Boot"); | 
| Jayanth Othayoth | 2b21170 | 2021-09-06 05:14:23 -0500 | [diff] [blame] | 316 |         openpower::pel::detail::processBootError(false); | 
| Jayanth Othayoth | ad3ff0f | 2021-11-01 06:35:17 -0500 | [diff] [blame] | 317 |         throw std::runtime_error("IPL initialization failed"); | 
| Ramesh Iyyar | c98bab5 | 2020-04-16 04:04:29 -0500 | [diff] [blame] | 318 |     } | 
| Dhruvaraj Subhashchandran | c2e4276 | 2020-06-17 00:30:12 -0500 | [diff] [blame] | 319 |  | 
| Ramesh Iyyar | c98bab5 | 2020-04-16 04:04:29 -0500 | [diff] [blame] | 320 |     // To clear trace if success | 
| Jayanth Othayoth | 2b21170 | 2021-09-06 05:14:23 -0500 | [diff] [blame] | 321 |     openpower::pel::detail::processBootError(true); | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 322 |  | 
| Marri Devender Rao | 7847960 | 2020-01-06 03:45:11 -0600 | [diff] [blame] | 323 |     // callback method will be called upon failure which will create the PEL | 
 | 324 |     int rc = ipl_run_major(0); | 
 | 325 |     if (rc > 0) | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 326 |     { | 
 | 327 |         log<level::ERR>("step 0 failed to start the host"); | 
| Marri Devender Rao | 7847960 | 2020-01-06 03:45:11 -0600 | [diff] [blame] | 328 |         throw std::runtime_error("Failed to execute host start boot step"); | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 329 |     } | 
 | 330 | } | 
 | 331 |  | 
| Dhruvaraj Subhashchandran | c2e4276 | 2020-06-17 00:30:12 -0500 | [diff] [blame] | 332 | /** | 
 | 333 |  * @brief Starts the reboot with type memory preserving reboot. | 
 | 334 |  * @return void | 
 | 335 |  */ | 
 | 336 | void startHostMpReboot() | 
 | 337 | { | 
 | 338 |     // set ipl type as mpipl | 
 | 339 |     startHost(IPL_TYPE_MPIPL); | 
 | 340 | } | 
 | 341 |  | 
 | 342 | /** | 
 | 343 |  * @brief Starts the normal boot type. | 
 | 344 |  * @return void | 
 | 345 |  */ | 
 | 346 | void startHostNormal() | 
 | 347 | { | 
| Jayanth Othayoth | ad3ff0f | 2021-11-01 06:35:17 -0500 | [diff] [blame] | 348 |     startHost(IPL_TYPE_NORMAL); | 
| Dhruvaraj Subhashchandran | c2e4276 | 2020-06-17 00:30:12 -0500 | [diff] [blame] | 349 | } | 
 | 350 |  | 
| Brad Bishop | 63508a7 | 2020-10-27 18:55:01 -0400 | [diff] [blame] | 351 | REGISTER_PROCEDURE("startHost", startHostNormal) | 
 | 352 | REGISTER_PROCEDURE("startHostMpReboot", startHostMpReboot) | 
| Ramesh Iyyar | b181d3b | 2019-10-17 13:39:10 -0500 | [diff] [blame] | 353 |  | 
 | 354 | } // namespace phal | 
 | 355 | } // namespace openpower |