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