"Das U-Boot" Source Tree
at master 600 lines 16 kB view raw
1/* SPDX-License-Identifier: GPL-2.0+ */ 2/* 3 * dfu.h - DFU flashable area description 4 * 5 * Copyright (C) 2012 Samsung Electronics 6 * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com> 7 * Lukasz Majewski <l.majewski@samsung.com> 8 */ 9 10#ifndef __DFU_ENTITY_H_ 11#define __DFU_ENTITY_H_ 12 13#include <linux/errno.h> 14#include <linux/list.h> 15#include <mmc.h> 16#include <spi_flash.h> 17#include <linux/usb/composite.h> 18 19enum dfu_device_type { 20 DFU_DEV_MMC = 1, 21 DFU_DEV_ONENAND, 22 DFU_DEV_NAND, 23 DFU_DEV_RAM, 24 DFU_DEV_SF, 25 DFU_DEV_MTD, 26 DFU_DEV_VIRT, 27 DFU_DEV_SCSI, 28}; 29 30enum dfu_layout { 31 DFU_RAW_ADDR = 1, 32 DFU_FS_FAT, 33 DFU_FS_EXT2, 34 DFU_FS_EXT3, 35 DFU_FS_EXT4, 36 DFU_RAM_ADDR, 37 DFU_SKIP, 38 DFU_SCRIPT, 39}; 40 41enum dfu_op { 42 DFU_OP_READ = 1, 43 DFU_OP_WRITE, 44 DFU_OP_SIZE, 45}; 46 47struct mmc_internal_data { 48 int dev_num; 49 50 /* RAW programming */ 51 unsigned int lba_start; 52 unsigned int lba_size; 53 unsigned int lba_blk_size; 54 55 /* eMMC HW partition access */ 56 int hw_partition; 57 58 /* FAT/EXT */ 59 unsigned int dev; 60 unsigned int part; 61}; 62 63struct mtd_internal_data { 64 struct mtd_info *info; 65 66 /* RAW programming */ 67 u64 start; 68 u64 size; 69 /* for ubi partition */ 70 unsigned int ubi; 71}; 72 73struct nand_internal_data { 74 /* RAW programming */ 75 u64 start; 76 u64 size; 77 78 unsigned int dev; 79 unsigned int part; 80 /* for nand/ubi use */ 81 unsigned int ubi; 82}; 83 84struct ram_internal_data { 85 unsigned long start; 86 unsigned int size; 87}; 88 89struct sf_internal_data { 90 struct spi_flash *dev; 91 92 /* RAW programming */ 93 u64 start; 94 u64 size; 95 /* for sf/ubi use */ 96 unsigned int ubi; 97}; 98 99struct virt_internal_data { 100 int dev_num; 101}; 102 103struct scsi_internal_data { 104 int lun; 105 106 /* RAW programming */ 107 unsigned int lba_start; 108 unsigned int lba_size; 109 unsigned int lba_blk_size; 110 111 /* FAT/EXT */ 112 unsigned int dev; // Always 0??? 113 unsigned int part; 114}; 115 116#if defined(CONFIG_DFU_NAME_MAX_SIZE) 117#define DFU_NAME_SIZE CONFIG_DFU_NAME_MAX_SIZE 118#else 119#define DFU_NAME_SIZE 32 120#endif 121#ifndef DFU_DEFAULT_POLL_TIMEOUT 122#define DFU_DEFAULT_POLL_TIMEOUT 0 123#endif 124#ifndef DFU_MANIFEST_POLL_TIMEOUT 125#define DFU_MANIFEST_POLL_TIMEOUT DFU_DEFAULT_POLL_TIMEOUT 126#endif 127 128struct dfu_entity { 129 char name[DFU_NAME_SIZE]; 130 int alt; 131 void *dev_private; 132 enum dfu_device_type dev_type; 133 enum dfu_layout layout; 134 unsigned long max_buf_size; 135 136 union { 137 struct mmc_internal_data mmc; 138 struct mtd_internal_data mtd; 139 struct nand_internal_data nand; 140 struct ram_internal_data ram; 141 struct sf_internal_data sf; 142 struct virt_internal_data virt; 143 struct scsi_internal_data scsi; 144 } data; 145 146 int (*get_medium_size)(struct dfu_entity *dfu, u64 *size); 147 148 int (*read_medium)(struct dfu_entity *dfu, 149 u64 offset, void *buf, long *len); 150 151 int (*write_medium)(struct dfu_entity *dfu, 152 u64 offset, void *buf, long *len); 153 154 int (*flush_medium)(struct dfu_entity *dfu); 155 unsigned int (*poll_timeout)(struct dfu_entity *dfu); 156 157 void (*free_entity)(struct dfu_entity *dfu); 158 159 struct list_head list; 160 161 /* on the fly state */ 162 u32 crc; 163 u64 offset; 164 int i_blk_seq_num; 165 u8 *i_buf; 166 u8 *i_buf_start; 167 u8 *i_buf_end; 168 u64 r_left; 169 long b_left; 170 171 u32 bad_skip; /* for nand use */ 172 173 unsigned int inited:1; 174}; 175 176struct list_head; 177extern struct list_head dfu_list; 178 179#ifdef CONFIG_SET_DFU_ALT_INFO 180/** 181 * set_dfu_alt_info() - set dfu_alt_info environment variable 182 * 183 * If CONFIG_SET_DFU_ALT_INFO=y, this board specific function is called to set 184 * environment variable dfu_alt_info. 185 * 186 * @interface: dfu interface, e.g. "mmc" or "nand" 187 * @devstr: device number as string 188 */ 189void set_dfu_alt_info(char *interface, char *devstr); 190#endif 191 192/** 193 * dfu_alt_init() - initialize buffer for dfu entities 194 * 195 * @num: number of entities 196 * @dfu: on return allocated buffer 197 * Return: 0 on success 198 */ 199int dfu_alt_init(int num, struct dfu_entity **dfu); 200 201/** 202 * dfu_alt_add() - add alternate to dfu entity buffer 203 * 204 * @dfu: dfu entity 205 * @interface: dfu interface, e.g. "mmc" or "nand" 206 * @devstr: device number as string 207 * @s: string description of alternate 208 * Return: 0 on success 209 */ 210int dfu_alt_add(struct dfu_entity *dfu, char *interface, char *devstr, char *s); 211 212/** 213 * dfu_config_entities() - initialize dfu entitities from envirionment 214 * 215 * Initialize the list of dfu entities from environment variable dfu_alt_info. 216 * The list must be freed by calling dfu_free_entities(). This function bypasses 217 * set_dfu_alt_info(). So typically you should use dfu_init_env_entities() 218 * instead. 219 * 220 * See function :c:func:`dfu_free_entities` 221 * See function :c:func:`dfu_init_env_entities` 222 * 223 * @s: string with alternates 224 * @interface: interface, e.g. "mmc" or "nand" 225 * @devstr: device number as string 226 * Return: 0 on success, a negative error code otherwise 227 */ 228int dfu_config_entities(char *s, char *interface, char *devstr); 229 230/** 231 * dfu_free_entities() - free the list of dfu entities 232 * 233 * Free the internal list of dfu entities. 234 * 235 * See function :c:func:`dfu_init_env_entities` 236 */ 237void dfu_free_entities(void); 238 239/** 240 * dfu_show_entities() - print DFU alt settings list 241 */ 242void dfu_show_entities(void); 243 244/** 245 * dfu_get_alt_number() - get number of alternates 246 * 247 * Return: number of alternates in the dfu entities list 248 */ 249int dfu_get_alt_number(void); 250 251/** 252 * dfu_get_dev_type() - get string representation for dfu device type 253 * 254 * @type: device type 255 * Return: string representation for device type 256 */ 257const char *dfu_get_dev_type(enum dfu_device_type type); 258 259/** 260 * dfu_get_layout() - get string describing layout 261 * 262 * Internally layouts are represented by enum dfu_device_type values. This 263 * function translates an enum value to a human readable string, e.g. DFU_FS_FAT 264 * is translated to "FAT". 265 * 266 * @layout: layout 267 * Result: string representation for the layout 268 */ 269const char *dfu_get_layout(enum dfu_layout layout); 270 271/** 272 * dfu_get_entity() - get dfu entity for an alternate id 273 * 274 * @alt: alternate id 275 * Return: dfu entity 276 */ 277struct dfu_entity *dfu_get_entity(int alt); 278 279char *dfu_extract_token(char** e, int *n); 280 281/** 282 * dfu_get_alt() - get alternate id for filename 283 * 284 * Environment variable dfu_alt_info defines the write destinations (alternates) 285 * for different filenames. This function get the index of the alternate for 286 * a filename. If an absolute filename is provided (starting with '/'), the 287 * directory path is ignored. 288 * 289 * @name: filename 290 * Return: id of the alternate or negative error number (-ENODEV) 291 */ 292int dfu_get_alt(char *name); 293 294/** 295 * dfu_init_env_entities() - initialize dfu entitities from envirionment 296 * 297 * Initialize the list of dfu entities from environment variable dfu_alt_info. 298 * The list must be freed by calling dfu_free_entities(). 299 * @interface and @devstr are used to select the relevant set of alternates 300 * from environment variable dfu_alt_info. 301 * 302 * If environment variable dfu_alt_info specifies the interface and the device, 303 * use NULL for @interface and @devstr. 304 * 305 * See function :c:func:`dfu_free_entities` 306 * 307 * @interface: interface, e.g. "mmc" or "nand" 308 * @devstr: device number as string 309 * Return: 0 on success, a negative error code otherwise 310 */ 311int dfu_init_env_entities(char *interface, char *devstr); 312 313unsigned char *dfu_get_buf(struct dfu_entity *dfu); 314unsigned char *dfu_free_buf(void); 315unsigned long dfu_get_buf_size(void); 316bool dfu_usb_get_reset(void); 317 318#ifdef CONFIG_DFU_TIMEOUT 319unsigned long dfu_get_timeout(void); 320void dfu_set_timeout(unsigned long); 321#endif 322 323/** 324 * dfu_read() - read from dfu entity 325 * 326 * The block sequence number @blk_seq_num is a 16 bit counter that must be 327 * incremented with each call for the same dfu entity @de. 328 * 329 * @de: dfu entity 330 * @buf: buffer 331 * @size: size of buffer 332 * @blk_seq_num: block sequence number 333 * Return: 0 for success, -1 for error 334 */ 335int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num); 336 337/** 338 * dfu_write() - write to dfu entity 339 * 340 * Write the contents of a buffer @buf to the dfu entity @de. After writing 341 * the last block call dfu_flush(). If a file is already loaded completely 342 * into memory it is preferable to use dfu_write_from_mem_addr() which takes 343 * care of blockwise transfer and flushing. 344 * 345 * The block sequence number @blk_seq_num is a 16 bit counter that must be 346 * incremented with each call for the same dfu entity @de. 347 * 348 * See function :c:func:`dfu_flush` 349 * See function :c:func:`dfu_write_from_mem_addr` 350 * 351 * @de: dfu entity 352 * @buf: buffer 353 * @size: size of buffer 354 * @blk_seq_num: block sequence number 355 * Return: 0 for success, -1 for error 356 */ 357int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num); 358 359/** 360 * dfu_flush() - flush to dfu entity 361 * 362 * This function has to be called after writing the last block to the dfu 363 * entity @de. 364 * 365 * The block sequence number @blk_seq_num is a 16 bit counter that must be 366 * incremented with each call for the same dfu entity @de. 367 * 368 * See function :c:func:`dfu_write` 369 * 370 * @de: dfu entity 371 * @buf: ignored 372 * @size: ignored 373 * @blk_seq_num: block sequence number of last write - ignored 374 * Return: 0 for success, -1 for error 375 */ 376int dfu_flush(struct dfu_entity *de, void *buf, int size, int blk_seq_num); 377 378/** 379 * dfu_initiated_callback() - weak callback called on DFU transaction start 380 * 381 * It is a callback function called by DFU stack when a DFU transaction is 382 * initiated. This function allows to manage some board specific behavior on 383 * DFU targets. 384 * 385 * @dfu: pointer to the dfu_entity, which should be initialized 386 */ 387void dfu_initiated_callback(struct dfu_entity *dfu); 388 389/** 390 * dfu_flush_callback() - weak callback called at the end of the DFU write 391 * 392 * It is a callback function called by DFU stack after DFU manifestation. 393 * This function allows to manage some board specific behavior on DFU targets 394 * 395 * @dfu: pointer to the dfu_entity, which should be flushed 396 */ 397void dfu_flush_callback(struct dfu_entity *dfu); 398 399/** 400 * dfu_error_callback() - weak callback called at the DFU write error 401 * 402 * It is a callback function called by DFU stack after DFU write error. 403 * This function allows to manage some board specific behavior on DFU targets 404 * 405 * @dfu: pointer to the dfu_entity which cause the error 406 * @msg: the message of the error 407 */ 408void dfu_error_callback(struct dfu_entity *dfu, const char *msg); 409 410int dfu_transaction_initiate(struct dfu_entity *dfu, bool read); 411void dfu_transaction_cleanup(struct dfu_entity *dfu); 412 413/* 414 * dfu_defer_flush - pointer to store dfu_entity for deferred flashing. 415 * It should be NULL when not used. 416 */ 417extern struct dfu_entity *dfu_defer_flush; 418 419/** 420 * dfu_get_defer_flush() - get current value of dfu_defer_flush pointer 421 * 422 * Return: value of the dfu_defer_flush pointer 423 */ 424static inline struct dfu_entity *dfu_get_defer_flush(void) 425{ 426 return dfu_defer_flush; 427} 428 429/** 430 * dfu_set_defer_flush() - set the dfu_defer_flush pointer 431 * 432 * @dfu: pointer to the dfu_entity, which should be written 433 */ 434static inline void dfu_set_defer_flush(struct dfu_entity *dfu) 435{ 436 dfu_defer_flush = dfu; 437} 438 439/** 440 * dfu_write_from_mem_addr() - write data from memory to DFU managed medium 441 * 442 * This function adds support for writing data starting from fixed memory 443 * address (like $loadaddr) to dfu managed medium (e.g. NAND, MMC, file system) 444 * 445 * @dfu: dfu entity to which we want to store data 446 * @buf: fixed memory address from where data starts 447 * @size: number of bytes to write 448 * 449 * Return: 0 on success, other value on failure 450 */ 451int dfu_write_from_mem_addr(struct dfu_entity *dfu, void *buf, int size); 452 453/* Device specific */ 454/* Each entity has 5 arguments in maximum. */ 455#define DFU_MAX_ENTITY_ARGS 5 456 457#if CONFIG_IS_ENABLED(DFU_MMC) 458extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, 459 char **argv, int argc); 460#else 461static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, 462 char **argv, int argc) 463{ 464 puts("MMC support not available!\n"); 465 return -1; 466} 467#endif 468 469#if CONFIG_IS_ENABLED(DFU_NAND) 470extern int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, 471 char **argv, int argc); 472#else 473static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, 474 char **argv, int argc) 475{ 476 puts("NAND support not available!\n"); 477 return -1; 478} 479#endif 480 481#if CONFIG_IS_ENABLED(DFU_RAM) 482extern int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, 483 char **argv, int argc); 484#else 485static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, 486 char **argv, int argc) 487{ 488 puts("RAM support not available!\n"); 489 return -1; 490} 491#endif 492 493#if CONFIG_IS_ENABLED(DFU_SF) 494extern int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, 495 char **argv, int argc); 496#else 497static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, 498 char **argv, int argc) 499{ 500 puts("SF support not available!\n"); 501 return -1; 502} 503#endif 504 505#if CONFIG_IS_ENABLED(DFU_MTD) 506extern int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, 507 char **argv, int argc); 508#else 509static inline int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, 510 char **argv, int argc) 511{ 512 puts("MTD support not available!\n"); 513 return -1; 514} 515#endif 516 517#if CONFIG_IS_ENABLED(DFU_VIRT) 518int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, 519 char **argv, int argc); 520int dfu_write_medium_virt(struct dfu_entity *dfu, u64 offset, 521 void *buf, long *len); 522int dfu_get_medium_size_virt(struct dfu_entity *dfu, u64 *size); 523int dfu_read_medium_virt(struct dfu_entity *dfu, u64 offset, 524 void *buf, long *len); 525#else 526static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr, 527 char **argv, int argc) 528{ 529 puts("VIRT support not available!\n"); 530 return -1; 531} 532#endif 533 534#if CONFIG_IS_ENABLED(DFU_SCSI) 535int dfu_fill_entity_scsi(struct dfu_entity *dfu, char *devstr, 536 char **argv, int argc); 537#else 538static inline int dfu_fill_entity_scsi(struct dfu_entity *dfu, char *devstr, 539 char **argv, int argc) 540{ 541 puts("SCSI support not available!\n"); 542 return -1; 543} 544#endif 545 546extern bool dfu_reinit_needed; 547extern bool dfu_alt_info_changed; 548 549#if CONFIG_IS_ENABLED(DFU_WRITE_ALT) 550/** 551 * dfu_write_by_name() - write data to DFU medium 552 * @dfu_entity_name: Name of DFU entity to write 553 * @addr: Address of data buffer to write 554 * @len: Number of bytes 555 * @interface: Destination DFU medium (e.g. "mmc") 556 * @devstring: Instance number of destination DFU medium (e.g. "1") 557 * 558 * This function is storing data received on DFU supported medium which 559 * is specified by @dfu_entity_name. 560 * 561 * Return: 0 - on success, error code - otherwise 562 */ 563int dfu_write_by_name(char *dfu_entity_name, void *addr, 564 unsigned int len, char *interface, char *devstring); 565 566/** 567 * dfu_write_by_alt() - write data to DFU medium 568 * @dfu_alt_num: DFU alt setting number 569 * @addr: Address of data buffer to write 570 * @len: Number of bytes 571 * @interface: Destination DFU medium (e.g. "mmc") 572 * @devstring: Instance number of destination DFU medium (e.g. "1") 573 * 574 * This function is storing data received on DFU supported medium which 575 * is specified by @dfu_alt_name. 576 * 577 * Return: 0 - on success, error code - otherwise 578 */ 579int dfu_write_by_alt(int dfu_alt_num, void *addr, unsigned int len, 580 char *interface, char *devstring); 581#else 582static inline int dfu_write_by_name(char *dfu_entity_name, void *addr, 583 unsigned int len, char *interface, 584 char *devstring) 585{ 586 puts("write support for DFU not available!\n"); 587 return -ENOSYS; 588} 589 590static inline int dfu_write_by_alt(int dfu_alt_num, void *addr, 591 unsigned int len, char *interface, 592 char *devstring) 593{ 594 puts("write support for DFU not available!\n"); 595 return -ENOSYS; 596} 597#endif 598 599int dfu_add(struct usb_configuration *c); 600#endif /* __DFU_ENTITY_H_ */