blob: 595b5c25b7ae1c9640ee1dcecf8ccc316421a4cf [file] [log] [blame]
Patrick Ventureef3aead2018-09-12 08:53:29 -07001/*
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 "process.hpp"
18
19#include "ipmi.hpp"
20
21#include <cstring>
22#include <vector>
23
24namespace blobs
25{
26
27/* Used by all commands with data. */
28struct BmcRx
29{
30 uint8_t cmd;
31 uint16_t crc;
32 uint8_t data; /* one byte minimum of data. */
33} __attribute__((packed));
34
35IpmiBlobHandler validateBlobCommand(CrcInterface* crc, const uint8_t* reqBuf,
36 uint8_t* replyCmdBuf, size_t* dataLen)
37{
38 IpmiBlobHandler cmd;
39 size_t requestLength = (*dataLen);
40 /* We know dataLen is at least 1 already */
41 auto command = static_cast<BlobOEMCommands>(reqBuf[0]);
42
43 /* Validate it's at least well-formed. */
44 if (!validateRequestLength(command, requestLength))
45 {
46 return nullptr;
47 }
48
49 /* If there is a payload. */
50 if (requestLength > sizeof(uint8_t))
51 {
52 /* Verify the request includes: command, crc16, data */
53 if (requestLength < sizeof(struct BmcRx))
54 {
55 return nullptr;
56 }
57
58 /* We don't include the command byte at offset 0 as part of the crc
59 * payload area or the crc bytes at the beginning.
60 */
61 size_t requestBodyLen = requestLength - 3;
62
63 /* We start after the command byte. */
64 std::vector<uint8_t> bytes(requestBodyLen);
65
66 /* It likely has a well-formed payload. */
67 struct BmcRx request;
68 std::memcpy(&request, reqBuf, sizeof(request));
69 uint16_t crcValue = request.crc;
70
71 /* Set the in-place CRC to zero. */
72 std::memcpy(bytes.data(), &reqBuf[3], requestBodyLen);
73
74 crc->clear();
75 crc->compute(bytes.data(), bytes.size());
76
77 /* Crc expected but didn't match. */
78 if (crcValue != crc->get())
79 {
80 return nullptr;
81 }
82 }
83
84 /* Grab the corresponding handler for the command (could do map or array
85 * of function pointer lookup).
86 */
87 switch (command)
88 {
89 case BlobOEMCommands::bmcBlobGetCount:
90 cmd = getBlobCount;
91 break;
92 case BlobOEMCommands::bmcBlobEnumerate:
93 cmd = enumerateBlob;
94 break;
95 case BlobOEMCommands::bmcBlobOpen:
96 cmd = openBlob;
97 break;
98 case BlobOEMCommands::bmcBlobRead:
99 cmd = readBlob;
100 break;
101 case BlobOEMCommands::bmcBlobWrite:
102 cmd = writeBlob;
103 break;
104 case BlobOEMCommands::bmcBlobCommit:
105 cmd = commitBlob;
106 break;
107 case BlobOEMCommands::bmcBlobClose:
108 cmd = closeBlob;
109 break;
110 case BlobOEMCommands::bmcBlobDelete:
111 cmd = deleteBlob;
112 break;
113 case BlobOEMCommands::bmcBlobStat:
114 cmd = statBlob;
115 break;
116 case BlobOEMCommands::bmcBlobSessionStat:
117 cmd = sessionStatBlob;
118 break;
119 default:
120 return nullptr;
121 }
122
123 return cmd;
124}
125
126ipmi_ret_t processBlobCommand(IpmiBlobHandler cmd, ManagerInterface* mgr,
127 CrcInterface* crc, const uint8_t* reqBuf,
128 uint8_t* replyCmdBuf, size_t* dataLen)
129{
130 ipmi_ret_t result = cmd(mgr, reqBuf, replyCmdBuf, dataLen);
131 if (result != IPMI_CC_OK)
132 {
133 return result;
134 }
135
136 size_t replyLength = (*dataLen);
137
138 /* The command, whatever it was, returned success. */
139 if (replyLength == 0)
140 {
141 return result;
142 }
143
144 /* The response, if it has one byte, has three, to include the crc16. */
145 if (replyLength < (sizeof(uint16_t) + 1))
146 {
147 return IPMI_CC_INVALID;
148 }
149
150 /* The command, whatever it was, replied, so let's set the CRC. */
151 crc->clear();
152 replyCmdBuf[0] = 0x00;
153 replyCmdBuf[1] = 0x00;
154 crc->compute(replyCmdBuf, replyLength);
155
156 /* Copy the CRC into place. */
157 uint16_t crcValue = crc->get();
158 std::memcpy(replyCmdBuf, &crcValue, sizeof(crcValue));
159
160 return result;
161}
162} // namespace blobs