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