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 "NHW_NVM_backend.h"
25
26 /**
27 * At boot, do whatever is necessary for a given storage
28 * (allocate memory, open files etc. )
29 */
nhw_nvm_initialize_data_storage(nvm_storage_state_t * st)30 void nhw_nvm_initialize_data_storage(nvm_storage_state_t *st){
31 struct stat f_stat;
32 int rc;
33
34 st->fd = -1;
35 st->storage = NULL;
36
37 if (st->in_ram == true) {
38 st->storage = (uint8_t *)bs_malloc(st->size);
39
40 } else {
41
42 bs_create_folders_in_path(st->file_path);
43 st->fd = open(st->file_path, O_RDWR | O_CREAT, (mode_t)0600);
44 if (st->fd == -1) {
45 bs_trace_error_line("%s: Failed to open %s device file %s: %s\n",
46 __func__, st->type_s, st->file_path, strerror(errno));
47 }
48
49 rc = fstat(st->fd, &f_stat);
50 if (rc) {
51 bs_trace_error_line("%s: Failed to get status of %s device file %s: %s\n",
52 __func__, st->type_s, st->file_path, strerror(errno));
53 }
54
55 if (ftruncate(st->fd, st->size) == -1) {
56 bs_trace_error_line("%s: Failed to resize %s device file %s: %s\n",
57 __func__, st->type_s, st->file_path, strerror(errno));
58 }
59
60 st->storage = mmap(NULL, st->size, PROT_WRITE | PROT_READ, MAP_SHARED, st->fd, 0);
61 if (st->storage == MAP_FAILED) {
62 bs_trace_error_line("%s: Failed to mmap %s device file %s: %s\n",
63 __func__, st->type_s, st->file_path, strerror(errno));
64 }
65 }
66
67 if ((st->erase_at_start == true) || (st->in_ram == true) || (f_stat.st_size == 0)) {
68 /* Erase the memory unit by pulling all bits to the configured erase value */
69 (void)memset(st->storage, 0xFF, st->size);
70 }
71 }
72
nhw_nvm_init_storage(nvm_storage_state_t * st,struct nhw_nvm_st_args_t * args,size_t size,char * type_s)73 void nhw_nvm_init_storage(nvm_storage_state_t *st, struct nhw_nvm_st_args_t *args,
74 size_t size, char *type_s)
75 {
76 st->file_path = args->file;
77 st->erase_at_start = args->erase;
78 st->rm_at_exit = args->rm;
79 st->in_ram = args->in_ram;
80 st->size = size;
81 st->type_s = type_s;
82
83 nhw_nvm_initialize_data_storage(st);
84 }
85
86 /**
87 * Before exiting the program, do whatever is
88 * necessary for a given storage (free'ing heap,
89 * closing file descriptors, etc)
90 */
nhw_nvm_clear_storage(nvm_storage_state_t * st)91 void nhw_nvm_clear_storage(nvm_storage_state_t *st){
92
93 if (st->in_ram == true) {
94 if (st->storage != NULL) {
95 free(st->storage);
96 st->storage = NULL;
97 }
98 return;
99 }
100
101 if ((st->storage != MAP_FAILED) && (st->storage != NULL)) {
102 munmap(st->storage, st->size);
103 st->storage = NULL;
104 }
105
106 if (st->fd != -1) {
107 close(st->fd);
108 st->fd = -1;
109 }
110
111 if ((st->rm_at_exit == true) && (st->file_path != NULL)) {
112 /* We try to remove the file but do not error out if we can't */
113 (void) remove(st->file_path);
114 st->file_path = NULL;
115 }
116 }
117