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