Line data Source code
1 : // Copyright 2024 Accenture.
2 :
3 : #include "eeprom/EepromDriver.h"
4 :
5 : #include "bsp/Bsp.h"
6 :
7 : #include <sys/stat.h>
8 :
9 : #include <cstdio>
10 :
11 : #include <cstring>
12 : #include <fcntl.h>
13 : #include <unistd.h>
14 :
15 : namespace eeprom
16 : {
17 :
18 8 : EepromDriver::EepromDriver() : eepromFd(-1)
19 : {
20 8 : bool fileExisted = false;
21 :
22 : // Try opening existing file first
23 : // POSIX open uses an optional mode argument.
24 : // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
25 8 : eepromFd = open(eepromFilePath.c_str(), O_RDWR);
26 :
27 8 : if (eepromFd != -1)
28 : {
29 7 : fileExisted = true;
30 : }
31 : else
32 : {
33 : // If opening fails, try creating it
34 : // POSIX open uses an optional mode argument.
35 : // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
36 1 : eepromFd = open(eepromFilePath.c_str(), O_RDWR | O_CREAT, 0600);
37 : }
38 :
39 : // Initialize only for newly created files
40 8 : if (eepromFd != -1 && !fileExisted)
41 : {
42 : // Resize EEPROM file
43 1 : if (ftruncate(eepromFd, EEPROM_SIZE) == 0)
44 : {
45 : // Fill with 0xFF
46 : uint8_t buffer[EEPROM_SIZE];
47 1 : memset(buffer, 0xFF, EEPROM_SIZE);
48 :
49 : // After truncate, file offset is guaranteed to be 0
50 1 : ssize_t const written = ::write(eepromFd, buffer, EEPROM_SIZE);
51 :
52 1 : if (written == static_cast<ssize_t>(EEPROM_SIZE))
53 : {
54 1 : fsync(eepromFd);
55 : }
56 : }
57 : }
58 8 : }
59 :
60 6 : bsp::BspReturnCode EepromDriver::init()
61 : {
62 6 : if (eepromFd == -1)
63 : {
64 0 : return ::bsp::BSP_ERROR;
65 : }
66 :
67 : // Verify file size is correct
68 : struct stat fileStat;
69 6 : if (fstat(eepromFd, &fileStat) != 0)
70 : {
71 0 : return ::bsp::BSP_ERROR;
72 : }
73 :
74 : // If file size doesn't match expected EEPROM size, resize it
75 6 : if (fileStat.st_size != EEPROM_SIZE)
76 : {
77 0 : if (ftruncate(eepromFd, EEPROM_SIZE) != 0)
78 : {
79 0 : return ::bsp::BSP_ERROR;
80 : }
81 :
82 0 : if (fsync(eepromFd) != 0)
83 : {
84 0 : return ::bsp::BSP_ERROR;
85 : }
86 : }
87 :
88 6 : return ::bsp::BSP_OK;
89 : }
90 :
91 : bsp::BspReturnCode
92 5 : EepromDriver::write(uint32_t const address, uint8_t const* const buffer, uint32_t const length)
93 : {
94 5 : bool success
95 5 : = ((-1 != eepromFd) && (address < EEPROM_SIZE) && (length <= (EEPROM_SIZE - address)));
96 :
97 5 : success = (success && (lseek(eepromFd, address, SEEK_SET) != -1));
98 5 : success = (success && (::write(eepromFd, buffer, length) == static_cast<ssize_t>(length)));
99 5 : success = (success && (fsync(eepromFd) == 0));
100 :
101 5 : if (!success)
102 : {
103 2 : (void)std::fputs("Failed to write to EEPROM file\r\n", stderr);
104 2 : return ::bsp::BSP_ERROR;
105 : }
106 3 : return ::bsp::BSP_OK;
107 : }
108 :
109 : bsp::BspReturnCode
110 5 : EepromDriver::read(uint32_t const address, uint8_t* const buffer, uint32_t const length)
111 : {
112 5 : bool success
113 5 : = ((-1 != eepromFd) && (address < EEPROM_SIZE) && (length <= (EEPROM_SIZE - address)));
114 :
115 5 : success = (success && (lseek(eepromFd, address, SEEK_SET) != -1));
116 5 : success = (success && (::read(eepromFd, buffer, length) == static_cast<ssize_t>(length)));
117 :
118 5 : if (!success)
119 : {
120 2 : (void)std::fputs("Failed to read from EEPROM file\r\n", stderr);
121 2 : return ::bsp::BSP_ERROR;
122 : }
123 3 : return ::bsp::BSP_OK;
124 : }
125 :
126 16 : EepromDriver::~EepromDriver()
127 : {
128 8 : if (-1 != eepromFd)
129 : {
130 8 : fsync(eepromFd);
131 8 : close(eepromFd);
132 8 : eepromFd = -1;
133 : }
134 8 : }
135 :
136 : } // namespace eeprom
|