xref: /openbmc/phosphor-ipmi-flash/bmc/firmware-handler/lpc_handler.cpp (revision ded66d0f7317f6e43a5301da6c3d9dda80b17250)
1 /*
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 "lpc_handler.hpp"
18 
19 #include <cstdint>
20 #include <cstring>
21 #include <vector>
22 
23 namespace ipmi_flash
24 {
25 
26 bool LpcDataHandler::open()
27 {
28     /* For the ASPEED LPC CTRL driver, the ioctl is required to set up the
29      * window, with information from writeMeta() below.
30      */
31     return true;
32 }
33 
34 bool LpcDataHandler::close()
35 {
36     mapper->close();
37 
38     return setInitializedAndReturn(false);
39 }
40 
41 std::vector<std::uint8_t> LpcDataHandler::copyFrom(std::uint32_t length)
42 {
43     /* TODO: implement this -- in an earlier and different version of this that
44      * didn't use BLOBs, the region was memory-mapped and the writes to the data
45      * were just done directly from the memory-mapped region instead of a
46      * copyFrom() first call.  The idea with this change is that we may not be
47      * able to get a memory-mapped handle from the driver from which to
48      * automatically read data, but rather must perform some ioctl or other
49      * access to get the data from the driver.
50      */
51     if (!initialized)
52     {
53         /* TODO: Consider designing some exceptions we can catch for when there
54          * is an error.
55          */
56         return {};
57     }
58 
59     std::vector<std::uint8_t> results(length);
60     std::memcpy(results.data(), memory.mapped + mappingResult.windowOffset,
61                 length);
62 
63     return results;
64 }
65 
66 bool LpcDataHandler::writeMeta(const std::vector<std::uint8_t>& configuration)
67 {
68     struct LpcRegion lpcRegion;
69 
70     if (configuration.size() != sizeof(lpcRegion))
71     {
72         return false;
73     }
74 
75     std::memcpy(&lpcRegion, configuration.data(), configuration.size());
76 
77     /* TODO: LpcRegion sanity checking. */
78     mappingResult = mapper->mapWindow(lpcRegion.address, lpcRegion.length);
79     if (mappingResult.response != 0)
80     {
81         std::fprintf(stderr, "mappingResult.response %u\n",
82                      mappingResult.response);
83         /* Failed to map region. */
84         return false;
85     }
86 
87     return setInitializedAndReturn(true);
88 }
89 
90 std::vector<std::uint8_t> LpcDataHandler::readMeta()
91 {
92     /* Return the MemoryResult structure packed. */
93     std::vector<std::uint8_t> output(
94         sizeof(std::uint8_t) + sizeof(std::uint32_t) + sizeof(std::uint32_t));
95 
96     int index = 0;
97     std::memcpy(&output[index], &mappingResult.response,
98                 sizeof(mappingResult.response));
99 
100     index += sizeof(mappingResult.response);
101     std::memcpy(&output[index], &mappingResult.windowOffset,
102                 sizeof(mappingResult.windowOffset));
103 
104     index += sizeof(mappingResult.windowOffset);
105     std::memcpy(&output[index], &mappingResult.windowSize,
106                 sizeof(mappingResult.windowSize));
107 
108     return output;
109 }
110 
111 } // namespace ipmi_flash
112