1 /**
2  * Copyright © 2017 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "util.hpp"
18 
19 #include <algorithm>
20 #include <map>
21 #include <string>
22 
23 using namespace std::literals::string_literals;
24 
25 template <typename T>
26 struct BusMeetsMSL
27 {
28     std::string path;
29 
30     BusMeetsMSL(const std::string& p) : path(p)
31     {
32     }
33 
34     auto operator()(const T& arg)
35     {
36         // Query each service hosting
37         // xyz.openbmc_project.Inventory.Decorator.MeetsMinimumShipLevel.
38 
39         const auto& busName = arg.first;
40         return util::sdbusplus::getProperty<bool>(
41             busName, path,
42             "xyz.openbmc_project.Inventory."
43             "Decorator.MeetsMinimumShipLevel"s,
44             "MeetsMinimumShipLevel"s);
45     }
46 };
47 
48 template <typename T>
49 struct PathMeetsMSL
50 {
51     auto operator()(const T& arg)
52     {
53         // A given path in the mapper response is composed of
54         // a map of services/interfaces.  Validate each service
55         // that hosts the MSL interface meets the MSL.
56 
57         const auto& path = arg.first;
58         return std::all_of(
59             arg.second.begin(), arg.second.end(),
60             BusMeetsMSL<typename decltype(arg.second)::value_type>(path));
61     }
62 };
63 
64 int main(void)
65 {
66     auto mslVerificationRequired = util::sdbusplus::getProperty<bool>(
67         "/xyz/openbmc_project/control/minimum_ship_level_required"s,
68         "xyz.openbmc_project.Control.MinimumShipLevel"s,
69         "MinimumShipLevelRequired"s);
70 
71     if (!mslVerificationRequired)
72     {
73         return 0;
74     }
75 
76     // Obtain references to all objects hosting
77     // xyz.openbmc_project.Inventory.Decorator.MeetsMinimumShipLevel
78     // with a mapper subtree query.  For each object, validate that
79     // the minimum ship level has been met.
80 
81     using SubTreeType =
82         std::map<std::string, std::map<std::string, std::vector<std::string>>>;
83 
84     auto subtree = util::sdbusplus::callMethodAndRead<SubTreeType>(
85         "xyz.openbmc_project.ObjectMapper"s,
86         "/xyz/openbmc_project/object_mapper"s,
87         "xyz.openbmc_project.ObjectMapper"s, "GetSubTree"s, "/"s, 0,
88         std::vector<std::string>{"xyz.openbmc_project.Inventory"
89                                  ".Decorator.MeetsMinimumShipLevel"s});
90 
91     auto result = std::all_of(subtree.begin(), subtree.end(),
92                               PathMeetsMSL<SubTreeType::value_type>());
93 
94     if (!result)
95     {
96         phosphor::logging::log<phosphor::logging::level::INFO>(
97             "The physical system configuration does not "
98             "satisfy the minimum ship level.");
99 
100         return 1;
101     }
102 
103     return 0;
104 }
105