1 #pragma once
2 
3 #include "async_resp.hpp"
4 #include "dbus_utility.hpp"
5 #include "error_messages.hpp"
6 #include "generated/enums/pcie_device.hpp"
7 #include "generated/enums/pcie_slots.hpp"
8 #include "http/utility.hpp"
9 
10 #include <boost/system/error_code.hpp>
11 #include <boost/url/format.hpp>
12 #include <nlohmann/json.hpp>
13 
14 #include <array>
15 #include <memory>
16 #include <optional>
17 #include <string>
18 #include <string_view>
19 
20 namespace redfish
21 {
22 namespace pcie_util
23 {
24 
25 /**
26  * @brief Populate the PCIe Device list from a GetSubTreePaths search of
27  *        inventory
28  *
29  * @param[i,o] asyncResp  Async response object
30  * @param[i]   Name   Key to store the list of PCIe devices in asyncResp
31  *
32  * @return void
33  */
34 
35 inline void
36     getPCIeDeviceList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
37                       const std::string& name)
38 {
39     static constexpr std::array<std::string_view, 1> pcieDeviceInterface = {
40         "xyz.openbmc_project.Inventory.Item.PCIeDevice"};
41 
42     dbus::utility::getSubTreePaths(
43         "/xyz/openbmc_project/inventory", 0, pcieDeviceInterface,
44         [asyncResp, name](const boost::system::error_code& ec,
45                           const dbus::utility::MapperGetSubTreePathsResponse&
46                               pcieDevicePaths) {
47         if (ec)
48         {
49             BMCWEB_LOG_DEBUG("no PCIe device paths found ec: {}", ec.message());
50             // Not an error, system just doesn't have PCIe info
51             return;
52         }
53         nlohmann::json& pcieDeviceList = asyncResp->res.jsonValue[name];
54         pcieDeviceList = nlohmann::json::array();
55         for (const std::string& pcieDevicePath : pcieDevicePaths)
56         {
57             size_t devStart = pcieDevicePath.rfind('/');
58             if (devStart == std::string::npos)
59             {
60                 continue;
61             }
62 
63             std::string devName = pcieDevicePath.substr(devStart + 1);
64             if (devName.empty())
65             {
66                 continue;
67             }
68             nlohmann::json::object_t pcieDevice;
69             pcieDevice["@odata.id"] = boost::urls::format(
70                 "/redfish/v1/Systems/system/PCIeDevices/{}", devName);
71             pcieDeviceList.emplace_back(std::move(pcieDevice));
72         }
73         asyncResp->res.jsonValue[name + "@odata.count"] = pcieDeviceList.size();
74     });
75 }
76 
77 inline std::optional<pcie_slots::SlotTypes>
78     dbusSlotTypeToRf(const std::string& slotType)
79 {
80     if (slotType ==
81         "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.FullLength")
82     {
83         return pcie_slots::SlotTypes::FullLength;
84     }
85     if (slotType ==
86         "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.HalfLength")
87     {
88         return pcie_slots::SlotTypes::HalfLength;
89     }
90     if (slotType ==
91         "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.LowProfile")
92     {
93         return pcie_slots::SlotTypes::LowProfile;
94     }
95     if (slotType ==
96         "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.Mini")
97     {
98         return pcie_slots::SlotTypes::Mini;
99     }
100     if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.M_2")
101     {
102         return pcie_slots::SlotTypes::M2;
103     }
104     if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OEM")
105     {
106         return pcie_slots::SlotTypes::OEM;
107     }
108     if (slotType ==
109         "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OCP3Small")
110     {
111         return pcie_slots::SlotTypes::OCP3Small;
112     }
113     if (slotType ==
114         "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.OCP3Large")
115     {
116         return pcie_slots::SlotTypes::OCP3Large;
117     }
118     if (slotType == "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.U_2")
119     {
120         return pcie_slots::SlotTypes::U2;
121     }
122     if (slotType ==
123         "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.Unknown")
124     {
125         return std::nullopt;
126     }
127 
128     return pcie_slots::SlotTypes::Invalid;
129 }
130 
131 inline std::optional<pcie_device::PCIeTypes>
132     redfishPcieGenerationFromDbus(const std::string& generationInUse)
133 {
134     if (generationInUse ==
135         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen1")
136     {
137         return pcie_device::PCIeTypes::Gen1;
138     }
139     if (generationInUse ==
140         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen2")
141     {
142         return pcie_device::PCIeTypes::Gen2;
143     }
144     if (generationInUse ==
145         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen3")
146     {
147         return pcie_device::PCIeTypes::Gen3;
148     }
149     if (generationInUse ==
150         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen4")
151     {
152         return pcie_device::PCIeTypes::Gen4;
153     }
154     if (generationInUse ==
155         "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5")
156     {
157         return pcie_device::PCIeTypes::Gen5;
158     }
159     if (generationInUse.empty() ||
160         generationInUse ==
161             "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Unknown")
162     {
163         return std::nullopt;
164     }
165 
166     return pcie_device::PCIeTypes::Invalid;
167 }
168 
169 } // namespace pcie_util
170 } // namespace redfish
171