1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * Backend for the Non-Volatile Memory devices
9 * which can use files on disk or just host RAM
10 * to keep their content.
11 */
12
13 #include <string.h>
14 #include <unistd.h>
15 #include <fcntl.h>
16 #include <errno.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/mman.h>
22 #include "bs_tracing.h"
23 #include "bs_oswrap.h"
24 #include "bs_compat.h"
25 #include "NHW_NVM_backend.h"
26
27 /**
28 * At boot, do whatever is necessary for a given storage
29 * (allocate memory, open files etc. )
30 */
nhw_nvm_initialize_data_storage(nvm_storage_state_t * st)31 void nhw_nvm_initialize_data_storage(nvm_storage_state_t *st){
32 struct stat f_stat;
33 int rc;
34
35 st->fd = -1;
36 st->storage = NULL;
37
38 if (st->in_ram == true) {
39 st->storage = (uint8_t *)bs_malloc(st->size);
40
41 } else {
42
43 _bs_create_folders_in_path(st->file_path);
44 st->fd = open(st->file_path, O_RDWR | O_CREAT, (mode_t)0600);
45 if (st->fd == -1) {
46 bs_trace_error_line("%s: Failed to open %s device file %s: %s\n",
47 __func__, st->type_s, st->file_path, strerror(errno));
48 }
49
50 rc = fstat(st->fd, &f_stat);
51 if (rc) {
52 bs_trace_error_line("%s: Failed to get status of %s device file %s: %s\n",
53 __func__, st->type_s, st->file_path, strerror(errno));
54 }
55
56 if (ftruncate(st->fd, st->size) == -1) {
57 bs_trace_error_line("%s: Failed to resize %s device file %s: %s\n",
58 __func__, st->type_s, st->file_path, strerror(errno));
59 }
60
61 st->storage = mmap(NULL, st->size, PROT_WRITE | PROT_READ, MAP_SHARED, st->fd, 0);
62 if (st->storage == MAP_FAILED) {
63 bs_trace_error_line("%s: Failed to mmap %s device file %s: %s\n",
64 __func__, st->type_s, st->file_path, strerror(errno));
65 }
66 }
67
68 if ((st->erase_at_start == true) || (st->in_ram == true) || (f_stat.st_size == 0)) {
69 /* Erase the memory unit by pulling all bits to the configured erase value */
70 (void)memset(st->storage, 0xFF, st->size);
71 }
72 }
73
nhw_nvm_init_storage(nvm_storage_state_t * st,struct nhw_nvm_st_args_t * args,size_t size,char * type_s)74 void nhw_nvm_init_storage(nvm_storage_state_t *st, struct nhw_nvm_st_args_t *args,
75 size_t size, char *type_s)
76 {
77 st->file_path = args->file;
78 st->erase_at_start = args->erase;
79 st->rm_at_exit = args->rm;
80 st->in_ram = args->in_ram;
81 st->size = size;
82 st->type_s = type_s;
83
84 nhw_nvm_initialize_data_storage(st);
85 }
86
87 /**
88 * Before exiting the program, do whatever is
89 * necessary for a given storage (free'ing heap,
90 * closing file descriptors, etc)
91 */
nhw_nvm_clear_storage(nvm_storage_state_t * st)92 void nhw_nvm_clear_storage(nvm_storage_state_t *st){
93
94 if (st->in_ram == true) {
95 if (st->storage != NULL) {
96 free(st->storage);
97 st->storage = NULL;
98 }
99 return;
100 }
101
102 if ((st->storage != MAP_FAILED) && (st->storage != NULL)) {
103 munmap(st->storage, st->size);
104 st->storage = NULL;
105 }
106
107 if (st->fd != -1) {
108 close(st->fd);
109 st->fd = -1;
110 }
111
112 if ((st->rm_at_exit == true) && (st->file_path != NULL)) {
113 /* We try to remove the file but do not error out if we can't */
114 (void) remove(st->file_path);
115 st->file_path = NULL;
116 }
117 }
118