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 /* Make this better */ 129 static inline int backend_init(struct backend *master, struct backend *with, 130 void *data) 131 { 132 int rc; 133 134 assert(master); 135 136 /* FIXME: A bit hacky? */ 137 with->flash_size = master->flash_size; 138 *master = *with; 139 140 #ifndef NDEBUG 141 /* Set some poison values to ensure backends init properly */ 142 master->erase_size_shift = 33; 143 master->block_size_shift = 34; 144 #endif 145 146 if (!master->ops->init) 147 return -ENOTSUP; 148 149 rc = master->ops->init(master, data); 150 if (rc < 0) 151 return rc; 152 153 assert(master->erase_size_shift < 32); 154 assert(master->block_size_shift < 32); 155 156 return 0; 157 } 158 159 static inline void backend_free(struct backend *backend) 160 { 161 assert(backend); 162 163 if (backend->ops->free) 164 backend->ops->free(backend); 165 } 166 167 static inline int64_t backend_copy(struct backend *backend, 168 uint32_t offset, void *mem, uint32_t size) 169 { 170 assert(backend); 171 assert(backend->ops->copy); 172 return backend->ops->copy(backend, offset, mem, size); 173 174 } 175 176 static inline int backend_set_bytemap(struct backend *backend, 177 uint32_t offset, uint32_t count, 178 uint8_t val) 179 { 180 assert(backend); 181 182 if (backend->ops->set_bytemap) 183 return backend->ops->set_bytemap(backend, offset, count, val); 184 185 return 0; 186 } 187 188 static inline int backend_erase(struct backend *backend, uint32_t offset, 189 uint32_t count) 190 { 191 assert(backend); 192 if (backend->ops->erase) 193 return backend->ops->erase(backend, offset, count); 194 195 return 0; 196 } 197 198 static inline int backend_write(struct backend *backend, uint32_t offset, 199 void *buf, uint32_t count) 200 { 201 assert(backend); 202 assert(backend->ops->write); 203 return backend->ops->write(backend, offset, buf, count); 204 } 205 206 static inline int backend_validate(struct backend *backend, 207 uint32_t offset, uint32_t size, bool ro) 208 { 209 assert(backend); 210 211 if (backend->ops->validate) 212 return backend->ops->validate(backend, offset, size, ro); 213 214 return 0; 215 } 216 217 static inline int backend_reset(struct backend *backend, void *buf, 218 uint32_t count) 219 { 220 assert(backend); 221 assert(backend->ops->reset); 222 return backend->ops->reset(backend, buf, count); 223 } 224 225 struct backend backend_get_mtd(void); 226 int backend_probe_mtd(struct backend *master, const char *path); 227 228 struct backend backend_get_file(void); 229 int backend_probe_file(struct backend *master, const char *path); 230 231 /* Avoid dependency on vpnor/mboxd_pnor_partition_table.h */ 232 struct vpnor_partition_paths; 233 #ifdef VIRTUAL_PNOR_ENABLED 234 struct backend backend_get_vpnor(void); 235 236 int backend_probe_vpnor(struct backend *master, 237 const struct vpnor_partition_paths *paths); 238 #else 239 static inline struct backend backend_get_vpnor(void) 240 { 241 struct backend be = { 0 }; 242 243 return be; 244 } 245 246 static inline int backend_probe_vpnor(struct backend *master, 247 const struct vpnor_partition_paths *paths) 248 { 249 return -ENOTSUP; 250 } 251 #endif 252 253 #endif /* BACKEND_H */ 254