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