blob: 2b92e3b1498cfa1add532e0a653181b4da90da78 [file] [log] [blame]
Patrick Delaunayb823d992020-03-18 09:25:00 +01001// 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>
Simon Glass7130b952020-07-19 10:15:40 -06008#include <dm.h>
Patrick Delaunayb823d992020-03-18 09:25:00 +01009#include <dfu.h>
10#include <malloc.h>
11#include <serial.h>
12#include <watchdog.h>
13#include <dm/lists.h>
14#include <dm/device-internal.h>
Simon Glassdbd79542020-05-10 11:40:11 -060015#include <linux/delay.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060016#include <asm/global_data.h>
Patrick Delaunayb823d992020-03-18 09:25:00 +010017#include "stm32prog.h"
18
19/* - configuration part -----------------------------*/
20#define USART_BL_VERSION 0x40 /* USART bootloader version V4.0*/
21#define UBOOT_BL_VERSION 0x03 /* bootloader version V0.3*/
22#define DEVICE_ID_BYTE1 0x05 /* MSB byte of device ID*/
23#define DEVICE_ID_BYTE2 0x00 /* LSB byte of device ID*/
24#define USART_RAM_BUFFER_SIZE 256 /* Size of USART_RAM_Buf buffer*/
25
26/* - Commands -----------------------------*/
27#define GET_CMD_COMMAND 0x00 /* Get CMD command*/
28#define GET_VER_COMMAND 0x01 /* Get Version command*/
29#define GET_ID_COMMAND 0x02 /* Get ID command*/
30#define GET_PHASE_COMMAND 0x03 /* Get Phase command*/
31#define RM_COMMAND 0x11 /* Read Memory command*/
32#define READ_PART_COMMAND 0x12 /* Read Partition command*/
33#define START_COMMAND 0x21 /* START command (Go)*/
34#define DOWNLOAD_COMMAND 0x31 /* Download command*/
35/* existing command for other STM32 but not used */
36/* ERASE 0x43 */
37/* EXTENDED_ERASE 0x44 */
38/* WRITE_UNPROTECTED 0x73 */
39/* READOUT_PROTECT 0x82 */
40/* READOUT_UNPROTECT 0x92 */
41
42/* - miscellaneous defines ----------------------------------------*/
43#define INIT_BYTE 0x7F /*Init Byte ID*/
44#define ACK_BYTE 0x79 /*Acknowlede Byte ID*/
45#define NACK_BYTE 0x1F /*No Acknowlede Byte ID*/
46#define ABORT_BYTE 0x5F /*ABORT*/
47
48struct udevice *down_serial_dev;
49
50const u8 cmd_id[] = {
51 GET_CMD_COMMAND,
52 GET_VER_COMMAND,
53 GET_ID_COMMAND,
54 GET_PHASE_COMMAND,
55 RM_COMMAND,
56 READ_PART_COMMAND,
57 START_COMMAND,
58 DOWNLOAD_COMMAND
59};
60
61#define NB_CMD sizeof(cmd_id)
62
63/* DFU support for serial *********************************************/
64static struct dfu_entity *stm32prog_get_entity(struct stm32prog_data *data)
65{
66 int alt_id;
67
68 if (!data->cur_part)
69 if (data->phase == PHASE_FLASHLAYOUT)
70 alt_id = 0;
71 else
72 return NULL;
73 else
74 alt_id = data->cur_part->alt_id;
75
76 return dfu_get_entity(alt_id);
77}
78
79static int stm32prog_write(struct stm32prog_data *data, u8 *buffer,
80 u32 buffer_size)
81{
82 struct dfu_entity *dfu_entity;
83 u8 ret = 0;
84
85 dfu_entity = stm32prog_get_entity(data);
86 if (!dfu_entity)
87 return -ENODEV;
88
89 ret = dfu_write(dfu_entity,
90 buffer,
91 buffer_size,
92 data->dfu_seq);
93
94 if (ret) {
95 stm32prog_err("DFU write failed [%d] cnt: %d",
96 ret, data->dfu_seq);
97 }
98 data->dfu_seq++;
99 /* handle rollover as in driver/dfu/dfu.c */
100 data->dfu_seq &= 0xffff;
101 if (buffer_size == 0)
102 data->dfu_seq = 0; /* flush done */
103
104 return ret;
105}
106
107static int stm32prog_read(struct stm32prog_data *data, u8 phase, u32 offset,
108 u8 *buffer, u32 buffer_size)
109{
110 struct dfu_entity *dfu_entity;
111 struct stm32prog_part_t *part;
112 u32 size;
113 int ret, i;
114
115 if (data->dfu_seq) {
116 stm32prog_err("DFU write pending for phase %d, seq %d",
117 data->phase, data->dfu_seq);
118 return -EINVAL;
119 }
120 if (phase == PHASE_FLASHLAYOUT || phase > PHASE_LAST_USER) {
121 stm32prog_err("read failed : phase %d is invalid", phase);
122 return -EINVAL;
123 }
124 if (data->read_phase <= PHASE_LAST_USER &&
125 phase != data->read_phase) {
126 /* clear previous read session */
127 dfu_entity = dfu_get_entity(data->read_phase - 1);
128 if (dfu_entity)
129 dfu_transaction_cleanup(dfu_entity);
130 }
131
132 dfu_entity = NULL;
133 /* found partition for the expected phase */
134 for (i = 0; i < data->part_nb; i++) {
135 part = &data->part_array[i];
136 if (part->id == phase)
137 dfu_entity = dfu_get_entity(part->alt_id);
138 }
139 if (!dfu_entity) {
140 stm32prog_err("read failed : phase %d is unknown", phase);
141 return -ENODEV;
142 }
143
144 /* clear pending read before to force offset */
145 if (dfu_entity->inited &&
146 (data->read_phase != phase || data->offset != offset))
147 dfu_transaction_cleanup(dfu_entity);
148
149 /* initiate before to force offset */
150 if (!dfu_entity->inited) {
151 ret = dfu_transaction_initiate(dfu_entity, true);
152 if (ret < 0) {
153 stm32prog_err("DFU read init failed [%d] phase = %d offset = 0x%08x",
154 ret, phase, offset);
155 return ret;
156 }
157 }
158 /* force new offset */
159 if (dfu_entity->offset != offset)
160 dfu_entity->offset = offset;
161 data->offset = offset;
162 data->read_phase = phase;
Patrick Delaunay2b15af52020-11-06 19:01:30 +0100163 log_debug("\nSTM32 download read %s offset=0x%x\n",
164 dfu_entity->name, offset);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100165 ret = dfu_read(dfu_entity, buffer, buffer_size,
166 dfu_entity->i_blk_seq_num);
167 if (ret < 0) {
168 stm32prog_err("DFU read failed [%d] phase = %d offset = 0x%08x",
169 ret, phase, offset);
170 return ret;
171 }
172
173 size = ret;
174
175 if (size < buffer_size) {
176 data->offset = 0;
177 data->read_phase = PHASE_END;
178 memset(buffer + size, 0, buffer_size - size);
179 } else {
180 data->offset += size;
181 }
182
183 return ret;
184}
185
186/* UART access ***************************************************/
187int stm32prog_serial_init(struct stm32prog_data *data, int link_dev)
188{
189 struct udevice *dev = NULL;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100190 struct dm_serial_ops *ops;
191 /* no parity, 8 bits, 1 stop */
192 u32 serial_config = SERIAL_DEFAULT_CONFIG;
193
194 down_serial_dev = NULL;
195
Patrick Delaunaye2592992021-02-25 13:37:03 +0100196 if (uclass_get_device_by_seq(UCLASS_SERIAL, link_dev, &dev)) {
197 log_err("serial %d device not found\n", link_dev);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100198 return -ENODEV;
199 }
Patrick Delaunaye2592992021-02-25 13:37:03 +0100200
201 down_serial_dev = dev;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100202
203 /* force silent console on uart only when used */
204 if (gd->cur_serial_dev == down_serial_dev)
205 gd->flags |= GD_FLG_DISABLE_CONSOLE | GD_FLG_SILENT;
206 else
207 gd->flags &= ~(GD_FLG_DISABLE_CONSOLE | GD_FLG_SILENT);
208
209 ops = serial_get_ops(down_serial_dev);
210
211 if (!ops) {
Patrick Delaunaye2592992021-02-25 13:37:03 +0100212 log_err("serial %d = %s missing ops\n", link_dev, dev->name);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100213 return -ENODEV;
214 }
215 if (!ops->setconfig) {
Patrick Delaunaye2592992021-02-25 13:37:03 +0100216 log_err("serial %d = %s missing setconfig\n", link_dev, dev->name);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100217 return -ENODEV;
218 }
219
220 clrsetbits_le32(&serial_config, SERIAL_PAR_MASK, SERIAL_PAR_EVEN);
221
222 data->buffer = memalign(CONFIG_SYS_CACHELINE_SIZE,
223 USART_RAM_BUFFER_SIZE);
224
225 return ops->setconfig(down_serial_dev, serial_config);
226}
227
228static void stm32prog_serial_flush(void)
229{
230 struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
231 int err;
232
233 do {
234 err = ops->getc(down_serial_dev);
235 } while (err != -EAGAIN);
236}
237
238static int stm32prog_serial_getc_err(void)
239{
240 struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
241 int err;
242
243 do {
244 err = ops->getc(down_serial_dev);
245 if (err == -EAGAIN) {
246 ctrlc();
247 WATCHDOG_RESET();
248 }
249 } while ((err == -EAGAIN) && (!had_ctrlc()));
250
251 return err;
252}
253
254static u8 stm32prog_serial_getc(void)
255{
256 int err;
257
258 err = stm32prog_serial_getc_err();
259
260 return err >= 0 ? err : 0;
261}
262
263static bool stm32prog_serial_get_buffer(u8 *buffer, u32 *count)
264{
265 struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
266 int err;
267
268 do {
269 err = ops->getc(down_serial_dev);
270 if (err >= 0) {
271 *buffer++ = err;
272 *count -= 1;
273 } else if (err == -EAGAIN) {
274 ctrlc();
275 WATCHDOG_RESET();
276 } else {
277 break;
278 }
279 } while (*count && !had_ctrlc());
280
281 return !!(err < 0);
282}
283
284static void stm32prog_serial_putc(u8 w_byte)
285{
286 struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
287 int err;
288
289 do {
290 err = ops->putc(down_serial_dev, w_byte);
291 } while (err == -EAGAIN);
292}
293
294/* Helper function ************************************************/
295
296static u8 stm32prog_header(struct stm32prog_data *data)
297{
298 u8 ret;
299 u8 boot = 0;
300 struct dfu_entity *dfu_entity;
301 u64 size = 0;
302
303 dfu_entity = stm32prog_get_entity(data);
304 if (!dfu_entity)
305 return -ENODEV;
306
307 printf("\nSTM32 download write %s\n", dfu_entity->name);
308
309 /* force cleanup to avoid issue with previous read */
310 dfu_transaction_cleanup(dfu_entity);
311
Patrick Delaunay19676ef2021-04-02 14:05:17 +0200312 stm32prog_header_check(data->header_data, &data->header);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100313
Patrick Delaunay19676ef2021-04-02 14:05:17 +0200314 /* no stm32 image header : max size is partition size */
315 if (data->header.type != HEADER_STM32IMAGE) {
Patrick Delaunayb823d992020-03-18 09:25:00 +0100316 dfu_entity->get_medium_size(dfu_entity, &size);
317 data->header.image_length = size;
318 }
319
320 /**** Flash the header if necessary for boot partition */
321 if (data->phase < PHASE_FIRST_USER)
322 boot = 1;
323
324 /* write header if boot partition */
325 if (boot) {
326 if (ret) {
327 stm32prog_err("invalid header (error %d)", ret);
328 } else {
329 ret = stm32prog_write(data,
330 (u8 *)data->header_data,
331 BL_HEADER_SIZE);
332 }
333 } else {
334 if (ret)
335 printf(" partition without checksum\n");
336 ret = 0;
337 }
338
339 free(data->header_data);
340 data->header_data = NULL;
341
342 return ret;
343}
344
345static u8 stm32prog_start(struct stm32prog_data *data, u32 address)
346{
347 u8 ret = 0;
348 struct dfu_entity *dfu_entity;
349
350 if (address < 0x100) {
351 if (address == PHASE_OTP)
352 return stm32prog_otp_start(data);
353
354 if (address == PHASE_PMIC)
355 return stm32prog_pmic_start(data);
356
357 if (address == PHASE_RESET || address == PHASE_END) {
358 data->cur_part = NULL;
359 data->dfu_seq = 0;
360 data->phase = address;
361 return 0;
362 }
363 if (address != data->phase) {
364 stm32prog_err("invalid received phase id %d, current phase is %d",
365 (u8)address, (u8)data->phase);
366 return -EINVAL;
367 }
368 }
369 /* check the last loaded partition */
370 if (address == DEFAULT_ADDRESS || address == data->phase) {
371 switch (data->phase) {
372 case PHASE_END:
373 case PHASE_RESET:
374 case PHASE_DO_RESET:
375 data->cur_part = NULL;
376 data->phase = PHASE_DO_RESET;
377 return 0;
378 }
379 dfu_entity = stm32prog_get_entity(data);
380 if (!dfu_entity)
381 return -ENODEV;
382
Patrick Delaunayefc7a3b2020-12-11 13:36:18 +0100383 ret = dfu_flush(dfu_entity, NULL, 0, data->dfu_seq);
384 if (ret) {
385 stm32prog_err("DFU flush failed [%d]", ret);
386 return ret;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100387 }
Patrick Delaunayefc7a3b2020-12-11 13:36:18 +0100388 data->dfu_seq = 0;
389
Patrick Delaunayb823d992020-03-18 09:25:00 +0100390 printf("\n received length = 0x%x\n", data->cursor);
Patrick Delaunay19676ef2021-04-02 14:05:17 +0200391 if (data->header.type == HEADER_STM32IMAGE) {
Patrick Delaunayb823d992020-03-18 09:25:00 +0100392 if (data->cursor !=
393 (data->header.image_length + BL_HEADER_SIZE)) {
394 stm32prog_err("transmission interrupted (length=0x%x expected=0x%x)",
395 data->cursor,
396 data->header.image_length +
397 BL_HEADER_SIZE);
398 return -EIO;
399 }
400 if (data->header.image_checksum != data->checksum) {
401 stm32prog_err("invalid checksum received (0x%x expected 0x%x)",
402 data->checksum,
403 data->header.image_checksum);
404 return -EIO;
405 }
406 printf("\n checksum OK (0x%x)\n", data->checksum);
407 }
408
409 /* update DFU with received flashlayout */
410 if (data->phase == PHASE_FLASHLAYOUT)
411 stm32prog_dfu_init(data);
412 } else {
413 void (*entry)(void) = (void *)address;
414
415 printf("## Starting application at 0x%x ...\n", address);
416 (*entry)();
417 printf("## Application terminated\n");
418 ret = -ENOEXEC;
419 }
420
421 return ret;
422}
423
424/**
425 * get_address() - Get address if it is valid
426 *
427 * @tmp_xor: Current xor value to update
428 * @return The address area
429 */
430static u32 get_address(u8 *tmp_xor)
431{
432 u32 address = 0x0;
433 u8 data;
434
435 data = stm32prog_serial_getc();
436 *tmp_xor ^= data;
437 address |= ((u32)data) << 24;
438
439 data = stm32prog_serial_getc();
440 address |= ((u32)data) << 16;
441 *tmp_xor ^= data;
442
443 data = stm32prog_serial_getc();
444 address |= ((u32)data) << 8;
445 *tmp_xor ^= data;
446
447 data = stm32prog_serial_getc();
448 address |= ((u32)data);
449 *tmp_xor ^= data;
450
451 return address;
452}
453
454static void stm32prog_serial_result(u8 result)
455{
456 /* always flush fifo before to send result */
457 stm32prog_serial_flush();
458 stm32prog_serial_putc(result);
459}
460
461/* Command -----------------------------------------------*/
462/**
463 * get_cmd_command() - Respond to Get command
464 *
465 * @data: Current command context
466 */
467static void get_cmd_command(struct stm32prog_data *data)
468{
469 u32 counter = 0x0;
470
471 stm32prog_serial_putc(NB_CMD);
472 stm32prog_serial_putc(USART_BL_VERSION);
473
474 for (counter = 0; counter < NB_CMD; counter++)
475 stm32prog_serial_putc(cmd_id[counter]);
476
477 stm32prog_serial_result(ACK_BYTE);
478}
479
480/**
481 * get_version_command() - Respond to Get Version command
482 *
483 * @data: Current command context
484 */
485static void get_version_command(struct stm32prog_data *data)
486{
487 stm32prog_serial_putc(UBOOT_BL_VERSION);
488 stm32prog_serial_result(ACK_BYTE);
489}
490
491/**
492 * get_id_command() - Respond to Get ID command
493 *
494 * @data: Current command context
495 */
496static void get_id_command(struct stm32prog_data *data)
497{
498 /* Send Device IDCode */
499 stm32prog_serial_putc(0x1);
500 stm32prog_serial_putc(DEVICE_ID_BYTE1);
501 stm32prog_serial_putc(DEVICE_ID_BYTE2);
502 stm32prog_serial_result(ACK_BYTE);
503}
504
505/**
506 * get_phase_command() - Respond to Get phase
507 *
508 * @data: Current command context
509 */
510static void get_phase_command(struct stm32prog_data *data)
511{
512 char *err_msg = NULL;
513 u8 i, length = 0;
514 u32 destination = DEFAULT_ADDRESS; /* destination address */
515 int phase = data->phase;
516
517 if (phase == PHASE_RESET || phase == PHASE_DO_RESET) {
518 err_msg = stm32prog_get_error(data);
519 length = strlen(err_msg);
520 }
521 if (phase == PHASE_FLASHLAYOUT)
522 destination = STM32_DDR_BASE;
523
524 stm32prog_serial_putc(length + 5); /* Total length */
525 stm32prog_serial_putc(phase & 0xFF); /* partition ID */
526 stm32prog_serial_putc(destination); /* byte 1 of address */
527 stm32prog_serial_putc(destination >> 8); /* byte 2 of address */
528 stm32prog_serial_putc(destination >> 16); /* byte 3 of address */
529 stm32prog_serial_putc(destination >> 24); /* byte 4 of address */
530
531 stm32prog_serial_putc(length); /* Information length */
532 for (i = 0; i < length; i++)
533 stm32prog_serial_putc(err_msg[i]);
534 stm32prog_serial_result(ACK_BYTE);
535
536 if (phase == PHASE_RESET)
537 stm32prog_do_reset(data);
538}
539
540/**
541 * read_memory_command() - Read data from memory
542 *
543 * @data: Current command context
544 */
545static void read_memory_command(struct stm32prog_data *data)
546{
547 u32 address = 0x0;
548 u8 rcv_data = 0x0, tmp_xor = 0x0;
549 u32 counter = 0x0;
550
551 /* Read memory address */
552 address = get_address(&tmp_xor);
553
554 /* If address memory is not received correctly */
555 rcv_data = stm32prog_serial_getc();
556 if (rcv_data != tmp_xor) {
557 stm32prog_serial_result(NACK_BYTE);
558 return;
559 }
560
561 stm32prog_serial_result(ACK_BYTE);
562
563 /* Read the number of bytes to be received:
564 * Max NbrOfData = Data + 1 = 256
565 */
566 rcv_data = stm32prog_serial_getc();
567 tmp_xor = ~rcv_data;
568 if (stm32prog_serial_getc() != tmp_xor) {
569 stm32prog_serial_result(NACK_BYTE);
570 return;
571 }
572
573 /* If checksum is correct send ACK */
574 stm32prog_serial_result(ACK_BYTE);
575
576 /* Send data to the host:
577 * Number of data to read = data + 1
578 */
579 for (counter = (rcv_data + 1); counter != 0; counter--)
580 stm32prog_serial_putc(*(u8 *)(address++));
581}
582
583/**
584 * start_command() - Respond to start command
585 *
586 * Jump to user application in RAM or partition check
587 *
588 * @data: Current command context
589 */
590static void start_command(struct stm32prog_data *data)
591{
592 u32 address = 0;
593 u8 tmp_xor = 0x0;
594 u8 ret, rcv_data;
595
596 /* Read memory address */
597 address = get_address(&tmp_xor);
598
599 /* If address memory is not received correctly */
600 rcv_data = stm32prog_serial_getc();
601 if (rcv_data != tmp_xor) {
602 stm32prog_serial_result(NACK_BYTE);
603 return;
604 }
605 /* validate partition */
606 ret = stm32prog_start(data,
607 address);
608
609 if (ret)
610 stm32prog_serial_result(ABORT_BYTE);
611 else
612 stm32prog_serial_result(ACK_BYTE);
613}
614
615/**
616 * download_command() - Respond to download command
617 *
618 * Write data to not volatile memory, Flash
619 *
620 * @data: Current command context
621 */
622static void download_command(struct stm32prog_data *data)
623{
624 u32 address = 0x0;
625 u8 my_xor = 0x0;
626 u8 rcv_xor;
627 u32 counter = 0x0, codesize = 0x0;
628 u8 *ramaddress = 0;
629 u8 rcv_data = 0x0;
630 struct image_header_s *image_header = &data->header;
631 u32 cursor = data->cursor;
632 long size = 0;
633 u8 operation;
634 u32 packet_number;
635 u32 result = ACK_BYTE;
636 u8 ret;
637 unsigned int i;
638 bool error;
639 int rcv;
640
641 address = get_address(&my_xor);
642
643 /* If address memory is not received correctly */
644 rcv_xor = stm32prog_serial_getc();
645 if (rcv_xor != my_xor) {
646 result = NACK_BYTE;
647 goto end;
648 }
649
650 /* If address valid send ACK */
651 stm32prog_serial_result(ACK_BYTE);
652
653 /* get packet number and operation type */
654 operation = (u8)((u32)address >> 24);
655 packet_number = ((u32)(((u32)address << 8))) >> 8;
656
657 switch (operation) {
658 /* supported operation */
659 case PHASE_FLASHLAYOUT:
660 case PHASE_OTP:
661 case PHASE_PMIC:
662 break;
663 default:
664 result = NACK_BYTE;
665 goto end;
666 }
667 /* check the packet number */
668 if (packet_number == 0) {
669 /* erase: re-initialize the image_header struct */
670 data->packet_number = 0;
671 if (data->header_data)
672 memset(data->header_data, 0, BL_HEADER_SIZE);
673 else
674 data->header_data = calloc(1, BL_HEADER_SIZE);
675 cursor = 0;
676 data->cursor = 0;
677 data->checksum = 0;
678 /*idx = cursor;*/
679 } else {
680 data->packet_number++;
681 }
682
683 /* Check with the number of current packet if the device receive
684 * the true packet
685 */
686 if (packet_number != data->packet_number) {
687 data->packet_number--;
688 result = NACK_BYTE;
689 goto end;
690 }
691
692 /*-- Read number of bytes to be written and data -----------*/
693
694 /* Read the number of bytes to be written:
695 * Max NbrOfData = data + 1 <= 256
696 */
697 rcv_data = stm32prog_serial_getc();
698
699 /* NbrOfData to write = data + 1 */
700 codesize = rcv_data + 0x01;
701
702 if (codesize > USART_RAM_BUFFER_SIZE) {
703 result = NACK_BYTE;
704 goto end;
705 }
706
707 /* Checksum Initialization */
708 my_xor = rcv_data;
709
710 /* UART receive data and send to Buffer */
711 counter = codesize;
712 error = stm32prog_serial_get_buffer(data->buffer, &counter);
713
714 /* read checksum */
715 if (!error) {
716 rcv = stm32prog_serial_getc_err();
717 error = !!(rcv < 0);
718 rcv_xor = rcv;
719 }
720
721 if (error) {
722 printf("transmission error on packet %d, byte %d\n",
723 packet_number, codesize - counter);
724 /* waiting end of packet before flush & NACK */
725 mdelay(30);
726 data->packet_number--;
727 result = NACK_BYTE;
728 goto end;
729 }
730
731 /* Compute Checksum */
732 ramaddress = data->buffer;
733 for (counter = codesize; counter != 0; counter--)
734 my_xor ^= *(ramaddress++);
735
736 /* If Checksum is incorrect */
737 if (rcv_xor != my_xor) {
738 printf("checksum error on packet %d\n",
739 packet_number);
740 /* wait to be sure that all data are received
741 * in the FIFO before flush
742 */
743 mdelay(30);
744 data->packet_number--;
745 result = NACK_BYTE;
746 goto end;
747 }
748
749 /* Update current position in buffer */
750 data->cursor += codesize;
751
752 if (operation == PHASE_OTP) {
753 size = data->cursor - cursor;
754 /* no header for OTP */
755 if (stm32prog_otp_write(data, cursor,
756 data->buffer, &size))
757 result = ABORT_BYTE;
758 goto end;
759 }
760
761 if (operation == PHASE_PMIC) {
762 size = data->cursor - cursor;
763 /* no header for PMIC */
764 if (stm32prog_pmic_write(data, cursor,
765 data->buffer, &size))
766 result = ABORT_BYTE;
767 goto end;
768 }
769
770 if (cursor < BL_HEADER_SIZE) {
771 /* size = portion of header in this chunck */
772 if (data->cursor >= BL_HEADER_SIZE)
773 size = BL_HEADER_SIZE - cursor;
774 else
775 size = data->cursor - cursor;
776 memcpy((void *)((u32)(data->header_data) + cursor),
777 data->buffer, size);
778 cursor += size;
779
780 if (cursor == BL_HEADER_SIZE) {
781 /* Check and Write the header */
782 if (stm32prog_header(data)) {
783 result = ABORT_BYTE;
784 goto end;
785 }
786 } else {
787 goto end;
788 }
789 }
790
Patrick Delaunay19676ef2021-04-02 14:05:17 +0200791 if (data->header.type == HEADER_STM32IMAGE) {
Patrick Delaunayb823d992020-03-18 09:25:00 +0100792 if (data->cursor <= BL_HEADER_SIZE)
793 goto end;
794 /* compute checksum on payload */
795 for (i = (unsigned long)size; i < codesize; i++)
796 data->checksum += data->buffer[i];
797
798 if (data->cursor >
799 image_header->image_length + BL_HEADER_SIZE) {
Patrick Delaunay2b15af52020-11-06 19:01:30 +0100800 log_err("expected size exceeded\n");
Patrick Delaunayb823d992020-03-18 09:25:00 +0100801 result = ABORT_BYTE;
802 goto end;
803 }
804
805 /* write data (payload) */
806 ret = stm32prog_write(data,
807 &data->buffer[size],
808 codesize - size);
809 } else {
810 /* write all */
811 ret = stm32prog_write(data,
812 data->buffer,
813 codesize);
814 }
815 if (ret)
816 result = ABORT_BYTE;
817
818end:
819 stm32prog_serial_result(result);
820}
821
822/**
823 * read_partition() - Respond to read command
824 *
825 * Read data from not volatile memory, Flash
826 *
827 * @data: Current command context
828 */
829static void read_partition_command(struct stm32prog_data *data)
830{
831 u32 i, part_id, codesize, offset = 0, rcv_data;
832 long size;
833 u8 tmp_xor;
834 int res;
835 u8 buffer[256];
836
837 part_id = stm32prog_serial_getc();
838 tmp_xor = part_id;
839
840 offset = get_address(&tmp_xor);
841
842 rcv_data = stm32prog_serial_getc();
843 if (rcv_data != tmp_xor) {
Patrick Delaunay2b15af52020-11-06 19:01:30 +0100844 log_debug("1st checksum received = %x, computed %x\n",
845 rcv_data, tmp_xor);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100846 goto error;
847 }
848 stm32prog_serial_putc(ACK_BYTE);
849
850 /* NbrOfData to read = data + 1 */
851 rcv_data = stm32prog_serial_getc();
852 codesize = rcv_data + 0x01;
853 tmp_xor = rcv_data;
854
855 rcv_data = stm32prog_serial_getc();
856 if ((rcv_data ^ tmp_xor) != 0xFF) {
Patrick Delaunay2b15af52020-11-06 19:01:30 +0100857 log_debug("2nd checksum received = %x, computed %x\n",
858 rcv_data, tmp_xor);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100859 goto error;
860 }
861
Patrick Delaunay2b15af52020-11-06 19:01:30 +0100862 log_debug("%s : %x\n", __func__, part_id);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100863 rcv_data = 0;
864 switch (part_id) {
865 case PHASE_OTP:
866 size = codesize;
867 if (!stm32prog_otp_read(data, offset, buffer, &size))
868 rcv_data = size;
869 break;
870 case PHASE_PMIC:
871 size = codesize;
872 if (!stm32prog_pmic_read(data, offset, buffer, &size))
873 rcv_data = size;
874 break;
875 default:
876 res = stm32prog_read(data, part_id, offset,
877 buffer, codesize);
878 if (res > 0)
879 rcv_data = res;
880 break;
881 }
882 if (rcv_data > 0) {
883 stm32prog_serial_putc(ACK_BYTE);
884 /*----------- Send data to the host -----------*/
885 for (i = 0; i < rcv_data; i++)
886 stm32prog_serial_putc(buffer[i]);
887 /*----------- Send filler to the host -----------*/
888 for (; i < codesize; i++)
889 stm32prog_serial_putc(0x0);
890 return;
891 }
892 stm32prog_serial_result(ABORT_BYTE);
893 return;
894
895error:
896 stm32prog_serial_result(NACK_BYTE);
897}
898
899/* MAIN function = SERIAL LOOP ***********************************************/
900
901/**
902 * stm32prog_serial_loop() - USART bootloader Loop routine
903 *
904 * @data: Current command context
905 * @return true if reset is needed after loop
906 */
907bool stm32prog_serial_loop(struct stm32prog_data *data)
908{
909 u32 counter = 0x0;
910 u8 command = 0x0;
911 u8 found;
912 int phase = data->phase;
913
914 /* element of cmd_func need to aligned with cmd_id[]*/
915 void (*cmd_func[NB_CMD])(struct stm32prog_data *) = {
916 /* GET_CMD_COMMAND */ get_cmd_command,
917 /* GET_VER_COMMAND */ get_version_command,
918 /* GET_ID_COMMAND */ get_id_command,
919 /* GET_PHASE_COMMAND */ get_phase_command,
920 /* RM_COMMAND */ read_memory_command,
921 /* READ_PART_COMMAND */ read_partition_command,
922 /* START_COMMAND */ start_command,
923 /* DOWNLOAD_COMMAND */ download_command
924 };
925
926 /* flush and NACK pending command received during u-boot init
927 * request command reemit
928 */
929 stm32prog_serial_result(NACK_BYTE);
930
931 clear_ctrlc(); /* forget any previous Control C */
932 while (!had_ctrlc()) {
933 phase = data->phase;
934
935 if (phase == PHASE_DO_RESET)
936 return true;
937
938 /* Get the user command: read first byte */
939 command = stm32prog_serial_getc();
940
941 if (command == INIT_BYTE) {
942 puts("\nConnected\n");
943 stm32prog_serial_result(ACK_BYTE);
944 continue;
945 }
946
947 found = 0;
948 for (counter = 0; counter < NB_CMD; counter++)
949 if (cmd_id[counter] == command) {
950 found = 1;
951 break;
952 }
953 if (found)
954 if ((command ^ stm32prog_serial_getc()) != 0xFF)
955 found = 0;
956 if (!found) {
957 /* wait to be sure that all data are received
958 * in the FIFO before flush (CMD and XOR)
959 */
960 mdelay(3);
961 stm32prog_serial_result(NACK_BYTE);
962 } else {
963 stm32prog_serial_result(ACK_BYTE);
964 cmd_func[counter](data);
965 }
966 WATCHDOG_RESET();
967 }
968
969 /* clean device */
970 if (gd->cur_serial_dev == down_serial_dev) {
971 /* restore console on uart */
972 gd->flags &= ~(GD_FLG_DISABLE_CONSOLE | GD_FLG_SILENT);
973 }
974 down_serial_dev = NULL;
975
976 return false; /* no reset after ctrlc */
977}