Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
app_storage.c
Go to the documentation of this file.
1/*****************************************************************************
2 * (c) 2024 Ledger SAS.
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#ifdef HAVE_APP_STORAGE
18#include <string.h>
19#include "app_storage.h"
21#include "os_nvm.h"
22#include "os_pic.h"
23
24#define APP_STORAGE_ERASE_BLOCK_SIZE 256
25
26/* In order to be used in unit testing */
27#if !defined(TEST)
28#define CONST const
29#else
30#define CONST
31#endif
32
33CONST app_storage_t app_storage_real __attribute__((section(".storage_section")));
34#define app_storage (*(volatile app_storage_t *) PIC(&app_storage_real))
35
39static bool app_storage_is_initalized(void)
40{
41 if (memcmp((const void *) &app_storage.header.tag, APP_STORAGE_TAG, APP_STORAGE_TAG_LEN) != 0) {
42 return false;
43 }
44 return true;
45}
46
50static inline void system_header_reset(void)
51{
52 /* Starting with zero application data size */
53 app_storage_header_t header = {0};
54
55 memcpy(&header.tag, (void *) APP_STORAGE_TAG, APP_STORAGE_TAG_LEN);
56 /* Setting up current system structure version */
57 header.struct_version = APP_STORAGE_HEADER_STRUCT_VERSION;
58 /* Setting up initial application datat version */
59 header.data_version = APP_STORAGE_INITIAL_APP_DATA_VERSION;
60 /* Setting up properties fields from the app makefile */
61 header.properties = ((HAVE_APP_STORAGE_PROP_SETTINGS << 0) | (HAVE_APP_STORAGE_PROP_DATA << 1));
62 nvm_write((void *) &app_storage.header, &header, sizeof(header));
63}
64
73void app_storage_init(void)
74{
75 if (app_storage_is_initalized()) {
76 return;
77 }
78 system_header_reset();
79}
80
84void app_storage_reset(void)
85{
86 system_header_reset();
87
88 uint8_t erase_buf[APP_STORAGE_ERASE_BLOCK_SIZE] = {0};
89 uint32_t offset = 0;
90 if (APP_STORAGE_SIZE > APP_STORAGE_ERASE_BLOCK_SIZE) {
91 for (; offset < APP_STORAGE_SIZE - APP_STORAGE_ERASE_BLOCK_SIZE;
92 offset += APP_STORAGE_ERASE_BLOCK_SIZE) {
93 nvm_write((void *) &app_storage.data[offset],
94 (void *) erase_buf,
95 APP_STORAGE_ERASE_BLOCK_SIZE);
96 }
97 }
98 if (APP_STORAGE_SIZE > offset) {
99 nvm_write(
100 (void *) &app_storage.data[offset], (void *) erase_buf, APP_STORAGE_SIZE - offset);
101 }
102}
103
107uint32_t app_storage_get_size(void)
108{
109 return app_storage.header.size;
110}
111
115uint32_t app_storage_get_data_version(void)
116{
117 return app_storage.header.data_version;
118}
119
123uint16_t app_storage_get_properties(void)
124{
125 return app_storage.header.properties;
126}
127
131void app_storage_increment_data_version(void)
132{
133 uint32_t data_version = app_storage.header.data_version;
134 data_version++;
135 if (data_version == 0) {
136 /* wraparound - we consider we'll never achieve this number,
137 knowing that the the maximum number of Flash write cycles
138 may be around 100 000.
139 */
140 data_version = APP_STORAGE_INITIAL_APP_DATA_VERSION;
141 }
142 nvm_write(
143 (void *) &app_storage.header.data_version, (void *) &data_version, sizeof(data_version));
144}
145
149void app_storage_set_data_version(uint32_t data_version)
150{
151 nvm_write(
152 (void *) &app_storage.header.data_version, (void *) &data_version, sizeof(data_version));
153}
154
158int32_t app_storage_write(const void *buf, uint32_t nbyte, uint32_t offset)
159{
160 /* Input parameters verification */
161 if (buf == NULL) {
162 return APP_STORAGE_ERR_INVALID_ARGUMENT;
163 }
164 if (nbyte == 0) {
165 return APP_STORAGE_ERR_INVALID_ARGUMENT;
166 }
167 uint32_t max_offset = 0;
168 if (__builtin_add_overflow(offset, nbyte, &max_offset)) {
169 return APP_STORAGE_ERR_INVALID_ARGUMENT;
170 }
171
172 /* Checking the app storage boundaries */
173 if (max_offset > APP_STORAGE_SIZE) {
174 return APP_STORAGE_ERR_OVERFLOW;
175 }
176
177 /* Updating data */
178 nvm_write((void *) &app_storage.data[offset], (void *) buf, nbyte);
179
180 /* Updating size if it increased */
181 if (app_storage.header.size < max_offset) {
182 nvm_write((void *) &app_storage.header.size, (void *) &max_offset, sizeof(max_offset));
183 }
184 return nbyte;
185}
186
190int32_t app_storage_read(void *buf, uint32_t nbyte, uint32_t offset)
191{
192 /* Input parameters verification */
193 if (buf == NULL) {
194 return APP_STORAGE_ERR_INVALID_ARGUMENT;
195 }
196 if (nbyte == 0) {
197 return APP_STORAGE_ERR_INVALID_ARGUMENT;
198 }
199 uint32_t max_offset = 0;
200 if (__builtin_add_overflow(offset, nbyte, &max_offset)) {
201 return APP_STORAGE_ERR_INVALID_ARGUMENT;
202 }
203
204 /* Checking if the data has been already written */
205 if (max_offset > app_storage.header.size) {
206 return APP_STORAGE_ERR_NO_DATA_AVAILABLE;
207 }
208
209 /* Reading data */
210 memcpy((void *) buf, (void *) &app_storage.data[offset], nbyte);
211
212 return nbyte;
213}
214
215#endif // HAVE_APP_STORAGE
__attribute__((section("._nbgl_fonts_"))) const
return the non-unicode font corresponding to the given font ID
Definition nbgl_fonts.c:67
unsigned short uint16_t
Definition usbd_conf.h:54
unsigned char uint8_t
Definition usbd_conf.h:53