xref: /openbmc/phosphor-ipmi-blobs/utils.cpp (revision c0fe5cd121948465a41adb69e29efdb0cd0e314b)
1 /*
2  * Copyright 2018 Google Inc.
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 "utils.hpp"
18 
19 #include <dlfcn.h>
20 
21 #include <blobs-ipmid/manager.hpp>
22 #include <experimental/filesystem>
23 #include <memory>
24 #include <phosphor-logging/log.hpp>
25 #include <regex>
26 
27 namespace blobs
28 {
29 
30 namespace fs = std::experimental::filesystem;
31 using namespace phosphor::logging;
32 
33 using HandlerFactory = std::unique_ptr<GenericBlobInterface> (*)();
34 
35 void loadLibraries(const std::string& path)
36 {
37     void* libHandle = NULL;
38     HandlerFactory factory;
39     auto* manager = getBlobManager();
40 
41     for (const auto& p : fs::recursive_directory_iterator(path))
42     {
43         auto ps = p.path().string();
44 
45         /* The bitbake recipe symlinks the library lib*.so.? into the folder
46          * only, and not the other names, .so, .so.?.?, .so.?.?.?
47          *
48          * Therefore only care if it's lib*.so.?
49          */
50         if (!std::regex_match(ps, std::regex(".+\\.so\\.\\d+$")))
51         {
52             continue;
53         }
54 
55         libHandle = dlopen(ps.c_str(), RTLD_NOW | RTLD_GLOBAL);
56         if (!libHandle)
57         {
58             log<level::ERR>("ERROR opening", entry("HANDLER=%s", ps.c_str()),
59                             entry("ERROR=%s", dlerror()));
60             continue;
61         }
62 
63         dlerror(); /* Clear any previous error. */
64 
65         factory =
66             reinterpret_cast<HandlerFactory>(dlsym(libHandle, "createHandler"));
67 
68         const char* error = dlerror();
69         if (error)
70         {
71             log<level::ERR>("ERROR loading symbol",
72                             entry("HANDLER=%s", ps.c_str()),
73                             entry("ERROR=%s", error));
74             continue;
75         }
76 
77         std::unique_ptr<GenericBlobInterface> result = factory();
78         if (!result)
79         {
80             log<level::ERR>("Unable to create handler",
81                             entry("HANDLER=%s", ps.c_str()));
82             continue;
83         }
84 
85         manager->registerHandler(std::move(result));
86     }
87 }
88 
89 } // namespace blobs
90