blob: d8e9f898c0d0fe2982d23276268595b66dc6fba4 [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},
28 };
29
30 auto results = minimumLengths.find(command);
31 if (results == minimumLengths.end())
32 {
33 /* Valid length by default if we don't care. */
34 return true;
35 }
36
37 /* If the request is shorter than the minimum, it's invalid. */
38 if (requestLen < results->second)
39 {
40 return false;
41 }
42
43 return true;
44}
45
Patrick Venture54c3b532018-08-01 11:45:49 -070046ipmi_ret_t startTransfer(UpdateInterface* updater, const uint8_t* reqBuf,
47 uint8_t* replyBuf, size_t* dataLen)
48{
Patrick Venture54c3b532018-08-01 11:45:49 -070049 auto request = reinterpret_cast<const struct StartTx*>(reqBuf);
50
51 if (!updater->start(request->length))
52 {
53 return IPMI_CC_INVALID;
54 }
55
56 /* We were successful and set the response byte to 0. */
57 replyBuf[0] = 0x00;
58 (*dataLen) = 1;
59 return IPMI_CC_OK;
60}
Patrick Venture79e131f2018-08-01 13:34:35 -070061
62ipmi_ret_t dataBlock(UpdateInterface* updater, const uint8_t* reqBuf,
63 uint8_t* replyBuf, size_t* dataLen)
64{
Patrick Venture79e131f2018-08-01 13:34:35 -070065 struct ChunkHdr hdr;
66 std::memcpy(&hdr, reqBuf, sizeof(hdr));
67
Patrick Venturea53a7b32018-08-03 09:15:20 -070068 size_t requestLength = (*dataLen);
69
Patrick Venture79e131f2018-08-01 13:34:35 -070070 /* Grab the bytes from the packet. */
71 size_t bytesLength = requestLength - sizeof(struct ChunkHdr);
72 std::vector<uint8_t> bytes(bytesLength);
73 std::memcpy(bytes.data(), &reqBuf[sizeof(struct ChunkHdr)], bytesLength);
74
75 if (!updater->flashData(hdr.offset, bytes))
76 {
77 return IPMI_CC_INVALID;
78 }
79
80 /* We were successful and set the response byte to 0. */
81 replyBuf[0] = 0x00;
82 (*dataLen) = 1;
83 return IPMI_CC_OK;
84}
Patrick Venture2c1205d2018-08-03 10:23:14 -070085
86ipmi_ret_t dataFinish(UpdateInterface* updater, const uint8_t* reqBuf,
87 uint8_t* replyBuf, size_t* dataLen)
88{
89 if (!updater->flashFinish())
90 {
91 return IPMI_CC_INVALID;
92 }
93
94 /* TODO: If all commands return this on success, handle it in one place. */
95
96 /* We were successful and set the response byte to 0. */
97 replyBuf[0] = 0x00;
98 (*dataLen) = 1;
99 return IPMI_CC_OK;
100}