1e7725610SArun Lal K M #pragma once
2e7725610SArun Lal K M 
3e7725610SArun Lal K M #include "tinyxml2.h"
4e7725610SArun Lal K M 
5e7725610SArun Lal K M #include <phosphor-logging/elog-errors.hpp>
6e7725610SArun Lal K M #include <phosphor-logging/log.hpp>
70748c69dSJason M. Bills #include <types.hpp>
8e7725610SArun Lal K M 
9e7725610SArun Lal K M #include <map>
10e7725610SArun Lal K M #include <sstream>
11e7725610SArun Lal K M #include <stack>
12e7725610SArun Lal K M #include <string>
13e7725610SArun Lal K M #include <variant>
14e7725610SArun Lal K M #include <vector>
15e7725610SArun Lal K M 
16e7725610SArun Lal K M namespace bios
17e7725610SArun Lal K M {
18e7725610SArun Lal K M /* Can hold one 'option'
19e7725610SArun Lal K M  * For example
20e7725610SArun Lal K M  *  <option text="TIS" value="0x0"/>
21e7725610SArun Lal K M  */
227a8ab9eeSArun Lal K M using OptionType = std::tuple<std::string, ipmi::DbusVariant, std::string>;
23e7725610SArun Lal K M 
24e7725610SArun Lal K M /* Can hold one 'options'
25e7725610SArun Lal K M  * For example
26e7725610SArun Lal K M  *  <options>
27e7725610SArun Lal K M  *		<option text="TIS" value="0x0"/>
28e7725610SArun Lal K M  *		<option text="PTP FIFO" value="0x1"/>
29e7725610SArun Lal K M  *		<option text="PTP CRB" value="0x2"/>
30e7725610SArun Lal K M  *	</options>
31e7725610SArun Lal K M  */
32e7725610SArun Lal K M using OptionTypeVector = std::vector<OptionType>;
33e7725610SArun Lal K M 
34e7725610SArun Lal K M /* Can hold one 'knob'
35e7725610SArun Lal K M  * For example
36e7725610SArun Lal K M  *  <knob  type="scalar" setupType="oneof" name="TpmDeviceInterfaceAttempt"
37e7725610SArun Lal K M  *  varstoreIndex="14" prompt="Attempt PTP TPM Device Interface"
38e7725610SArun Lal K M  *  description="Attempt PTP TPM Device Interface: PTP FIFO, PTP CRB" size="1"
39e7725610SArun Lal K M  *  offset="0x0005" depex="Sif( _LIST_ TpmDevice _EQU_ 0 1 ) _AND_ Sif(
40e7725610SArun Lal K M  *  TpmDeviceInterfacePtpFifoSupported _EQU_ 0 OR
41e7725610SArun Lal K M  *  TpmDeviceInterfacePtpCrbSupported _EQU_ 0 )" default="0x00"
42e7725610SArun Lal K M  *CurrentVal="0x00"> <options> <option text="TIS" value="0x0"/> <option
43e7725610SArun Lal K M  *text="PTP FIFO" value="0x1"/> <option text="PTP CRB" value="0x2"/>
44e7725610SArun Lal K M  *		</options>
45e7725610SArun Lal K M  *	</knob>
46e7725610SArun Lal K M  */
47e7725610SArun Lal K M using BiosBaseTableTypeEntry =
48e7725610SArun Lal K M     std::tuple<std::string, bool, std::string, std::string, std::string,
490748c69dSJason M. Bills                ipmi::DbusVariant, ipmi::DbusVariant, OptionTypeVector>;
50e7725610SArun Lal K M 
51e7725610SArun Lal K M /* Can hold one 'biosknobs'
52e7725610SArun Lal K M  * biosknobs has array of 'knob' */
53e7725610SArun Lal K M using BiosBaseTableType = std::map<std::string, BiosBaseTableTypeEntry>;
54e7725610SArun Lal K M 
55e7725610SArun Lal K M namespace knob
56e7725610SArun Lal K M {
57e7725610SArun Lal K M /* These are the operators we support in a 'depex' expression
58e7725610SArun Lal K M  * Note: We also support '_LIST_', 'Sif', 'Gif', 'Dif', and 'NOT'. But they are
59e7725610SArun Lal K M  * handeled sepeartely. */
60e7725610SArun Lal K M enum class DepexOperators
61e7725610SArun Lal K M {
62e7725610SArun Lal K M     unknown = 0,
63e7725610SArun Lal K M     OR,
64e7725610SArun Lal K M     AND,
65e83c70aaSArun Lal K M     GT,
66e83c70aaSArun Lal K M     GTE,
67e7725610SArun Lal K M     LTE,
68e7725610SArun Lal K M     LT,
69e7725610SArun Lal K M     EQU,
70e7725610SArun Lal K M     NEQ,
71e7725610SArun Lal K M     MODULO
72e7725610SArun Lal K M };
73e7725610SArun Lal K M 
74e7725610SArun Lal K M namespace option
75e7725610SArun Lal K M {
76e7725610SArun Lal K M /* Can hold one 'option' */
77e7725610SArun Lal K M struct option
78e7725610SArun Lal K M {
optionbios::knob::option::option79e7725610SArun Lal K M     option(std::string text, std::string value) :
80e7725610SArun Lal K M         text(std::move(text)), value(std::move(value))
81e7725610SArun Lal K M     {}
82e7725610SArun Lal K M 
83e7725610SArun Lal K M     std::string text;
84e7725610SArun Lal K M     std::string value;
85e7725610SArun Lal K M };
86e7725610SArun Lal K M } // namespace option
87e7725610SArun Lal K M 
88e7725610SArun Lal K M /* Can hold one 'knob' */
89e7725610SArun Lal K M struct knob
90e7725610SArun Lal K M {
knobbios::knob::knob91e7725610SArun Lal K M     knob(std::string nameStr, std::string currentValStr, int currentVal,
92e7725610SArun Lal K M          std::string descriptionStr, std::string defaultStr,
93e7725610SArun Lal K M          std::string promptStr, std::string depexStr,
94e7725610SArun Lal K M          std::string& setupTypeStr) :
95dcff1506SVernon Mauery         depex(false),
96dcff1506SVernon Mauery         readOnly(("ReadOnly" == setupTypeStr) ? true : false),
97dcff1506SVernon Mauery         currentVal(currentVal), nameStr(std::move(nameStr)),
98dcff1506SVernon Mauery         currentValStr(std::move(currentValStr)),
99e7725610SArun Lal K M         descriptionStr(std::move(descriptionStr)),
100e7725610SArun Lal K M         defaultStr(std::move(defaultStr)), promptStr(std::move(promptStr)),
101dcff1506SVernon Mauery         depexStr(std::move(depexStr))
102e7725610SArun Lal K M     {}
103e7725610SArun Lal K M 
104e7725610SArun Lal K M     bool depex;
105e7725610SArun Lal K M     bool readOnly;
106e7725610SArun Lal K M     int currentVal;
107e7725610SArun Lal K M 
108e7725610SArun Lal K M     std::string nameStr;
109e7725610SArun Lal K M     std::string currentValStr;
110e7725610SArun Lal K M     std::string descriptionStr;
111e7725610SArun Lal K M     std::string defaultStr;
112e7725610SArun Lal K M     std::string promptStr;
113e7725610SArun Lal K M     std::string depexStr;
114e7725610SArun Lal K M 
115e7725610SArun Lal K M     /* Can hold one 'options' */
116e7725610SArun Lal K M     std::vector<option::option> options;
117e7725610SArun Lal K M };
118e7725610SArun Lal K M } // namespace knob
119e7725610SArun Lal K M 
120e7725610SArun Lal K M /* Class capable of computing 'depex' expression. */
121e7725610SArun Lal K M class Depex
122e7725610SArun Lal K M {
123e7725610SArun Lal K M   public:
Depex(std::vector<knob::knob> & knobs)124b37abfb2SPatrick Williams     Depex(std::vector<knob::knob>& knobs) : mKnobs(knobs) {}
125e7725610SArun Lal K M 
126e7725610SArun Lal K M     /* Compute 'depex' expression of all knobs in 'biosknobs'. */
compute()127e7725610SArun Lal K M     void compute()
128e7725610SArun Lal K M     {
129e7725610SArun Lal K M         mError.clear();
130e7725610SArun Lal K M 
131e7725610SArun Lal K M         for (auto& knob : mKnobs)
132e7725610SArun Lal K M         {
133e7725610SArun Lal K M             /* if 'depex' == "TRUE" no need to execute expression. */
134e7725610SArun Lal K M             if ("TRUE" == knob.depexStr)
135e7725610SArun Lal K M             {
136e7725610SArun Lal K M                 knob.depex = true;
137e7725610SArun Lal K M             }
138e7725610SArun Lal K M             else if (!knob.readOnly)
139e7725610SArun Lal K M             {
140e7725610SArun Lal K M                 int value = 0;
141e7725610SArun Lal K M 
142e7725610SArun Lal K M                 if (!evaluateExpression(knob.depexStr, value))
143e7725610SArun Lal K M                 {
144e7725610SArun Lal K M                     mError.emplace_back("bad depex: " + knob.depexStr +
145e7725610SArun Lal K M                                         " in knob: " + knob.nameStr);
146e7725610SArun Lal K M                 }
147e7725610SArun Lal K M                 else
148e7725610SArun Lal K M                 {
149e7725610SArun Lal K M                     if (value)
150e7725610SArun Lal K M                     {
151e7725610SArun Lal K M                         knob.depex = true;
152e7725610SArun Lal K M                     }
153e7725610SArun Lal K M                 }
154e7725610SArun Lal K M             }
155e7725610SArun Lal K M         }
156e7725610SArun Lal K M     }
157e7725610SArun Lal K M 
158e7725610SArun Lal K M     /* Returns the number of 'knob's which have a bad 'depex' expression. */
getErrorCount()159e7725610SArun Lal K M     size_t getErrorCount()
160e7725610SArun Lal K M     {
161e7725610SArun Lal K M         return mError.size();
162e7725610SArun Lal K M     }
163e7725610SArun Lal K M 
164e7725610SArun Lal K M     /* Prints all the 'knob's which have a bad 'depex' expression. */
printError()165e7725610SArun Lal K M     void printError()
166e7725610SArun Lal K M     {
167e7725610SArun Lal K M         for (auto& error : mError)
168e7725610SArun Lal K M         {
169e7725610SArun Lal K M             phosphor::logging::log<phosphor::logging::level::ERR>(
170e7725610SArun Lal K M                 error.c_str());
171e7725610SArun Lal K M         }
172e7725610SArun Lal K M     }
173e7725610SArun Lal K M 
174e7725610SArun Lal K M   private:
175e7725610SArun Lal K M     /* Returns 'true' if the argument string is a number. */
isNumber(const std::string & s)176e7725610SArun Lal K M     bool isNumber(const std::string& s)
177e7725610SArun Lal K M     {
178e7725610SArun Lal K M         return !s.empty() &&
179e7725610SArun Lal K M                std::find_if(s.begin(), s.end(), [](unsigned char c) {
180e7725610SArun Lal K M             return !std::isdigit(c);
181e7725610SArun Lal K M         }) == s.end();
182e7725610SArun Lal K M     }
183e7725610SArun Lal K M 
184e7725610SArun Lal K M     /* Returns 'true' if the argument string is hex representation of a number.
185e7725610SArun Lal K M      */
isHexNotation(const std::string & s)186b37abfb2SPatrick Williams     bool isHexNotation(const std::string& s)
187e7725610SArun Lal K M     {
188e7725610SArun Lal K M         return s.compare(0, 2, "0x") == 0 && s.size() > 2 &&
189e7725610SArun Lal K M                s.find_first_not_of("0123456789abcdefABCDEF", 2) ==
190e7725610SArun Lal K M                    std::string::npos;
191e7725610SArun Lal K M     }
192e7725610SArun Lal K M 
193e7725610SArun Lal K M     /* Function to find current value of a 'knob'
194e7725610SArun Lal K M      * search is done using 'knob' attribute 'name' */
getValue(std::string & variableName,int & value)195e7725610SArun Lal K M     bool getValue(std::string& variableName, int& value)
196e7725610SArun Lal K M     {
197e7725610SArun Lal K M         for (auto& knob : mKnobs)
198e7725610SArun Lal K M         {
199e7725610SArun Lal K M             if (knob.nameStr == variableName)
200e7725610SArun Lal K M             {
201e7725610SArun Lal K M                 value = knob.currentVal;
202e7725610SArun Lal K M                 return true;
203e7725610SArun Lal K M             }
204e7725610SArun Lal K M         }
205e7725610SArun Lal K M 
206b37abfb2SPatrick Williams         std::string error = "Unable to find knob: " + variableName +
207b37abfb2SPatrick Williams                             " in knob list\n";
208e7725610SArun Lal K M         phosphor::logging::log<phosphor::logging::level::ERR>(error.c_str());
209e7725610SArun Lal K M 
210e7725610SArun Lal K M         return false;
211e7725610SArun Lal K M     }
212e7725610SArun Lal K M 
213e7725610SArun Lal K M     /* Get the expression enclosed within brackets, i.e., between '(' and ')' */
getSubExpression(const std::string & expression,std::string & subExpression,size_t & i)214e7725610SArun Lal K M     bool getSubExpression(const std::string& expression,
215e7725610SArun Lal K M                           std::string& subExpression, size_t& i)
216e7725610SArun Lal K M     {
217e7725610SArun Lal K M         int level = 1;
218e7725610SArun Lal K M         subExpression.clear();
219e7725610SArun Lal K M 
220e7725610SArun Lal K M         for (; i < expression.length(); i++)
221e7725610SArun Lal K M         {
222e7725610SArun Lal K M             if (expression[i] == '(')
223e7725610SArun Lal K M             {
224e7725610SArun Lal K M                 ++level;
225e7725610SArun Lal K M             }
226e7725610SArun Lal K M             else if (expression[i] == ')')
227e7725610SArun Lal K M             {
228e7725610SArun Lal K M                 --level;
229e7725610SArun Lal K M                 if (level == 0)
230e7725610SArun Lal K M                 {
231e7725610SArun Lal K M                     break;
232e7725610SArun Lal K M                 }
233e7725610SArun Lal K M             }
234e7725610SArun Lal K M 
235e7725610SArun Lal K M             subExpression.push_back(expression[i]);
236e7725610SArun Lal K M         }
237e7725610SArun Lal K M 
238e7725610SArun Lal K M         if (!subExpression.empty())
239e7725610SArun Lal K M         {
240e7725610SArun Lal K M             return true;
241e7725610SArun Lal K M         }
242e7725610SArun Lal K M 
243e7725610SArun Lal K M         return false;
244e7725610SArun Lal K M     }
245e7725610SArun Lal K M 
246e7725610SArun Lal K M     /* Function to handle operator '_LIST_'
247e7725610SArun Lal K M      * Convert a '_LIST_' expression to a normal expression
248e7725610SArun Lal K M      * Example "_LIST_ VariableA _EQU_ 0 1" is converted to "VariableA _EQU_ 0
249e7725610SArun Lal K M      * OR VariableA _EQU_ 1" */
getListExpression(const std::string & expression,std::string & subExpression,size_t & i)250e7725610SArun Lal K M     bool getListExpression(const std::string& expression,
251e7725610SArun Lal K M                            std::string& subExpression, size_t& i)
252e7725610SArun Lal K M     {
253e7725610SArun Lal K M         subExpression.clear();
254e7725610SArun Lal K M 
255e7725610SArun Lal K M         int cnt = 0;
256e7725610SArun Lal K M         std::string variableStr;
257e7725610SArun Lal K M         std::string operatorStr;
258e7725610SArun Lal K M 
259e7725610SArun Lal K M         for (; i < expression.length(); i++)
260e7725610SArun Lal K M         {
261e7725610SArun Lal K M             if (expression[i] == '(')
262e7725610SArun Lal K M             {
263e7725610SArun Lal K M                 return false;
264e7725610SArun Lal K M             }
265e7725610SArun Lal K M             else if (expression[i] == ')')
266e7725610SArun Lal K M             {
267e7725610SArun Lal K M                 break;
268e7725610SArun Lal K M             }
269e7725610SArun Lal K M             else if (expression[i] == ' ')
270e7725610SArun Lal K M             {
271e7725610SArun Lal K M                 /* whitespace */
272e7725610SArun Lal K M                 continue;
273e7725610SArun Lal K M             }
274e7725610SArun Lal K M             else
275e7725610SArun Lal K M             {
276e7725610SArun Lal K M                 std::string word;
277e7725610SArun Lal K M 
278e7725610SArun Lal K M                 /* Get the next word in expression string */
279e7725610SArun Lal K M                 while ((i < expression.length()) && (expression[i] != ' '))
280e7725610SArun Lal K M                 {
281e7725610SArun Lal K M                     word.push_back(expression[i++]);
282e7725610SArun Lal K M                 }
283e7725610SArun Lal K M 
284e7725610SArun Lal K M                 if (word == "_OR_" || word == "OR" || word == "_AND_" ||
285e7725610SArun Lal K M                     word == "AND" || word == "NOT")
286e7725610SArun Lal K M                 {
287e7725610SArun Lal K M                     i = i - word.length();
288e7725610SArun Lal K M                     break;
289e7725610SArun Lal K M                 }
290e7725610SArun Lal K M 
291e7725610SArun Lal K M                 ++cnt;
292e7725610SArun Lal K M 
293e7725610SArun Lal K M                 if (cnt == 1)
294e7725610SArun Lal K M                 {
295e7725610SArun Lal K M                     variableStr = word;
296e7725610SArun Lal K M                 }
297e7725610SArun Lal K M                 else if (cnt == 2)
298e7725610SArun Lal K M                 {
299e7725610SArun Lal K M                     operatorStr = word;
300e7725610SArun Lal K M                 }
301e7725610SArun Lal K M                 else
302e7725610SArun Lal K M                 {
303e7725610SArun Lal K M                     if (cnt > 3)
304e7725610SArun Lal K M                     {
305*16bbc6bdSJatkiewicz, Joanna                         if (operatorStr == "_EQU_" || operatorStr == "EQU")
306*16bbc6bdSJatkiewicz, Joanna                         {
307e7725610SArun Lal K M                             subExpression += " OR ";
308e7725610SArun Lal K M                         }
309*16bbc6bdSJatkiewicz, Joanna                         if (operatorStr == "_NEQ_" || operatorStr == "NEQ")
310*16bbc6bdSJatkiewicz, Joanna                         {
311*16bbc6bdSJatkiewicz, Joanna                             subExpression += " AND ";
312*16bbc6bdSJatkiewicz, Joanna                         }
313*16bbc6bdSJatkiewicz, Joanna                     }
314e7725610SArun Lal K M 
315e7725610SArun Lal K M                     subExpression += "( ";
316e7725610SArun Lal K M                     subExpression += variableStr;
317e7725610SArun Lal K M                     subExpression += " ";
318e7725610SArun Lal K M                     subExpression += operatorStr;
319e7725610SArun Lal K M                     subExpression += " ";
320e7725610SArun Lal K M                     subExpression += word;
321e7725610SArun Lal K M                     subExpression += " )";
322e7725610SArun Lal K M                 }
323e7725610SArun Lal K M             }
324e7725610SArun Lal K M         }
325e7725610SArun Lal K M 
326e7725610SArun Lal K M         if (!subExpression.empty())
327e7725610SArun Lal K M         {
328e7725610SArun Lal K M             return true;
329e7725610SArun Lal K M         }
330e7725610SArun Lal K M 
331e7725610SArun Lal K M         return false;
332e7725610SArun Lal K M     }
333e7725610SArun Lal K M 
334e7725610SArun Lal K M     /* Function to handle operator 'NOT'
335e7725610SArun Lal K M      * 1) Find the variable
336e7725610SArun Lal K M      * 2) apply NOT on the variable */
getNotValue(const std::string & expression,size_t & i,int & value)337e7725610SArun Lal K M     bool getNotValue(const std::string& expression, size_t& i, int& value)
338e7725610SArun Lal K M     {
339e7725610SArun Lal K M         std::string word;
340e7725610SArun Lal K M 
341e7725610SArun Lal K M         for (; i < expression.length(); i++)
342e7725610SArun Lal K M         {
343e7725610SArun Lal K M             if (expression[i] == ' ')
344e7725610SArun Lal K M             {
345e7725610SArun Lal K M                 /* whitespace */
346e7725610SArun Lal K M                 continue;
347e7725610SArun Lal K M             }
348e7725610SArun Lal K M             else
349e7725610SArun Lal K M             {
350e7725610SArun Lal K M                 /* Get the next word in expression string */
351e7725610SArun Lal K M                 while ((i < expression.length()) && (expression[i] != ' '))
352e7725610SArun Lal K M                 {
353e7725610SArun Lal K M                     word.push_back(expression[i++]);
354e7725610SArun Lal K M                 }
355e7725610SArun Lal K M 
356e7725610SArun Lal K M                 break;
357e7725610SArun Lal K M             }
358e7725610SArun Lal K M         }
359e7725610SArun Lal K M 
360e7725610SArun Lal K M         if (!word.empty())
361e7725610SArun Lal K M         {
362e7725610SArun Lal K M             if (getValue(word, value))
363e7725610SArun Lal K M             {
364e7725610SArun Lal K M                 value = !value;
365e7725610SArun Lal K M                 return true;
366e7725610SArun Lal K M             }
367e7725610SArun Lal K M         }
368e7725610SArun Lal K M 
369e7725610SArun Lal K M         return false;
370e7725610SArun Lal K M     }
371e7725610SArun Lal K M 
372e7725610SArun Lal K M     /* 1) Pop one operator from operator stack, example 'OR'
373e7725610SArun Lal K M      * 2) Pop two variable from variable stack, example VarA and VarB
374e7725610SArun Lal K M      * 3) Push back result of 'VarA OR VarB' to variable stack
375e7725610SArun Lal K M      * 4) Repeat till operator stack is empty
376e7725610SArun Lal K M      *
377e7725610SArun Lal K M      * The last variable in variable stack is the output of the expression. */
evaluateExprStack(std::stack<int> & values,std::stack<knob::DepexOperators> & operators,int & output)378e7725610SArun Lal K M     bool evaluateExprStack(std::stack<int>& values,
379e7725610SArun Lal K M                            std::stack<knob::DepexOperators>& operators,
380e7725610SArun Lal K M                            int& output)
381e7725610SArun Lal K M     {
382e7725610SArun Lal K M         if (values.size() != (operators.size() + 1))
383e7725610SArun Lal K M         {
384e7725610SArun Lal K M             return false;
385e7725610SArun Lal K M         }
386e7725610SArun Lal K M 
387e7725610SArun Lal K M         while (!operators.empty())
388e7725610SArun Lal K M         {
389e7725610SArun Lal K M             int b = values.top();
390e7725610SArun Lal K M             values.pop();
391e7725610SArun Lal K M 
392e7725610SArun Lal K M             int a = values.top();
393e7725610SArun Lal K M             values.pop();
394e7725610SArun Lal K M 
395e7725610SArun Lal K M             switch (operators.top())
396e7725610SArun Lal K M             {
397e7725610SArun Lal K M                 case knob::DepexOperators::OR:
398e7725610SArun Lal K M                     values.emplace(a | b);
399e7725610SArun Lal K M                     break;
400e7725610SArun Lal K M 
401e7725610SArun Lal K M                 case knob::DepexOperators::AND:
402e7725610SArun Lal K M                     values.emplace(a & b);
403e7725610SArun Lal K M                     break;
404e7725610SArun Lal K M 
405e7725610SArun Lal K M                 case knob::DepexOperators::EQU:
406e7725610SArun Lal K M                     if (a == b)
407e7725610SArun Lal K M                     {
408e7725610SArun Lal K M                         values.emplace(1);
409e7725610SArun Lal K M                         break;
410e7725610SArun Lal K M                     }
411e7725610SArun Lal K M 
412e7725610SArun Lal K M                     values.emplace(0);
413e7725610SArun Lal K M                     break;
414e7725610SArun Lal K M 
415e7725610SArun Lal K M                 case knob::DepexOperators::NEQ:
416e7725610SArun Lal K M                     if (a != b)
417e7725610SArun Lal K M                     {
418e7725610SArun Lal K M                         values.emplace(1);
419e7725610SArun Lal K M                         break;
420e7725610SArun Lal K M                     }
421e7725610SArun Lal K M 
422e7725610SArun Lal K M                     values.emplace(0);
423e7725610SArun Lal K M                     break;
424e7725610SArun Lal K M 
425e7725610SArun Lal K M                 case knob::DepexOperators::LTE:
426e7725610SArun Lal K M                     if (a <= b)
427e7725610SArun Lal K M                     {
428e7725610SArun Lal K M                         values.emplace(1);
429e7725610SArun Lal K M                         break;
430e7725610SArun Lal K M                     }
431e7725610SArun Lal K M 
432e7725610SArun Lal K M                     values.emplace(0);
433e7725610SArun Lal K M                     break;
434e7725610SArun Lal K M 
435e7725610SArun Lal K M                 case knob::DepexOperators::LT:
436e7725610SArun Lal K M                     if (a < b)
437e7725610SArun Lal K M                     {
438e7725610SArun Lal K M                         values.emplace(1);
439e7725610SArun Lal K M                         break;
440e7725610SArun Lal K M                     }
441e7725610SArun Lal K M 
442e7725610SArun Lal K M                     values.emplace(0);
443e7725610SArun Lal K M                     break;
444e7725610SArun Lal K M 
445e83c70aaSArun Lal K M                 case knob::DepexOperators::GTE:
446e83c70aaSArun Lal K M                     if (a >= b)
447e83c70aaSArun Lal K M                     {
448e83c70aaSArun Lal K M                         values.emplace(1);
449e83c70aaSArun Lal K M                         break;
450e83c70aaSArun Lal K M                     }
451e83c70aaSArun Lal K M 
452e83c70aaSArun Lal K M                     values.emplace(0);
453e83c70aaSArun Lal K M                     break;
454e83c70aaSArun Lal K M 
455e83c70aaSArun Lal K M                 case knob::DepexOperators::GT:
456e83c70aaSArun Lal K M                     if (a > b)
457e83c70aaSArun Lal K M                     {
458e83c70aaSArun Lal K M                         values.emplace(1);
459e83c70aaSArun Lal K M                         break;
460e83c70aaSArun Lal K M                     }
461e83c70aaSArun Lal K M 
462e83c70aaSArun Lal K M                     values.emplace(0);
463e83c70aaSArun Lal K M                     break;
464e83c70aaSArun Lal K M 
465e7725610SArun Lal K M                 case knob::DepexOperators::MODULO:
466e7725610SArun Lal K M                     if (b == 0)
467e7725610SArun Lal K M                     {
468e7725610SArun Lal K M                         return false;
469e7725610SArun Lal K M                     }
470e7725610SArun Lal K M                     values.emplace(a % b);
471e7725610SArun Lal K M                     break;
472e7725610SArun Lal K M 
473e7725610SArun Lal K M                 default:
474e7725610SArun Lal K M                     return false;
475e7725610SArun Lal K M             }
476e7725610SArun Lal K M 
477e7725610SArun Lal K M             operators.pop();
478e7725610SArun Lal K M         }
479e7725610SArun Lal K M 
480e7725610SArun Lal K M         if (values.size() == 1)
481e7725610SArun Lal K M         {
482e7725610SArun Lal K M             output = values.top();
483e7725610SArun Lal K M             values.pop();
484e7725610SArun Lal K M 
485e7725610SArun Lal K M             return true;
486e7725610SArun Lal K M         }
487e7725610SArun Lal K M 
488e7725610SArun Lal K M         return false;
489e7725610SArun Lal K M     }
490e7725610SArun Lal K M 
491e7725610SArun Lal K M     /* Evaluvate one 'depex' expression
492e7725610SArun Lal K M      * 1) Find a word in expression string
493e7725610SArun Lal K M      * 2) If word is a variable push to variable stack
494e7725610SArun Lal K M      * 3) If word is a operator push to operator stack
495e7725610SArun Lal K M      *
496e7725610SArun Lal K M      * Execute the stack at end to get the result of expression. */
evaluateExpression(const std::string & expression,int & output)497e7725610SArun Lal K M     bool evaluateExpression(const std::string& expression, int& output)
498e7725610SArun Lal K M     {
499e7725610SArun Lal K M         if (expression.empty())
500e7725610SArun Lal K M         {
501e7725610SArun Lal K M             return false;
502e7725610SArun Lal K M         }
503e7725610SArun Lal K M 
504e7725610SArun Lal K M         size_t i;
505e7725610SArun Lal K M         int value;
506*16bbc6bdSJatkiewicz, Joanna         bool ifFormSetOperator = false;
507e7725610SArun Lal K M         std::stack<int> values;
508e7725610SArun Lal K M         std::stack<knob::DepexOperators> operators;
509e7725610SArun Lal K M         std::string subExpression;
510e7725610SArun Lal K M 
511e7725610SArun Lal K M         for (i = 0; i < expression.length(); i++)
512e7725610SArun Lal K M         {
513e7725610SArun Lal K M             if (expression[i] == ' ')
514e7725610SArun Lal K M             {
515e7725610SArun Lal K M                 /* whitespace */
516e7725610SArun Lal K M                 continue;
517e7725610SArun Lal K M             }
518e7725610SArun Lal K M             else
519e7725610SArun Lal K M             {
520e7725610SArun Lal K M                 std::string word;
521e7725610SArun Lal K M 
522e7725610SArun Lal K M                 /* Get the next word in expression string */
523e7725610SArun Lal K M                 while ((i < expression.length()) && (expression[i] != ' '))
524e7725610SArun Lal K M                 {
525e7725610SArun Lal K M                     word.push_back(expression[i++]);
526e7725610SArun Lal K M                 }
527e7725610SArun Lal K M 
528e7725610SArun Lal K M                 if (word == "_OR_" || word == "OR")
529e7725610SArun Lal K M                 {
530e7725610SArun Lal K M                     /* OR and AND has more precedence than other operators
531e7725610SArun Lal K M                      * To handle statements like "a != b or c != d"
532e7725610SArun Lal K M                      * we need to execute, for above example, both '!=' before
533e7725610SArun Lal K M                      * 'or' */
534e7725610SArun Lal K M                     if (!operators.empty())
535e7725610SArun Lal K M                     {
536e7725610SArun Lal K M                         if (!evaluateExprStack(values, operators, value))
537e7725610SArun Lal K M                         {
538e7725610SArun Lal K M                             return false;
539e7725610SArun Lal K M                         }
540e7725610SArun Lal K M 
541e7725610SArun Lal K M                         values.emplace(value);
542e7725610SArun Lal K M                     }
543e7725610SArun Lal K M 
544e7725610SArun Lal K M                     operators.emplace(knob::DepexOperators::OR);
545e7725610SArun Lal K M                 }
546e7725610SArun Lal K M                 else if (word == "_AND_" || word == "AND")
547e7725610SArun Lal K M                 {
548e7725610SArun Lal K M                     /* OR and AND has more precedence than other operators
549e7725610SArun Lal K M                      * To handle statements like "a == b and c == d"
550e7725610SArun Lal K M                      * we need to execute, for above example, both '==' before
551e7725610SArun Lal K M                      * 'and' */
552e7725610SArun Lal K M                     if (!operators.empty())
553e7725610SArun Lal K M                     {
554e7725610SArun Lal K M                         if (!evaluateExprStack(values, operators, value))
555e7725610SArun Lal K M                         {
556e7725610SArun Lal K M                             return false;
557e7725610SArun Lal K M                         }
558e7725610SArun Lal K M 
559e7725610SArun Lal K M                         values.emplace(value);
560e7725610SArun Lal K M                     }
561e7725610SArun Lal K M 
562e7725610SArun Lal K M                     operators.emplace(knob::DepexOperators::AND);
563e7725610SArun Lal K M                 }
564e7725610SArun Lal K M                 else if (word == "_LTE_")
565e7725610SArun Lal K M                 {
566e7725610SArun Lal K M                     operators.emplace(knob::DepexOperators::LTE);
567e7725610SArun Lal K M                 }
568e7725610SArun Lal K M                 else if (word == "_LT_")
569e7725610SArun Lal K M                 {
570e7725610SArun Lal K M                     operators.emplace(knob::DepexOperators::LT);
571e7725610SArun Lal K M                 }
572e83c70aaSArun Lal K M                 else if (word == "_GTE_")
573e83c70aaSArun Lal K M                 {
574e83c70aaSArun Lal K M                     operators.emplace(knob::DepexOperators::GTE);
575e83c70aaSArun Lal K M                 }
576e83c70aaSArun Lal K M                 else if (word == "_GT_")
577e83c70aaSArun Lal K M                 {
578e83c70aaSArun Lal K M                     operators.emplace(knob::DepexOperators::GT);
579e83c70aaSArun Lal K M                 }
580e7725610SArun Lal K M                 else if (word == "_NEQ_")
581e7725610SArun Lal K M                 {
582e7725610SArun Lal K M                     operators.emplace(knob::DepexOperators::NEQ);
583e7725610SArun Lal K M                 }
584e7725610SArun Lal K M                 else if (word == "_EQU_")
585e7725610SArun Lal K M                 {
586e7725610SArun Lal K M                     operators.emplace(knob::DepexOperators::EQU);
587e7725610SArun Lal K M                 }
588e7725610SArun Lal K M                 else if (word == "%")
589e7725610SArun Lal K M                 {
590e7725610SArun Lal K M                     operators.emplace(knob::DepexOperators::MODULO);
591e7725610SArun Lal K M                 }
592e7725610SArun Lal K M                 else
593e7725610SArun Lal K M                 {
594e7725610SArun Lal K M                     /* Handle 'Sif(', 'Gif(', 'Dif(' and '('
595e7725610SArun Lal K M                      * by taking the inner/sub expression and evaluating it */
596e7725610SArun Lal K M                     if (word.back() == '(')
597e7725610SArun Lal K M                     {
598*16bbc6bdSJatkiewicz, Joanna                         if (word == "Sif(" || word == "Gif(" || word == "Dif(")
599*16bbc6bdSJatkiewicz, Joanna                         {
600*16bbc6bdSJatkiewicz, Joanna                             ifFormSetOperator = true;
601*16bbc6bdSJatkiewicz, Joanna                         }
602e7725610SArun Lal K M                         if (!getSubExpression(expression, subExpression, i))
603e7725610SArun Lal K M                             break;
604e7725610SArun Lal K M 
605e7725610SArun Lal K M                         if (!evaluateExpression(subExpression, value))
606e7725610SArun Lal K M                             break;
607e7725610SArun Lal K M                     }
608e7725610SArun Lal K M                     else if (word == "_LIST_")
609e7725610SArun Lal K M                     {
610e7725610SArun Lal K M                         if (!getListExpression(expression, subExpression, i))
611e7725610SArun Lal K M                             break;
612e7725610SArun Lal K M 
613e7725610SArun Lal K M                         --i;
614e7725610SArun Lal K M 
615e7725610SArun Lal K M                         if (!evaluateExpression(subExpression, value))
616e7725610SArun Lal K M                             break;
617e7725610SArun Lal K M                     }
618e7725610SArun Lal K M                     else if (word == "NOT")
619e7725610SArun Lal K M                     {
620e7725610SArun Lal K M                         if (!getNotValue(expression, i, value))
621e7725610SArun Lal K M                             break;
622e7725610SArun Lal K M                     }
623e7725610SArun Lal K M                     else if (isNumber(word) || isHexNotation(word))
624e7725610SArun Lal K M                     {
625e7725610SArun Lal K M                         try
626e7725610SArun Lal K M                         {
627*16bbc6bdSJatkiewicz, Joanna                             value = std::stoi(word, nullptr, 0);
628e7725610SArun Lal K M                         }
629bd51e6a9SPatrick Williams                         catch (const std::exception& ex)
630e7725610SArun Lal K M                         {
631e7725610SArun Lal K M                             phosphor::logging::log<
632e7725610SArun Lal K M                                 phosphor::logging::level::ERR>(ex.what());
633e7725610SArun Lal K M                             return false;
634e7725610SArun Lal K M                         }
635e7725610SArun Lal K M                     }
636e7725610SArun Lal K M                     else
637e7725610SArun Lal K M                     {
638e7725610SArun Lal K M                         if (!getValue(word, value))
639e7725610SArun Lal K M                             break;
640e7725610SArun Lal K M                     }
641e7725610SArun Lal K M 
642*16bbc6bdSJatkiewicz, Joanna                     /* 'Sif(', 'Gif(', 'Dif( == IF NOT,
643*16bbc6bdSJatkiewicz, Joanna                     we have to negate the vaule */
644*16bbc6bdSJatkiewicz, Joanna                     if (ifFormSetOperator == true)
645*16bbc6bdSJatkiewicz, Joanna                     {
646*16bbc6bdSJatkiewicz, Joanna                         value = !value;
647*16bbc6bdSJatkiewicz, Joanna                     }
648e7725610SArun Lal K M                     values.emplace(value);
649e7725610SArun Lal K M                 }
650e7725610SArun Lal K M             }
651e7725610SArun Lal K M         }
652e7725610SArun Lal K M 
653e7725610SArun Lal K M         if (i == expression.length())
654e7725610SArun Lal K M         {
655e7725610SArun Lal K M             if (evaluateExprStack(values, operators, output))
656e7725610SArun Lal K M             {
657e7725610SArun Lal K M                 return true;
658e7725610SArun Lal K M             }
659e7725610SArun Lal K M         }
660e7725610SArun Lal K M 
661e7725610SArun Lal K M         return false;
662e7725610SArun Lal K M     }
663e7725610SArun Lal K M 
664e7725610SArun Lal K M   private:
665e7725610SArun Lal K M     /* To store all 'knob's in 'biosknobs' */
666e7725610SArun Lal K M     std::vector<knob::knob>& mKnobs;
667e7725610SArun Lal K M 
668e7725610SArun Lal K M     /* To store all bad 'depex' expression */
669e7725610SArun Lal K M     std::vector<std::string> mError;
670e7725610SArun Lal K M };
671e7725610SArun Lal K M 
672e7725610SArun Lal K M class Xml
673e7725610SArun Lal K M {
674e7725610SArun Lal K M   public:
Xml(const char * filePath)675e7725610SArun Lal K M     Xml(const char* filePath) : mDepex(std::make_unique<Depex>(mKnobs))
676e7725610SArun Lal K M     {
677e7725610SArun Lal K M         if (!getKnobs(filePath))
678e7725610SArun Lal K M         {
679b37abfb2SPatrick Williams             std::string error = "Unable to get knobs in file: " +
680b37abfb2SPatrick Williams                                 std::string(filePath);
681e7725610SArun Lal K M             throw std::runtime_error(error);
682e7725610SArun Lal K M         }
683e7725610SArun Lal K M     }
684e7725610SArun Lal K M 
685e7725610SArun Lal K M     /* Fill Bios table with all 'knob's which have output of 'depex' expression
686e7725610SArun Lal K M      * as 'true' */
getBaseTable(bios::BiosBaseTableType & baseTable)687e7725610SArun Lal K M     bool getBaseTable(bios::BiosBaseTableType& baseTable)
688e7725610SArun Lal K M     {
689e7725610SArun Lal K M         baseTable.clear();
690e7725610SArun Lal K M 
691e7725610SArun Lal K M         for (auto& knob : mKnobs)
692e7725610SArun Lal K M         {
693e7725610SArun Lal K M             if (knob.depex)
694e7725610SArun Lal K M             {
695e7725610SArun Lal K M                 std::string text =
696e7725610SArun Lal K M                     "xyz.openbmc_project.BIOSConfig.Manager.BoundType.OneOf";
697e7725610SArun Lal K M                 bios::OptionTypeVector options;
698e7725610SArun Lal K M 
699e7725610SArun Lal K M                 for (auto& option : knob.options)
700e7725610SArun Lal K M                 {
7017a8ab9eeSArun Lal K M                     options.emplace_back(text, option.value, option.text);
702e7725610SArun Lal K M                 }
703e7725610SArun Lal K M 
704e7725610SArun Lal K M                 bios::BiosBaseTableTypeEntry baseTableEntry = std::make_tuple(
705e7725610SArun Lal K M                     "xyz.openbmc_project.BIOSConfig.Manager.AttributeType."
706d2d60ab5SArun Lal K M                     "Enumeration",
7071eb3d64cSArun Lal K M                     false, knob.promptStr, knob.descriptionStr, "./",
708e7725610SArun Lal K M                     knob.currentValStr, knob.defaultStr, options);
709e7725610SArun Lal K M 
710e7725610SArun Lal K M                 baseTable.emplace(knob.nameStr, baseTableEntry);
711e7725610SArun Lal K M             }
712e7725610SArun Lal K M         }
713e7725610SArun Lal K M 
714e7725610SArun Lal K M         if (!baseTable.empty())
715e7725610SArun Lal K M         {
716e7725610SArun Lal K M             return true;
717e7725610SArun Lal K M         }
718e7725610SArun Lal K M 
719e7725610SArun Lal K M         return false;
720e7725610SArun Lal K M     }
721e7725610SArun Lal K M 
722e7725610SArun Lal K M     /* Execute all 'depex' expression */
doDepexCompute()723e7725610SArun Lal K M     bool doDepexCompute()
724e7725610SArun Lal K M     {
725e7725610SArun Lal K M         mDepex->compute();
726e7725610SArun Lal K M 
727e7725610SArun Lal K M         if (mDepex->getErrorCount())
728e7725610SArun Lal K M         {
729e7725610SArun Lal K M             mDepex->printError();
730e7725610SArun Lal K M             return false;
731e7725610SArun Lal K M         }
732e7725610SArun Lal K M 
733e7725610SArun Lal K M         return true;
734e7725610SArun Lal K M     }
735e7725610SArun Lal K M 
736e7725610SArun Lal K M   private:
737e7725610SArun Lal K M     /* Get 'option' */
getOption(tinyxml2::XMLElement * pOption)738e7725610SArun Lal K M     void getOption(tinyxml2::XMLElement* pOption)
739e7725610SArun Lal K M     {
740e7725610SArun Lal K M         if (pOption)
741e7725610SArun Lal K M         {
742e7725610SArun Lal K M             std::string valueStr;
743e7725610SArun Lal K M             std::string textStr;
744e7725610SArun Lal K M 
745e7725610SArun Lal K M             if (pOption->Attribute("text"))
746e7725610SArun Lal K M                 valueStr = pOption->Attribute("text");
747e7725610SArun Lal K M 
748e7725610SArun Lal K M             if (pOption->Attribute("value"))
749e7725610SArun Lal K M                 textStr = pOption->Attribute("value");
750e7725610SArun Lal K M 
751e7725610SArun Lal K M             mKnobs.back().options.emplace_back(pOption->Attribute("text"),
752e7725610SArun Lal K M                                                pOption->Attribute("value"));
753e7725610SArun Lal K M         }
754e7725610SArun Lal K M     }
755e7725610SArun Lal K M 
756e7725610SArun Lal K M     /* Get 'options' */
getOptions(tinyxml2::XMLElement * pKnob)757e7725610SArun Lal K M     void getOptions(tinyxml2::XMLElement* pKnob)
758e7725610SArun Lal K M     {
759e7725610SArun Lal K M         uint16_t reserveCnt = 0;
760e7725610SArun Lal K M 
761e7725610SArun Lal K M         /* Get node options inside knob */
762e7725610SArun Lal K M         tinyxml2::XMLElement* pOptions = pKnob->FirstChildElement("options");
763e7725610SArun Lal K M 
764e7725610SArun Lal K M         if (pOptions)
765e7725610SArun Lal K M         {
766e7725610SArun Lal K M             for (tinyxml2::XMLElement* pOption =
767e7725610SArun Lal K M                      pOptions->FirstChildElement("option");
768e7725610SArun Lal K M                  pOption; pOption = pOption->NextSiblingElement("option"))
769e7725610SArun Lal K M             {
770e7725610SArun Lal K M                 ++reserveCnt;
771e7725610SArun Lal K M             }
772e7725610SArun Lal K M 
773e7725610SArun Lal K M             mKnobs.back().options.reserve(reserveCnt);
774e7725610SArun Lal K M 
775e7725610SArun Lal K M             /* Loop through all option inside options */
776e7725610SArun Lal K M             for (tinyxml2::XMLElement* pOption =
777e7725610SArun Lal K M                      pOptions->FirstChildElement("option");
778e7725610SArun Lal K M                  pOption; pOption = pOption->NextSiblingElement("option"))
779e7725610SArun Lal K M             {
780e7725610SArun Lal K M                 getOption(pOption);
781e7725610SArun Lal K M             }
782e7725610SArun Lal K M         }
783e7725610SArun Lal K M     }
784e7725610SArun Lal K M 
785e7725610SArun Lal K M     /* Get 'knob' */
getKnob(tinyxml2::XMLElement * pKnob)786e7725610SArun Lal K M     void getKnob(tinyxml2::XMLElement* pKnob)
787e7725610SArun Lal K M     {
788e7725610SArun Lal K M         if (pKnob)
789e7725610SArun Lal K M         {
790e7725610SArun Lal K M             int currentVal = 0;
791e7725610SArun Lal K M             std::string nameStr;
792e7725610SArun Lal K M             std::string currentValStr;
793e7725610SArun Lal K M             std::string descriptionStr;
794e7725610SArun Lal K M             std::string defaultStr;
795e7725610SArun Lal K M             std::string depexStr;
796e7725610SArun Lal K M             std::string promptStr;
797e7725610SArun Lal K M             std::string setupTypeStr;
798e7725610SArun Lal K M 
799e7725610SArun Lal K M             if (!pKnob->Attribute("name") || !pKnob->Attribute("CurrentVal"))
800e7725610SArun Lal K M             {
801e7725610SArun Lal K M                 return;
802e7725610SArun Lal K M             }
803e7725610SArun Lal K M 
804e7725610SArun Lal K M             nameStr = pKnob->Attribute("name");
805e7725610SArun Lal K M             currentValStr = pKnob->Attribute("CurrentVal");
806713928b9SSnehalatha Venkatesh             std::stringstream ss;
807713928b9SSnehalatha Venkatesh             ss << std::hex << currentValStr;
808713928b9SSnehalatha Venkatesh             if (ss.good())
809e7725610SArun Lal K M             {
810713928b9SSnehalatha Venkatesh                 ss >> currentVal;
811e7725610SArun Lal K M             }
812713928b9SSnehalatha Venkatesh             else
813e7725610SArun Lal K M             {
814713928b9SSnehalatha Venkatesh                 std::string error = "Invalid hex value input " + currentValStr +
815713928b9SSnehalatha Venkatesh                                     " for " + nameStr + "\n";
816e7725610SArun Lal K M                 phosphor::logging::log<phosphor::logging::level::ERR>(
817713928b9SSnehalatha Venkatesh                     error.c_str());
818e7725610SArun Lal K M                 return;
819e7725610SArun Lal K M             }
820e7725610SArun Lal K M             if (pKnob->Attribute("description"))
821e7725610SArun Lal K M                 descriptionStr = pKnob->Attribute("description");
822e7725610SArun Lal K M 
823e7725610SArun Lal K M             if (pKnob->Attribute("default"))
824e7725610SArun Lal K M                 defaultStr = pKnob->Attribute("default");
825e7725610SArun Lal K M 
826e7725610SArun Lal K M             if (pKnob->Attribute("depex"))
827e7725610SArun Lal K M                 depexStr = pKnob->Attribute("depex");
828e7725610SArun Lal K M 
829e7725610SArun Lal K M             if (pKnob->Attribute("prompt"))
830e7725610SArun Lal K M                 promptStr = pKnob->Attribute("prompt");
831e7725610SArun Lal K M 
832e7725610SArun Lal K M             if (pKnob->Attribute("setupType"))
833e7725610SArun Lal K M                 setupTypeStr = pKnob->Attribute("setupType");
834e7725610SArun Lal K M 
835e7725610SArun Lal K M             mKnobs.emplace_back(nameStr, currentValStr, currentVal,
836e7725610SArun Lal K M                                 descriptionStr, defaultStr, promptStr, depexStr,
837e7725610SArun Lal K M                                 setupTypeStr);
838e7725610SArun Lal K M 
839e7725610SArun Lal K M             getOptions(pKnob);
840e7725610SArun Lal K M         }
841e7725610SArun Lal K M     }
842e7725610SArun Lal K M 
843e7725610SArun Lal K M     /* Get 'biosknobs' */
getKnobs(const char * biosXmlFilePath)844e7725610SArun Lal K M     bool getKnobs(const char* biosXmlFilePath)
845e7725610SArun Lal K M     {
846e7725610SArun Lal K M         uint16_t reserveCnt = 0;
847e7725610SArun Lal K M 
848e7725610SArun Lal K M         mKnobs.clear();
849e7725610SArun Lal K M 
850e7725610SArun Lal K M         tinyxml2::XMLDocument biosXml;
851e7725610SArun Lal K M 
852e7725610SArun Lal K M         /* Load the XML file into the Doc instance */
853e7725610SArun Lal K M         biosXml.LoadFile(biosXmlFilePath);
854e7725610SArun Lal K M 
855e7725610SArun Lal K M         /* Get 'SYSTEM' */
856e7725610SArun Lal K M         tinyxml2::XMLElement* pRootElement = biosXml.RootElement();
857e7725610SArun Lal K M         if (pRootElement)
858e7725610SArun Lal K M         {
859e7725610SArun Lal K M             /* Get 'biosknobs' inside 'SYSTEM' */
860e7725610SArun Lal K M             tinyxml2::XMLElement* pBiosknobs =
861e7725610SArun Lal K M                 pRootElement->FirstChildElement("biosknobs");
862e7725610SArun Lal K M             if (pBiosknobs)
863e7725610SArun Lal K M             {
864e7725610SArun Lal K M                 for (tinyxml2::XMLElement* pKnob =
865e7725610SArun Lal K M                          pBiosknobs->FirstChildElement("knob");
866e7725610SArun Lal K M                      pKnob; pKnob = pKnob->NextSiblingElement("knob"))
867e7725610SArun Lal K M                 {
868e7725610SArun Lal K M                     ++reserveCnt;
869e7725610SArun Lal K M                 }
870e7725610SArun Lal K M 
871e7725610SArun Lal K M                 /* reserve before emplace_back will avoids realloc(s) */
872e7725610SArun Lal K M                 mKnobs.reserve(reserveCnt);
873e7725610SArun Lal K M 
874e7725610SArun Lal K M                 for (tinyxml2::XMLElement* pKnob =
875e7725610SArun Lal K M                          pBiosknobs->FirstChildElement("knob");
876e7725610SArun Lal K M                      pKnob; pKnob = pKnob->NextSiblingElement("knob"))
877e7725610SArun Lal K M                 {
878e7725610SArun Lal K M                     getKnob(pKnob);
879e7725610SArun Lal K M                 }
880e7725610SArun Lal K M             }
881e7725610SArun Lal K M         }
882e7725610SArun Lal K M 
883e7725610SArun Lal K M         if (!mKnobs.empty())
884e7725610SArun Lal K M         {
885e7725610SArun Lal K M             return true;
886e7725610SArun Lal K M         }
887e7725610SArun Lal K M 
888e7725610SArun Lal K M         return false;
889e7725610SArun Lal K M     }
890e7725610SArun Lal K M 
891e7725610SArun Lal K M   private:
892e7725610SArun Lal K M     /* To store all 'knob's in 'biosknobs' */
893e7725610SArun Lal K M     std::vector<knob::knob> mKnobs;
894e7725610SArun Lal K M 
895e7725610SArun Lal K M     /* Object of Depex class to compute 'depex' expression */
896e7725610SArun Lal K M     std::unique_ptr<Depex> mDepex;
897e7725610SArun Lal K M };
898e7725610SArun Lal K M } // namespace bios
899