xref: /openbmc/openpower-proc-control/procedures/phal/start_host.cpp (revision 56d14d049bcb1966fac953d1bf07a9e5bedf5ebc)
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