1 /*
2 * Block device emulated in RAM
3 *
4 * Copyright (c) 2017, Arm Limited. All rights reserved.
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7 #include "bd/lfs_rambd.h"
8
lfs_rambd_createcfg(const struct lfs_config * cfg,const struct lfs_rambd_config * bdcfg)9 int lfs_rambd_createcfg(const struct lfs_config *cfg,
10 const struct lfs_rambd_config *bdcfg) {
11 LFS_RAMBD_TRACE("lfs_rambd_createcfg(%p {.context=%p, "
12 ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
13 ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
14 ".block_size=%"PRIu32", .block_count=%"PRIu32"}, "
15 "%p {.erase_value=%"PRId32", .buffer=%p})",
16 (void*)cfg, cfg->context,
17 (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
18 (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
19 cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
20 (void*)bdcfg, bdcfg->erase_value, bdcfg->buffer);
21 lfs_rambd_t *bd = cfg->context;
22 bd->cfg = bdcfg;
23
24 // allocate buffer?
25 if (bd->cfg->buffer) {
26 bd->buffer = bd->cfg->buffer;
27 } else {
28 bd->buffer = lfs_malloc(cfg->block_size * cfg->block_count);
29 if (!bd->buffer) {
30 LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", LFS_ERR_NOMEM);
31 return LFS_ERR_NOMEM;
32 }
33 }
34
35 // zero for reproducability?
36 if (bd->cfg->erase_value != -1) {
37 memset(bd->buffer, bd->cfg->erase_value,
38 cfg->block_size * cfg->block_count);
39 }
40
41 LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", 0);
42 return 0;
43 }
44
lfs_rambd_create(const struct lfs_config * cfg)45 int lfs_rambd_create(const struct lfs_config *cfg) {
46 LFS_RAMBD_TRACE("lfs_rambd_create(%p {.context=%p, "
47 ".read=%p, .prog=%p, .erase=%p, .sync=%p, "
48 ".read_size=%"PRIu32", .prog_size=%"PRIu32", "
49 ".block_size=%"PRIu32", .block_count=%"PRIu32"})",
50 (void*)cfg, cfg->context,
51 (void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
52 (void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
53 cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count);
54 static const struct lfs_rambd_config defaults = {.erase_value=-1};
55 int err = lfs_rambd_createcfg(cfg, &defaults);
56 LFS_RAMBD_TRACE("lfs_rambd_create -> %d", err);
57 return err;
58 }
59
lfs_rambd_destroy(const struct lfs_config * cfg)60 int lfs_rambd_destroy(const struct lfs_config *cfg) {
61 LFS_RAMBD_TRACE("lfs_rambd_destroy(%p)", (void*)cfg);
62 // clean up memory
63 lfs_rambd_t *bd = cfg->context;
64 if (!bd->cfg->buffer) {
65 lfs_free(bd->buffer);
66 }
67 LFS_RAMBD_TRACE("lfs_rambd_destroy -> %d", 0);
68 return 0;
69 }
70
lfs_rambd_read(const struct lfs_config * cfg,lfs_block_t block,lfs_off_t off,void * buffer,lfs_size_t size)71 int lfs_rambd_read(const struct lfs_config *cfg, lfs_block_t block,
72 lfs_off_t off, void *buffer, lfs_size_t size) {
73 LFS_RAMBD_TRACE("lfs_rambd_read(%p, "
74 "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
75 (void*)cfg, block, off, buffer, size);
76 lfs_rambd_t *bd = cfg->context;
77
78 // check if read is valid
79 LFS_ASSERT(off % cfg->read_size == 0);
80 LFS_ASSERT(size % cfg->read_size == 0);
81 LFS_ASSERT(block < cfg->block_count);
82
83 // read data
84 memcpy(buffer, &bd->buffer[block*cfg->block_size + off], size);
85
86 LFS_RAMBD_TRACE("lfs_rambd_read -> %d", 0);
87 return 0;
88 }
89
lfs_rambd_prog(const struct lfs_config * cfg,lfs_block_t block,lfs_off_t off,const void * buffer,lfs_size_t size)90 int lfs_rambd_prog(const struct lfs_config *cfg, lfs_block_t block,
91 lfs_off_t off, const void *buffer, lfs_size_t size) {
92 LFS_RAMBD_TRACE("lfs_rambd_prog(%p, "
93 "0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
94 (void*)cfg, block, off, buffer, size);
95 lfs_rambd_t *bd = cfg->context;
96
97 // check if write is valid
98 LFS_ASSERT(off % cfg->prog_size == 0);
99 LFS_ASSERT(size % cfg->prog_size == 0);
100 LFS_ASSERT(block < cfg->block_count);
101
102 // check that data was erased? only needed for testing
103 if (bd->cfg->erase_value != -1) {
104 for (lfs_off_t i = 0; i < size; i++) {
105 LFS_ASSERT(bd->buffer[block*cfg->block_size + off + i] ==
106 bd->cfg->erase_value);
107 }
108 }
109
110 // program data
111 memcpy(&bd->buffer[block*cfg->block_size + off], buffer, size);
112
113 LFS_RAMBD_TRACE("lfs_rambd_prog -> %d", 0);
114 return 0;
115 }
116
lfs_rambd_erase(const struct lfs_config * cfg,lfs_block_t block)117 int lfs_rambd_erase(const struct lfs_config *cfg, lfs_block_t block) {
118 LFS_RAMBD_TRACE("lfs_rambd_erase(%p, 0x%"PRIx32")", (void*)cfg, block);
119 lfs_rambd_t *bd = cfg->context;
120
121 // check if erase is valid
122 LFS_ASSERT(block < cfg->block_count);
123
124 // erase, only needed for testing
125 if (bd->cfg->erase_value != -1) {
126 memset(&bd->buffer[block*cfg->block_size],
127 bd->cfg->erase_value, cfg->block_size);
128 }
129
130 LFS_RAMBD_TRACE("lfs_rambd_erase -> %d", 0);
131 return 0;
132 }
133
lfs_rambd_sync(const struct lfs_config * cfg)134 int lfs_rambd_sync(const struct lfs_config *cfg) {
135 LFS_RAMBD_TRACE("lfs_rambd_sync(%p)", (void*)cfg);
136 // sync does nothing because we aren't backed by anything real
137 (void)cfg;
138 LFS_RAMBD_TRACE("lfs_rambd_sync -> %d", 0);
139 return 0;
140 }
141