| Alexander Hansen | 4e1142d | 2025-07-25 17:07:27 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: Apache-2.0 | 
 | 2 | // SPDX-FileCopyrightText: Copyright 2022 Equinix, Inc. | 
| Zev Weiss | 309c0b1 | 2022-02-25 01:44:12 +0000 | [diff] [blame] | 3 |  | 
 | 4 | #include "fru_reader.hpp" | 
 | 5 |  | 
 | 6 | #include <cstring> | 
 | 7 |  | 
 | 8 | ssize_t FRUReader::read(off_t start, size_t len, uint8_t* outbuf) | 
 | 9 | { | 
 | 10 |     size_t done = 0; | 
 | 11 |     size_t remaining = len; | 
 | 12 |     size_t cursor = start; | 
 | 13 |     while (done < len) | 
 | 14 |     { | 
 | 15 |         if (eof.has_value() && cursor >= eof.value()) | 
 | 16 |         { | 
 | 17 |             break; | 
 | 18 |         } | 
 | 19 |  | 
| Ed Tanous | 3013fb4 | 2022-07-09 08:27:06 -0700 | [diff] [blame] | 20 |         const uint8_t* blkData = nullptr; | 
 | 21 |         size_t available = 0; | 
| Zev Weiss | 309c0b1 | 2022-02-25 01:44:12 +0000 | [diff] [blame] | 22 |         size_t blk = cursor / cacheBlockSize; | 
 | 23 |         size_t blkOffset = cursor % cacheBlockSize; | 
 | 24 |         auto findBlk = cache.find(blk); | 
 | 25 |         if (findBlk == cache.end()) | 
 | 26 |         { | 
 | 27 |             // miss, populate cache | 
 | 28 |             uint8_t* newData = cache[blk].data(); | 
| Patrick Williams | b707743 | 2024-08-16 15:22:21 -0400 | [diff] [blame] | 29 |             int64_t ret = | 
 | 30 |                 readFunc(blk * cacheBlockSize, cacheBlockSize, newData); | 
| Zev Weiss | 309c0b1 | 2022-02-25 01:44:12 +0000 | [diff] [blame] | 31 |  | 
 | 32 |             // if we've reached the end of the eeprom, record its size | 
 | 33 |             if (ret >= 0 && static_cast<size_t>(ret) < cacheBlockSize) | 
 | 34 |             { | 
 | 35 |                 eof = (blk * cacheBlockSize) + ret; | 
 | 36 |             } | 
 | 37 |  | 
 | 38 |             if (ret <= 0) | 
 | 39 |             { | 
 | 40 |                 // don't leave empty blocks in the cache | 
 | 41 |                 cache.erase(blk); | 
| Ed Tanous | 3013fb4 | 2022-07-09 08:27:06 -0700 | [diff] [blame] | 42 |                 return done != 0U ? done : ret; | 
| Zev Weiss | 309c0b1 | 2022-02-25 01:44:12 +0000 | [diff] [blame] | 43 |             } | 
 | 44 |  | 
 | 45 |             blkData = newData; | 
 | 46 |             available = ret; | 
 | 47 |         } | 
 | 48 |         else | 
 | 49 |         { | 
 | 50 |             // hit, use cached data | 
 | 51 |             blkData = findBlk->second.data(); | 
 | 52 |  | 
 | 53 |             // if the hit is to the block containing the (previously | 
 | 54 |             // discovered on the miss that populated it) end of the eeprom, | 
 | 55 |             // don't copy spurious bytes past the end | 
 | 56 |             if (eof.has_value() && (eof.value() / cacheBlockSize == blk)) | 
 | 57 |             { | 
 | 58 |                 available = eof.value() % cacheBlockSize; | 
 | 59 |             } | 
 | 60 |             else | 
 | 61 |             { | 
 | 62 |                 available = cacheBlockSize; | 
 | 63 |             } | 
 | 64 |         } | 
 | 65 |  | 
 | 66 |         size_t toCopy = (blkOffset >= available) | 
 | 67 |                             ? 0 | 
 | 68 |                             : std::min(available - blkOffset, remaining); | 
 | 69 |  | 
| Ed Tanous | 3013fb4 | 2022-07-09 08:27:06 -0700 | [diff] [blame] | 70 |         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) | 
| Zev Weiss | 309c0b1 | 2022-02-25 01:44:12 +0000 | [diff] [blame] | 71 |         memcpy(outbuf + done, blkData + blkOffset, toCopy); | 
 | 72 |         cursor += toCopy; | 
 | 73 |         done += toCopy; | 
 | 74 |         remaining -= toCopy; | 
 | 75 |     } | 
 | 76 |  | 
 | 77 |     return done; | 
 | 78 | } |