Skip to content

Commit 6ab550a

Browse files
Merge pull request #1138 from LedgerHQ/FWEO-1481-app-storage-crc
FWEO-1481: app storage crc
2 parents adaf020 + 62441da commit 6ab550a

File tree

9 files changed

+296
-67
lines changed

9 files changed

+296
-67
lines changed

include/app_storage.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@
3434
#define APP_STORAGE_HEADER_STRUCT_VERSION 1
3535

3636
///< Error codes
37+
#define APP_STORAGE_SUCCESS 0 ///< No error
3738
#define APP_STORAGE_ERR_INVALID_ARGUMENT -1 ///< Invalid argument
3839
#define APP_STORAGE_ERR_NO_DATA_AVAILABLE -2 ///< Address not available for reading
3940
#define APP_STORAGE_ERR_OVERFLOW -3 ///< Value too large to be stored
41+
#define APP_STORAGE_ERR_INVALID_HEADER -4 ///< Invalid storage header
42+
#define APP_STORAGE_ERR_CORRUPTED -5 ///< App storage is corrupted
4043

4144
/// Initial app data storage version
4245
#define APP_STORAGE_INITIAL_APP_DATA_VERSION 1

include/decorators.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,9 @@
7272
#else
7373
#define STATIC
7474
#endif
75+
76+
#if !defined(UNIT_TESTING)
77+
#define CONST const
78+
#else
79+
#define CONST
80+
#endif

lib_cxng/src/cx_crc32.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "lcx_crc.h"
2222
#include "cx_ram.h"
23+
#include "ox_crc.h"
2324

2425
static uint32_t reverse_32_bits(uint32_t value)
2526
{

lib_standard_app/app_storage.c

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,48 @@
1818
#include <string.h>
1919
#include "app_storage.h"
2020
#include "app_storage_internal.h"
21+
#include "lcx_crc.h"
2122
#include "os_nvm.h"
2223
#include "os_pic.h"
2324

2425
#define APP_STORAGE_ERASE_BLOCK_SIZE 256
2526

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-
3327
CONST app_storage_t app_storage_real __attribute__((section(".storage_section")));
3428
#define app_storage (*(volatile app_storage_t *) PIC(&app_storage_real))
3529

3630
/**
37-
* @brief checks if the app storage struct is initialized
31+
* @brief checks if the app storage struct is initialized and valid
3832
*/
39-
static bool app_storage_is_initalized(void)
33+
STATIC int32_t app_storage_is_initalized(void)
4034
{
41-
if (memcmp((const void *) &app_storage.header.tag, APP_STORAGE_TAG, APP_STORAGE_TAG_LEN) != 0) {
42-
return false;
35+
int32_t status = APP_STORAGE_ERR_INVALID_ARGUMENT;
36+
if (memcmp((const void *) &app_storage.header.tag, APP_STORAGE_TAG, APP_STORAGE_TAG_LEN) == 0) {
37+
status = APP_STORAGE_SUCCESS;
38+
}
39+
else {
40+
status = APP_STORAGE_ERR_INVALID_HEADER;
41+
goto error;
42+
}
43+
44+
uint32_t crc = cx_crc32((void *) &app_storage.header,
45+
sizeof(app_storage.header) + app_storage.header.size);
46+
if (crc != app_storage.crc) {
47+
// Invalid CRC, force reset
48+
status = APP_STORAGE_ERR_CORRUPTED;
4349
}
44-
return true;
50+
else {
51+
status = APP_STORAGE_SUCCESS;
52+
}
53+
54+
error:
55+
return status;
56+
}
57+
58+
static inline void update_crc(void)
59+
{
60+
uint32_t crc = cx_crc32((void *) &app_storage.header,
61+
sizeof(app_storage.header) + app_storage.header.size);
62+
nvm_write((void *) &app_storage.crc, &crc, sizeof(app_storage.crc));
4563
}
4664

4765
/**
@@ -60,6 +78,7 @@ static inline void system_header_reset(void)
6078
/* Setting up properties fields from the app makefile */
6179
header.properties = ((HAVE_APP_STORAGE_PROP_SETTINGS << 0) | (HAVE_APP_STORAGE_PROP_DATA << 1));
6280
nvm_write((void *) &app_storage.header, &header, sizeof(header));
81+
update_crc();
6382
}
6483

6584
/**
@@ -69,13 +88,31 @@ static inline void system_header_reset(void)
6988
* - sets initial size (0)
7089
* - sets struct and data versions (1)
7190
* - sets properties (from Makefile)
91+
*
92+
* @returns int32_t
93+
*
94+
* @retval APP_STORAGE_SUCCESS Application storage is successfully initialized.
95+
* @retval APP_STORAGE_ERR_CORRUPTED Error, application storage is corrupted.
7296
*/
73-
void app_storage_init(void)
97+
int32_t app_storage_init(void)
7498
{
75-
if (app_storage_is_initalized()) {
76-
return;
99+
int32_t status = app_storage_is_initalized();
100+
switch (status) {
101+
case APP_STORAGE_ERR_INVALID_HEADER:
102+
// Invalid tag or uninitialized storage, reset the HEADER
103+
system_header_reset();
104+
status = APP_STORAGE_SUCCESS;
105+
break;
106+
case APP_STORAGE_ERR_CORRUPTED:
107+
system_header_reset();
108+
break;
109+
case APP_STORAGE_SUCCESS:
110+
default:
111+
// Return status as-is
112+
break;
77113
}
78-
system_header_reset();
114+
115+
return status;
79116
}
80117

81118
/**
@@ -87,17 +124,24 @@ void app_storage_reset(void)
87124

88125
uint8_t erase_buf[APP_STORAGE_ERASE_BLOCK_SIZE] = {0};
89126
uint32_t offset = 0;
127+
bool need_update = false;
128+
90129
if (APP_STORAGE_SIZE > APP_STORAGE_ERASE_BLOCK_SIZE) {
91130
for (; offset < APP_STORAGE_SIZE - APP_STORAGE_ERASE_BLOCK_SIZE;
92131
offset += APP_STORAGE_ERASE_BLOCK_SIZE) {
93132
nvm_write((void *) &app_storage.data[offset],
94133
(void *) erase_buf,
95134
APP_STORAGE_ERASE_BLOCK_SIZE);
96135
}
136+
need_update = true;
97137
}
98138
if (APP_STORAGE_SIZE > offset) {
99139
nvm_write(
100140
(void *) &app_storage.data[offset], (void *) erase_buf, APP_STORAGE_SIZE - offset);
141+
need_update = true;
142+
}
143+
if (need_update) {
144+
update_crc();
101145
}
102146
}
103147

@@ -141,6 +185,7 @@ void app_storage_increment_data_version(void)
141185
}
142186
nvm_write(
143187
(void *) &app_storage.header.data_version, (void *) &data_version, sizeof(data_version));
188+
update_crc();
144189
}
145190

146191
/**
@@ -150,6 +195,7 @@ void app_storage_set_data_version(uint32_t data_version)
150195
{
151196
nvm_write(
152197
(void *) &app_storage.header.data_version, (void *) &data_version, sizeof(data_version));
198+
update_crc();
153199
}
154200

155201
/**
@@ -181,6 +227,8 @@ int32_t app_storage_write(const void *buf, uint32_t nbyte, uint32_t offset)
181227
if (app_storage.header.size < max_offset) {
182228
nvm_write((void *) &app_storage.header.size, (void *) &max_offset, sizeof(max_offset));
183229
}
230+
update_crc();
231+
184232
return nbyte;
185233
}
186234

lib_standard_app/app_storage_internal.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,30 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*****************************************************************************/
16-
#ifdef HAVE_APP_STORAGE
16+
#if defined(HAVE_APP_STORAGE) || defined(HAVE_BOLOS)
1717

1818
#pragma once
1919

2020
#include "app_storage.h"
2121

22-
/* The storage consists of the system and the app parts */
22+
/**
23+
* @brief The storage consists of the system and the app parts
24+
*/
2325
typedef struct app_storage_s {
26+
uint32_t crc; ///< CRC32 of the app storage header and data
2427
app_storage_header_t header;
2528
uint8_t data[APP_STORAGE_SIZE];
2629
} app_storage_t;
2730

28-
void app_storage_init(void);
31+
/**
32+
* @brief initializes the application storage.
33+
*
34+
* @returns int32_t Initialization status.
35+
*
36+
* @retval APP_STORAGE_SUCCESS Application storage is successfully initialized.
37+
* @retval APP_STORAGE_ERR_CORRUPTED Error, application storage is corrupted.
38+
*
39+
*/
40+
int32_t app_storage_init(void);
2941

30-
#endif /* #ifdef HAVE_APP_STORAGE */
42+
#endif /* HAVE_APP_STORAGE || HAVE_BOLOS */

unit-tests/app_storage/CMakeLists.txt

Lines changed: 71 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ endif()
77
# project information
88
project(unit_tests
99
VERSION 0.1
10-
DESCRIPTION "Unit tests for UX_SYNC"
10+
DESCRIPTION "Unit tests for Application storage"
1111
LANGUAGES C)
1212

13-
1413
# guard against bad build-type strings
1514
if (NOT CMAKE_BUILD_TYPE)
1615
set(CMAKE_BUILD_TYPE "Debug")
@@ -22,42 +21,80 @@ ENABLE_TESTING()
2221
# specify C standard
2322
set(CMAKE_C_STANDARD 11)
2423
set(CMAKE_C_STANDARD_REQUIRED True)
25-
add_compile_definitions(SCREEN_SIZE_WALLET)
26-
add_compile_definitions(USB_SEGMENT_SIZE=64)
27-
add_compile_definitions(HAVE_NBGL)
28-
add_compile_definitions(WITH_STDIO)
29-
add_compile_definitions(HAVE_APP_STORAGE)
30-
add_compile_definitions(APP_STORAGE_SIZE=5555)
31-
add_compile_definitions(HAVE_APP_STORAGE_PROP_SETTINGS)
32-
add_compile_definitions(HAVE_APP_STORAGE_PROP_DATA)
33-
3424

35-
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall ${DEFINES} -g -O0 --coverage")
36-
37-
set(GCC_COVERAGE_LINK_FLAGS "--coverage -lgcov")
38-
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
39-
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
25+
set(CMAKE_BUILD_TYPE Debug)
4026

4127
# guard against in-source builds
4228
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
4329
message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ")
4430
endif()
4531

46-
add_compile_definitions(TEST)
47-
48-
include_directories(.)
49-
include_directories(../../target/stax/include)
50-
include_directories(../../include)
51-
include_directories(../../lib_nbgl/include)
52-
include_directories(../../lib_nbgl/include/fonts)
53-
include_directories(../../lib_ux_nbgl)
54-
include_directories(../../lib_standard_app)
55-
56-
add_executable(test_app_storage test_app_storage.c)
57-
58-
add_library(app_storage_stubs SHARED app_storage_stubs.c)
59-
add_library(app_storage SHARED ../../lib_standard_app/app_storage.c)
60-
61-
target_link_libraries(test_app_storage PUBLIC cmocka gcov app_storage app_storage_stubs)
62-
63-
add_test(test_app_storage test_app_storage)
32+
set(TEST test_app_storage)
33+
34+
add_executable(
35+
${TEST}
36+
test_app_storage.c
37+
app_storage_stubs.c
38+
../../lib_standard_app/app_storage.c
39+
../../lib_cxng/src/cx_crc32.c
40+
../../mock/src/cx_crc.c
41+
)
42+
43+
target_include_directories(
44+
${TEST}
45+
PRIVATE
46+
./
47+
../../target/stax/include
48+
../../include
49+
../../lib_cxng/include
50+
../../lib_nbgl/include
51+
../../lib_nbgl/include/fonts
52+
../../lib_ux_nbgl
53+
../../lib_standard_app
54+
../mock/include
55+
)
56+
57+
target_compile_options(
58+
${TEST}
59+
PRIVATE
60+
-Wall
61+
-Werror
62+
-O0
63+
--coverage
64+
-fsanitize=address,undefined
65+
)
66+
67+
target_compile_definitions(
68+
${TEST}
69+
PRIVATE
70+
UNIT_TESTING
71+
SCREEN_SIZE_WALLET
72+
USB_SEGMENT_SIZE=64
73+
HAVE_NBGL
74+
WITH_STDIO
75+
HAVE_APP_STORAGE
76+
APP_STORAGE_SIZE=5555
77+
HAVE_APP_STORAGE_PROP_SETTINGS
78+
HAVE_APP_STORAGE_PROP_DATA
79+
HAVE_CRC
80+
)
81+
82+
target_link_libraries(
83+
${TEST}
84+
PRIVATE
85+
cmocka
86+
gcov
87+
)
88+
89+
target_link_options(
90+
${TEST}
91+
PRIVATE
92+
--coverage
93+
-lgcov
94+
-fsanitize=address,undefined
95+
)
96+
97+
add_test(
98+
NAME ${TEST}
99+
COMMAND ${TEST}
100+
)

unit-tests/app_storage/app_storage_stubs.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@
1818
#include <setjmp.h>
1919
#include <string.h>
2020

21+
#ifdef UNIT_TESTING
22+
// When defined cmocka redefine malloc/free which does not work well with
23+
// address-sanitizer
24+
#undef UNIT_TESTING
25+
#include <cmocka.h>
26+
#define UNIT_TESTING
27+
#else
28+
#include <cmocka.h>
29+
#endif
30+
2131
#include <cmocka.h>
2232
#include <malloc.h>
2333
#include <stdio.h>

0 commit comments

Comments
 (0)