xref: /openbmc/phosphor-ipmi-blobs/process.cpp (revision ef3aeadc9be37c47d0627e576e81a74a5bb9e94f)
1*ef3aeadcSPatrick Venture /*
2*ef3aeadcSPatrick Venture  * Copyright 2018 Google Inc.
3*ef3aeadcSPatrick Venture  *
4*ef3aeadcSPatrick Venture  * Licensed under the Apache License, Version 2.0 (the "License");
5*ef3aeadcSPatrick Venture  * you may not use this file except in compliance with the License.
6*ef3aeadcSPatrick Venture  * You may obtain a copy of the License at
7*ef3aeadcSPatrick Venture  *
8*ef3aeadcSPatrick Venture  *     http://www.apache.org/licenses/LICENSE-2.0
9*ef3aeadcSPatrick Venture  *
10*ef3aeadcSPatrick Venture  * Unless required by applicable law or agreed to in writing, software
11*ef3aeadcSPatrick Venture  * distributed under the License is distributed on an "AS IS" BASIS,
12*ef3aeadcSPatrick Venture  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ef3aeadcSPatrick Venture  * See the License for the specific language governing permissions and
14*ef3aeadcSPatrick Venture  * limitations under the License.
15*ef3aeadcSPatrick Venture  */
16*ef3aeadcSPatrick Venture 
17*ef3aeadcSPatrick Venture #include "process.hpp"
18*ef3aeadcSPatrick Venture 
19*ef3aeadcSPatrick Venture #include "ipmi.hpp"
20*ef3aeadcSPatrick Venture 
21*ef3aeadcSPatrick Venture #include <cstring>
22*ef3aeadcSPatrick Venture #include <vector>
23*ef3aeadcSPatrick Venture 
24*ef3aeadcSPatrick Venture namespace blobs
25*ef3aeadcSPatrick Venture {
26*ef3aeadcSPatrick Venture 
27*ef3aeadcSPatrick Venture /* Used by all commands with data. */
28*ef3aeadcSPatrick Venture struct BmcRx
29*ef3aeadcSPatrick Venture {
30*ef3aeadcSPatrick Venture     uint8_t cmd;
31*ef3aeadcSPatrick Venture     uint16_t crc;
32*ef3aeadcSPatrick Venture     uint8_t data; /* one byte minimum of data. */
33*ef3aeadcSPatrick Venture } __attribute__((packed));
34*ef3aeadcSPatrick Venture 
35*ef3aeadcSPatrick Venture IpmiBlobHandler validateBlobCommand(CrcInterface* crc, const uint8_t* reqBuf,
36*ef3aeadcSPatrick Venture                                     uint8_t* replyCmdBuf, size_t* dataLen)
37*ef3aeadcSPatrick Venture {
38*ef3aeadcSPatrick Venture     IpmiBlobHandler cmd;
39*ef3aeadcSPatrick Venture     size_t requestLength = (*dataLen);
40*ef3aeadcSPatrick Venture     /* We know dataLen is at least 1 already */
41*ef3aeadcSPatrick Venture     auto command = static_cast<BlobOEMCommands>(reqBuf[0]);
42*ef3aeadcSPatrick Venture 
43*ef3aeadcSPatrick Venture     /* Validate it's at least well-formed. */
44*ef3aeadcSPatrick Venture     if (!validateRequestLength(command, requestLength))
45*ef3aeadcSPatrick Venture     {
46*ef3aeadcSPatrick Venture         return nullptr;
47*ef3aeadcSPatrick Venture     }
48*ef3aeadcSPatrick Venture 
49*ef3aeadcSPatrick Venture     /* If there is a payload. */
50*ef3aeadcSPatrick Venture     if (requestLength > sizeof(uint8_t))
51*ef3aeadcSPatrick Venture     {
52*ef3aeadcSPatrick Venture         /* Verify the request includes: command, crc16, data */
53*ef3aeadcSPatrick Venture         if (requestLength < sizeof(struct BmcRx))
54*ef3aeadcSPatrick Venture         {
55*ef3aeadcSPatrick Venture             return nullptr;
56*ef3aeadcSPatrick Venture         }
57*ef3aeadcSPatrick Venture 
58*ef3aeadcSPatrick Venture         /* We don't include the command byte at offset 0 as part of the crc
59*ef3aeadcSPatrick Venture          * payload area or the crc bytes at the beginning.
60*ef3aeadcSPatrick Venture          */
61*ef3aeadcSPatrick Venture         size_t requestBodyLen = requestLength - 3;
62*ef3aeadcSPatrick Venture 
63*ef3aeadcSPatrick Venture         /* We start after the command byte. */
64*ef3aeadcSPatrick Venture         std::vector<uint8_t> bytes(requestBodyLen);
65*ef3aeadcSPatrick Venture 
66*ef3aeadcSPatrick Venture         /* It likely has a well-formed payload. */
67*ef3aeadcSPatrick Venture         struct BmcRx request;
68*ef3aeadcSPatrick Venture         std::memcpy(&request, reqBuf, sizeof(request));
69*ef3aeadcSPatrick Venture         uint16_t crcValue = request.crc;
70*ef3aeadcSPatrick Venture 
71*ef3aeadcSPatrick Venture         /* Set the in-place CRC to zero. */
72*ef3aeadcSPatrick Venture         std::memcpy(bytes.data(), &reqBuf[3], requestBodyLen);
73*ef3aeadcSPatrick Venture 
74*ef3aeadcSPatrick Venture         crc->clear();
75*ef3aeadcSPatrick Venture         crc->compute(bytes.data(), bytes.size());
76*ef3aeadcSPatrick Venture 
77*ef3aeadcSPatrick Venture         /* Crc expected but didn't match. */
78*ef3aeadcSPatrick Venture         if (crcValue != crc->get())
79*ef3aeadcSPatrick Venture         {
80*ef3aeadcSPatrick Venture             return nullptr;
81*ef3aeadcSPatrick Venture         }
82*ef3aeadcSPatrick Venture     }
83*ef3aeadcSPatrick Venture 
84*ef3aeadcSPatrick Venture     /* Grab the corresponding handler for the command (could do map or array
85*ef3aeadcSPatrick Venture      * of function pointer lookup).
86*ef3aeadcSPatrick Venture      */
87*ef3aeadcSPatrick Venture     switch (command)
88*ef3aeadcSPatrick Venture     {
89*ef3aeadcSPatrick Venture         case BlobOEMCommands::bmcBlobGetCount:
90*ef3aeadcSPatrick Venture             cmd = getBlobCount;
91*ef3aeadcSPatrick Venture             break;
92*ef3aeadcSPatrick Venture         case BlobOEMCommands::bmcBlobEnumerate:
93*ef3aeadcSPatrick Venture             cmd = enumerateBlob;
94*ef3aeadcSPatrick Venture             break;
95*ef3aeadcSPatrick Venture         case BlobOEMCommands::bmcBlobOpen:
96*ef3aeadcSPatrick Venture             cmd = openBlob;
97*ef3aeadcSPatrick Venture             break;
98*ef3aeadcSPatrick Venture         case BlobOEMCommands::bmcBlobRead:
99*ef3aeadcSPatrick Venture             cmd = readBlob;
100*ef3aeadcSPatrick Venture             break;
101*ef3aeadcSPatrick Venture         case BlobOEMCommands::bmcBlobWrite:
102*ef3aeadcSPatrick Venture             cmd = writeBlob;
103*ef3aeadcSPatrick Venture             break;
104*ef3aeadcSPatrick Venture         case BlobOEMCommands::bmcBlobCommit:
105*ef3aeadcSPatrick Venture             cmd = commitBlob;
106*ef3aeadcSPatrick Venture             break;
107*ef3aeadcSPatrick Venture         case BlobOEMCommands::bmcBlobClose:
108*ef3aeadcSPatrick Venture             cmd = closeBlob;
109*ef3aeadcSPatrick Venture             break;
110*ef3aeadcSPatrick Venture         case BlobOEMCommands::bmcBlobDelete:
111*ef3aeadcSPatrick Venture             cmd = deleteBlob;
112*ef3aeadcSPatrick Venture             break;
113*ef3aeadcSPatrick Venture         case BlobOEMCommands::bmcBlobStat:
114*ef3aeadcSPatrick Venture             cmd = statBlob;
115*ef3aeadcSPatrick Venture             break;
116*ef3aeadcSPatrick Venture         case BlobOEMCommands::bmcBlobSessionStat:
117*ef3aeadcSPatrick Venture             cmd = sessionStatBlob;
118*ef3aeadcSPatrick Venture             break;
119*ef3aeadcSPatrick Venture         default:
120*ef3aeadcSPatrick Venture             return nullptr;
121*ef3aeadcSPatrick Venture     }
122*ef3aeadcSPatrick Venture 
123*ef3aeadcSPatrick Venture     return cmd;
124*ef3aeadcSPatrick Venture }
125*ef3aeadcSPatrick Venture 
126*ef3aeadcSPatrick Venture ipmi_ret_t processBlobCommand(IpmiBlobHandler cmd, ManagerInterface* mgr,
127*ef3aeadcSPatrick Venture                               CrcInterface* crc, const uint8_t* reqBuf,
128*ef3aeadcSPatrick Venture                               uint8_t* replyCmdBuf, size_t* dataLen)
129*ef3aeadcSPatrick Venture {
130*ef3aeadcSPatrick Venture     ipmi_ret_t result = cmd(mgr, reqBuf, replyCmdBuf, dataLen);
131*ef3aeadcSPatrick Venture     if (result != IPMI_CC_OK)
132*ef3aeadcSPatrick Venture     {
133*ef3aeadcSPatrick Venture         return result;
134*ef3aeadcSPatrick Venture     }
135*ef3aeadcSPatrick Venture 
136*ef3aeadcSPatrick Venture     size_t replyLength = (*dataLen);
137*ef3aeadcSPatrick Venture 
138*ef3aeadcSPatrick Venture     /* The command, whatever it was, returned success. */
139*ef3aeadcSPatrick Venture     if (replyLength == 0)
140*ef3aeadcSPatrick Venture     {
141*ef3aeadcSPatrick Venture         return result;
142*ef3aeadcSPatrick Venture     }
143*ef3aeadcSPatrick Venture 
144*ef3aeadcSPatrick Venture     /* The response, if it has one byte, has three, to include the crc16. */
145*ef3aeadcSPatrick Venture     if (replyLength < (sizeof(uint16_t) + 1))
146*ef3aeadcSPatrick Venture     {
147*ef3aeadcSPatrick Venture         return IPMI_CC_INVALID;
148*ef3aeadcSPatrick Venture     }
149*ef3aeadcSPatrick Venture 
150*ef3aeadcSPatrick Venture     /* The command, whatever it was, replied, so let's set the CRC. */
151*ef3aeadcSPatrick Venture     crc->clear();
152*ef3aeadcSPatrick Venture     replyCmdBuf[0] = 0x00;
153*ef3aeadcSPatrick Venture     replyCmdBuf[1] = 0x00;
154*ef3aeadcSPatrick Venture     crc->compute(replyCmdBuf, replyLength);
155*ef3aeadcSPatrick Venture 
156*ef3aeadcSPatrick Venture     /* Copy the CRC into place. */
157*ef3aeadcSPatrick Venture     uint16_t crcValue = crc->get();
158*ef3aeadcSPatrick Venture     std::memcpy(replyCmdBuf, &crcValue, sizeof(crcValue));
159*ef3aeadcSPatrick Venture 
160*ef3aeadcSPatrick Venture     return result;
161*ef3aeadcSPatrick Venture }
162*ef3aeadcSPatrick Venture } // namespace blobs
163