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