1*55dcadaeSBrandon Kim #include "pci_handler.hpp"
2*55dcadaeSBrandon Kim 
3*55dcadaeSBrandon Kim #include <fcntl.h>
4*55dcadaeSBrandon Kim #include <fmt/format.h>
5*55dcadaeSBrandon Kim 
6*55dcadaeSBrandon Kim #include <stdplus/fd/managed.hpp>
7*55dcadaeSBrandon Kim #include <stdplus/fd/mmap.hpp>
8*55dcadaeSBrandon Kim 
9*55dcadaeSBrandon Kim #include <cstdint>
10*55dcadaeSBrandon Kim #include <cstring>
11*55dcadaeSBrandon Kim #include <memory>
12*55dcadaeSBrandon Kim #include <span>
13*55dcadaeSBrandon Kim #include <vector>
14*55dcadaeSBrandon Kim 
15*55dcadaeSBrandon Kim namespace bios_bmc_smm_error_logger
16*55dcadaeSBrandon Kim {
17*55dcadaeSBrandon Kim 
18*55dcadaeSBrandon Kim PciDataHandler::PciDataHandler(uint32_t regionAddress, size_t regionSize,
19*55dcadaeSBrandon Kim                                std::unique_ptr<stdplus::fd::Fd> fd) :
20*55dcadaeSBrandon Kim     regionAddress(regionAddress),
21*55dcadaeSBrandon Kim     regionSize(regionSize), fd(std::move(fd)),
22*55dcadaeSBrandon Kim     mmap(stdplus::fd::MMap(
23*55dcadaeSBrandon Kim         *this->fd, regionSize, stdplus::fd::ProtFlags{PROT_READ | PROT_WRITE},
24*55dcadaeSBrandon Kim         stdplus::fd::MMapFlags{stdplus::fd::MMapAccess::Shared}, regionAddress))
25*55dcadaeSBrandon Kim {}
26*55dcadaeSBrandon Kim 
27*55dcadaeSBrandon Kim std::vector<uint8_t> PciDataHandler::read(const uint32_t offset,
28*55dcadaeSBrandon Kim                                           const uint32_t length)
29*55dcadaeSBrandon Kim {
30*55dcadaeSBrandon Kim     if (offset > regionSize || length == 0)
31*55dcadaeSBrandon Kim     {
32*55dcadaeSBrandon Kim         fmt::print(stderr,
33*55dcadaeSBrandon Kim                    "[read] Offset [{}] was bigger than regionSize [{}] "
34*55dcadaeSBrandon Kim                    "OR length [{}] was equal to 0\n",
35*55dcadaeSBrandon Kim                    offset, regionSize, length);
36*55dcadaeSBrandon Kim         return {};
37*55dcadaeSBrandon Kim     }
38*55dcadaeSBrandon Kim 
39*55dcadaeSBrandon Kim     // Read up to regionSize in case the offset + length overflowed
40*55dcadaeSBrandon Kim     uint32_t finalLength =
41*55dcadaeSBrandon Kim         (offset + length < regionSize) ? length : regionSize - offset;
42*55dcadaeSBrandon Kim     std::vector<uint8_t> results(finalLength);
43*55dcadaeSBrandon Kim 
44*55dcadaeSBrandon Kim     std::memcpy(results.data(), mmap.get().data() + offset, finalLength);
45*55dcadaeSBrandon Kim     return results;
46*55dcadaeSBrandon Kim }
47*55dcadaeSBrandon Kim 
48*55dcadaeSBrandon Kim uint32_t PciDataHandler::write(const uint32_t offset,
49*55dcadaeSBrandon Kim                                const std::span<const uint8_t> bytes)
50*55dcadaeSBrandon Kim {
51*55dcadaeSBrandon Kim     const size_t length = bytes.size();
52*55dcadaeSBrandon Kim     if (offset > regionSize || length == 0)
53*55dcadaeSBrandon Kim     {
54*55dcadaeSBrandon Kim         fmt::print(stderr,
55*55dcadaeSBrandon Kim                    "[write] Offset [{}] was bigger than regionSize [{}] "
56*55dcadaeSBrandon Kim                    "OR length [{}] was equal to 0\n",
57*55dcadaeSBrandon Kim                    offset, regionSize, length);
58*55dcadaeSBrandon Kim         return 0;
59*55dcadaeSBrandon Kim     }
60*55dcadaeSBrandon Kim 
61*55dcadaeSBrandon Kim     // Write up to regionSize in case the offset + length overflowed
62*55dcadaeSBrandon Kim     uint16_t finalLength =
63*55dcadaeSBrandon Kim         (offset + length < regionSize) ? length : regionSize - offset;
64*55dcadaeSBrandon Kim     std::memcpy(mmap.get().data() + offset, bytes.data(), finalLength);
65*55dcadaeSBrandon Kim     return finalLength;
66*55dcadaeSBrandon Kim }
67*55dcadaeSBrandon Kim 
68*55dcadaeSBrandon Kim uint32_t PciDataHandler::getMemoryRegionSize()
69*55dcadaeSBrandon Kim {
70*55dcadaeSBrandon Kim     return regionSize;
71*55dcadaeSBrandon Kim }
72*55dcadaeSBrandon Kim 
73*55dcadaeSBrandon Kim } // namespace bios_bmc_smm_error_logger
74