1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * dfu.h - DFU flashable area description
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2012 Samsung Electronics
5*4882a593Smuzhiyun * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
6*4882a593Smuzhiyun * Lukasz Majewski <l.majewski@samsung.com>
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #ifndef __DFU_ENTITY_H_
12*4882a593Smuzhiyun #define __DFU_ENTITY_H_
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <common.h>
15*4882a593Smuzhiyun #include <linux/list.h>
16*4882a593Smuzhiyun #include <mmc.h>
17*4882a593Smuzhiyun #include <spi_flash.h>
18*4882a593Smuzhiyun #include <linux/usb/composite.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun enum dfu_device_type {
21*4882a593Smuzhiyun DFU_DEV_MMC = 1,
22*4882a593Smuzhiyun DFU_DEV_ONENAND,
23*4882a593Smuzhiyun DFU_DEV_NAND,
24*4882a593Smuzhiyun DFU_DEV_RAM,
25*4882a593Smuzhiyun DFU_DEV_SF,
26*4882a593Smuzhiyun DFU_DEV_MTD,
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun enum dfu_layout {
30*4882a593Smuzhiyun DFU_RAW_ADDR = 1,
31*4882a593Smuzhiyun DFU_FS_FAT,
32*4882a593Smuzhiyun DFU_FS_EXT2,
33*4882a593Smuzhiyun DFU_FS_EXT3,
34*4882a593Smuzhiyun DFU_FS_EXT4,
35*4882a593Smuzhiyun DFU_RAM_ADDR,
36*4882a593Smuzhiyun };
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun enum dfu_op {
39*4882a593Smuzhiyun DFU_OP_READ = 1,
40*4882a593Smuzhiyun DFU_OP_WRITE,
41*4882a593Smuzhiyun DFU_OP_SIZE,
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun struct mmc_internal_data {
45*4882a593Smuzhiyun int dev_num;
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun /* RAW programming */
48*4882a593Smuzhiyun unsigned int lba_start;
49*4882a593Smuzhiyun unsigned int lba_size;
50*4882a593Smuzhiyun unsigned int lba_blk_size;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /* eMMC HW partition access */
53*4882a593Smuzhiyun int hw_partition;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* FAT/EXT */
56*4882a593Smuzhiyun unsigned int dev;
57*4882a593Smuzhiyun unsigned int part;
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun struct nand_internal_data {
61*4882a593Smuzhiyun /* RAW programming */
62*4882a593Smuzhiyun u64 start;
63*4882a593Smuzhiyun u64 size;
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun unsigned int dev;
66*4882a593Smuzhiyun unsigned int part;
67*4882a593Smuzhiyun /* for nand/ubi use */
68*4882a593Smuzhiyun unsigned int ubi;
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun struct mtd_internal_data {
72*4882a593Smuzhiyun /* RAW programming */
73*4882a593Smuzhiyun u64 start;
74*4882a593Smuzhiyun u64 size;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun unsigned int dev;
77*4882a593Smuzhiyun unsigned int part;
78*4882a593Smuzhiyun /* for nand/ubi use */
79*4882a593Smuzhiyun unsigned int ubi;
80*4882a593Smuzhiyun };
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun struct ram_internal_data {
83*4882a593Smuzhiyun void *start;
84*4882a593Smuzhiyun unsigned int size;
85*4882a593Smuzhiyun };
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun struct sf_internal_data {
88*4882a593Smuzhiyun struct spi_flash *dev;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* RAW programming */
91*4882a593Smuzhiyun u64 start;
92*4882a593Smuzhiyun u64 size;
93*4882a593Smuzhiyun };
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun #define DFU_NAME_SIZE 32
96*4882a593Smuzhiyun #define DFU_CMD_BUF_SIZE 128
97*4882a593Smuzhiyun #ifndef CONFIG_SYS_DFU_DATA_BUF_SIZE
98*4882a593Smuzhiyun #define CONFIG_SYS_DFU_DATA_BUF_SIZE (1024*1024*8) /* 8 MiB */
99*4882a593Smuzhiyun #endif
100*4882a593Smuzhiyun #ifndef CONFIG_SYS_DFU_MAX_FILE_SIZE
101*4882a593Smuzhiyun #define CONFIG_SYS_DFU_MAX_FILE_SIZE CONFIG_SYS_DFU_DATA_BUF_SIZE
102*4882a593Smuzhiyun #endif
103*4882a593Smuzhiyun #ifndef DFU_DEFAULT_POLL_TIMEOUT
104*4882a593Smuzhiyun #define DFU_DEFAULT_POLL_TIMEOUT 0
105*4882a593Smuzhiyun #endif
106*4882a593Smuzhiyun #ifndef DFU_MANIFEST_POLL_TIMEOUT
107*4882a593Smuzhiyun #define DFU_MANIFEST_POLL_TIMEOUT DFU_DEFAULT_POLL_TIMEOUT
108*4882a593Smuzhiyun #endif
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun struct dfu_entity {
111*4882a593Smuzhiyun char name[DFU_NAME_SIZE];
112*4882a593Smuzhiyun int alt;
113*4882a593Smuzhiyun void *dev_private;
114*4882a593Smuzhiyun enum dfu_device_type dev_type;
115*4882a593Smuzhiyun enum dfu_layout layout;
116*4882a593Smuzhiyun unsigned long max_buf_size;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun union {
119*4882a593Smuzhiyun struct mmc_internal_data mmc;
120*4882a593Smuzhiyun struct nand_internal_data nand;
121*4882a593Smuzhiyun struct ram_internal_data ram;
122*4882a593Smuzhiyun struct sf_internal_data sf;
123*4882a593Smuzhiyun struct mtd_internal_data mtd;
124*4882a593Smuzhiyun } data;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun int (*get_medium_size)(struct dfu_entity *dfu, u64 *size);
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun int (*read_medium)(struct dfu_entity *dfu,
129*4882a593Smuzhiyun u64 offset, void *buf, long *len);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun int (*write_medium)(struct dfu_entity *dfu,
132*4882a593Smuzhiyun u64 offset, void *buf, long *len);
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun int (*flush_medium)(struct dfu_entity *dfu);
135*4882a593Smuzhiyun unsigned int (*poll_timeout)(struct dfu_entity *dfu);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun void (*free_entity)(struct dfu_entity *dfu);
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun struct list_head list;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun /* on the fly state */
142*4882a593Smuzhiyun u32 crc;
143*4882a593Smuzhiyun u64 offset;
144*4882a593Smuzhiyun int i_blk_seq_num;
145*4882a593Smuzhiyun u8 *i_buf;
146*4882a593Smuzhiyun u8 *i_buf_start;
147*4882a593Smuzhiyun u8 *i_buf_end;
148*4882a593Smuzhiyun u64 r_left;
149*4882a593Smuzhiyun long b_left;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun u32 bad_skip; /* for nand use */
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun unsigned int inited:1;
154*4882a593Smuzhiyun };
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun #ifdef CONFIG_SET_DFU_ALT_INFO
157*4882a593Smuzhiyun void set_dfu_alt_info(char *interface, char *devstr);
158*4882a593Smuzhiyun #endif
159*4882a593Smuzhiyun int dfu_config_entities(char *s, char *interface, char *devstr);
160*4882a593Smuzhiyun void dfu_free_entities(void);
161*4882a593Smuzhiyun void dfu_show_entities(void);
162*4882a593Smuzhiyun int dfu_get_alt_number(void);
163*4882a593Smuzhiyun const char *dfu_get_dev_type(enum dfu_device_type t);
164*4882a593Smuzhiyun const char *dfu_get_layout(enum dfu_layout l);
165*4882a593Smuzhiyun struct dfu_entity *dfu_get_entity(int alt);
166*4882a593Smuzhiyun char *dfu_extract_token(char** e, int *n);
167*4882a593Smuzhiyun void dfu_trigger_reset(void);
168*4882a593Smuzhiyun int dfu_get_alt(char *name);
169*4882a593Smuzhiyun int dfu_init_env_entities(char *interface, char *devstr);
170*4882a593Smuzhiyun unsigned char *dfu_get_buf(struct dfu_entity *dfu);
171*4882a593Smuzhiyun unsigned char *dfu_free_buf(void);
172*4882a593Smuzhiyun unsigned long dfu_get_buf_size(void);
173*4882a593Smuzhiyun bool dfu_usb_get_reset(void);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun int dfu_read(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
176*4882a593Smuzhiyun int dfu_write(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
177*4882a593Smuzhiyun int dfu_flush(struct dfu_entity *de, void *buf, int size, int blk_seq_num);
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun /*
180*4882a593Smuzhiyun * dfu_defer_flush - pointer to store dfu_entity for deferred flashing.
181*4882a593Smuzhiyun * It should be NULL when not used.
182*4882a593Smuzhiyun */
183*4882a593Smuzhiyun extern struct dfu_entity *dfu_defer_flush;
184*4882a593Smuzhiyun /**
185*4882a593Smuzhiyun * dfu_get_defer_flush - get current value of dfu_defer_flush pointer
186*4882a593Smuzhiyun *
187*4882a593Smuzhiyun * @return - value of the dfu_defer_flush pointer
188*4882a593Smuzhiyun */
dfu_get_defer_flush(void)189*4882a593Smuzhiyun static inline struct dfu_entity *dfu_get_defer_flush(void)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun return dfu_defer_flush;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun /**
195*4882a593Smuzhiyun * dfu_set_defer_flush - set the dfu_defer_flush pointer
196*4882a593Smuzhiyun *
197*4882a593Smuzhiyun * @param dfu - pointer to the dfu_entity, which should be written
198*4882a593Smuzhiyun */
dfu_set_defer_flush(struct dfu_entity * dfu)199*4882a593Smuzhiyun static inline void dfu_set_defer_flush(struct dfu_entity *dfu)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun dfu_defer_flush = dfu;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /**
205*4882a593Smuzhiyun * dfu_write_from_mem_addr - write data from memory to DFU managed medium
206*4882a593Smuzhiyun *
207*4882a593Smuzhiyun * This function adds support for writing data starting from fixed memory
208*4882a593Smuzhiyun * address (like $loadaddr) to dfu managed medium (e.g. NAND, MMC, file system)
209*4882a593Smuzhiyun *
210*4882a593Smuzhiyun * @param dfu - dfu entity to which we want to store data
211*4882a593Smuzhiyun * @param buf - fixed memory addres from where data starts
212*4882a593Smuzhiyun * @param size - number of bytes to write
213*4882a593Smuzhiyun *
214*4882a593Smuzhiyun * @return - 0 on success, other value on failure
215*4882a593Smuzhiyun */
216*4882a593Smuzhiyun int dfu_write_from_mem_addr(struct dfu_entity *dfu, void *buf, int size);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun /* Device specific */
219*4882a593Smuzhiyun #ifdef CONFIG_DFU_MMC
220*4882a593Smuzhiyun extern int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s);
221*4882a593Smuzhiyun #else
dfu_fill_entity_mmc(struct dfu_entity * dfu,char * devstr,char * s)222*4882a593Smuzhiyun static inline int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr,
223*4882a593Smuzhiyun char *s)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun puts("MMC support not available!\n");
226*4882a593Smuzhiyun return -1;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun #endif
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun #ifdef CONFIG_DFU_MTD
231*4882a593Smuzhiyun extern int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr, char *s);
232*4882a593Smuzhiyun #else
dfu_fill_entity_mtd(struct dfu_entity * dfu,char * devstr,char * s)233*4882a593Smuzhiyun static inline int dfu_fill_entity_mtd(struct dfu_entity *dfu, char *devstr,
234*4882a593Smuzhiyun char *s)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun puts("MTD support not available!\n");
237*4882a593Smuzhiyun return -1;
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun #endif
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun #ifdef CONFIG_DFU_NAND
242*4882a593Smuzhiyun extern int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr, char *s);
243*4882a593Smuzhiyun #else
dfu_fill_entity_nand(struct dfu_entity * dfu,char * devstr,char * s)244*4882a593Smuzhiyun static inline int dfu_fill_entity_nand(struct dfu_entity *dfu, char *devstr,
245*4882a593Smuzhiyun char *s)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun puts("NAND support not available!\n");
248*4882a593Smuzhiyun return -1;
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun #endif
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun #ifdef CONFIG_DFU_RAM
253*4882a593Smuzhiyun extern int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr, char *s);
254*4882a593Smuzhiyun #else
dfu_fill_entity_ram(struct dfu_entity * dfu,char * devstr,char * s)255*4882a593Smuzhiyun static inline int dfu_fill_entity_ram(struct dfu_entity *dfu, char *devstr,
256*4882a593Smuzhiyun char *s)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun puts("RAM support not available!\n");
259*4882a593Smuzhiyun return -1;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun #endif
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun #ifdef CONFIG_DFU_SF
264*4882a593Smuzhiyun extern int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr, char *s);
265*4882a593Smuzhiyun #else
dfu_fill_entity_sf(struct dfu_entity * dfu,char * devstr,char * s)266*4882a593Smuzhiyun static inline int dfu_fill_entity_sf(struct dfu_entity *dfu, char *devstr,
267*4882a593Smuzhiyun char *s)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun puts("SF support not available!\n");
270*4882a593Smuzhiyun return -1;
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun #endif
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun /**
275*4882a593Smuzhiyun * dfu_tftp_write - Write TFTP data to DFU medium
276*4882a593Smuzhiyun *
277*4882a593Smuzhiyun * This function is storing data received via TFTP on DFU supported medium.
278*4882a593Smuzhiyun *
279*4882a593Smuzhiyun * @param dfu_entity_name - name of DFU entity to write
280*4882a593Smuzhiyun * @param addr - address of data buffer to write
281*4882a593Smuzhiyun * @param len - number of bytes
282*4882a593Smuzhiyun * @param interface - destination DFU medium (e.g. "mmc")
283*4882a593Smuzhiyun * @param devstring - instance number of destination DFU medium (e.g. "1")
284*4882a593Smuzhiyun *
285*4882a593Smuzhiyun * @return 0 on success, otherwise error code
286*4882a593Smuzhiyun */
287*4882a593Smuzhiyun #ifdef CONFIG_DFU_TFTP
288*4882a593Smuzhiyun int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
289*4882a593Smuzhiyun char *interface, char *devstring);
290*4882a593Smuzhiyun #else
dfu_tftp_write(char * dfu_entity_name,unsigned int addr,unsigned int len,char * interface,char * devstring)291*4882a593Smuzhiyun static inline int dfu_tftp_write(char *dfu_entity_name, unsigned int addr,
292*4882a593Smuzhiyun unsigned int len, char *interface,
293*4882a593Smuzhiyun char *devstring)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun puts("TFTP write support for DFU not available!\n");
296*4882a593Smuzhiyun return -ENOSYS;
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun #endif
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun int dfu_add(struct usb_configuration *c);
301*4882a593Smuzhiyun #endif /* __DFU_ENTITY_H_ */
302