stm32mp: stm32prog: add support for delete option in flashlayout
[oweals/u-boot.git] / arch / arm / mach-stm32mp / cmd_stm32prog / stm32prog.c
1 // SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2 /*
3  * Copyright (C) 2020, STMicroelectronics - All Rights Reserved
4  */
5
6 #include <common.h>
7 #include <console.h>
8 #include <dfu.h>
9 #include <malloc.h>
10 #include <mmc.h>
11 #include <part.h>
12 #include <dm/uclass.h>
13 #include <jffs2/load_kernel.h>
14 #include <linux/list.h>
15 #include <linux/list_sort.h>
16 #include <linux/mtd/mtd.h>
17 #include <linux/sizes.h>
18
19 #include "stm32prog.h"
20
21 /* Primary GPT header size for 128 entries : 17kB = 34 LBA of 512B */
22 #define GPT_HEADER_SZ   34
23
24 #define OPT_SELECT      BIT(0)
25 #define OPT_EMPTY       BIT(1)
26 #define OPT_DELETE      BIT(2)
27
28 #define IS_SELECT(part) ((part)->option & OPT_SELECT)
29 #define IS_EMPTY(part)  ((part)->option & OPT_EMPTY)
30 #define IS_DELETE(part) ((part)->option & OPT_DELETE)
31
32 #define ALT_BUF_LEN                     SZ_1K
33
34 #define ROOTFS_MMC0_UUID \
35         EFI_GUID(0xE91C4E10, 0x16E6, 0x4C0E, \
36                  0xBD, 0x0E, 0x77, 0xBE, 0xCF, 0x4A, 0x35, 0x82)
37
38 #define ROOTFS_MMC1_UUID \
39         EFI_GUID(0x491F6117, 0x415D, 0x4F53, \
40                  0x88, 0xC9, 0x6E, 0x0D, 0xE5, 0x4D, 0xEA, 0xC6)
41
42 #define ROOTFS_MMC2_UUID \
43         EFI_GUID(0xFD58F1C7, 0xBE0D, 0x4338, \
44                  0x88, 0xE9, 0xAD, 0x8F, 0x05, 0x0A, 0xEB, 0x18)
45
46 /* RAW parttion (binary / bootloader) used Linux - reserved UUID */
47 #define LINUX_RESERVED_UUID "8DA63339-0007-60C0-C436-083AC8230908"
48
49 /*
50  * unique partition guid (uuid) for partition named "rootfs"
51  * on each MMC instance = SD Card or eMMC
52  * allow fixed kernel bootcmd: "rootf=PARTUID=e91c4e10-..."
53  */
54 static const efi_guid_t uuid_mmc[3] = {
55         ROOTFS_MMC0_UUID,
56         ROOTFS_MMC1_UUID,
57         ROOTFS_MMC2_UUID
58 };
59
60 DECLARE_GLOBAL_DATA_PTR;
61
62 /* order of column in flash layout file */
63 enum stm32prog_col_t {
64         COL_OPTION,
65         COL_ID,
66         COL_NAME,
67         COL_TYPE,
68         COL_IP,
69         COL_OFFSET,
70         COL_NB_STM32
71 };
72
73 /* partition handling routines : CONFIG_CMD_MTDPARTS */
74 int mtdparts_init(void);
75 int find_dev_and_part(const char *id, struct mtd_device **dev,
76                       u8 *part_num, struct part_info **part);
77
78 char *stm32prog_get_error(struct stm32prog_data *data)
79 {
80         static const char error_msg[] = "Unspecified";
81
82         if (strlen(data->error) == 0)
83                 strcpy(data->error, error_msg);
84
85         return data->error;
86 }
87
88 u8 stm32prog_header_check(struct raw_header_s *raw_header,
89                           struct image_header_s *header)
90 {
91         unsigned int i;
92
93         header->present = 0;
94         header->image_checksum = 0x0;
95         header->image_length = 0x0;
96
97         if (!raw_header || !header) {
98                 pr_debug("%s:no header data\n", __func__);
99                 return -1;
100         }
101         if (raw_header->magic_number !=
102                 (('S' << 0) | ('T' << 8) | ('M' << 16) | (0x32 << 24))) {
103                 pr_debug("%s:invalid magic number : 0x%x\n",
104                          __func__, raw_header->magic_number);
105                 return -2;
106         }
107         /* only header v1.0 supported */
108         if (raw_header->header_version != 0x00010000) {
109                 pr_debug("%s:invalid header version : 0x%x\n",
110                          __func__, raw_header->header_version);
111                 return -3;
112         }
113         if (raw_header->reserved1 != 0x0 || raw_header->reserved2) {
114                 pr_debug("%s:invalid reserved field\n", __func__);
115                 return -4;
116         }
117         for (i = 0; i < (sizeof(raw_header->padding) / 4); i++) {
118                 if (raw_header->padding[i] != 0) {
119                         pr_debug("%s:invalid padding field\n", __func__);
120                         return -5;
121                 }
122         }
123         header->present = 1;
124         header->image_checksum = le32_to_cpu(raw_header->image_checksum);
125         header->image_length = le32_to_cpu(raw_header->image_length);
126
127         return 0;
128 }
129
130 static u32 stm32prog_header_checksum(u32 addr, struct image_header_s *header)
131 {
132         u32 i, checksum;
133         u8 *payload;
134
135         /* compute checksum on payload */
136         payload = (u8 *)addr;
137         checksum = 0;
138         for (i = header->image_length; i > 0; i--)
139                 checksum += *(payload++);
140
141         return checksum;
142 }
143
144 /* FLASHLAYOUT PARSING *****************************************/
145 static int parse_option(struct stm32prog_data *data,
146                         int i, char *p, struct stm32prog_part_t *part)
147 {
148         int result = 0;
149         char *c = p;
150
151         part->option = 0;
152         if (!strcmp(p, "-"))
153                 return 0;
154
155         while (*c) {
156                 switch (*c) {
157                 case 'P':
158                         part->option |= OPT_SELECT;
159                         break;
160                 case 'E':
161                         part->option |= OPT_EMPTY;
162                         break;
163                 case 'D':
164                         part->option |= OPT_DELETE;
165                         break;
166                 default:
167                         result = -EINVAL;
168                         stm32prog_err("Layout line %d: invalid option '%c' in %s)",
169                                       i, *c, p);
170                         return -EINVAL;
171                 }
172                 c++;
173         }
174         if (!(part->option & OPT_SELECT)) {
175                 stm32prog_err("Layout line %d: missing 'P' in option %s", i, p);
176                 return -EINVAL;
177         }
178
179         return result;
180 }
181
182 static int parse_id(struct stm32prog_data *data,
183                     int i, char *p, struct stm32prog_part_t *part)
184 {
185         int result = 0;
186         unsigned long value;
187
188         result = strict_strtoul(p, 0, &value);
189         part->id = value;
190         if (result || value > PHASE_LAST_USER) {
191                 stm32prog_err("Layout line %d: invalid phase value = %s", i, p);
192                 result = -EINVAL;
193         }
194
195         return result;
196 }
197
198 static int parse_name(struct stm32prog_data *data,
199                       int i, char *p, struct stm32prog_part_t *part)
200 {
201         int result = 0;
202
203         if (strlen(p) < sizeof(part->name)) {
204                 strcpy(part->name, p);
205         } else {
206                 stm32prog_err("Layout line %d: partition name too long [%d]: %s",
207                               i, strlen(p), p);
208                 result = -EINVAL;
209         }
210
211         return result;
212 }
213
214 static int parse_type(struct stm32prog_data *data,
215                       int i, char *p, struct stm32prog_part_t *part)
216 {
217         int result = 0;
218         int len = 0;
219
220         part->bin_nb = 0;
221         if (!strncmp(p, "Binary", 6)) {
222                 part->part_type = PART_BINARY;
223
224                 /* search for Binary(X) case */
225                 len = strlen(p);
226                 part->bin_nb = 1;
227                 if (len > 6) {
228                         if (len < 8 ||
229                             (p[6] != '(') ||
230                             (p[len - 1] != ')'))
231                                 result = -EINVAL;
232                         else
233                                 part->bin_nb =
234                                         simple_strtoul(&p[7], NULL, 10);
235                 }
236         } else if (!strcmp(p, "System")) {
237                 part->part_type = PART_SYSTEM;
238         } else if (!strcmp(p, "FileSystem")) {
239                 part->part_type = PART_FILESYSTEM;
240         } else if (!strcmp(p, "RawImage")) {
241                 part->part_type = RAW_IMAGE;
242         } else {
243                 result = -EINVAL;
244         }
245         if (result)
246                 stm32prog_err("Layout line %d: type parsing error : '%s'",
247                               i, p);
248
249         return result;
250 }
251
252 static int parse_ip(struct stm32prog_data *data,
253                     int i, char *p, struct stm32prog_part_t *part)
254 {
255         int result = 0;
256         unsigned int len = 0;
257
258         part->dev_id = 0;
259         if (!strcmp(p, "none")) {
260                 part->target = STM32PROG_NONE;
261         } else if (!strncmp(p, "mmc", 3)) {
262                 part->target = STM32PROG_MMC;
263                 len = 3;
264         } else if (!strncmp(p, "nor", 3)) {
265                 part->target = STM32PROG_NOR;
266                 len = 3;
267         } else if (!strncmp(p, "nand", 4)) {
268                 part->target = STM32PROG_NAND;
269                 len = 4;
270         } else if (!strncmp(p, "spi-nand", 8)) {
271                 part->target = STM32PROG_SPI_NAND;
272                 len = 8;
273         } else {
274                 result = -EINVAL;
275         }
276         if (len) {
277                 /* only one digit allowed for device id */
278                 if (strlen(p) != len + 1) {
279                         result = -EINVAL;
280                 } else {
281                         part->dev_id = p[len] - '0';
282                         if (part->dev_id > 9)
283                                 result = -EINVAL;
284                 }
285         }
286         if (result)
287                 stm32prog_err("Layout line %d: ip parsing error: '%s'", i, p);
288
289         return result;
290 }
291
292 static int parse_offset(struct stm32prog_data *data,
293                         int i, char *p, struct stm32prog_part_t *part)
294 {
295         int result = 0;
296         char *tail;
297
298         part->part_id = 0;
299         part->addr = 0;
300         part->size = 0;
301         /* eMMC boot parttion */
302         if (!strncmp(p, "boot", 4)) {
303                 if (strlen(p) != 5) {
304                         result = -EINVAL;
305                 } else {
306                         if (p[4] == '1')
307                                 part->part_id = -1;
308                         else if (p[4] == '2')
309                                 part->part_id = -2;
310                         else
311                                 result = -EINVAL;
312                 }
313                 if (result)
314                         stm32prog_err("Layout line %d: invalid part '%s'",
315                                       i, p);
316         } else {
317                 part->addr = simple_strtoull(p, &tail, 0);
318                 if (tail == p || *tail != '\0') {
319                         stm32prog_err("Layout line %d: invalid offset '%s'",
320                                       i, p);
321                         result = -EINVAL;
322                 }
323         }
324
325         return result;
326 }
327
328 static
329 int (* const parse[COL_NB_STM32])(struct stm32prog_data *data, int i, char *p,
330                                   struct stm32prog_part_t *part) = {
331         [COL_OPTION] = parse_option,
332         [COL_ID] = parse_id,
333         [COL_NAME] =  parse_name,
334         [COL_TYPE] = parse_type,
335         [COL_IP] = parse_ip,
336         [COL_OFFSET] = parse_offset,
337 };
338
339 static int parse_flash_layout(struct stm32prog_data *data,
340                               ulong addr,
341                               ulong size)
342 {
343         int column = 0, part_nb = 0, ret;
344         bool end_of_line, eof;
345         char *p, *start, *last, *col;
346         struct stm32prog_part_t *part;
347         int part_list_size;
348         int i;
349
350         data->part_nb = 0;
351
352         /* check if STM32image is detected */
353         if (!stm32prog_header_check((struct raw_header_s *)addr,
354                                     &data->header)) {
355                 u32 checksum;
356
357                 addr = addr + BL_HEADER_SIZE;
358                 size = data->header.image_length;
359
360                 checksum = stm32prog_header_checksum(addr, &data->header);
361                 if (checksum != data->header.image_checksum) {
362                         stm32prog_err("Layout: invalid checksum : 0x%x expected 0x%x",
363                                       checksum, data->header.image_checksum);
364                         return -EIO;
365                 }
366         }
367         if (!size)
368                 return -EINVAL;
369
370         start = (char *)addr;
371         last = start + size;
372
373         *last = 0x0; /* force null terminated string */
374         pr_debug("flash layout =\n%s\n", start);
375
376         /* calculate expected number of partitions */
377         part_list_size = 1;
378         p = start;
379         while (*p && (p < last)) {
380                 if (*p++ == '\n') {
381                         part_list_size++;
382                         if (p < last && *p == '#')
383                                 part_list_size--;
384                 }
385         }
386         if (part_list_size > PHASE_LAST_USER) {
387                 stm32prog_err("Layout: too many partition (%d)",
388                               part_list_size);
389                 return -1;
390         }
391         part = calloc(sizeof(struct stm32prog_part_t), part_list_size);
392         if (!part) {
393                 stm32prog_err("Layout: alloc failed");
394                 return -ENOMEM;
395         }
396         data->part_array = part;
397
398         /* main parsing loop */
399         i = 1;
400         eof = false;
401         p = start;
402         col = start; /* 1st column */
403         end_of_line = false;
404         while (!eof) {
405                 switch (*p) {
406                 /* CR is ignored and replaced by NULL character */
407                 case '\r':
408                         *p = '\0';
409                         p++;
410                         continue;
411                 case '\0':
412                         end_of_line = true;
413                         eof = true;
414                         break;
415                 case '\n':
416                         end_of_line = true;
417                         break;
418                 case '\t':
419                         break;
420                 case '#':
421                         /* comment line is skipped */
422                         if (column == 0 && p == col) {
423                                 while ((p < last) && *p)
424                                         if (*p++ == '\n')
425                                                 break;
426                                 col = p;
427                                 i++;
428                                 if (p >= last || !*p) {
429                                         eof = true;
430                                         end_of_line = true;
431                                 }
432                                 continue;
433                         }
434                         /* fall through */
435                 /* by default continue with the next character */
436                 default:
437                         p++;
438                         continue;
439                 }
440
441                 /* replace by \0: allow string parsing for each column */
442                 *p = '\0';
443                 p++;
444                 if (p >= last) {
445                         eof = true;
446                         end_of_line = true;
447                 }
448
449                 /* skip empty line and multiple TAB in tsv file */
450                 if (strlen(col) == 0) {
451                         col = p;
452                         /* skip empty line */
453                         if (column == 0 && end_of_line) {
454                                 end_of_line = false;
455                                 i++;
456                         }
457                         continue;
458                 }
459
460                 if (column < COL_NB_STM32) {
461                         ret = parse[column](data, i, col, part);
462                         if (ret)
463                                 return ret;
464                 }
465
466                 /* save the beginning of the next column */
467                 column++;
468                 col = p;
469
470                 if (!end_of_line)
471                         continue;
472
473                 /* end of the line detected */
474                 end_of_line = false;
475
476                 if (column < COL_NB_STM32) {
477                         stm32prog_err("Layout line %d: no enought column", i);
478                         return -EINVAL;
479                 }
480                 column = 0;
481                 part_nb++;
482                 part++;
483                 i++;
484                 if (part_nb >= part_list_size) {
485                         part = NULL;
486                         if (!eof) {
487                                 stm32prog_err("Layout: no enought memory for %d part",
488                                               part_nb);
489                                 return -EINVAL;
490                         }
491                 }
492         }
493         data->part_nb = part_nb;
494         if (data->part_nb == 0) {
495                 stm32prog_err("Layout: no partition found");
496                 return -ENODEV;
497         }
498
499         return 0;
500 }
501
502 static int __init part_cmp(void *priv, struct list_head *a, struct list_head *b)
503 {
504         struct stm32prog_part_t *parta, *partb;
505
506         parta = container_of(a, struct stm32prog_part_t, list);
507         partb = container_of(b, struct stm32prog_part_t, list);
508
509         if (parta->part_id != partb->part_id)
510                 return parta->part_id - partb->part_id;
511         else
512                 return parta->addr > partb->addr ? 1 : -1;
513 }
514
515 static void get_mtd_by_target(char *string, enum stm32prog_target target,
516                               int dev_id)
517 {
518         const char *dev_str;
519
520         switch (target) {
521         case STM32PROG_NOR:
522                 dev_str = "nor";
523                 break;
524         case STM32PROG_NAND:
525                 dev_str = "nand";
526                 break;
527         case STM32PROG_SPI_NAND:
528                 dev_str = "spi-nand";
529                 break;
530         default:
531                 dev_str = "invalid";
532                 break;
533         }
534         sprintf(string, "%s%d", dev_str, dev_id);
535 }
536
537 static int init_device(struct stm32prog_data *data,
538                        struct stm32prog_dev_t *dev)
539 {
540         struct mmc *mmc = NULL;
541         struct blk_desc *block_dev = NULL;
542 #ifdef CONFIG_MTD
543         struct mtd_info *mtd = NULL;
544         char mtd_id[16];
545 #endif
546         int part_id;
547         int ret;
548         u64 first_addr = 0, last_addr = 0;
549         struct stm32prog_part_t *part, *next_part;
550         u64 part_addr, part_size;
551         bool part_found;
552         const char *part_name;
553
554         switch (dev->target) {
555 #ifdef CONFIG_MMC
556         case STM32PROG_MMC:
557                 mmc = find_mmc_device(dev->dev_id);
558                 if (mmc_init(mmc)) {
559                         stm32prog_err("mmc device %d not found", dev->dev_id);
560                         return -ENODEV;
561                 }
562                 block_dev = mmc_get_blk_desc(mmc);
563                 if (!block_dev) {
564                         stm32prog_err("mmc device %d not probed", dev->dev_id);
565                         return -ENODEV;
566                 }
567                 dev->erase_size = mmc->erase_grp_size * block_dev->blksz;
568                 dev->mmc = mmc;
569
570                 /* reserve a full erase group for each GTP headers */
571                 if (mmc->erase_grp_size > GPT_HEADER_SZ) {
572                         first_addr = dev->erase_size;
573                         last_addr = (u64)(block_dev->lba -
574                                           mmc->erase_grp_size) *
575                                     block_dev->blksz;
576                 } else {
577                         first_addr = (u64)GPT_HEADER_SZ * block_dev->blksz;
578                         last_addr = (u64)(block_dev->lba - GPT_HEADER_SZ - 1) *
579                                     block_dev->blksz;
580                 }
581                 pr_debug("MMC %d: lba=%ld blksz=%ld\n", dev->dev_id,
582                          block_dev->lba, block_dev->blksz);
583                 pr_debug(" available address = 0x%llx..0x%llx\n",
584                          first_addr, last_addr);
585                 pr_debug(" full_update = %d\n", dev->full_update);
586                 break;
587 #endif
588 #ifdef CONFIG_MTD
589         case STM32PROG_NOR:
590         case STM32PROG_NAND:
591         case STM32PROG_SPI_NAND:
592                 get_mtd_by_target(mtd_id, dev->target, dev->dev_id);
593                 pr_debug("%s\n", mtd_id);
594
595                 mtdparts_init();
596                 mtd = get_mtd_device_nm(mtd_id);
597                 if (IS_ERR(mtd)) {
598                         stm32prog_err("MTD device %s not found", mtd_id);
599                         return -ENODEV;
600                 }
601                 first_addr = 0;
602                 last_addr = mtd->size;
603                 dev->erase_size = mtd->erasesize;
604                 pr_debug("MTD device %s: size=%lld erasesize=%d\n",
605                          mtd_id, mtd->size, mtd->erasesize);
606                 pr_debug(" available address = 0x%llx..0x%llx\n",
607                          first_addr, last_addr);
608                 dev->mtd = mtd;
609                 break;
610 #endif
611         default:
612                 stm32prog_err("unknown device type = %d", dev->target);
613                 return -ENODEV;
614         }
615         pr_debug(" erase size = 0x%x\n", dev->erase_size);
616         pr_debug(" full_update = %d\n", dev->full_update);
617
618         /* order partition list in offset order */
619         list_sort(NULL, &dev->part_list, &part_cmp);
620         part_id = 1;
621         pr_debug("id : Opt Phase     Name target.n dev.n addr     size     part_off part_size\n");
622         list_for_each_entry(part, &dev->part_list, list) {
623                 if (part->bin_nb > 1) {
624                         if ((dev->target != STM32PROG_NAND &&
625                              dev->target != STM32PROG_SPI_NAND) ||
626                             part->id >= PHASE_FIRST_USER ||
627                             strncmp(part->name, "fsbl", 4)) {
628                                 stm32prog_err("%s (0x%x): multiple binary %d not supported",
629                                               part->name, part->id,
630                                               part->bin_nb);
631                                 return -EINVAL;
632                         }
633                 }
634                 if (part->part_type == RAW_IMAGE) {
635                         part->part_id = 0x0;
636                         part->addr = 0x0;
637                         if (block_dev)
638                                 part->size = block_dev->lba * block_dev->blksz;
639                         else
640                                 part->size = last_addr;
641                         pr_debug("-- : %1d %02x %14s %02d.%d %02d.%02d %08llx %08llx\n",
642                                  part->option, part->id, part->name,
643                                  part->part_type, part->bin_nb, part->target,
644                                  part->dev_id, part->addr, part->size);
645                         continue;
646                 }
647                 if (part->part_id < 0) { /* boot hw partition for eMMC */
648                         if (mmc) {
649                                 part->size = mmc->capacity_boot;
650                         } else {
651                                 stm32prog_err("%s (0x%x): hw partition not expected : %d",
652                                               part->name, part->id,
653                                               part->part_id);
654                                 return -ENODEV;
655                         }
656                 } else {
657                         part->part_id = part_id++;
658
659                         /* last partition : size to the end of the device */
660                         if (part->list.next != &dev->part_list) {
661                                 next_part =
662                                         container_of(part->list.next,
663                                                      struct stm32prog_part_t,
664                                                      list);
665                                 if (part->addr < next_part->addr) {
666                                         part->size = next_part->addr -
667                                                      part->addr;
668                                 } else {
669                                         stm32prog_err("%s (0x%x): same address : 0x%llx == %s (0x%x): 0x%llx",
670                                                       part->name, part->id,
671                                                       part->addr,
672                                                       next_part->name,
673                                                       next_part->id,
674                                                       next_part->addr);
675                                         return -EINVAL;
676                                 }
677                         } else {
678                                 if (part->addr <= last_addr) {
679                                         part->size = last_addr - part->addr;
680                                 } else {
681                                         stm32prog_err("%s (0x%x): invalid address 0x%llx (max=0x%llx)",
682                                                       part->name, part->id,
683                                                       part->addr, last_addr);
684                                         return -EINVAL;
685                                 }
686                         }
687                         if (part->addr < first_addr) {
688                                 stm32prog_err("%s (0x%x): invalid address 0x%llx (min=0x%llx)",
689                                               part->name, part->id,
690                                               part->addr, first_addr);
691                                 return -EINVAL;
692                         }
693                 }
694                 if ((part->addr & ((u64)part->dev->erase_size - 1)) != 0) {
695                         stm32prog_err("%s (0x%x): not aligned address : 0x%llx on erase size 0x%x",
696                                       part->name, part->id, part->addr,
697                                       part->dev->erase_size);
698                         return -EINVAL;
699                 }
700                 pr_debug("%02d : %1d %02x %14s %02d.%d %02d.%02d %08llx %08llx",
701                          part->part_id, part->option, part->id, part->name,
702                          part->part_type, part->bin_nb, part->target,
703                          part->dev_id, part->addr, part->size);
704
705                 part_addr = 0;
706                 part_size = 0;
707                 part_found = false;
708
709                 /* check coherency with existing partition */
710                 if (block_dev) {
711                         /*
712                          * block devices with GPT: check user partition size
713                          * only for partial update, the GPT partions are be
714                          * created for full update
715                          */
716                         if (dev->full_update || part->part_id < 0) {
717                                 pr_debug("\n");
718                                 continue;
719                         }
720                         disk_partition_t partinfo;
721
722                         ret = part_get_info(block_dev, part->part_id,
723                                             &partinfo);
724
725                         if (ret) {
726                                 stm32prog_err("%s (0x%x):Couldn't find part %d on device mmc %d",
727                                               part->name, part->id,
728                                               part_id, part->dev_id);
729                                 return -ENODEV;
730                         }
731                         part_addr = (u64)partinfo.start * partinfo.blksz;
732                         part_size = (u64)partinfo.size * partinfo.blksz;
733                         part_name = (char *)partinfo.name;
734                         part_found = true;
735                 }
736
737 #ifdef CONFIG_MTD
738                 if (mtd) {
739                         char mtd_part_id[32];
740                         struct part_info *mtd_part;
741                         struct mtd_device *mtd_dev;
742                         u8 part_num;
743
744                         sprintf(mtd_part_id, "%s,%d", mtd_id,
745                                 part->part_id - 1);
746                         ret = find_dev_and_part(mtd_part_id, &mtd_dev,
747                                                 &part_num, &mtd_part);
748                         if (ret != 0) {
749                                 stm32prog_err("%s (0x%x): Invalid MTD partition %s",
750                                               part->name, part->id,
751                                               mtd_part_id);
752                                 return -ENODEV;
753                         }
754                         part_addr = mtd_part->offset;
755                         part_size = mtd_part->size;
756                         part_name = mtd_part->name;
757                         part_found = true;
758                 }
759 #endif
760                 if (!part_found) {
761                         stm32prog_err("%s (0x%x): Invalid partition",
762                                       part->name, part->id);
763                         pr_debug("\n");
764                         continue;
765                 }
766
767                 pr_debug(" %08llx %08llx\n", part_addr, part_size);
768
769                 if (part->addr != part_addr) {
770                         stm32prog_err("%s (0x%x): Bad address for partition %d (%s) = 0x%llx <> 0x%llx expected",
771                                       part->name, part->id, part->part_id,
772                                       part_name, part->addr, part_addr);
773                         return -ENODEV;
774                 }
775                 if (part->size != part_size) {
776                         stm32prog_err("%s (0x%x): Bad size for partition %d (%s) at 0x%llx = 0x%llx <> 0x%llx expected",
777                                       part->name, part->id, part->part_id,
778                                       part_name, part->addr, part->size,
779                                       part_size);
780                         return -ENODEV;
781                 }
782         }
783         return 0;
784 }
785
786 static int treat_partition_list(struct stm32prog_data *data)
787 {
788         int i, j;
789         struct stm32prog_part_t *part;
790
791         for (j = 0; j < STM32PROG_MAX_DEV; j++) {
792                 data->dev[j].target = STM32PROG_NONE;
793                 INIT_LIST_HEAD(&data->dev[j].part_list);
794         }
795
796         data->tee_detected = false;
797         data->fsbl_nor_detected = false;
798         for (i = 0; i < data->part_nb; i++) {
799                 part = &data->part_array[i];
800                 part->alt_id = -1;
801
802                 /* skip partition with IP="none" */
803                 if (part->target == STM32PROG_NONE) {
804                         if (IS_SELECT(part)) {
805                                 stm32prog_err("Layout: selected none phase = 0x%x",
806                                               part->id);
807                                 return -EINVAL;
808                         }
809                         continue;
810                 }
811
812                 if (part->id == PHASE_FLASHLAYOUT ||
813                     part->id > PHASE_LAST_USER) {
814                         stm32prog_err("Layout: invalid phase = 0x%x",
815                                       part->id);
816                         return -EINVAL;
817                 }
818                 for (j = i + 1; j < data->part_nb; j++) {
819                         if (part->id == data->part_array[j].id) {
820                                 stm32prog_err("Layout: duplicated phase 0x%x at line %d and %d",
821                                               part->id, i, j);
822                                 return -EINVAL;
823                         }
824                 }
825                 for (j = 0; j < STM32PROG_MAX_DEV; j++) {
826                         if (data->dev[j].target == STM32PROG_NONE) {
827                                 /* new device found */
828                                 data->dev[j].target = part->target;
829                                 data->dev[j].dev_id = part->dev_id;
830                                 data->dev[j].full_update = true;
831                                 data->dev_nb++;
832                                 break;
833                         } else if ((part->target == data->dev[j].target) &&
834                                    (part->dev_id == data->dev[j].dev_id)) {
835                                 break;
836                         }
837                 }
838                 if (j == STM32PROG_MAX_DEV) {
839                         stm32prog_err("Layout: too many device");
840                         return -EINVAL;
841                 }
842                 switch (part->target)  {
843                 case STM32PROG_NOR:
844                         if (!data->fsbl_nor_detected &&
845                             !strncmp(part->name, "fsbl", 4))
846                                 data->fsbl_nor_detected = true;
847                         /* fallthrough */
848                 case STM32PROG_NAND:
849                 case STM32PROG_SPI_NAND:
850                         if (!data->tee_detected &&
851                             !strncmp(part->name, "tee", 3))
852                                 data->tee_detected = true;
853                         break;
854                 default:
855                         break;
856                 }
857                 part->dev = &data->dev[j];
858                 if (!IS_SELECT(part))
859                         part->dev->full_update = false;
860                 list_add_tail(&part->list, &data->dev[j].part_list);
861         }
862
863         return 0;
864 }
865
866 static int create_partitions(struct stm32prog_data *data)
867 {
868 #ifdef CONFIG_MMC
869         int offset = 0;
870         const int buflen = SZ_8K;
871         char *buf;
872         char uuid[UUID_STR_LEN + 1];
873         unsigned char *uuid_bin;
874         unsigned int mmc_id;
875         int i;
876         bool rootfs_found;
877         struct stm32prog_part_t *part;
878
879         buf = malloc(buflen);
880         if (!buf)
881                 return -ENOMEM;
882
883         puts("partitions : ");
884         /* initialize the selected device */
885         for (i = 0; i < data->dev_nb; i++) {
886                 /* create gpt partition support only for full update on MMC */
887                 if (data->dev[i].target != STM32PROG_MMC ||
888                     !data->dev[i].full_update)
889                         continue;
890
891                 offset = 0;
892                 rootfs_found = false;
893                 memset(buf, 0, buflen);
894
895                 list_for_each_entry(part, &data->dev[i].part_list, list) {
896                         /* skip eMMC boot partitions */
897                         if (part->part_id < 0)
898                                 continue;
899                         /* skip Raw Image */
900                         if (part->part_type == RAW_IMAGE)
901                                 continue;
902
903                         if (offset + 100 > buflen) {
904                                 pr_debug("\n%s: buffer too small, %s skippped",
905                                          __func__, part->name);
906                                 continue;
907                         }
908
909                         if (!offset)
910                                 offset += sprintf(buf, "gpt write mmc %d \"",
911                                                   data->dev[i].dev_id);
912
913                         offset += snprintf(buf + offset, buflen - offset,
914                                            "name=%s,start=0x%llx,size=0x%llx",
915                                            part->name,
916                                            part->addr,
917                                            part->size);
918
919                         if (part->part_type == PART_BINARY)
920                                 offset += snprintf(buf + offset,
921                                                    buflen - offset,
922                                                    ",type="
923                                                    LINUX_RESERVED_UUID);
924                         else
925                                 offset += snprintf(buf + offset,
926                                                    buflen - offset,
927                                                    ",type=linux");
928
929                         if (part->part_type == PART_SYSTEM)
930                                 offset += snprintf(buf + offset,
931                                                    buflen - offset,
932                                                    ",bootable");
933
934                         if (!rootfs_found && !strcmp(part->name, "rootfs")) {
935                                 mmc_id = part->dev_id;
936                                 rootfs_found = true;
937                                 if (mmc_id < ARRAY_SIZE(uuid_mmc)) {
938                                         uuid_bin =
939                                           (unsigned char *)uuid_mmc[mmc_id].b;
940                                         uuid_bin_to_str(uuid_bin, uuid,
941                                                         UUID_STR_FORMAT_GUID);
942                                         offset += snprintf(buf + offset,
943                                                            buflen - offset,
944                                                            ",uuid=%s", uuid);
945                                 }
946                         }
947
948                         offset += snprintf(buf + offset, buflen - offset, ";");
949                 }
950
951                 if (offset) {
952                         offset += snprintf(buf + offset, buflen - offset, "\"");
953                         pr_debug("\ncmd: %s\n", buf);
954                         if (run_command(buf, 0)) {
955                                 stm32prog_err("GPT partitionning fail: %s",
956                                               buf);
957                                 free(buf);
958
959                                 return -1;
960                         }
961                 }
962
963                 if (data->dev[i].mmc)
964                         part_init(mmc_get_blk_desc(data->dev[i].mmc));
965
966 #ifdef DEBUG
967                 sprintf(buf, "gpt verify mmc %d", data->dev[i].dev_id);
968                 pr_debug("\ncmd: %s", buf);
969                 if (run_command(buf, 0))
970                         printf("fail !\n");
971                 else
972                         printf("OK\n");
973
974                 sprintf(buf, "part list mmc %d", data->dev[i].dev_id);
975                 run_command(buf, 0);
976 #endif
977         }
978         puts("done\n");
979
980 #ifdef DEBUG
981         run_command("mtd list", 0);
982 #endif
983         free(buf);
984 #endif
985
986         return 0;
987 }
988
989 static int stm32prog_alt_add(struct stm32prog_data *data,
990                              struct dfu_entity *dfu,
991                              struct stm32prog_part_t *part)
992 {
993         int ret = 0;
994         int offset = 0;
995         char devstr[10];
996         char dfustr[10];
997         char buf[ALT_BUF_LEN];
998         u32 size;
999         char multiplier,  type;
1000
1001         /* max 3 digit for sector size */
1002         if (part->size > SZ_1M) {
1003                 size = (u32)(part->size / SZ_1M);
1004                 multiplier = 'M';
1005         } else if (part->size > SZ_1K) {
1006                 size = (u32)(part->size / SZ_1K);
1007                 multiplier = 'K';
1008         } else {
1009                 size = (u32)part->size;
1010                 multiplier = 'B';
1011         }
1012         if (IS_SELECT(part) && !IS_EMPTY(part))
1013                 type = 'e'; /*Readable and Writeable*/
1014         else
1015                 type = 'a';/*Readable*/
1016
1017         memset(buf, 0, sizeof(buf));
1018         offset = snprintf(buf, ALT_BUF_LEN - offset,
1019                           "@%s/0x%02x/1*%d%c%c ",
1020                           part->name, part->id,
1021                           size, multiplier, type);
1022
1023         if (part->part_type == RAW_IMAGE) {
1024                 u64 dfu_size;
1025
1026                 if (part->dev->target == STM32PROG_MMC)
1027                         dfu_size = part->size / part->dev->mmc->read_bl_len;
1028                 else
1029                         dfu_size = part->size;
1030                 offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
1031                                    "raw 0x0 0x%llx", dfu_size);
1032         } else if (part->part_id < 0) {
1033                 u64 nb_blk = part->size / part->dev->mmc->read_bl_len;
1034
1035                 offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
1036                                    "raw 0x%llx 0x%llx",
1037                                    part->addr, nb_blk);
1038                 offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
1039                                    " mmcpart %d;", -(part->part_id));
1040         } else {
1041                 if (part->part_type == PART_SYSTEM &&
1042                     (part->target == STM32PROG_NAND ||
1043                      part->target == STM32PROG_NOR ||
1044                      part->target == STM32PROG_SPI_NAND))
1045                         offset += snprintf(buf + offset,
1046                                            ALT_BUF_LEN - offset,
1047                                            "partubi");
1048                 else
1049                         offset += snprintf(buf + offset,
1050                                            ALT_BUF_LEN - offset,
1051                                            "part");
1052                 /* dev_id requested by DFU MMC */
1053                 if (part->target == STM32PROG_MMC)
1054                         offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
1055                                            " %d", part->dev_id);
1056                 offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
1057                                    " %d;", part->part_id);
1058         }
1059         switch (part->target) {
1060 #ifdef CONFIG_MMC
1061         case STM32PROG_MMC:
1062                 sprintf(dfustr, "mmc");
1063                 sprintf(devstr, "%d", part->dev_id);
1064                 break;
1065 #endif
1066 #ifdef CONFIG_MTD
1067         case STM32PROG_NAND:
1068         case STM32PROG_NOR:
1069         case STM32PROG_SPI_NAND:
1070                 sprintf(dfustr, "mtd");
1071                 get_mtd_by_target(devstr, part->target, part->dev_id);
1072                 break;
1073 #endif
1074         default:
1075                 stm32prog_err("invalid target: %d", part->target);
1076                 return -ENODEV;
1077         }
1078         pr_debug("dfu_alt_add(%s,%s,%s)\n", dfustr, devstr, buf);
1079         ret = dfu_alt_add(dfu, dfustr, devstr, buf);
1080         pr_debug("dfu_alt_add(%s,%s,%s) result %d\n",
1081                  dfustr, devstr, buf, ret);
1082
1083         return ret;
1084 }
1085
1086 static int stm32prog_alt_add_virt(struct dfu_entity *dfu,
1087                                   char *name, int phase, int size)
1088 {
1089         int ret = 0;
1090         char devstr[4];
1091         char buf[ALT_BUF_LEN];
1092
1093         sprintf(devstr, "%d", phase);
1094         sprintf(buf, "@%s/0x%02x/1*%dBe", name, phase, size);
1095         ret = dfu_alt_add(dfu, "virt", devstr, buf);
1096         pr_debug("dfu_alt_add(virt,%s,%s) result %d\n", devstr, buf, ret);
1097
1098         return ret;
1099 }
1100
1101 static int dfu_init_entities(struct stm32prog_data *data)
1102 {
1103         int ret = 0;
1104         int phase, i, alt_id;
1105         struct stm32prog_part_t *part;
1106         struct dfu_entity *dfu;
1107         int alt_nb;
1108
1109         alt_nb = 1; /* number of virtual = CMD */
1110         if (data->part_nb == 0)
1111                 alt_nb++;  /* +1 for FlashLayout */
1112         else
1113                 for (i = 0; i < data->part_nb; i++) {
1114                         if (data->part_array[i].target != STM32PROG_NONE)
1115                                 alt_nb++;
1116                 }
1117
1118         if (dfu_alt_init(alt_nb, &dfu))
1119                 return -ENODEV;
1120
1121         puts("DFU alt info setting: ");
1122         if (data->part_nb) {
1123                 alt_id = 0;
1124                 for (phase = 1;
1125                      (phase <= PHASE_LAST_USER) &&
1126                      (alt_id < alt_nb) && !ret;
1127                      phase++) {
1128                         /* ordering alt setting by phase id */
1129                         part = NULL;
1130                         for (i = 0; i < data->part_nb; i++) {
1131                                 if (phase == data->part_array[i].id) {
1132                                         part = &data->part_array[i];
1133                                         break;
1134                                 }
1135                         }
1136                         if (!part)
1137                                 continue;
1138                         if (part->target == STM32PROG_NONE)
1139                                 continue;
1140                         part->alt_id = alt_id;
1141                         alt_id++;
1142
1143                         ret = stm32prog_alt_add(data, dfu, part);
1144                 }
1145         } else {
1146                 char buf[ALT_BUF_LEN];
1147
1148                 sprintf(buf, "@FlashLayout/0x%02x/1*256Ke ram %x 40000",
1149                         PHASE_FLASHLAYOUT, STM32_DDR_BASE);
1150                 ret = dfu_alt_add(dfu, "ram", NULL, buf);
1151                 pr_debug("dfu_alt_add(ram, NULL,%s) result %d\n", buf, ret);
1152         }
1153
1154         if (!ret)
1155                 ret = stm32prog_alt_add_virt(dfu, "virtual", PHASE_CMD, 512);
1156
1157         if (ret)
1158                 stm32prog_err("dfu init failed: %d", ret);
1159         puts("done\n");
1160
1161 #ifdef DEBUG
1162         dfu_show_entities();
1163 #endif
1164         return ret;
1165 }
1166
1167 /* copy FSBL on NAND to improve reliability on NAND */
1168 static int stm32prog_copy_fsbl(struct stm32prog_part_t *part)
1169 {
1170         int ret, i;
1171         void *fsbl;
1172         struct image_header_s header;
1173         struct raw_header_s raw_header;
1174         struct dfu_entity *dfu;
1175         long size, offset;
1176
1177         if (part->target != STM32PROG_NAND &&
1178             part->target != STM32PROG_SPI_NAND)
1179                 return -1;
1180
1181         dfu = dfu_get_entity(part->alt_id);
1182
1183         /* read header */
1184         dfu_transaction_cleanup(dfu);
1185         size = BL_HEADER_SIZE;
1186         ret = dfu->read_medium(dfu, 0, (void *)&raw_header, &size);
1187         if (ret)
1188                 return ret;
1189         if (stm32prog_header_check(&raw_header, &header))
1190                 return -1;
1191
1192         /* read header + payload */
1193         size = header.image_length + BL_HEADER_SIZE;
1194         size = round_up(size, part->dev->mtd->erasesize);
1195         fsbl = calloc(1, size);
1196         if (!fsbl)
1197                 return -ENOMEM;
1198         ret = dfu->read_medium(dfu, 0, fsbl, &size);
1199         pr_debug("%s read size=%lx ret=%d\n", __func__, size, ret);
1200         if (ret)
1201                 goto error;
1202
1203         dfu_transaction_cleanup(dfu);
1204         offset = 0;
1205         for (i = part->bin_nb - 1; i > 0; i--) {
1206                 offset += size;
1207                 /* write to the next erase block */
1208                 ret = dfu->write_medium(dfu, offset, fsbl, &size);
1209                 pr_debug("%s copy at ofset=%lx size=%lx ret=%d",
1210                          __func__, offset, size, ret);
1211                 if (ret)
1212                         goto error;
1213         }
1214
1215 error:
1216         free(fsbl);
1217         return ret;
1218 }
1219
1220 static void stm32prog_end_phase(struct stm32prog_data *data)
1221 {
1222         if (data->phase == PHASE_FLASHLAYOUT) {
1223                 if (parse_flash_layout(data, STM32_DDR_BASE, 0))
1224                         stm32prog_err("Layout: invalid FlashLayout");
1225                 return;
1226         }
1227
1228         if (!data->cur_part)
1229                 return;
1230
1231         if (CONFIG_IS_ENABLED(MMC) &&
1232             data->cur_part->part_id < 0) {
1233                 char cmdbuf[60];
1234
1235                 sprintf(cmdbuf, "mmc bootbus %d 0 0 0; mmc partconf %d 1 %d 0",
1236                         data->cur_part->dev_id, data->cur_part->dev_id,
1237                         -(data->cur_part->part_id));
1238                 if (run_command(cmdbuf, 0)) {
1239                         stm32prog_err("commands '%s' failed", cmdbuf);
1240                         return;
1241                 }
1242         }
1243
1244         if (CONFIG_IS_ENABLED(MTD) &&
1245             data->cur_part->bin_nb > 1) {
1246                 if (stm32prog_copy_fsbl(data->cur_part)) {
1247                         stm32prog_err("%s (0x%x): copy of fsbl failed",
1248                                       data->cur_part->name, data->cur_part->id);
1249                         return;
1250                 }
1251         }
1252 }
1253
1254 void stm32prog_do_reset(struct stm32prog_data *data)
1255 {
1256         if (data->phase == PHASE_RESET) {
1257                 data->phase = PHASE_DO_RESET;
1258                 puts("Reset requested\n");
1259         }
1260 }
1261
1262 void stm32prog_next_phase(struct stm32prog_data *data)
1263 {
1264         int phase, i;
1265         struct stm32prog_part_t *part;
1266         bool found;
1267
1268         phase = data->phase;
1269         switch (phase) {
1270         case PHASE_RESET:
1271         case PHASE_END:
1272         case PHASE_DO_RESET:
1273                 return;
1274         }
1275
1276         /* found next selected partition */
1277         data->cur_part = NULL;
1278         data->phase = PHASE_END;
1279         found = false;
1280         do {
1281                 phase++;
1282                 if (phase > PHASE_LAST_USER)
1283                         break;
1284                 for (i = 0; i < data->part_nb; i++) {
1285                         part = &data->part_array[i];
1286                         if (part->id == phase) {
1287                                 if (IS_SELECT(part) && !IS_EMPTY(part)) {
1288                                         data->cur_part = part;
1289                                         data->phase = phase;
1290                                         found = true;
1291                                 }
1292                                 break;
1293                         }
1294                 }
1295         } while (!found);
1296
1297         if (data->phase == PHASE_END)
1298                 puts("Phase=END\n");
1299 }
1300
1301 static int part_delete(struct stm32prog_data *data,
1302                        struct stm32prog_part_t *part)
1303 {
1304         int ret = 0;
1305 #ifdef CONFIG_MMC
1306         unsigned long blks, blks_offset, blks_size;
1307         struct blk_desc *block_dev = NULL;
1308  #endif
1309 #ifdef CONFIG_MTD
1310         char cmdbuf[40];
1311         char devstr[10];
1312 #endif
1313
1314         printf("Erasing %s ", part->name);
1315         switch (part->target) {
1316 #ifdef CONFIG_MMC
1317         case STM32PROG_MMC:
1318                 printf("on mmc %d: ", part->dev->dev_id);
1319                 block_dev = mmc_get_blk_desc(part->dev->mmc);
1320                 blks_offset = lldiv(part->addr, part->dev->mmc->read_bl_len);
1321                 blks_size = lldiv(part->size, part->dev->mmc->read_bl_len);
1322                 /* -1 or -2 : delete boot partition of MMC
1323                  * need to switch to associated hwpart 1 or 2
1324                  */
1325                 if (part->part_id < 0)
1326                         if (blk_select_hwpart_devnum(IF_TYPE_MMC,
1327                                                      part->dev->dev_id,
1328                                                      -part->part_id))
1329                                 return -1;
1330
1331                 blks = blk_derase(block_dev, blks_offset, blks_size);
1332
1333                 /* return to user partition */
1334                 if (part->part_id < 0)
1335                         blk_select_hwpart_devnum(IF_TYPE_MMC,
1336                                                  part->dev->dev_id, 0);
1337                 if (blks != blks_size) {
1338                         ret = -1;
1339                         stm32prog_err("%s (0x%x): MMC erase failed",
1340                                       part->name, part->id);
1341                 }
1342                 break;
1343 #endif
1344 #ifdef CONFIG_MTD
1345         case STM32PROG_NOR:
1346         case STM32PROG_NAND:
1347         case STM32PROG_SPI_NAND:
1348                 get_mtd_by_target(devstr, part->target, part->dev->dev_id);
1349                 printf("on %s: ", devstr);
1350                 sprintf(cmdbuf, "mtd erase %s 0x%llx 0x%llx",
1351                         devstr, part->addr, part->size);
1352                 if (run_command(cmdbuf, 0)) {
1353                         ret = -1;
1354                         stm32prog_err("%s (0x%x): MTD erase commands failed (%s)",
1355                                       part->name, part->id, cmdbuf);
1356                 }
1357                 break;
1358 #endif
1359         default:
1360                 ret = -1;
1361                 stm32prog_err("%s (0x%x): erase invalid", part->name, part->id);
1362                 break;
1363         }
1364         if (!ret)
1365                 printf("done\n");
1366
1367         return ret;
1368 }
1369
1370 static void stm32prog_devices_init(struct stm32prog_data *data)
1371 {
1372         int i;
1373         int ret;
1374         struct stm32prog_part_t *part;
1375
1376         ret = treat_partition_list(data);
1377         if (ret)
1378                 goto error;
1379
1380         /* initialize the selected device */
1381         for (i = 0; i < data->dev_nb; i++) {
1382                 ret = init_device(data, &data->dev[i]);
1383                 if (ret)
1384                         goto error;
1385         }
1386
1387         /* delete RAW partition before create partition */
1388         for (i = 0; i < data->part_nb; i++) {
1389                 part = &data->part_array[i];
1390
1391                 if (part->part_type != RAW_IMAGE)
1392                         continue;
1393
1394                 if (!IS_SELECT(part) || !IS_DELETE(part))
1395                         continue;
1396
1397                 ret = part_delete(data, part);
1398                 if (ret)
1399                         goto error;
1400         }
1401
1402         ret = create_partitions(data);
1403         if (ret)
1404                 goto error;
1405
1406         /* delete partition GPT or MTD */
1407         for (i = 0; i < data->part_nb; i++) {
1408                 part = &data->part_array[i];
1409
1410                 if (part->part_type == RAW_IMAGE)
1411                         continue;
1412
1413                 if (!IS_SELECT(part) || !IS_DELETE(part))
1414                         continue;
1415
1416                 ret = part_delete(data, part);
1417                 if (ret)
1418                         goto error;
1419         }
1420
1421         return;
1422
1423 error:
1424         data->part_nb = 0;
1425 }
1426
1427 int stm32prog_dfu_init(struct stm32prog_data *data)
1428 {
1429         /* init device if no error */
1430         if (data->part_nb)
1431                 stm32prog_devices_init(data);
1432
1433         if (data->part_nb)
1434                 stm32prog_next_phase(data);
1435
1436         /* prepare DFU for device read/write */
1437         dfu_free_entities();
1438         return dfu_init_entities(data);
1439 }
1440
1441 int stm32prog_init(struct stm32prog_data *data, ulong addr, ulong size)
1442 {
1443         memset(data, 0x0, sizeof(*data));
1444         data->phase = PHASE_FLASHLAYOUT;
1445
1446         return parse_flash_layout(data, addr, size);
1447 }
1448
1449 void stm32prog_clean(struct stm32prog_data *data)
1450 {
1451         /* clean */
1452         dfu_free_entities();
1453         free(data->part_array);
1454         free(data->header_data);
1455 }
1456
1457 /* DFU callback: used after serial and direct DFU USB access */
1458 void dfu_flush_callback(struct dfu_entity *dfu)
1459 {
1460         if (!stm32prog_data)
1461                 return;
1462
1463         if (dfu->dev_type == DFU_DEV_RAM) {
1464                 if (dfu->alt == 0 &&
1465                     stm32prog_data->phase == PHASE_FLASHLAYOUT) {
1466                         stm32prog_end_phase(stm32prog_data);
1467                         /* waiting DFU DETACH for reenumeration */
1468                 }
1469         }
1470
1471         if (!stm32prog_data->cur_part)
1472                 return;
1473
1474         if (dfu->alt == stm32prog_data->cur_part->alt_id) {
1475                 stm32prog_end_phase(stm32prog_data);
1476                 stm32prog_next_phase(stm32prog_data);
1477         }
1478 }
1479
1480 void dfu_initiated_callback(struct dfu_entity *dfu)
1481 {
1482         if (!stm32prog_data)
1483                 return;
1484
1485         if (!stm32prog_data->cur_part)
1486                 return;
1487
1488         /* force the saved offset for the current partition */
1489         if (dfu->alt == stm32prog_data->cur_part->alt_id) {
1490                 dfu->offset = stm32prog_data->offset;
1491                 pr_debug("dfu offset = 0x%llx\n", dfu->offset);
1492         }
1493 }