Line data Source code
1 : /**
2 : * The MIT License (MIT)
3 : *
4 : * Copyright (c) 2021 RSK Labs Ltd
5 : *
6 : * Permission is hereby granted, free of charge, to any person obtaining a copy
7 : * of this software and associated documentation files (the "Software"), to
8 : * deal in the Software without restriction, including without limitation the
9 : * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 : * sell copies of the Software, and to permit persons to whom the Software is
11 : * furnished to do so, subject to the following conditions:
12 : *
13 : * The above copyright notice and this permission notice shall be included in
14 : * all copies or substantial portions of the Software.
15 : *
16 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 : * IN THE SOFTWARE.
23 : */
24 :
25 : #include <stdlib.h>
26 : #include <stdbool.h>
27 : #include <string.h>
28 :
29 : #include "hal/nvmem.h"
30 : #include "hal/log.h"
31 :
32 : #include "secret_store.h"
33 :
34 : #define MAX_NVM_BLOCKS 5
35 :
36 : typedef struct {
37 : char* key;
38 : void* addr;
39 : size_t size;
40 : } nvm_block_t;
41 :
42 : static nvm_block_t nvm_blocks[MAX_NVM_BLOCKS];
43 : static unsigned int nvm_blocks_count;
44 :
45 : #define STORE_PREFIX "nvmem-"
46 :
47 14 : static char* store_key_for(char* key) {
48 14 : size_t key_size = strlen(STORE_PREFIX) + strlen(key);
49 14 : char* store_key = malloc(key_size + 1);
50 14 : strcpy(store_key, "");
51 14 : strcat(store_key, STORE_PREFIX);
52 14 : strcat(store_key, key);
53 14 : return store_key;
54 : }
55 :
56 10 : void nvmem_init() {
57 10 : memset(nvm_blocks, 0, sizeof(nvm_blocks));
58 10 : nvm_blocks_count = 0;
59 10 : }
60 :
61 18 : bool nvmem_register_block(char* key, void* addr, size_t size) {
62 18 : if (nvm_blocks_count >= MAX_NVM_BLOCKS) {
63 : LOG("Error registering NVM block <%s>: too many blocks\n", key);
64 1 : return false;
65 : }
66 :
67 17 : nvm_blocks[nvm_blocks_count].key = key;
68 17 : nvm_blocks[nvm_blocks_count].addr = addr;
69 17 : nvm_blocks[nvm_blocks_count].size = size;
70 17 : nvm_blocks_count++;
71 :
72 17 : return true;
73 : }
74 :
75 1 : static void clear_blocks() {
76 2 : for (unsigned int i = 0; i < nvm_blocks_count; i++) {
77 1 : memset((uint8_t*)nvm_blocks[i].addr, 0, nvm_blocks[i].size);
78 : }
79 1 : }
80 :
81 7 : bool nvmem_load() {
82 : LOG("Loading NVM blocks...\n");
83 12 : for (unsigned int i = 0; i < nvm_blocks_count; i++) {
84 6 : char* key = store_key_for(nvm_blocks[i].key);
85 6 : if (sest_exists(key)) {
86 5 : uint8_t* tmp = malloc(nvm_blocks[i].size);
87 5 : if (sest_read(key, tmp, nvm_blocks[i].size) == nvm_blocks[i].size) {
88 4 : memcpy((uint8_t*)nvm_blocks[i].addr, tmp, nvm_blocks[i].size);
89 : } else {
90 : LOG("Error loading NVM block <%s>\n", nvm_blocks[i].key);
91 1 : clear_blocks();
92 1 : free(key);
93 1 : free(tmp);
94 1 : return false;
95 : }
96 4 : free(tmp);
97 : } else {
98 : LOG("No record found for NVM block <%s>\n", nvm_blocks[i].key);
99 1 : memset((uint8_t*)nvm_blocks[i].addr, 0, nvm_blocks[i].size);
100 : }
101 5 : free(key);
102 : }
103 6 : return true;
104 : }
105 :
106 9 : static bool nvmem_flush() {
107 : LOG("Flushing NVM blocks...\n");
108 16 : for (unsigned int i = 0; i < nvm_blocks_count; i++) {
109 8 : char* key = store_key_for(nvm_blocks[i].key);
110 8 : if (!sest_write(
111 8 : key, (uint8_t*)nvm_blocks[i].addr, nvm_blocks[i].size)) {
112 : LOG("Error flushing NVM block <%s>\n", nvm_blocks[i].key);
113 1 : free(key);
114 1 : return false;
115 : }
116 7 : free(key);
117 : }
118 8 : return true;
119 : }
120 :
121 9 : bool nvmem_write(void* dst, void* src, unsigned int length) {
122 9 : if (src == NULL) {
123 : // Treat as memory reset
124 1 : memset(dst, 0, length);
125 : } else {
126 : // Treat as normal copy
127 8 : memmove(dst, src, length);
128 : }
129 : // Flush to disk
130 9 : return nvmem_flush();
131 : }
|