1ded66d0fSJason Ling /*
2ded66d0fSJason Ling  * Copyright 2018 Google Inc.
3ded66d0fSJason Ling  *
4ded66d0fSJason Ling  * Licensed under the Apache License, Version 2.0 (the "License");
5ded66d0fSJason Ling  * you may not use this file except in compliance with the License.
6ded66d0fSJason Ling  * You may obtain a copy of the License at
7ded66d0fSJason Ling  *
8ded66d0fSJason Ling  *     http://www.apache.org/licenses/LICENSE-2.0
9ded66d0fSJason Ling  *
10ded66d0fSJason Ling  * Unless required by applicable law or agreed to in writing, software
11ded66d0fSJason Ling  * distributed under the License is distributed on an "AS IS" BASIS,
12ded66d0fSJason Ling  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ded66d0fSJason Ling  * See the License for the specific language governing permissions and
14ded66d0fSJason Ling  * limitations under the License.
15ded66d0fSJason Ling  */
16ded66d0fSJason Ling 
17ded66d0fSJason Ling #include "data.hpp"
18ded66d0fSJason Ling #include "pci_handler.hpp"
19ded66d0fSJason Ling 
20ded66d0fSJason Ling #include <fcntl.h>
21ded66d0fSJason Ling 
22ded66d0fSJason Ling #include <cstdint>
23ded66d0fSJason Ling #include <cstring>
24ded66d0fSJason Ling #include <string>
25ded66d0fSJason Ling #include <vector>
26ded66d0fSJason Ling 
27ded66d0fSJason Ling namespace ipmi_flash
28ded66d0fSJason Ling {
29ded66d0fSJason Ling 
open()30ded66d0fSJason Ling bool PciDataHandler::open()
31ded66d0fSJason Ling {
32ded66d0fSJason Ling     static constexpr auto devmem = "/dev/mem";
33ded66d0fSJason Ling 
34ded66d0fSJason Ling     mappedFd = sys->open(devmem, O_RDWR | O_SYNC);
35ded66d0fSJason Ling     if (mappedFd == -1)
36ded66d0fSJason Ling     {
37ded66d0fSJason Ling         std::fprintf(stderr, "PciDataHandler::Unable to open /dev/mem");
38ded66d0fSJason Ling         return false;
39ded66d0fSJason Ling     }
40ded66d0fSJason Ling 
41ded66d0fSJason Ling     mapped = reinterpret_cast<uint8_t*>(sys->mmap(
42ded66d0fSJason Ling         0, memoryRegionSize, PROT_READ, MAP_SHARED, mappedFd, regionAddress));
43ded66d0fSJason Ling     if (mapped == MAP_FAILED)
44ded66d0fSJason Ling     {
45ded66d0fSJason Ling         sys->close(mappedFd);
46ded66d0fSJason Ling         mappedFd = -1;
47ded66d0fSJason Ling         mapped = nullptr;
48ded66d0fSJason Ling 
49ded66d0fSJason Ling         std::fprintf(stderr, "PciDataHandler::Unable to map region");
50ded66d0fSJason Ling         return false;
51ded66d0fSJason Ling     }
52ded66d0fSJason Ling 
53ded66d0fSJason Ling     return true;
54ded66d0fSJason Ling }
55ded66d0fSJason Ling 
close()56ded66d0fSJason Ling bool PciDataHandler::close()
57ded66d0fSJason Ling {
58ded66d0fSJason Ling     /* TODO: Turn off the P2A bridge and region to disable host-side access.
59ded66d0fSJason Ling      */
60ded66d0fSJason Ling     if (mapped)
61ded66d0fSJason Ling     {
62ded66d0fSJason Ling         sys->munmap(mapped, memoryRegionSize);
63ded66d0fSJason Ling         mapped = nullptr;
64ded66d0fSJason Ling     }
65ded66d0fSJason Ling 
66ded66d0fSJason Ling     if (mappedFd != -1)
67ded66d0fSJason Ling     {
68ded66d0fSJason Ling         sys->close(mappedFd);
69ded66d0fSJason Ling         mappedFd = -1;
70ded66d0fSJason Ling     }
71ded66d0fSJason Ling 
72ded66d0fSJason Ling     return true;
73ded66d0fSJason Ling }
74ded66d0fSJason Ling 
copyFrom(std::uint32_t length)75ded66d0fSJason Ling std::vector<std::uint8_t> PciDataHandler::copyFrom(std::uint32_t length)
76ded66d0fSJason Ling {
77ded66d0fSJason Ling     std::vector<std::uint8_t> results(length);
78ded66d0fSJason Ling     std::memcpy(results.data(), mapped, length);
79ded66d0fSJason Ling 
80ded66d0fSJason Ling     return results;
81ded66d0fSJason Ling }
82ded66d0fSJason Ling 
writeMeta(const std::vector<std::uint8_t> &)83*b487eb47SWilly Tu bool PciDataHandler::writeMeta(const std::vector<std::uint8_t>&)
84ded66d0fSJason Ling {
85ded66d0fSJason Ling     /* PCI handler doesn't require configuration write, only read. */
86ded66d0fSJason Ling     return false;
87ded66d0fSJason Ling }
88ded66d0fSJason Ling 
readMeta()89ded66d0fSJason Ling std::vector<std::uint8_t> PciDataHandler::readMeta()
90ded66d0fSJason Ling {
91ded66d0fSJason Ling     /* PCI handler does require returning a configuration from read. */
92ded66d0fSJason Ling     struct PciConfigResponse reply;
93ded66d0fSJason Ling     reply.address = regionAddress;
94ded66d0fSJason Ling 
95ded66d0fSJason Ling     std::vector<std::uint8_t> bytes;
96ded66d0fSJason Ling     bytes.resize(sizeof(reply));
97ded66d0fSJason Ling     std::memcpy(bytes.data(), &reply, sizeof(reply));
98ded66d0fSJason Ling 
99ded66d0fSJason Ling     return bytes;
100ded66d0fSJason Ling }
101ded66d0fSJason Ling 
102ded66d0fSJason Ling } // namespace ipmi_flash
103