diff --git a/Makefile.standard_app b/Makefile.standard_app index 6aa7cbfe6..4bb3af1a5 100644 --- a/Makefile.standard_app +++ b/Makefile.standard_app @@ -47,6 +47,14 @@ ifeq ($(ENABLE_SWAP), 1) DEFINES += HAVE_SWAP endif +##################################################################### +# APP STORAGE # +##################################################################### +ifeq ($(ENABLE_APP_STORAGE), 1) + HAVE_APP_STORAGE = 1 + DEFINES += HAVE_APP_STORAGE +endif + ##################################################################### # DEBUG # ##################################################################### diff --git a/include/app_storage.h b/include/app_storage.h new file mode 100644 index 000000000..4293890dc --- /dev/null +++ b/include/app_storage.h @@ -0,0 +1,81 @@ +/***************************************************************************** + * (c) 2024 Ledger SAS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#pragma once + +#include +#include + +#ifndef HAVE_BOLOS +/* "app_storage_data.h" needs to be created in all apps including this file */ +#include "app_storage_data.h" +#endif // HAVE_BOLOS + +///< bit to indicate in properties that the application storage contains settings +#define APP_STORAGE_PROP_SETTINGS (1 << 0) +///< bit to indicate in properties that the application contains data +#define APP_STORAGE_PROP_DATA (1 << 1) + +/** + * @brief Structure defining the header of application storage header + * + */ +typedef struct app_storage_header_s { + char tag[4]; ///< ['N','V','R','A'] array, when properly initialized + uint32_t size; ///< size in bytes of the data (app_storage_data_t structure) + uint16_t struct_version; ///< version of the structure of data (to be set once at first + ///< application start-up) + uint16_t properties; ///< used as a bitfield to set properties, like: contains settings, + ///< contains sensitive data + uint32_t data_version; ///< version of the content of data (to be updated every time data are + ///< updated) +} app_storage_header_t; + +/** + * @brief Structure defining the application storage + * + */ +typedef struct app_storage_s { + app_storage_header_t header; ///< header describing the data +#ifndef HAVE_BOLOS + app_storage_data_t data; ///< application data, app_storage_data_t must be defined in + ///< "app_storage_data.h" file +#endif // HAVE_BOLOS +} app_storage_t; + +#ifndef HAVE_BOLOS +/** + * @brief This variable must be defined in Application code, and never used directly, + * except by @ref N_nvram + * + */ +extern const app_storage_t N_app_storage_real; + +/** + * @brief To be used by function accessing application storage data (not N_storage_real) + * + */ +#define N_app_storage (*(volatile app_storage_t *) PIC(&N_app_storage_real)) + +void app_storage_init(uint32_t data_version); +uint32_t app_storage_get_size(void); +uint16_t app_storage_get_struct_version(void); +uint16_t app_storage_get_properties(void); +uint32_t app_storage_get_data_version(void); +bool app_storage_is_initalized(void); +void app_storage_set_data_version(uint32_t data_version); + +#endif // HAVE_BOLOS diff --git a/lib_standard_app/app_storage.c b/lib_standard_app/app_storage.c new file mode 100644 index 000000000..c8ad9ddc6 --- /dev/null +++ b/lib_standard_app/app_storage.c @@ -0,0 +1,106 @@ +/***************************************************************************** + * (c) 2024 Ledger SAS. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *****************************************************************************/ + +#ifdef HAVE_APP_STORAGE +#include +#include "app_storage.h" +#include "os_nvm.h" +#include "os_pic.h" + +// TODO: Create new section for the linker script +/*app_storage app_storage_real __attribute__((section(".bss.app_storage")));*/ +const app_storage_t N_app_storage_real; + +/** + * @brief init header of application storage structure : + * - set "NVRA" tag + * - set size + * - set struct and data versions + * - set properties + * @param data_version Version of the data + */ +void app_storage_init(uint32_t data_version) +{ + app_storage_header_t header = {0}; + + memcpy(header.tag, (void *) "NVRA", 4); + // APP_STORAGE_DATA_STRUCT_VERSION and APP_STORAGE_PROPERTIES must be defined in + // app_storage_data.h + header.struct_version = APP_STORAGE_DATA_STRUCT_VERSION; + header.data_version = data_version; + header.properties = APP_STORAGE_PROPERTIES; + // TODO: Doing this lead to have app storage bigger than needed + header.size = sizeof(app_storage_data_t); + nvm_write((void *) &N_app_storage.header, &header, sizeof(header)); +} + +/** + * @brief get the size of app data + */ +uint32_t app_storage_get_size(void) +{ + return N_app_storage.header.size; +} + +/** + * @brief get the version of app data structure + */ +uint16_t app_storage_get_struct_version(void) +{ + return N_app_storage.header.struct_version; +} + +/** + * @brief get the version of app data + */ +uint32_t app_storage_get_data_version(void) +{ + return N_app_storage.header.data_version; +} + +/** + * @brief get the properties of app data + */ +uint16_t app_storage_get_properties(void) +{ + return N_app_storage.header.properties; +} + +/** + * @brief ensure app storage struct is initialized + */ +bool app_storage_is_initalized(void) +{ + if (memcmp((void *) N_app_storage.header.tag, "NVRA", 4)) { + return false; + } + if (N_app_storage.header.size == 0) { + return false; + } + return true; +} + +/** + * @brief set data version of app data + */ +void app_storage_set_data_version(uint32_t data_version) +{ + nvm_write((void *) &N_app_storage.header.data_version, + (void *) &data_version, + sizeof(N_app_storage.header.data_version)); +} + +#endif // HAVE_APP_STORAGE