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