1 extern "C"
2 {
3 #include <libpdbg.h>
4 }
5 
6 #include "attributes_info.H"
7 
8 #include "phalerror/phal_error.hpp"
9 #include "procedures/phal/common_utils.hpp"
10 
11 #include <libekb.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     try
124     {
125         phal_init();
126         ipl_set_type(iplType);
127     }
128     catch (std::exception& ex)
129     {
130         log<level::ERR>("Exception raised during init PHAL",
131                         entry("EXCEPTION=%s", ex.what()));
132         openpower::pel::detail::processBootErrorCallback(false);
133         throw std::runtime_error("PHAL initialization failed");
134     }
135 
136     // To clear trace if success
137     openpower::pel::detail::processBootErrorCallback(true);
138 
139     // callback method will be called upon failure which will create the PEL
140     int rc = ipl_run_major(0);
141     if (rc > 0)
142     {
143         log<level::ERR>("step 0 failed to start the host");
144         throw std::runtime_error("Failed to execute host start boot step");
145     }
146 }
147 
148 /**
149  * @brief Starts the reboot with type memory preserving reboot.
150  * @return void
151  */
152 void startHostMpReboot()
153 {
154     // set ipl type as mpipl
155     startHost(IPL_TYPE_MPIPL);
156 }
157 
158 /**
159  * @brief Starts the normal boot type.
160  * @return void
161  */
162 void startHostNormal()
163 {
164     // Run select seeprom before poweron
165     try
166     {
167         selectBootSeeprom();
168 
169         // To clear trace as it is success
170         openpower::pel::detail::processBootErrorCallback(true);
171     }
172     catch (const std::exception& ex)
173     {
174         // create PEL in failure
175         openpower::pel::detail::processBootErrorCallback(false);
176         log<level::ERR>("SEEPROM selection failed", entry("ERR=%s", ex.what()));
177         throw ex;
178     }
179 
180     startHost();
181 }
182 
183 REGISTER_PROCEDURE("startHost", startHostNormal)
184 REGISTER_PROCEDURE("startHostMpReboot", startHostMpReboot)
185 
186 } // namespace phal
187 } // namespace openpower
188