blob: b9a894346cdd1ec97afb8438530537b4a155a41f [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 Venturea53a7b32018-08-03 09:15:20 -070023bool validateRequestLength(FlashSubCmds command, size_t requestLen)
24{
25 static const std::unordered_map<FlashSubCmds, size_t> minimumLengths = {
26 {FlashSubCmds::flashStartTransfer, sizeof(struct StartTx)},
27 {FlashSubCmds::flashDataBlock, sizeof(struct ChunkHdr) + 1},
Patrick Venture8d9f7322018-08-03 10:39:13 -070028 {FlashSubCmds::flashStartHash, sizeof(struct StartTx)},
Patrick Venturecfe66872018-08-03 13:32:33 -070029 {FlashSubCmds::flashHashData, sizeof(struct ChunkHdr) + 1},
Patrick Venturea53a7b32018-08-03 09:15:20 -070030 };
31
32 auto results = minimumLengths.find(command);
33 if (results == minimumLengths.end())
34 {
35 /* Valid length by default if we don't care. */
36 return true;
37 }
38
39 /* If the request is shorter than the minimum, it's invalid. */
40 if (requestLen < results->second)
41 {
42 return false;
43 }
44
45 return true;
46}
47
Patrick Venture54c3b532018-08-01 11:45:49 -070048ipmi_ret_t startTransfer(UpdateInterface* updater, const uint8_t* reqBuf,
49 uint8_t* replyBuf, size_t* dataLen)
50{
Patrick Venture54c3b532018-08-01 11:45:49 -070051 auto request = reinterpret_cast<const struct StartTx*>(reqBuf);
52
53 if (!updater->start(request->length))
54 {
55 return IPMI_CC_INVALID;
56 }
57
58 /* We were successful and set the response byte to 0. */
59 replyBuf[0] = 0x00;
60 (*dataLen) = 1;
61 return IPMI_CC_OK;
62}
Patrick Venture79e131f2018-08-01 13:34:35 -070063
64ipmi_ret_t dataBlock(UpdateInterface* updater, const uint8_t* reqBuf,
65 uint8_t* replyBuf, size_t* dataLen)
66{
Patrick Venture79e131f2018-08-01 13:34:35 -070067 struct ChunkHdr hdr;
68 std::memcpy(&hdr, reqBuf, sizeof(hdr));
69
Patrick Venturecfe66872018-08-03 13:32:33 -070070 auto requestLength = *dataLen;
Patrick Venturea53a7b32018-08-03 09:15:20 -070071
Patrick Venture79e131f2018-08-01 13:34:35 -070072 /* Grab the bytes from the packet. */
Patrick Venturecfe66872018-08-03 13:32:33 -070073 auto bytesLength = requestLength - sizeof(struct ChunkHdr);
Patrick Venture79e131f2018-08-01 13:34:35 -070074 std::vector<uint8_t> bytes(bytesLength);
75 std::memcpy(bytes.data(), &reqBuf[sizeof(struct ChunkHdr)], bytesLength);
76
77 if (!updater->flashData(hdr.offset, bytes))
78 {
79 return IPMI_CC_INVALID;
80 }
81
82 /* We were successful and set the response byte to 0. */
83 replyBuf[0] = 0x00;
84 (*dataLen) = 1;
85 return IPMI_CC_OK;
86}
Patrick Venture2c1205d2018-08-03 10:23:14 -070087
88ipmi_ret_t dataFinish(UpdateInterface* updater, const uint8_t* reqBuf,
89 uint8_t* replyBuf, size_t* dataLen)
90{
91 if (!updater->flashFinish())
92 {
93 return IPMI_CC_INVALID;
94 }
95
96 /* TODO: If all commands return this on success, handle it in one place. */
97
98 /* We were successful and set the response byte to 0. */
99 replyBuf[0] = 0x00;
100 (*dataLen) = 1;
101 return IPMI_CC_OK;
102}
Patrick Venture8d9f7322018-08-03 10:39:13 -0700103
104ipmi_ret_t startHash(UpdateInterface* updater, const uint8_t* reqBuf,
105 uint8_t* replyBuf, size_t* dataLen)
106{
107 auto request = reinterpret_cast<const struct StartTx*>(reqBuf);
108
109 if (!updater->startHash(request->length))
110 {
111 return IPMI_CC_INVALID;
112 }
113
114 /* We were successful and set the response byte to 0. */
115 replyBuf[0] = 0x00;
116 (*dataLen) = 1;
117 return IPMI_CC_OK;
118}
Patrick Venturecfe66872018-08-03 13:32:33 -0700119
120ipmi_ret_t hashBlock(UpdateInterface* updater, const uint8_t* reqBuf,
121 uint8_t* replyBuf, size_t* dataLen)
122{
123 struct ChunkHdr hdr;
124 std::memcpy(&hdr, reqBuf, sizeof(hdr));
125
126 auto requestLength = *dataLen;
127
128 /* Grab the bytes from the packet. */
129 auto bytesLength = requestLength - sizeof(struct ChunkHdr);
130 std::vector<uint8_t> bytes(bytesLength);
131 std::memcpy(bytes.data(), &reqBuf[sizeof(struct ChunkHdr)], bytesLength);
132
133 /* TODO: Refactor this and dataBlock for re-use. */
134
135 if (!updater->hashData(hdr.offset, bytes))
136 {
137 return IPMI_CC_INVALID;
138 }
139
140 /* We were successful and set the response byte to 0. */
141 replyBuf[0] = 0x00;
142 (*dataLen) = 1;
143 return IPMI_CC_OK;
144}
Patrick Venturefbc7d192018-08-03 13:54:21 -0700145
146ipmi_ret_t hashFinish(UpdateInterface* updater, const uint8_t* reqBuf,
147 uint8_t* replyBuf, size_t* dataLen)
148{
149 if (!updater->hashFinish())
150 {
151 return IPMI_CC_INVALID;
152 }
153
154 /* We were successful and set the response byte to 0. */
155 replyBuf[0] = 0x00;
156 (*dataLen) = 1;
157 return IPMI_CC_OK;
158}