blob: 4c24d6f71c9103a9840344d726841a951b9c6807 [file] [log] [blame]
/**
******************************************************************************
* @file flash_wb.c
* @author MCD Application Team
* @brief Middleware between keymanager and flahs_driver ,
* to manage key needed for Matter
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "flash_wb.h"
#include "flash_driver.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
/* Private defines -----------------------------------------------------------*/
#define MATTER_KEY_NAME_MAX_LENGTH (15 * 2) // ADD Max key name string size is 30 "keyType...;KeyName..."
// ^ STM32STORE_MAX_KEY_SIZE
#define NVM_OFFSET_KEY 512
#define NVM_END_FLASH
#define NVM_BLOCK_SIZE NVM_OFFSET_KEY
#define FLASH_START 0x08000000
#define DEFAULT_VALUE 0xFF
#define NB_SECTOR 3
#define NVM_MATTER_ADDR_INIT_SECURE 0x08082000
#define NVM_MATTER_ADDR_INIT_SECURE_PTR ((void * const) NVM_MATTER_ADDR_INIT_SECURE)
#define SECTOR_SIZE_SECURE 4096 * 2
#define NVM_MATTER_ADDR_INIT_NO_SECURE NVM_MATTER_ADDR_INIT_SECURE + SECTOR_SIZE_SECURE
#define NVM_MATTER_ADDR_INIT_NOSECURE_PTR ((void * const) NVM_MATTER_ADDR_INIT_NO_SECURE)
#define SECTOR_SIZE_NO_SECURE 4096
#define NVM_SIZE_FLASH (SECTOR_SIZE_SECURE + SECTOR_SIZE_NO_SECURE)
#define NVM_MAX_KEY NVM_SIZE_FLASH / NVM_OFFSET_KEY
typedef struct
{
NVM_Sector id_sector;
uint8_t * ram_ptr;
size_t sector_size;
} NVM_Sector_Struct;
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
uint8_t ram_nvm[SECTOR_SIZE_SECURE + SECTOR_SIZE_NO_SECURE] = { 0 };
const NVM_Sector_Struct sector_no_secure = { .id_sector = SECTOR_NO_SECURE,
.ram_ptr = ram_nvm + SECTOR_SIZE_SECURE,
.sector_size = SECTOR_SIZE_NO_SECURE };
//*SIMULATE TO EXAMPLE*
const NVM_Sector_Struct sector_secure = { .id_sector = SECTOR_SECURE, .ram_ptr = ram_nvm, .sector_size = SECTOR_SIZE_SECURE };
uint8_t CheckSanity = 0;
/* Global variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static uint8_t flash_get(uint8_t * KeyValue, uint8_t * KeyAddr, size_t KeySize, size_t * read_by_size);
static uint8_t flash_update(const NVM_Sector_Struct select_sector, uint8_t * KeyName, uint8_t * KeyValue, size_t KeySize);
static NVM_StatusTypeDef flash_replace(const NVM_Sector_Struct select_sector, uint8_t * PtKeyfind, uint8_t * KeyName,
uint8_t * KeyValue, size_t KeySize);
static NVM_StatusTypeDef flash_write(uint8_t * PtKeyFree, uint8_t * key, uint8_t * value, size_t value_size);
static uint8_t * SearchKey(uint8_t * PtPage, uint8_t * KeyName);
static NVM_StatusTypeDef delete_key(const NVM_Sector_Struct select_sector, uint8_t * PtkeyFind);
/* Public functions ----------------------------------------------------------*/
void NM_Init(void)
{
// Copy Nvm flash to ram, it used one time for boot
// copy no secure nvm to no secure ram
memcpy(sector_no_secure.ram_ptr, NVM_MATTER_ADDR_INIT_NOSECURE_PTR, sector_no_secure.sector_size);
// copy secure nvm to secure ram *SIMULATE TO EXAMPLE*
memcpy(sector_secure.ram_ptr, NVM_MATTER_ADDR_INIT_SECURE_PTR, sector_secure.sector_size);
}
NVM_StatusTypeDef NM_Check_Validity(void)
{
NVM_StatusTypeDef err = NVM_OK;
if (CheckSanity != 0)
{
err = NVM_FLASH_CORRUPTION;
}
return err;
}
NVM_StatusTypeDef NM_Dump(void)
{
NVM_StatusTypeDef err = NVM_DELETE_FAILED;
err = FD_EraseSectors((NVM_MATTER_ADDR_INIT_SECURE - FLASH_START) / (NVM_SIZE_FLASH / NB_SECTOR), NB_SECTOR);
if (err == 0)
{
err = FD_WriteData(NVM_MATTER_ADDR_INIT_SECURE, (uint64_t *) ram_nvm, (uint32_t) (NVM_SIZE_FLASH / sizeof(uint64_t)));
if (err != 0)
{
err = NVM_WRITE_FAILED;
}
else
{
if (memcmp(ram_nvm, (void *) NVM_MATTER_ADDR_INIT_SECURE, (size_t) NVM_SIZE_FLASH))
{
err = NVM_WRITE_FAILED;
}
else
{
err = NVM_OK;
}
}
}
return err;
}
NVM_StatusTypeDef NM_GetKeyValue(void * KeyValue, const char * KeyName, uint32_t KeySize, size_t * read_by_size, NVM_Sector sector)
{
NVM_Sector_Struct select_nvm = { 0 };
switch (sector)
{
case SECTOR_NO_SECURE:
select_nvm = sector_no_secure;
break;
case SECTOR_SECURE:
select_nvm = sector_secure;
break;
default:
return NVM_WRITE_FAILED;
}
uint8_t * key_search = SearchKey(select_nvm.ram_ptr, (uint8_t *) KeyName);
if (key_search != NULL)
{
// copy Keyname's value in KeyValue and copy the size of KeyValue in read_by_size
return flash_get(KeyValue, key_search, KeySize, read_by_size);
}
return NVM_KEY_NOT_FOUND;
}
NVM_StatusTypeDef NM_SetKeyValue(char * KeyValue, char * KeyName, uint32_t KeySize, NVM_Sector sector)
{
NVM_Sector_Struct select_nvm = { 0 };
void * Ptkey = NULL;
switch (sector)
{
case SECTOR_NO_SECURE:
select_nvm = sector_no_secure;
break;
case SECTOR_SECURE:
select_nvm = sector_secure;
break;
default:
return NVM_WRITE_FAILED;
}
if (KeySize > NVM_BLOCK_SIZE)
{
return NVM_BLOCK_SIZE_OVERFLOW;
}
// call function to search the pointer of key if it exist else return null
Ptkey = SearchKey(select_nvm.ram_ptr, (uint8_t *) KeyName);
if (Ptkey == NULL)
{
return flash_update(select_nvm, (uint8_t *) KeyName, (uint8_t *) KeyValue, KeySize);
}
else
{
if (!flash_replace(select_nvm, Ptkey, (uint8_t *) KeyName, (uint8_t *) KeyValue, KeySize))
{
return NVM_OK;
}
}
return NVM_WRITE_FAILED;
}
uint8_t NM_DeleteKey(const char * Keyname, NVM_Sector sector)
{
NVM_Sector_Struct select_nvm = { 0 };
switch (sector)
{
case SECTOR_NO_SECURE:
select_nvm = sector_no_secure;
break;
case SECTOR_SECURE:
select_nvm = sector_secure;
break;
default:
return NVM_WRITE_FAILED;
}
uint8_t * Ptkey = SearchKey(select_nvm.ram_ptr, (uint8_t *) Keyname);
if (Ptkey != NULL)
{
return delete_key(select_nvm, Ptkey);
}
return NVM_KEY_NOT_FOUND;
}
void NM_ResetFactory(void)
{
while (1)
{
FD_EraseSectors((NVM_MATTER_ADDR_INIT_SECURE - FLASH_START) / (NVM_SIZE_FLASH / NB_SECTOR), NB_SECTOR);
NVIC_SystemReset();
}
}
/*************************************************************
*
* LOCAL FUNCTIONS
*
*************************************************************/
static uint8_t * SearchKey(uint8_t * PtPage, uint8_t * KeyName)
{
uint8_t * i = PtPage;
size_t read_by_size = 0;
while ((i >= PtPage) || (i < (PtPage + NVM_SIZE_FLASH)))
{
if (*i != DEFAULT_VALUE)
{
if (strcmp((char *) KeyName, (char *) i) == 0)
{
return i;
}
read_by_size = *(size_t *) ((uint8_t *) i + MATTER_KEY_NAME_MAX_LENGTH);
i += read_by_size + sizeof(size_t) + MATTER_KEY_NAME_MAX_LENGTH;
// Flash is corrupted
if ((i < PtPage) || (i > (PtPage + NVM_SIZE_FLASH)))
{
NM_ResetFactory();
}
}
else
{
return NULL;
}
}
return NULL;
}
static uint8_t flash_get(uint8_t * KeyValue, uint8_t * KeyAddr, size_t KeySize, size_t * read_by_size)
{
*read_by_size = *(size_t *) ((uint8_t *) KeyAddr + MATTER_KEY_NAME_MAX_LENGTH);
if (KeySize >= *read_by_size)
{
memcpy(KeyValue, KeyAddr + MATTER_KEY_NAME_MAX_LENGTH + sizeof(size_t), *read_by_size);
return NVM_OK;
}
else
{
return NVM_BUFFER_TOO_SMALL;
}
}
static NVM_StatusTypeDef flash_update(const NVM_Sector_Struct select_sector, uint8_t * KeyName, uint8_t * KeyValue, size_t KeySize)
{
uint8_t * i = select_sector.ram_ptr;
size_t read_by_size = 0;
while (i < (select_sector.ram_ptr + select_sector.sector_size))
{
if (*i == DEFAULT_VALUE)
{
return flash_write(i, KeyName, KeyValue, KeySize);
}
read_by_size = *(size_t *) ((uint8_t *) i + MATTER_KEY_NAME_MAX_LENGTH);
if (read_by_size > NVM_BLOCK_SIZE)
{
return NVM_ERROR_BLOCK_ALIGN;
}
i += read_by_size + sizeof(size_t) + MATTER_KEY_NAME_MAX_LENGTH;
}
return NVM_SIZE_FULL;
}
static NVM_StatusTypeDef flash_replace(const NVM_Sector_Struct select_sector, uint8_t * PtKeyfind, uint8_t * KeyName,
uint8_t * KeyValue, size_t KeySize)
{
NVM_StatusTypeDef err = NVM_OK;
if ((PtKeyfind != NULL) && (KeyName != NULL) && (KeyValue != NULL))
{
err = delete_key(select_sector, PtKeyfind);
if (err != NVM_OK)
return err;
err = flash_update(select_sector, KeyName, KeyValue, KeySize);
if (err != NVM_OK)
return err;
return err;
}
return NVM_WRITE_FAILED;
}
static NVM_StatusTypeDef delete_key(const NVM_Sector_Struct select_sector, uint8_t * PtkeyFind)
{
uint8_t * PtKeyNext = NULL;
uint8_t * PtKeyCpy = NULL;
size_t size_key = 0;
if (PtkeyFind != NULL)
{
size_key = *(size_t *) ((uint8_t *) PtkeyFind + MATTER_KEY_NAME_MAX_LENGTH);
PtKeyNext = PtkeyFind + size_key + MATTER_KEY_NAME_MAX_LENGTH + sizeof(size_key);
PtKeyCpy = PtkeyFind;
while ((*PtKeyNext != 0xFF) && (PtKeyNext < (ram_nvm + NVM_SIZE_FLASH)))
{
size_key = *(size_t *) ((uint8_t *) PtKeyNext + MATTER_KEY_NAME_MAX_LENGTH);
memcpy(PtKeyCpy, PtKeyNext, size_key + sizeof(size_t) + MATTER_KEY_NAME_MAX_LENGTH);
PtKeyCpy += size_key + sizeof(size_t) + MATTER_KEY_NAME_MAX_LENGTH;
PtKeyNext += size_key + MATTER_KEY_NAME_MAX_LENGTH + sizeof(size_key);
}
memset(PtKeyCpy, DEFAULT_VALUE, (ram_nvm + NVM_SIZE_FLASH - PtKeyCpy));
return NVM_OK;
}
return NVM_DELETE_FAILED;
}
static NVM_StatusTypeDef flash_write(uint8_t * PtKeyFree, uint8_t * key, uint8_t * value, size_t value_size)
{
if ((PtKeyFree != NULL) && (key != NULL) && (value != NULL))
{
memset(PtKeyFree, DEFAULT_VALUE, value_size);
memset(PtKeyFree, 0x00, MATTER_KEY_NAME_MAX_LENGTH);
memcpy(PtKeyFree, key, strlen((char *) key));
memcpy(PtKeyFree + MATTER_KEY_NAME_MAX_LENGTH, &value_size, sizeof(size_t));
memcpy(PtKeyFree + MATTER_KEY_NAME_MAX_LENGTH + sizeof(size_t), value, value_size);
return NVM_OK;
}
return NVM_WRITE_FAILED;
}