1 /* SPDX-License-Identifier: Apache-2.0 */ 2 /* Copyright (C) 2018 IBM Corp. */ 3 /* Copyright (C) 2018 Evan Lojewski. */ 4 5 #ifndef BACKEND_H 6 #define BACKEND_H 7 8 #include <assert.h> 9 #include <errno.h> 10 #include <stdbool.h> 11 #include <stdint.h> 12 #include <mtd/mtd-abi.h> 13 14 #define FLASH_DIRTY 0x00 15 #define FLASH_ERASED 0x01 16 17 /* Estimate as to how long (milliseconds) it takes to access a MB from flash */ 18 #define FLASH_ACCESS_MS_PER_MB 8000 19 20 enum backend_reset_mode { reset_lpc_flash, reset_lpc_memory }; 21 22 struct backend_ops; 23 24 struct backend { 25 const struct backend_ops *ops; 26 27 /* Backend private data */ 28 void *priv; 29 30 /* Flash size from command line (bytes) */ 31 uint32_t flash_size; 32 33 /* Erase size (as a shift) */ 34 uint32_t erase_size_shift; 35 /* Block size (as a shift) */ 36 uint32_t block_size_shift; 37 }; 38 39 struct backend_ops { 40 /* 41 * init() - Main initialization function for backing device 42 * @context: The backend context pointer 43 * @data: Additional backend-implementation-specifc data 44 * Return: Zero on success, otherwise negative error 45 */ 46 int (*init)(struct backend *backend, void *data); 47 48 /* 49 * free() - Main teardown function for backing device 50 * @context: The backend context pointer 51 */ 52 void (*free)(struct backend *backend); 53 54 /* 55 * copy() - Copy data from the flash device into a provided buffer 56 * @context: The mbox context pointer 57 * @offset: The flash offset to copy from (bytes) 58 * @mem: The buffer to copy into (must be of atleast 'size' bytes) 59 * @size: The number of bytes to copy 60 * Return: Number of bytes copied on success, otherwise negative error 61 * code. flash_copy will copy at most 'size' bytes, but it may 62 * copy less. 63 */ 64 int64_t (*copy)(struct backend *backend, uint32_t offset, void *mem, 65 uint32_t size); 66 67 /* 68 * set_bytemap() - Set the flash erased bytemap 69 * @context: The mbox context pointer 70 * @offset: The flash offset to set (bytes) 71 * @count: Number of bytes to set 72 * @val: Value to set the bytemap to 73 * 74 * The flash bytemap only tracks the erased status at the erase block level so 75 * this will update the erased state for an (or many) erase blocks 76 * 77 * Return: 0 if success otherwise negative error code 78 */ 79 int (*set_bytemap)(struct backend *backend, uint32_t offset, 80 uint32_t count, uint8_t val); 81 82 /* 83 * erase() - Erase the flash 84 * @context: The backend context pointer 85 * @offset: The flash offset to erase (bytes) 86 * @size: The number of bytes to erase 87 * 88 * Return: 0 on success otherwise negative error code 89 */ 90 int (*erase)(struct backend *backend, uint32_t offset, 91 uint32_t count); 92 /* 93 * write() - Write the flash from a provided buffer 94 * @context: The backend context pointer 95 * @offset: The flash offset to write to (bytes) 96 * @buf: The buffer to write from (must be of atleast size) 97 * @size: The number of bytes to write 98 * 99 * Return: 0 on success otherwise negative error code 100 */ 101 int (*write)(struct backend *backend, uint32_t offset, void *buf, 102 uint32_t count); 103 104 /* 105 * validate() - Validates a requested window 106 * @context: The backend context pointer 107 * @offset: The requested flash offset 108 * @size: The requested region size 109 * @ro: The requested access type: True for read-only, false 110 * for read-write 111 * 112 * Return: 0 on valid otherwise negative error code 113 */ 114 int (*validate)(struct backend *backend, 115 uint32_t offset, uint32_t size, bool ro); 116 117 /* 118 * reset() - Ready the reserved memory for host startup 119 * @context: The backend context pointer 120 * @buf: The LPC reserved memory pointer 121 * @count The size of the LPC reserved memory region 122 * 123 * Return: 0 on success otherwise negative error code 124 */ 125 int (*reset)(struct backend *backend, void *buf, uint32_t count); 126 127 /* 128 * align_offset() - Align the offset to avoid overlap 129 * @context: The backend context pointer 130 * @offset: The flash offset 131 * @window_size:The window size 132 * 133 * Return: 0 on success otherwise negative error code 134 */ 135 int (*align_offset)(struct backend *backend, uint32_t *offset, 136 uint32_t window_size); 137 }; 138 139 /* Make this better */ 140 static inline int backend_init(struct backend *master, struct backend *with, 141 void *data) 142 { 143 int rc; 144 145 assert(master); 146 147 /* FIXME: A bit hacky? */ 148 with->flash_size = master->flash_size; 149 *master = *with; 150 151 #ifndef NDEBUG 152 /* Set some poison values to ensure backends init properly */ 153 master->erase_size_shift = 33; 154 master->block_size_shift = 34; 155 #endif 156 157 if (!(master && master->ops && master->ops->init)) 158 return -ENOTSUP; 159 160 rc = master->ops->init(master, data); 161 if (rc < 0) 162 return rc; 163 164 assert(master->erase_size_shift < 32); 165 assert(master->block_size_shift < 32); 166 167 return 0; 168 } 169 170 static inline void backend_free(struct backend *backend) 171 { 172 assert(backend); 173 174 if (backend->ops->free) 175 backend->ops->free(backend); 176 } 177 178 static inline int64_t backend_copy(struct backend *backend, 179 uint32_t offset, void *mem, uint32_t size) 180 { 181 assert(backend); 182 assert(backend->ops->copy); 183 return backend->ops->copy(backend, offset, mem, size); 184 185 } 186 187 static inline int backend_set_bytemap(struct backend *backend, 188 uint32_t offset, uint32_t count, 189 uint8_t val) 190 { 191 assert(backend); 192 193 if (backend->ops->set_bytemap) 194 return backend->ops->set_bytemap(backend, offset, count, val); 195 196 return 0; 197 } 198 199 static inline int backend_erase(struct backend *backend, uint32_t offset, 200 uint32_t count) 201 { 202 assert(backend); 203 if (backend->ops->erase) 204 return backend->ops->erase(backend, offset, count); 205 206 return 0; 207 } 208 209 static inline int backend_write(struct backend *backend, uint32_t offset, 210 void *buf, uint32_t count) 211 { 212 assert(backend); 213 assert(backend->ops->write); 214 return backend->ops->write(backend, offset, buf, count); 215 } 216 217 static inline int backend_validate(struct backend *backend, 218 uint32_t offset, uint32_t size, bool ro) 219 { 220 assert(backend); 221 222 if (backend->ops->validate) 223 return backend->ops->validate(backend, offset, size, ro); 224 225 return 0; 226 } 227 228 static inline int backend_reset(struct backend *backend, void *buf, 229 uint32_t count) 230 { 231 assert(backend); 232 assert(backend->ops->reset); 233 return backend->ops->reset(backend, buf, count); 234 } 235 236 237 static inline int backend_align_offset(struct backend *backend, uint32_t *offset, uint32_t window_size) 238 { 239 assert(backend); 240 if (backend->ops->align_offset){ 241 return backend->ops->align_offset(backend, offset, window_size); 242 }else{ 243 /* 244 * It would be nice to align the offsets which we map to window 245 * size, this will help prevent overlap which would be an 246 * inefficient use of our reserved memory area (we would like 247 * to "cache" as much of the acutal flash as possible in 248 * memory). If we're protocol V1 however we must ensure the 249 * offset requested is exactly mapped. 250 */ 251 *offset &= ~(window_size - 1); 252 return 0; 253 } 254 } 255 256 struct backend backend_get_mtd(void); 257 int backend_probe_mtd(struct backend *master, const char *path); 258 259 struct backend backend_get_file(void); 260 int backend_probe_file(struct backend *master, const char *path); 261 262 /* Avoid dependency on vpnor/mboxd_pnor_partition_table.h */ 263 struct vpnor_partition_paths; 264 #ifdef VIRTUAL_PNOR_ENABLED 265 struct backend backend_get_vpnor(void); 266 267 int backend_probe_vpnor(struct backend *master, 268 const struct vpnor_partition_paths *paths); 269 #else 270 static inline struct backend backend_get_vpnor(void) 271 { 272 struct backend be = { 0 }; 273 274 return be; 275 } 276 277 static inline int backend_probe_vpnor(struct backend *master, 278 const struct vpnor_partition_paths *paths) 279 { 280 return -ENOTSUP; 281 } 282 #endif 283 284 #endif /* BACKEND_H */ 285