blob: fad204957bc8fe05a97196685e19f09a7824fdd2 [file] [log] [blame]
Patrick Venture54c3b532018-08-01 11:45:49 -07001/*
2 * Copyright 2017 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
Patrick Venture79e131f2018-08-01 13:34:35 -070017#include <cstring>
Patrick Venturea53a7b32018-08-03 09:15:20 -070018#include <unordered_map>
Patrick Venture79e131f2018-08-01 13:34:35 -070019
Patrick Venture54c3b532018-08-01 11:45:49 -070020#include "flash-ipmi.hpp"
21#include "ipmi.hpp"
22
Patrick Venture9a5a79a2018-08-03 17:23:57 -070023IpmiFlashHandler getCommandHandler(FlashSubCmds command)
24{
25 static const std::unordered_map<FlashSubCmds, IpmiFlashHandler>
26 subHandlers = {
27 {FlashSubCmds::flashStartTransfer, startTransfer},
28 {FlashSubCmds::flashDataBlock, dataBlock},
29 {FlashSubCmds::flashDataFinish, dataFinish},
30 {FlashSubCmds::flashStartHash, startHash},
31 {FlashSubCmds::flashHashData, hashBlock},
32 {FlashSubCmds::flashHashFinish, hashFinish},
33 };
34
35 auto results = subHandlers.find(command);
36 if (results == subHandlers.end())
37 {
38 return nullptr;
39 }
40
41 return results->second;
42}
43
Patrick Venturea53a7b32018-08-03 09:15:20 -070044bool validateRequestLength(FlashSubCmds command, size_t requestLen)
45{
46 static const std::unordered_map<FlashSubCmds, size_t> minimumLengths = {
47 {FlashSubCmds::flashStartTransfer, sizeof(struct StartTx)},
48 {FlashSubCmds::flashDataBlock, sizeof(struct ChunkHdr) + 1},
Patrick Venture8d9f7322018-08-03 10:39:13 -070049 {FlashSubCmds::flashStartHash, sizeof(struct StartTx)},
Patrick Venturecfe66872018-08-03 13:32:33 -070050 {FlashSubCmds::flashHashData, sizeof(struct ChunkHdr) + 1},
Patrick Venturea53a7b32018-08-03 09:15:20 -070051 };
52
53 auto results = minimumLengths.find(command);
54 if (results == minimumLengths.end())
55 {
56 /* Valid length by default if we don't care. */
57 return true;
58 }
59
60 /* If the request is shorter than the minimum, it's invalid. */
61 if (requestLen < results->second)
62 {
63 return false;
64 }
65
66 return true;
67}
68
Patrick Venture54c3b532018-08-01 11:45:49 -070069ipmi_ret_t startTransfer(UpdateInterface* updater, const uint8_t* reqBuf,
70 uint8_t* replyBuf, size_t* dataLen)
71{
Patrick Venture54c3b532018-08-01 11:45:49 -070072 auto request = reinterpret_cast<const struct StartTx*>(reqBuf);
73
74 if (!updater->start(request->length))
75 {
76 return IPMI_CC_INVALID;
77 }
78
79 /* We were successful and set the response byte to 0. */
80 replyBuf[0] = 0x00;
81 (*dataLen) = 1;
82 return IPMI_CC_OK;
83}
Patrick Venture79e131f2018-08-01 13:34:35 -070084
85ipmi_ret_t dataBlock(UpdateInterface* updater, const uint8_t* reqBuf,
86 uint8_t* replyBuf, size_t* dataLen)
87{
Patrick Venture79e131f2018-08-01 13:34:35 -070088 struct ChunkHdr hdr;
89 std::memcpy(&hdr, reqBuf, sizeof(hdr));
90
Patrick Venturecfe66872018-08-03 13:32:33 -070091 auto requestLength = *dataLen;
Patrick Venturea53a7b32018-08-03 09:15:20 -070092
Patrick Venture79e131f2018-08-01 13:34:35 -070093 /* Grab the bytes from the packet. */
Patrick Venturecfe66872018-08-03 13:32:33 -070094 auto bytesLength = requestLength - sizeof(struct ChunkHdr);
Patrick Venture79e131f2018-08-01 13:34:35 -070095 std::vector<uint8_t> bytes(bytesLength);
96 std::memcpy(bytes.data(), &reqBuf[sizeof(struct ChunkHdr)], bytesLength);
97
98 if (!updater->flashData(hdr.offset, bytes))
99 {
100 return IPMI_CC_INVALID;
101 }
102
103 /* We were successful and set the response byte to 0. */
104 replyBuf[0] = 0x00;
105 (*dataLen) = 1;
106 return IPMI_CC_OK;
107}
Patrick Venture2c1205d2018-08-03 10:23:14 -0700108
109ipmi_ret_t dataFinish(UpdateInterface* updater, const uint8_t* reqBuf,
110 uint8_t* replyBuf, size_t* dataLen)
111{
112 if (!updater->flashFinish())
113 {
114 return IPMI_CC_INVALID;
115 }
116
117 /* TODO: If all commands return this on success, handle it in one place. */
118
119 /* We were successful and set the response byte to 0. */
120 replyBuf[0] = 0x00;
121 (*dataLen) = 1;
122 return IPMI_CC_OK;
123}
Patrick Venture8d9f7322018-08-03 10:39:13 -0700124
125ipmi_ret_t startHash(UpdateInterface* updater, const uint8_t* reqBuf,
126 uint8_t* replyBuf, size_t* dataLen)
127{
128 auto request = reinterpret_cast<const struct StartTx*>(reqBuf);
129
130 if (!updater->startHash(request->length))
131 {
132 return IPMI_CC_INVALID;
133 }
134
135 /* We were successful and set the response byte to 0. */
136 replyBuf[0] = 0x00;
137 (*dataLen) = 1;
138 return IPMI_CC_OK;
139}
Patrick Venturecfe66872018-08-03 13:32:33 -0700140
141ipmi_ret_t hashBlock(UpdateInterface* updater, const uint8_t* reqBuf,
142 uint8_t* replyBuf, size_t* dataLen)
143{
144 struct ChunkHdr hdr;
145 std::memcpy(&hdr, reqBuf, sizeof(hdr));
146
147 auto requestLength = *dataLen;
148
149 /* Grab the bytes from the packet. */
150 auto bytesLength = requestLength - sizeof(struct ChunkHdr);
151 std::vector<uint8_t> bytes(bytesLength);
152 std::memcpy(bytes.data(), &reqBuf[sizeof(struct ChunkHdr)], bytesLength);
153
154 /* TODO: Refactor this and dataBlock for re-use. */
155
156 if (!updater->hashData(hdr.offset, bytes))
157 {
158 return IPMI_CC_INVALID;
159 }
160
161 /* We were successful and set the response byte to 0. */
162 replyBuf[0] = 0x00;
163 (*dataLen) = 1;
164 return IPMI_CC_OK;
165}
Patrick Venturefbc7d192018-08-03 13:54:21 -0700166
167ipmi_ret_t hashFinish(UpdateInterface* updater, const uint8_t* reqBuf,
168 uint8_t* replyBuf, size_t* dataLen)
169{
170 if (!updater->hashFinish())
171 {
172 return IPMI_CC_INVALID;
173 }
174
175 /* We were successful and set the response byte to 0. */
176 replyBuf[0] = 0x00;
177 (*dataLen) = 1;
178 return IPMI_CC_OK;
179}