xref: /openbmc/phosphor-ipmi-blobs/example/example.cpp (revision 5250957212ebf851d49df046acd6416a0d17c749)
1 #include "example/example.hpp"
2 
3 #include <phosphor-logging/log.hpp>
4 
5 #include <algorithm>
6 #include <cstring>
7 #include <memory>
8 #include <string>
9 #include <vector>
10 
11 namespace blobs
12 {
13 
14 using namespace phosphor::logging;
15 
16 constexpr char ExampleBlobHandler::supportedPath[];
17 
getSession(uint16_t id)18 ExampleBlob* ExampleBlobHandler::getSession(uint16_t id)
19 {
20     auto search = sessions.find(id);
21     if (search == sessions.end())
22     {
23         return nullptr;
24     }
25     /* Not thread-safe, however, the blob handler deliberately assumes serial
26      * execution. */
27     return &search->second;
28 }
29 
canHandleBlob(const std::string & path)30 bool ExampleBlobHandler::canHandleBlob(const std::string& path)
31 {
32     return (path == supportedPath);
33 }
34 
getBlobIds()35 std::vector<std::string> ExampleBlobHandler::getBlobIds()
36 {
37     return {supportedPath};
38 }
39 
deleteBlob(const std::string &)40 bool ExampleBlobHandler::deleteBlob(const std::string&)
41 {
42     return false;
43 }
44 
stat(const std::string &,BlobMeta *)45 bool ExampleBlobHandler::stat(const std::string&, BlobMeta*)
46 {
47     return false;
48 }
49 
open(uint16_t session,uint16_t flags,const std::string & path)50 bool ExampleBlobHandler::open(uint16_t session, uint16_t flags,
51                               const std::string& path)
52 {
53     if (!canHandleBlob(path))
54     {
55         return false;
56     }
57 
58     auto findSess = sessions.find(session);
59     if (findSess != sessions.end())
60     {
61         /* This session is already active. */
62         return false;
63     }
64     sessions[session] = ExampleBlob(session, flags);
65     return true;
66 }
67 
read(uint16_t session,uint32_t offset,uint32_t requestedSize)68 std::vector<uint8_t> ExampleBlobHandler::read(uint16_t session, uint32_t offset,
69                                               uint32_t requestedSize)
70 {
71     ExampleBlob* sess = getSession(session);
72     if (!sess)
73     {
74         return std::vector<uint8_t>();
75     }
76 
77     /* Is the offset beyond the array? */
78     if (offset >= sizeof(sess->buffer))
79     {
80         return std::vector<uint8_t>();
81     }
82 
83     /* Determine how many bytes we can read from the offset.
84      * In this case, if they read beyond "size" we allow it.
85      */
86     uint32_t remain = sizeof(sess->buffer) - offset;
87     uint32_t numBytes = std::min(remain, requestedSize);
88     /* Copy the bytes! */
89     std::vector<uint8_t> result(numBytes);
90     std::memcpy(result.data(), &sess->buffer[offset], numBytes);
91     return result;
92 }
93 
write(uint16_t session,uint32_t offset,const std::vector<uint8_t> & data)94 bool ExampleBlobHandler::write(uint16_t session, uint32_t offset,
95                                const std::vector<uint8_t>& data)
96 {
97     ExampleBlob* sess = getSession(session);
98     if (!sess)
99     {
100         return false;
101     }
102     /* Is the offset beyond the array? */
103     if (offset >= sizeof(sess->buffer))
104     {
105         return false;
106     }
107     /* Determine whether all their bytes will fit. */
108     uint32_t remain = sizeof(sess->buffer) - offset;
109     if (data.size() > remain)
110     {
111         return false;
112     }
113     sess->length =
114         std::max(offset + data.size(),
115                  static_cast<std::vector<uint8_t>::size_type>(sess->length));
116     std::memcpy(&sess->buffer[offset], data.data(), data.size());
117     return true;
118 }
119 
writeMeta(uint16_t,uint32_t,const std::vector<uint8_t> &)120 bool ExampleBlobHandler::writeMeta(uint16_t, uint32_t,
121                                    const std::vector<uint8_t>&)
122 {
123     /* Not supported. */
124     return false;
125 }
126 
commit(uint16_t session,const std::vector<uint8_t> &)127 bool ExampleBlobHandler::commit(uint16_t session, const std::vector<uint8_t>&)
128 {
129     ExampleBlob* sess = getSession(session);
130     if (!sess)
131     {
132         return false;
133     }
134 
135     /* Do something with the staged data!. */
136 
137     return false;
138 }
139 
close(uint16_t session)140 bool ExampleBlobHandler::close(uint16_t session)
141 {
142     ExampleBlob* sess = getSession(session);
143     if (!sess)
144     {
145         return false;
146     }
147 
148     sessions.erase(session);
149     return true;
150 }
151 
stat(uint16_t session,BlobMeta * meta)152 bool ExampleBlobHandler::stat(uint16_t session, BlobMeta* meta)
153 {
154     ExampleBlob* sess = getSession(session);
155     if (!sess)
156     {
157         return false;
158     }
159     if (!meta)
160     {
161         return false;
162     }
163     meta->size = sess->length;
164     meta->blobState = sess->state;
165     return true;
166 }
167 
expire(uint16_t session)168 bool ExampleBlobHandler::expire(uint16_t session)
169 {
170     ExampleBlob* sess = getSession(session);
171     if (!sess)
172     {
173         return false;
174     }
175     /* TODO: implement session expiration behavior. */
176     return false;
177 }
178 
179 void setupExampleHandler() __attribute__((constructor));
180 
setupExampleHandler()181 void setupExampleHandler()
182 {
183     // You don't need to do anything in the constructor.
184 }
185 
186 } // namespace blobs
187 
188 /**
189  * This method is required by the blob manager.
190  *
191  * It is called to grab a handler for registering the blob handler instance.
192  */
createHandler()193 std::unique_ptr<blobs::GenericBlobInterface> createHandler()
194 {
195     return std::make_unique<blobs::ExampleBlobHandler>();
196 }
197