1 extern "C" 2 { 3 #include <libpdbg.h> 4 } 5 6 #include "attributes_info.H" 7 8 #include "phalerror/phal_error.hpp" 9 10 #include <libekb.H> 11 #include <libipl.H> 12 13 #include <ext_interface.hpp> 14 #include <phosphor-logging/log.hpp> 15 #include <registration.hpp> 16 namespace openpower 17 { 18 namespace phal 19 { 20 21 using namespace phosphor::logging; 22 23 /** 24 * @brief Check if master processor or not 25 * 26 * @return True/False 27 */ 28 bool isMasterProc(struct pdbg_target* procTarget) 29 { 30 ATTR_PROC_MASTER_TYPE_Type type; 31 32 // Get processor type (Master or Alt-master) 33 if (DT_GET_PROP(ATTR_PROC_MASTER_TYPE, procTarget, type)) 34 { 35 log<level::ERR>("Attribute [ATTR_PROC_MASTER_TYPE] get failed"); 36 throw std::runtime_error( 37 "Attribute [ATTR_PROC_MASTER_TYPE] get failed"); 38 } 39 40 /* Attribute value 0 corresponds to master processor */ 41 if (type == 0) 42 { 43 return true; 44 } 45 else 46 { 47 return false; 48 } 49 } 50 51 /** 52 * @brief Select BOOT SEEPROM and Measurement SEEPROM(PRIMARY/BACKUP) on POWER 53 * processor position 0/1 depending on boot count before kicking off 54 * the boot. 55 * 56 * @return void 57 */ 58 void selectBootSeeprom() 59 { 60 struct pdbg_target* procTarget; 61 ATTR_BACKUP_SEEPROM_SELECT_Enum bkpSeePromSelect; 62 ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_Enum bkpMeaSeePromSelect; 63 64 pdbg_for_each_class_target("proc", procTarget) 65 { 66 if (!isMasterProc(procTarget)) 67 { 68 continue; 69 } 70 71 // Choose seeprom side to boot from based on boot count 72 if (getBootCount() > 0) 73 { 74 log<level::INFO>("Setting SBE seeprom side to 0", 75 entry("SBE_SIDE_SELECT=%d", 76 ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY)); 77 78 bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_PRIMARY; 79 bkpMeaSeePromSelect = 80 ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_PRIMARY; 81 } 82 else 83 { 84 log<level::INFO>("Setting SBE seeprom side to 1", 85 entry("SBE_SIDE_SELECT=%d", 86 ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY)); 87 bkpSeePromSelect = ENUM_ATTR_BACKUP_SEEPROM_SELECT_SECONDARY; 88 bkpMeaSeePromSelect = 89 ENUM_ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT_SECONDARY; 90 } 91 92 // Set the Attribute as per bootcount policy for boot seeprom 93 if (DT_SET_PROP(ATTR_BACKUP_SEEPROM_SELECT, procTarget, 94 bkpSeePromSelect)) 95 { 96 log<level::ERR>( 97 "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed"); 98 throw std::runtime_error( 99 "Attribute [ATTR_BACKUP_SEEPROM_SELECT] set failed"); 100 } 101 102 // Set the Attribute as per bootcount policy for measurement seeprom 103 if (DT_SET_PROP(ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT, procTarget, 104 bkpMeaSeePromSelect)) 105 { 106 log<level::ERR>( 107 "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set " 108 "failed"); 109 throw std::runtime_error( 110 "Attribute [ATTR_BACKUP_MEASUREMENT_SEEPROM_SELECT] set " 111 "failed"); 112 } 113 } 114 } 115 116 /** 117 * @brief Starts the self boot engine on POWER processor position 0 118 * to kick off a boot. 119 * @return void 120 */ 121 void startHost(enum ipl_type iplType = IPL_TYPE_NORMAL) 122 { 123 // add callback methods for debug traces and for boot failures 124 openpower::pel::addBootErrorCallbacks(); 125 126 if (!pdbg_targets_init(NULL)) 127 { 128 log<level::ERR>("pdbg_targets_init failed"); 129 openpower::pel::detail::processBootErrorCallback(false); 130 throw std::runtime_error("pdbg target initialization failed"); 131 } 132 // To clear trace if success 133 openpower::pel::detail::processBootErrorCallback(true); 134 135 if (libekb_init()) 136 { 137 log<level::ERR>("libekb_init failed"); 138 openpower::pel::detail::processBootErrorCallback(false); 139 throw std::runtime_error("libekb initialization failed"); 140 } 141 // To clear trace if success 142 openpower::pel::detail::processBootErrorCallback(true); 143 144 if (ipl_init(IPL_AUTOBOOT) != 0) 145 { 146 log<level::ERR>("ipl_init failed"); 147 openpower::pel::detail::processBootErrorCallback(false); 148 throw std::runtime_error("Boot initialization failed"); 149 } 150 151 ipl_set_type(iplType); 152 153 // To clear trace if success 154 openpower::pel::detail::processBootErrorCallback(true); 155 156 // callback method will be called upon failure which will create the PEL 157 int rc = ipl_run_major(0); 158 if (rc > 0) 159 { 160 log<level::ERR>("step 0 failed to start the host"); 161 throw std::runtime_error("Failed to execute host start boot step"); 162 } 163 } 164 165 /** 166 * @brief Starts the reboot with type memory preserving reboot. 167 * @return void 168 */ 169 void startHostMpReboot() 170 { 171 // set ipl type as mpipl 172 startHost(IPL_TYPE_MPIPL); 173 } 174 175 /** 176 * @brief Starts the normal boot type. 177 * @return void 178 */ 179 void startHostNormal() 180 { 181 // Run select seeprom before poweron 182 try 183 { 184 selectBootSeeprom(); 185 186 // To clear trace as it is success 187 openpower::pel::detail::processBootErrorCallback(true); 188 } 189 catch (const std::exception& ex) 190 { 191 // create PEL in failure 192 openpower::pel::detail::processBootErrorCallback(false); 193 log<level::ERR>("SEEPROM selection failed", entry("ERR=%s", ex.what())); 194 throw ex; 195 } 196 197 startHost(); 198 } 199 200 REGISTER_PROCEDURE("startHost", startHostNormal) 201 REGISTER_PROCEDURE("startHostMpReboot", startHostMpReboot) 202 203 } // namespace phal 204 } // namespace openpower 205