stm32mp: stm32prog: adapt the MTD partitions
[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
214         if (!strcmp(p, "Binary")) {
215                 part->part_type = PART_BINARY;
216         } else if (!strcmp(p, "System")) {
217                 part->part_type = PART_SYSTEM;
218         } else if (!strcmp(p, "FileSystem")) {
219                 part->part_type = PART_FILESYSTEM;
220         } else if (!strcmp(p, "RawImage")) {
221                 part->part_type = RAW_IMAGE;
222         } else {
223                 result = -EINVAL;
224         }
225         if (result)
226                 stm32prog_err("Layout line %d: type parsing error : '%s'",
227                               i, p);
228
229         return result;
230 }
231
232 static int parse_ip(struct stm32prog_data *data,
233                     int i, char *p, struct stm32prog_part_t *part)
234 {
235         int result = 0;
236         unsigned int len = 0;
237
238         part->dev_id = 0;
239         if (!strcmp(p, "none")) {
240                 part->target = STM32PROG_NONE;
241         } else if (!strncmp(p, "mmc", 3)) {
242                 part->target = STM32PROG_MMC;
243                 len = 3;
244         } else if (!strncmp(p, "nor", 3)) {
245                 part->target = STM32PROG_NOR;
246                 len = 3;
247         } else if (!strncmp(p, "nand", 4)) {
248                 part->target = STM32PROG_NAND;
249                 len = 4;
250         } else if (!strncmp(p, "spi-nand", 8)) {
251                 part->target = STM32PROG_SPI_NAND;
252                 len = 8;
253         } else {
254                 result = -EINVAL;
255         }
256         if (len) {
257                 /* only one digit allowed for device id */
258                 if (strlen(p) != len + 1) {
259                         result = -EINVAL;
260                 } else {
261                         part->dev_id = p[len] - '0';
262                         if (part->dev_id > 9)
263                                 result = -EINVAL;
264                 }
265         }
266         if (result)
267                 stm32prog_err("Layout line %d: ip parsing error: '%s'", i, p);
268
269         return result;
270 }
271
272 static int parse_offset(struct stm32prog_data *data,
273                         int i, char *p, struct stm32prog_part_t *part)
274 {
275         int result = 0;
276         char *tail;
277
278         part->part_id = 0;
279         part->addr = 0;
280         part->size = 0;
281         /* eMMC boot parttion */
282         if (!strncmp(p, "boot", 4)) {
283                 if (strlen(p) != 5) {
284                         result = -EINVAL;
285                 } else {
286                         if (p[4] == '1')
287                                 part->part_id = -1;
288                         else if (p[4] == '2')
289                                 part->part_id = -2;
290                         else
291                                 result = -EINVAL;
292                 }
293                 if (result)
294                         stm32prog_err("Layout line %d: invalid part '%s'",
295                                       i, p);
296         } else {
297                 part->addr = simple_strtoull(p, &tail, 0);
298                 if (tail == p || *tail != '\0') {
299                         stm32prog_err("Layout line %d: invalid offset '%s'",
300                                       i, p);
301                         result = -EINVAL;
302                 }
303         }
304
305         return result;
306 }
307
308 static
309 int (* const parse[COL_NB_STM32])(struct stm32prog_data *data, int i, char *p,
310                                   struct stm32prog_part_t *part) = {
311         [COL_OPTION] = parse_option,
312         [COL_ID] = parse_id,
313         [COL_NAME] =  parse_name,
314         [COL_TYPE] = parse_type,
315         [COL_IP] = parse_ip,
316         [COL_OFFSET] = parse_offset,
317 };
318
319 static int parse_flash_layout(struct stm32prog_data *data,
320                               ulong addr,
321                               ulong size)
322 {
323         int column = 0, part_nb = 0, ret;
324         bool end_of_line, eof;
325         char *p, *start, *last, *col;
326         struct stm32prog_part_t *part;
327         int part_list_size;
328         int i;
329
330         data->part_nb = 0;
331
332         /* check if STM32image is detected */
333         if (!stm32prog_header_check((struct raw_header_s *)addr,
334                                     &data->header)) {
335                 u32 checksum;
336
337                 addr = addr + BL_HEADER_SIZE;
338                 size = data->header.image_length;
339
340                 checksum = stm32prog_header_checksum(addr, &data->header);
341                 if (checksum != data->header.image_checksum) {
342                         stm32prog_err("Layout: invalid checksum : 0x%x expected 0x%x",
343                                       checksum, data->header.image_checksum);
344                         return -EIO;
345                 }
346         }
347         if (!size)
348                 return -EINVAL;
349
350         start = (char *)addr;
351         last = start + size;
352
353         *last = 0x0; /* force null terminated string */
354         pr_debug("flash layout =\n%s\n", start);
355
356         /* calculate expected number of partitions */
357         part_list_size = 1;
358         p = start;
359         while (*p && (p < last)) {
360                 if (*p++ == '\n') {
361                         part_list_size++;
362                         if (p < last && *p == '#')
363                                 part_list_size--;
364                 }
365         }
366         if (part_list_size > PHASE_LAST_USER) {
367                 stm32prog_err("Layout: too many partition (%d)",
368                               part_list_size);
369                 return -1;
370         }
371         part = calloc(sizeof(struct stm32prog_part_t), part_list_size);
372         if (!part) {
373                 stm32prog_err("Layout: alloc failed");
374                 return -ENOMEM;
375         }
376         data->part_array = part;
377
378         /* main parsing loop */
379         i = 1;
380         eof = false;
381         p = start;
382         col = start; /* 1st column */
383         end_of_line = false;
384         while (!eof) {
385                 switch (*p) {
386                 /* CR is ignored and replaced by NULL character */
387                 case '\r':
388                         *p = '\0';
389                         p++;
390                         continue;
391                 case '\0':
392                         end_of_line = true;
393                         eof = true;
394                         break;
395                 case '\n':
396                         end_of_line = true;
397                         break;
398                 case '\t':
399                         break;
400                 case '#':
401                         /* comment line is skipped */
402                         if (column == 0 && p == col) {
403                                 while ((p < last) && *p)
404                                         if (*p++ == '\n')
405                                                 break;
406                                 col = p;
407                                 i++;
408                                 if (p >= last || !*p) {
409                                         eof = true;
410                                         end_of_line = true;
411                                 }
412                                 continue;
413                         }
414                         /* fall through */
415                 /* by default continue with the next character */
416                 default:
417                         p++;
418                         continue;
419                 }
420
421                 /* replace by \0: allow string parsing for each column */
422                 *p = '\0';
423                 p++;
424                 if (p >= last) {
425                         eof = true;
426                         end_of_line = true;
427                 }
428
429                 /* skip empty line and multiple TAB in tsv file */
430                 if (strlen(col) == 0) {
431                         col = p;
432                         /* skip empty line */
433                         if (column == 0 && end_of_line) {
434                                 end_of_line = false;
435                                 i++;
436                         }
437                         continue;
438                 }
439
440                 if (column < COL_NB_STM32) {
441                         ret = parse[column](data, i, col, part);
442                         if (ret)
443                                 return ret;
444                 }
445
446                 /* save the beginning of the next column */
447                 column++;
448                 col = p;
449
450                 if (!end_of_line)
451                         continue;
452
453                 /* end of the line detected */
454                 end_of_line = false;
455
456                 if (column < COL_NB_STM32) {
457                         stm32prog_err("Layout line %d: no enought column", i);
458                         return -EINVAL;
459                 }
460                 column = 0;
461                 part_nb++;
462                 part++;
463                 i++;
464                 if (part_nb >= part_list_size) {
465                         part = NULL;
466                         if (!eof) {
467                                 stm32prog_err("Layout: no enought memory for %d part",
468                                               part_nb);
469                                 return -EINVAL;
470                         }
471                 }
472         }
473         data->part_nb = part_nb;
474         if (data->part_nb == 0) {
475                 stm32prog_err("Layout: no partition found");
476                 return -ENODEV;
477         }
478
479         return 0;
480 }
481
482 static int __init part_cmp(void *priv, struct list_head *a, struct list_head *b)
483 {
484         struct stm32prog_part_t *parta, *partb;
485
486         parta = container_of(a, struct stm32prog_part_t, list);
487         partb = container_of(b, struct stm32prog_part_t, list);
488
489         if (parta->part_id != partb->part_id)
490                 return parta->part_id - partb->part_id;
491         else
492                 return parta->addr > partb->addr ? 1 : -1;
493 }
494
495 static void get_mtd_by_target(char *string, enum stm32prog_target target,
496                               int dev_id)
497 {
498         const char *dev_str;
499
500         switch (target) {
501         case STM32PROG_NOR:
502                 dev_str = "nor";
503                 break;
504         case STM32PROG_NAND:
505                 dev_str = "nand";
506                 break;
507         case STM32PROG_SPI_NAND:
508                 dev_str = "spi-nand";
509                 break;
510         default:
511                 dev_str = "invalid";
512                 break;
513         }
514         sprintf(string, "%s%d", dev_str, dev_id);
515 }
516
517 static int init_device(struct stm32prog_data *data,
518                        struct stm32prog_dev_t *dev)
519 {
520         struct mmc *mmc = NULL;
521         struct blk_desc *block_dev = NULL;
522 #ifdef CONFIG_MTD
523         struct mtd_info *mtd = NULL;
524         char mtd_id[16];
525 #endif
526         int part_id;
527         int ret;
528         u64 first_addr = 0, last_addr = 0;
529         struct stm32prog_part_t *part, *next_part;
530         u64 part_addr, part_size;
531         bool part_found;
532         const char *part_name;
533
534         switch (dev->target) {
535 #ifdef CONFIG_MMC
536         case STM32PROG_MMC:
537                 mmc = find_mmc_device(dev->dev_id);
538                 if (mmc_init(mmc)) {
539                         stm32prog_err("mmc device %d not found", dev->dev_id);
540                         return -ENODEV;
541                 }
542                 block_dev = mmc_get_blk_desc(mmc);
543                 if (!block_dev) {
544                         stm32prog_err("mmc device %d not probed", dev->dev_id);
545                         return -ENODEV;
546                 }
547                 dev->erase_size = mmc->erase_grp_size * block_dev->blksz;
548                 dev->mmc = mmc;
549
550                 /* reserve a full erase group for each GTP headers */
551                 if (mmc->erase_grp_size > GPT_HEADER_SZ) {
552                         first_addr = dev->erase_size;
553                         last_addr = (u64)(block_dev->lba -
554                                           mmc->erase_grp_size) *
555                                     block_dev->blksz;
556                 } else {
557                         first_addr = (u64)GPT_HEADER_SZ * block_dev->blksz;
558                         last_addr = (u64)(block_dev->lba - GPT_HEADER_SZ - 1) *
559                                     block_dev->blksz;
560                 }
561                 pr_debug("MMC %d: lba=%ld blksz=%ld\n", dev->dev_id,
562                          block_dev->lba, block_dev->blksz);
563                 pr_debug(" available address = 0x%llx..0x%llx\n",
564                          first_addr, last_addr);
565                 pr_debug(" full_update = %d\n", dev->full_update);
566                 break;
567 #endif
568 #ifdef CONFIG_MTD
569         case STM32PROG_NOR:
570         case STM32PROG_NAND:
571         case STM32PROG_SPI_NAND:
572                 get_mtd_by_target(mtd_id, dev->target, dev->dev_id);
573                 pr_debug("%s\n", mtd_id);
574
575                 mtdparts_init();
576                 mtd = get_mtd_device_nm(mtd_id);
577                 if (IS_ERR(mtd)) {
578                         stm32prog_err("MTD device %s not found", mtd_id);
579                         return -ENODEV;
580                 }
581                 first_addr = 0;
582                 last_addr = mtd->size;
583                 dev->erase_size = mtd->erasesize;
584                 pr_debug("MTD device %s: size=%lld erasesize=%d\n",
585                          mtd_id, mtd->size, mtd->erasesize);
586                 pr_debug(" available address = 0x%llx..0x%llx\n",
587                          first_addr, last_addr);
588                 dev->mtd = mtd;
589                 break;
590 #endif
591         default:
592                 stm32prog_err("unknown device type = %d", dev->target);
593                 return -ENODEV;
594         }
595         pr_debug(" erase size = 0x%x\n", dev->erase_size);
596         pr_debug(" full_update = %d\n", dev->full_update);
597
598         /* order partition list in offset order */
599         list_sort(NULL, &dev->part_list, &part_cmp);
600         part_id = 1;
601         pr_debug("id : Opt Phase     Name target.n dev.n addr     size     part_off part_size\n");
602         list_for_each_entry(part, &dev->part_list, list) {
603                 if (part->part_type == RAW_IMAGE) {
604                         part->part_id = 0x0;
605                         part->addr = 0x0;
606                         if (block_dev)
607                                 part->size = block_dev->lba * block_dev->blksz;
608                         else
609                                 part->size = last_addr;
610                         pr_debug("-- : %1d %02x %14s %02d %02d.%02d %08llx %08llx\n",
611                                  part->option, part->id, part->name,
612                                  part->part_type, part->target,
613                                  part->dev_id, part->addr, part->size);
614                         continue;
615                 }
616                 if (part->part_id < 0) { /* boot hw partition for eMMC */
617                         if (mmc) {
618                                 part->size = mmc->capacity_boot;
619                         } else {
620                                 stm32prog_err("%s (0x%x): hw partition not expected : %d",
621                                               part->name, part->id,
622                                               part->part_id);
623                                 return -ENODEV;
624                         }
625                 } else {
626                         part->part_id = part_id++;
627
628                         /* last partition : size to the end of the device */
629                         if (part->list.next != &dev->part_list) {
630                                 next_part =
631                                         container_of(part->list.next,
632                                                      struct stm32prog_part_t,
633                                                      list);
634                                 if (part->addr < next_part->addr) {
635                                         part->size = next_part->addr -
636                                                      part->addr;
637                                 } else {
638                                         stm32prog_err("%s (0x%x): same address : 0x%llx == %s (0x%x): 0x%llx",
639                                                       part->name, part->id,
640                                                       part->addr,
641                                                       next_part->name,
642                                                       next_part->id,
643                                                       next_part->addr);
644                                         return -EINVAL;
645                                 }
646                         } else {
647                                 if (part->addr <= last_addr) {
648                                         part->size = last_addr - part->addr;
649                                 } else {
650                                         stm32prog_err("%s (0x%x): invalid address 0x%llx (max=0x%llx)",
651                                                       part->name, part->id,
652                                                       part->addr, last_addr);
653                                         return -EINVAL;
654                                 }
655                         }
656                         if (part->addr < first_addr) {
657                                 stm32prog_err("%s (0x%x): invalid address 0x%llx (min=0x%llx)",
658                                               part->name, part->id,
659                                               part->addr, first_addr);
660                                 return -EINVAL;
661                         }
662                 }
663                 if ((part->addr & ((u64)part->dev->erase_size - 1)) != 0) {
664                         stm32prog_err("%s (0x%x): not aligned address : 0x%llx on erase size 0x%x",
665                                       part->name, part->id, part->addr,
666                                       part->dev->erase_size);
667                         return -EINVAL;
668                 }
669                 pr_debug("%02d : %1d %02x %14s %02d %02d.%02d %08llx %08llx",
670                          part->part_id, part->option, part->id, part->name,
671                          part->part_type, part->target,
672                          part->dev_id, part->addr, part->size);
673
674                 part_addr = 0;
675                 part_size = 0;
676                 part_found = false;
677
678                 /* check coherency with existing partition */
679                 if (block_dev) {
680                         /*
681                          * block devices with GPT: check user partition size
682                          * only for partial update, the GPT partions are be
683                          * created for full update
684                          */
685                         if (dev->full_update || part->part_id < 0) {
686                                 pr_debug("\n");
687                                 continue;
688                         }
689                         disk_partition_t partinfo;
690
691                         ret = part_get_info(block_dev, part->part_id,
692                                             &partinfo);
693
694                         if (ret) {
695                                 stm32prog_err("%s (0x%x):Couldn't find part %d on device mmc %d",
696                                               part->name, part->id,
697                                               part_id, part->dev_id);
698                                 return -ENODEV;
699                         }
700                         part_addr = (u64)partinfo.start * partinfo.blksz;
701                         part_size = (u64)partinfo.size * partinfo.blksz;
702                         part_name = (char *)partinfo.name;
703                         part_found = true;
704                 }
705
706 #ifdef CONFIG_MTD
707                 if (mtd) {
708                         char mtd_part_id[32];
709                         struct part_info *mtd_part;
710                         struct mtd_device *mtd_dev;
711                         u8 part_num;
712
713                         sprintf(mtd_part_id, "%s,%d", mtd_id,
714                                 part->part_id - 1);
715                         ret = find_dev_and_part(mtd_part_id, &mtd_dev,
716                                                 &part_num, &mtd_part);
717                         if (ret != 0) {
718                                 stm32prog_err("%s (0x%x): Invalid MTD partition %s",
719                                               part->name, part->id,
720                                               mtd_part_id);
721                                 return -ENODEV;
722                         }
723                         part_addr = mtd_part->offset;
724                         part_size = mtd_part->size;
725                         part_name = mtd_part->name;
726                         part_found = true;
727                 }
728 #endif
729                 if (!part_found) {
730                         stm32prog_err("%s (0x%x): Invalid partition",
731                                       part->name, part->id);
732                         pr_debug("\n");
733                         continue;
734                 }
735
736                 pr_debug(" %08llx %08llx\n", part_addr, part_size);
737
738                 if (part->addr != part_addr) {
739                         stm32prog_err("%s (0x%x): Bad address for partition %d (%s) = 0x%llx <> 0x%llx expected",
740                                       part->name, part->id, part->part_id,
741                                       part_name, part->addr, part_addr);
742                         return -ENODEV;
743                 }
744                 if (part->size != part_size) {
745                         stm32prog_err("%s (0x%x): Bad size for partition %d (%s) at 0x%llx = 0x%llx <> 0x%llx expected",
746                                       part->name, part->id, part->part_id,
747                                       part_name, part->addr, part->size,
748                                       part_size);
749                         return -ENODEV;
750                 }
751         }
752         return 0;
753 }
754
755 static int treat_partition_list(struct stm32prog_data *data)
756 {
757         int i, j;
758         struct stm32prog_part_t *part;
759
760         for (j = 0; j < STM32PROG_MAX_DEV; j++) {
761                 data->dev[j].target = STM32PROG_NONE;
762                 INIT_LIST_HEAD(&data->dev[j].part_list);
763         }
764
765         data->tee_detected = false;
766         data->fsbl_nor_detected = false;
767         for (i = 0; i < data->part_nb; i++) {
768                 part = &data->part_array[i];
769                 part->alt_id = -1;
770
771                 /* skip partition with IP="none" */
772                 if (part->target == STM32PROG_NONE) {
773                         if (IS_SELECT(part)) {
774                                 stm32prog_err("Layout: selected none phase = 0x%x",
775                                               part->id);
776                                 return -EINVAL;
777                         }
778                         continue;
779                 }
780
781                 if (part->id == PHASE_FLASHLAYOUT ||
782                     part->id > PHASE_LAST_USER) {
783                         stm32prog_err("Layout: invalid phase = 0x%x",
784                                       part->id);
785                         return -EINVAL;
786                 }
787                 for (j = i + 1; j < data->part_nb; j++) {
788                         if (part->id == data->part_array[j].id) {
789                                 stm32prog_err("Layout: duplicated phase 0x%x at line %d and %d",
790                                               part->id, i, j);
791                                 return -EINVAL;
792                         }
793                 }
794                 for (j = 0; j < STM32PROG_MAX_DEV; j++) {
795                         if (data->dev[j].target == STM32PROG_NONE) {
796                                 /* new device found */
797                                 data->dev[j].target = part->target;
798                                 data->dev[j].dev_id = part->dev_id;
799                                 data->dev[j].full_update = true;
800                                 data->dev_nb++;
801                                 break;
802                         } else if ((part->target == data->dev[j].target) &&
803                                    (part->dev_id == data->dev[j].dev_id)) {
804                                 break;
805                         }
806                 }
807                 if (j == STM32PROG_MAX_DEV) {
808                         stm32prog_err("Layout: too many device");
809                         return -EINVAL;
810                 }
811                 switch (part->target)  {
812                 case STM32PROG_NOR:
813                         if (!data->fsbl_nor_detected &&
814                             !strncmp(part->name, "fsbl", 4))
815                                 data->fsbl_nor_detected = true;
816                         /* fallthrough */
817                 case STM32PROG_NAND:
818                 case STM32PROG_SPI_NAND:
819                         if (!data->tee_detected &&
820                             !strncmp(part->name, "tee", 3))
821                                 data->tee_detected = true;
822                         break;
823                 default:
824                         break;
825                 }
826                 part->dev = &data->dev[j];
827                 if (!IS_SELECT(part))
828                         part->dev->full_update = false;
829                 list_add_tail(&part->list, &data->dev[j].part_list);
830         }
831
832         return 0;
833 }
834
835 static int create_partitions(struct stm32prog_data *data)
836 {
837 #ifdef CONFIG_MMC
838         int offset = 0;
839         const int buflen = SZ_8K;
840         char *buf;
841         char uuid[UUID_STR_LEN + 1];
842         unsigned char *uuid_bin;
843         unsigned int mmc_id;
844         int i;
845         bool rootfs_found;
846         struct stm32prog_part_t *part;
847
848         buf = malloc(buflen);
849         if (!buf)
850                 return -ENOMEM;
851
852         puts("partitions : ");
853         /* initialize the selected device */
854         for (i = 0; i < data->dev_nb; i++) {
855                 /* create gpt partition support only for full update on MMC */
856                 if (data->dev[i].target != STM32PROG_MMC ||
857                     !data->dev[i].full_update)
858                         continue;
859
860                 offset = 0;
861                 rootfs_found = false;
862                 memset(buf, 0, buflen);
863
864                 list_for_each_entry(part, &data->dev[i].part_list, list) {
865                         /* skip eMMC boot partitions */
866                         if (part->part_id < 0)
867                                 continue;
868                         /* skip Raw Image */
869                         if (part->part_type == RAW_IMAGE)
870                                 continue;
871
872                         if (offset + 100 > buflen) {
873                                 pr_debug("\n%s: buffer too small, %s skippped",
874                                          __func__, part->name);
875                                 continue;
876                         }
877
878                         if (!offset)
879                                 offset += sprintf(buf, "gpt write mmc %d \"",
880                                                   data->dev[i].dev_id);
881
882                         offset += snprintf(buf + offset, buflen - offset,
883                                            "name=%s,start=0x%llx,size=0x%llx",
884                                            part->name,
885                                            part->addr,
886                                            part->size);
887
888                         if (part->part_type == PART_BINARY)
889                                 offset += snprintf(buf + offset,
890                                                    buflen - offset,
891                                                    ",type="
892                                                    LINUX_RESERVED_UUID);
893                         else
894                                 offset += snprintf(buf + offset,
895                                                    buflen - offset,
896                                                    ",type=linux");
897
898                         if (part->part_type == PART_SYSTEM)
899                                 offset += snprintf(buf + offset,
900                                                    buflen - offset,
901                                                    ",bootable");
902
903                         if (!rootfs_found && !strcmp(part->name, "rootfs")) {
904                                 mmc_id = part->dev_id;
905                                 rootfs_found = true;
906                                 if (mmc_id < ARRAY_SIZE(uuid_mmc)) {
907                                         uuid_bin =
908                                           (unsigned char *)uuid_mmc[mmc_id].b;
909                                         uuid_bin_to_str(uuid_bin, uuid,
910                                                         UUID_STR_FORMAT_GUID);
911                                         offset += snprintf(buf + offset,
912                                                            buflen - offset,
913                                                            ",uuid=%s", uuid);
914                                 }
915                         }
916
917                         offset += snprintf(buf + offset, buflen - offset, ";");
918                 }
919
920                 if (offset) {
921                         offset += snprintf(buf + offset, buflen - offset, "\"");
922                         pr_debug("\ncmd: %s\n", buf);
923                         if (run_command(buf, 0)) {
924                                 stm32prog_err("GPT partitionning fail: %s",
925                                               buf);
926                                 free(buf);
927
928                                 return -1;
929                         }
930                 }
931
932                 if (data->dev[i].mmc)
933                         part_init(mmc_get_blk_desc(data->dev[i].mmc));
934
935 #ifdef DEBUG
936                 sprintf(buf, "gpt verify mmc %d", data->dev[i].dev_id);
937                 pr_debug("\ncmd: %s", buf);
938                 if (run_command(buf, 0))
939                         printf("fail !\n");
940                 else
941                         printf("OK\n");
942
943                 sprintf(buf, "part list mmc %d", data->dev[i].dev_id);
944                 run_command(buf, 0);
945 #endif
946         }
947         puts("done\n");
948
949 #ifdef DEBUG
950         run_command("mtd list", 0);
951 #endif
952         free(buf);
953 #endif
954
955         return 0;
956 }
957
958 static int stm32prog_alt_add(struct stm32prog_data *data,
959                              struct dfu_entity *dfu,
960                              struct stm32prog_part_t *part)
961 {
962         int ret = 0;
963         int offset = 0;
964         char devstr[10];
965         char dfustr[10];
966         char buf[ALT_BUF_LEN];
967         u32 size;
968         char multiplier,  type;
969
970         /* max 3 digit for sector size */
971         if (part->size > SZ_1M) {
972                 size = (u32)(part->size / SZ_1M);
973                 multiplier = 'M';
974         } else if (part->size > SZ_1K) {
975                 size = (u32)(part->size / SZ_1K);
976                 multiplier = 'K';
977         } else {
978                 size = (u32)part->size;
979                 multiplier = 'B';
980         }
981         if (IS_SELECT(part) && !IS_EMPTY(part))
982                 type = 'e'; /*Readable and Writeable*/
983         else
984                 type = 'a';/*Readable*/
985
986         memset(buf, 0, sizeof(buf));
987         offset = snprintf(buf, ALT_BUF_LEN - offset,
988                           "@%s/0x%02x/1*%d%c%c ",
989                           part->name, part->id,
990                           size, multiplier, type);
991
992         if (part->part_type == RAW_IMAGE) {
993                 u64 dfu_size;
994
995                 if (part->dev->target == STM32PROG_MMC)
996                         dfu_size = part->size / part->dev->mmc->read_bl_len;
997                 else
998                         dfu_size = part->size;
999                 offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
1000                                    "raw 0x0 0x%llx", dfu_size);
1001         } else if (part->part_id < 0) {
1002                 u64 nb_blk = part->size / part->dev->mmc->read_bl_len;
1003
1004                 offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
1005                                    "raw 0x%llx 0x%llx",
1006                                    part->addr, nb_blk);
1007                 offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
1008                                    " mmcpart %d;", -(part->part_id));
1009         } else {
1010                 if (part->part_type == PART_SYSTEM &&
1011                     (part->target == STM32PROG_NAND ||
1012                      part->target == STM32PROG_NOR ||
1013                      part->target == STM32PROG_SPI_NAND))
1014                         offset += snprintf(buf + offset,
1015                                            ALT_BUF_LEN - offset,
1016                                            "partubi");
1017                 else
1018                         offset += snprintf(buf + offset,
1019                                            ALT_BUF_LEN - offset,
1020                                            "part");
1021                 /* dev_id requested by DFU MMC */
1022                 if (part->target == STM32PROG_MMC)
1023                         offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
1024                                            " %d", part->dev_id);
1025                 offset += snprintf(buf + offset, ALT_BUF_LEN - offset,
1026                                    " %d;", part->part_id);
1027         }
1028         switch (part->target) {
1029 #ifdef CONFIG_MMC
1030         case STM32PROG_MMC:
1031                 sprintf(dfustr, "mmc");
1032                 sprintf(devstr, "%d", part->dev_id);
1033                 break;
1034 #endif
1035 #ifdef CONFIG_MTD
1036         case STM32PROG_NAND:
1037         case STM32PROG_NOR:
1038         case STM32PROG_SPI_NAND:
1039                 sprintf(dfustr, "mtd");
1040                 get_mtd_by_target(devstr, part->target, part->dev_id);
1041                 break;
1042 #endif
1043         default:
1044                 stm32prog_err("invalid target: %d", part->target);
1045                 return -ENODEV;
1046         }
1047         pr_debug("dfu_alt_add(%s,%s,%s)\n", dfustr, devstr, buf);
1048         ret = dfu_alt_add(dfu, dfustr, devstr, buf);
1049         pr_debug("dfu_alt_add(%s,%s,%s) result %d\n",
1050                  dfustr, devstr, buf, ret);
1051
1052         return ret;
1053 }
1054
1055 static int stm32prog_alt_add_virt(struct dfu_entity *dfu,
1056                                   char *name, int phase, int size)
1057 {
1058         int ret = 0;
1059         char devstr[4];
1060         char buf[ALT_BUF_LEN];
1061
1062         sprintf(devstr, "%d", phase);
1063         sprintf(buf, "@%s/0x%02x/1*%dBe", name, phase, size);
1064         ret = dfu_alt_add(dfu, "virt", devstr, buf);
1065         pr_debug("dfu_alt_add(virt,%s,%s) result %d\n", devstr, buf, ret);
1066
1067         return ret;
1068 }
1069
1070 static int dfu_init_entities(struct stm32prog_data *data)
1071 {
1072         int ret = 0;
1073         int phase, i, alt_id;
1074         struct stm32prog_part_t *part;
1075         struct dfu_entity *dfu;
1076         int alt_nb;
1077
1078         alt_nb = 1; /* number of virtual = CMD */
1079         if (data->part_nb == 0)
1080                 alt_nb++;  /* +1 for FlashLayout */
1081         else
1082                 for (i = 0; i < data->part_nb; i++) {
1083                         if (data->part_array[i].target != STM32PROG_NONE)
1084                                 alt_nb++;
1085                 }
1086
1087         if (dfu_alt_init(alt_nb, &dfu))
1088                 return -ENODEV;
1089
1090         puts("DFU alt info setting: ");
1091         if (data->part_nb) {
1092                 alt_id = 0;
1093                 for (phase = 1;
1094                      (phase <= PHASE_LAST_USER) &&
1095                      (alt_id < alt_nb) && !ret;
1096                      phase++) {
1097                         /* ordering alt setting by phase id */
1098                         part = NULL;
1099                         for (i = 0; i < data->part_nb; i++) {
1100                                 if (phase == data->part_array[i].id) {
1101                                         part = &data->part_array[i];
1102                                         break;
1103                                 }
1104                         }
1105                         if (!part)
1106                                 continue;
1107                         if (part->target == STM32PROG_NONE)
1108                                 continue;
1109                         part->alt_id = alt_id;
1110                         alt_id++;
1111
1112                         ret = stm32prog_alt_add(data, dfu, part);
1113                 }
1114         } else {
1115                 char buf[ALT_BUF_LEN];
1116
1117                 sprintf(buf, "@FlashLayout/0x%02x/1*256Ke ram %x 40000",
1118                         PHASE_FLASHLAYOUT, STM32_DDR_BASE);
1119                 ret = dfu_alt_add(dfu, "ram", NULL, buf);
1120                 pr_debug("dfu_alt_add(ram, NULL,%s) result %d\n", buf, ret);
1121         }
1122
1123         if (!ret)
1124                 ret = stm32prog_alt_add_virt(dfu, "virtual", PHASE_CMD, 512);
1125
1126         if (ret)
1127                 stm32prog_err("dfu init failed: %d", ret);
1128         puts("done\n");
1129
1130 #ifdef DEBUG
1131         dfu_show_entities();
1132 #endif
1133         return ret;
1134 }
1135
1136 static void stm32prog_end_phase(struct stm32prog_data *data)
1137 {
1138         if (data->phase == PHASE_FLASHLAYOUT) {
1139                 if (parse_flash_layout(data, STM32_DDR_BASE, 0))
1140                         stm32prog_err("Layout: invalid FlashLayout");
1141                 return;
1142         }
1143
1144         if (!data->cur_part)
1145                 return;
1146
1147         if (CONFIG_IS_ENABLED(MMC) &&
1148             data->cur_part->part_id < 0) {
1149                 char cmdbuf[60];
1150
1151                 sprintf(cmdbuf, "mmc bootbus %d 0 0 0; mmc partconf %d 1 %d 0",
1152                         data->cur_part->dev_id, data->cur_part->dev_id,
1153                         -(data->cur_part->part_id));
1154                 if (run_command(cmdbuf, 0)) {
1155                         stm32prog_err("commands '%s' failed", cmdbuf);
1156                         return;
1157                 }
1158         }
1159 }
1160
1161 void stm32prog_do_reset(struct stm32prog_data *data)
1162 {
1163         if (data->phase == PHASE_RESET) {
1164                 data->phase = PHASE_DO_RESET;
1165                 puts("Reset requested\n");
1166         }
1167 }
1168
1169 void stm32prog_next_phase(struct stm32prog_data *data)
1170 {
1171         int phase, i;
1172         struct stm32prog_part_t *part;
1173         bool found;
1174
1175         phase = data->phase;
1176         switch (phase) {
1177         case PHASE_RESET:
1178         case PHASE_END:
1179         case PHASE_DO_RESET:
1180                 return;
1181         }
1182
1183         /* found next selected partition */
1184         data->cur_part = NULL;
1185         data->phase = PHASE_END;
1186         found = false;
1187         do {
1188                 phase++;
1189                 if (phase > PHASE_LAST_USER)
1190                         break;
1191                 for (i = 0; i < data->part_nb; i++) {
1192                         part = &data->part_array[i];
1193                         if (part->id == phase) {
1194                                 if (IS_SELECT(part) && !IS_EMPTY(part)) {
1195                                         data->cur_part = part;
1196                                         data->phase = phase;
1197                                         found = true;
1198                                 }
1199                                 break;
1200                         }
1201                 }
1202         } while (!found);
1203
1204         if (data->phase == PHASE_END)
1205                 puts("Phase=END\n");
1206 }
1207
1208 static void stm32prog_devices_init(struct stm32prog_data *data)
1209 {
1210         int i;
1211         int ret;
1212
1213         ret = treat_partition_list(data);
1214         if (ret)
1215                 goto error;
1216
1217         /* initialize the selected device */
1218         for (i = 0; i < data->dev_nb; i++) {
1219                 ret = init_device(data, &data->dev[i]);
1220                 if (ret)
1221                         goto error;
1222         }
1223
1224         ret = create_partitions(data);
1225         if (ret)
1226                 goto error;
1227
1228         return;
1229
1230 error:
1231         data->part_nb = 0;
1232 }
1233
1234 int stm32prog_dfu_init(struct stm32prog_data *data)
1235 {
1236         /* init device if no error */
1237         if (data->part_nb)
1238                 stm32prog_devices_init(data);
1239
1240         if (data->part_nb)
1241                 stm32prog_next_phase(data);
1242
1243         /* prepare DFU for device read/write */
1244         dfu_free_entities();
1245         return dfu_init_entities(data);
1246 }
1247
1248 int stm32prog_init(struct stm32prog_data *data, ulong addr, ulong size)
1249 {
1250         memset(data, 0x0, sizeof(*data));
1251         data->phase = PHASE_FLASHLAYOUT;
1252
1253         return parse_flash_layout(data, addr, size);
1254 }
1255
1256 void stm32prog_clean(struct stm32prog_data *data)
1257 {
1258         /* clean */
1259         dfu_free_entities();
1260         free(data->part_array);
1261         free(data->header_data);
1262 }
1263
1264 /* DFU callback: used after serial and direct DFU USB access */
1265 void dfu_flush_callback(struct dfu_entity *dfu)
1266 {
1267         if (!stm32prog_data)
1268                 return;
1269
1270         if (dfu->dev_type == DFU_DEV_RAM) {
1271                 if (dfu->alt == 0 &&
1272                     stm32prog_data->phase == PHASE_FLASHLAYOUT) {
1273                         stm32prog_end_phase(stm32prog_data);
1274                         /* waiting DFU DETACH for reenumeration */
1275                 }
1276         }
1277
1278         if (!stm32prog_data->cur_part)
1279                 return;
1280
1281         if (dfu->alt == stm32prog_data->cur_part->alt_id) {
1282                 stm32prog_end_phase(stm32prog_data);
1283                 stm32prog_next_phase(stm32prog_data);
1284         }
1285 }
1286
1287 void dfu_initiated_callback(struct dfu_entity *dfu)
1288 {
1289         if (!stm32prog_data)
1290                 return;
1291
1292         if (!stm32prog_data->cur_part)
1293                 return;
1294
1295         /* force the saved offset for the current partition */
1296         if (dfu->alt == stm32prog_data->cur_part->alt_id) {
1297                 dfu->offset = stm32prog_data->offset;
1298                 pr_debug("dfu offset = 0x%llx\n", dfu->offset);
1299         }
1300 }