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