blob: 4dbdd772114d43722996e5017fb89409043d46c8 [file] [log] [blame]
Alexander Hansen4e1142d2025-07-25 17:07:27 +02001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2022 Equinix, Inc.
Zev Weiss309c0b12022-02-25 01:44:12 +00003
4#pragma once
5
6#include <cstdint>
Patrick Williamsb9a1f962024-07-13 16:34:49 -05007#include <cstdio>
Zev Weiss309c0b12022-02-25 01:44:12 +00008#include <functional>
9#include <map>
10#include <optional>
11#include <utility>
12
13extern "C"
14{
15// For I2C_SMBUS_BLOCK_MAX
16#include <linux/i2c.h>
17}
18
19// A function to read up to I2C_SMBUS_BLOCK_MAX bytes of FRU data. Returns
20// negative on error, or the number of bytes read otherwise, which may be (but
21// is not guaranteed to be) less than len if the read would go beyond the end
22// of the FRU.
23using ReadBlockFunc =
24 std::function<int64_t(off_t offset, size_t len, uint8_t* outbuf)>;
25
26// A caching wrapper around a ReadBlockFunc
27class FRUReader
28{
29 public:
Ed Tanous3013fb42022-07-09 08:27:06 -070030 explicit FRUReader(ReadBlockFunc readFunc) : readFunc(std::move(readFunc))
Zev Weiss309c0b12022-02-25 01:44:12 +000031 {}
32 // The ::read() operation here is analogous to ReadBlockFunc (with the same
33 // return value semantics), but is not subject to SMBus block size
34 // limitations; it can read as much data as needed in a single call.
35 ssize_t read(off_t start, size_t len, uint8_t* outbuf);
36
37 private:
38 static constexpr size_t cacheBlockSize = 32;
39 static_assert(cacheBlockSize <= I2C_SMBUS_BLOCK_MAX);
40 using CacheBlock = std::array<uint8_t, cacheBlockSize>;
41
42 // indexed by block number (byte number / block size)
43 using Cache = std::map<uint32_t, CacheBlock>;
44
45 ReadBlockFunc readFunc;
46 Cache cache;
47
48 // byte offset of the end of the FRU (if readFunc has reported it)
49 std::optional<size_t> eof;
50};