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