xref: /openbmc/entity-manager/src/fru_device/fru_reader.hpp (revision 3cbff97f6980709aec45730515e48e85c7c02cc1)
1*3cbff97fSChristopher Meis /*
2*3cbff97fSChristopher Meis // Copyright (c) 2022 Equinix, Inc.
3*3cbff97fSChristopher Meis //
4*3cbff97fSChristopher Meis // Licensed under the Apache License, Version 2.0 (the "License");
5*3cbff97fSChristopher Meis // you may not use this file except in compliance with the License.
6*3cbff97fSChristopher Meis // You may obtain a copy of the License at
7*3cbff97fSChristopher Meis //
8*3cbff97fSChristopher Meis //      http://www.apache.org/licenses/LICENSE-2.0
9*3cbff97fSChristopher Meis //
10*3cbff97fSChristopher Meis // Unless required by applicable law or agreed to in writing, software
11*3cbff97fSChristopher Meis // distributed under the License is distributed on an "AS IS" BASIS,
12*3cbff97fSChristopher Meis // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*3cbff97fSChristopher Meis // See the License for the specific language governing permissions and
14*3cbff97fSChristopher Meis // limitations under the License.
15*3cbff97fSChristopher Meis */
16*3cbff97fSChristopher Meis 
17*3cbff97fSChristopher Meis #pragma once
18*3cbff97fSChristopher Meis 
19*3cbff97fSChristopher Meis #include <cstdint>
20*3cbff97fSChristopher Meis #include <cstdio>
21*3cbff97fSChristopher Meis #include <functional>
22*3cbff97fSChristopher Meis #include <map>
23*3cbff97fSChristopher Meis #include <optional>
24*3cbff97fSChristopher Meis #include <utility>
25*3cbff97fSChristopher Meis 
26*3cbff97fSChristopher Meis extern "C"
27*3cbff97fSChristopher Meis {
28*3cbff97fSChristopher Meis // For I2C_SMBUS_BLOCK_MAX
29*3cbff97fSChristopher Meis #include <linux/i2c.h>
30*3cbff97fSChristopher Meis }
31*3cbff97fSChristopher Meis 
32*3cbff97fSChristopher Meis // A function to read up to I2C_SMBUS_BLOCK_MAX bytes of FRU data.  Returns
33*3cbff97fSChristopher Meis // negative on error, or the number of bytes read otherwise, which may be (but
34*3cbff97fSChristopher Meis // is not guaranteed to be) less than len if the read would go beyond the end
35*3cbff97fSChristopher Meis // of the FRU.
36*3cbff97fSChristopher Meis using ReadBlockFunc =
37*3cbff97fSChristopher Meis     std::function<int64_t(off_t offset, size_t len, uint8_t* outbuf)>;
38*3cbff97fSChristopher Meis 
39*3cbff97fSChristopher Meis // A caching wrapper around a ReadBlockFunc
40*3cbff97fSChristopher Meis class FRUReader
41*3cbff97fSChristopher Meis {
42*3cbff97fSChristopher Meis   public:
FRUReader(ReadBlockFunc readFunc)43*3cbff97fSChristopher Meis     explicit FRUReader(ReadBlockFunc readFunc) : readFunc(std::move(readFunc))
44*3cbff97fSChristopher Meis     {}
45*3cbff97fSChristopher Meis     // The ::read() operation here is analogous to ReadBlockFunc (with the same
46*3cbff97fSChristopher Meis     // return value semantics), but is not subject to SMBus block size
47*3cbff97fSChristopher Meis     // limitations; it can read as much data as needed in a single call.
48*3cbff97fSChristopher Meis     ssize_t read(off_t start, size_t len, uint8_t* outbuf);
49*3cbff97fSChristopher Meis 
50*3cbff97fSChristopher Meis   private:
51*3cbff97fSChristopher Meis     static constexpr size_t cacheBlockSize = 32;
52*3cbff97fSChristopher Meis     static_assert(cacheBlockSize <= I2C_SMBUS_BLOCK_MAX);
53*3cbff97fSChristopher Meis     using CacheBlock = std::array<uint8_t, cacheBlockSize>;
54*3cbff97fSChristopher Meis 
55*3cbff97fSChristopher Meis     // indexed by block number (byte number / block size)
56*3cbff97fSChristopher Meis     using Cache = std::map<uint32_t, CacheBlock>;
57*3cbff97fSChristopher Meis 
58*3cbff97fSChristopher Meis     ReadBlockFunc readFunc;
59*3cbff97fSChristopher Meis     Cache cache;
60*3cbff97fSChristopher Meis 
61*3cbff97fSChristopher Meis     // byte offset of the end of the FRU (if readFunc has reported it)
62*3cbff97fSChristopher Meis     std::optional<size_t> eof;
63*3cbff97fSChristopher Meis };
64