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