blob: f1bed7d1a33bbe15c55e58dfef43a10126850822 [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>
Patrick Delaunay7ef09a32021-05-18 15:12:10 +020013#include <asm/arch/sys_proto.h>
Patrick Delaunayb823d992020-03-18 09:25:00 +010014#include <dm/lists.h>
15#include <dm/device-internal.h>
Simon Glassdbd79542020-05-10 11:40:11 -060016#include <linux/delay.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060017#include <asm/global_data.h>
Patrick Delaunayb823d992020-03-18 09:25:00 +010018#include "stm32prog.h"
19
20/* - configuration part -----------------------------*/
21#define USART_BL_VERSION 0x40 /* USART bootloader version V4.0*/
22#define UBOOT_BL_VERSION 0x03 /* bootloader version V0.3*/
Patrick Delaunay7ef09a32021-05-18 15:12:10 +020023
Patrick Delaunayb823d992020-03-18 09:25:00 +010024#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
Patrick Delaunay4daf9942021-05-18 15:12:05 +020063/* with 115200 bauds, 20 ms allow to receive the 256 bytes buffer */
64#define TIMEOUT_SERIAL_BUFFER 30
65
Patrick Delaunayb823d992020-03-18 09:25:00 +010066/* DFU support for serial *********************************************/
67static struct dfu_entity *stm32prog_get_entity(struct stm32prog_data *data)
68{
69 int alt_id;
70
71 if (!data->cur_part)
72 if (data->phase == PHASE_FLASHLAYOUT)
73 alt_id = 0;
74 else
75 return NULL;
76 else
77 alt_id = data->cur_part->alt_id;
78
79 return dfu_get_entity(alt_id);
80}
81
82static int stm32prog_write(struct stm32prog_data *data, u8 *buffer,
83 u32 buffer_size)
84{
85 struct dfu_entity *dfu_entity;
86 u8 ret = 0;
87
88 dfu_entity = stm32prog_get_entity(data);
89 if (!dfu_entity)
90 return -ENODEV;
91
92 ret = dfu_write(dfu_entity,
93 buffer,
94 buffer_size,
95 data->dfu_seq);
96
97 if (ret) {
98 stm32prog_err("DFU write failed [%d] cnt: %d",
99 ret, data->dfu_seq);
100 }
101 data->dfu_seq++;
102 /* handle rollover as in driver/dfu/dfu.c */
103 data->dfu_seq &= 0xffff;
104 if (buffer_size == 0)
105 data->dfu_seq = 0; /* flush done */
106
107 return ret;
108}
109
110static int stm32prog_read(struct stm32prog_data *data, u8 phase, u32 offset,
111 u8 *buffer, u32 buffer_size)
112{
113 struct dfu_entity *dfu_entity;
114 struct stm32prog_part_t *part;
115 u32 size;
116 int ret, i;
117
118 if (data->dfu_seq) {
119 stm32prog_err("DFU write pending for phase %d, seq %d",
120 data->phase, data->dfu_seq);
121 return -EINVAL;
122 }
123 if (phase == PHASE_FLASHLAYOUT || phase > PHASE_LAST_USER) {
124 stm32prog_err("read failed : phase %d is invalid", phase);
125 return -EINVAL;
126 }
127 if (data->read_phase <= PHASE_LAST_USER &&
128 phase != data->read_phase) {
129 /* clear previous read session */
130 dfu_entity = dfu_get_entity(data->read_phase - 1);
131 if (dfu_entity)
132 dfu_transaction_cleanup(dfu_entity);
133 }
134
135 dfu_entity = NULL;
136 /* found partition for the expected phase */
137 for (i = 0; i < data->part_nb; i++) {
138 part = &data->part_array[i];
139 if (part->id == phase)
140 dfu_entity = dfu_get_entity(part->alt_id);
141 }
142 if (!dfu_entity) {
143 stm32prog_err("read failed : phase %d is unknown", phase);
144 return -ENODEV;
145 }
146
147 /* clear pending read before to force offset */
148 if (dfu_entity->inited &&
149 (data->read_phase != phase || data->offset != offset))
150 dfu_transaction_cleanup(dfu_entity);
151
152 /* initiate before to force offset */
153 if (!dfu_entity->inited) {
154 ret = dfu_transaction_initiate(dfu_entity, true);
155 if (ret < 0) {
156 stm32prog_err("DFU read init failed [%d] phase = %d offset = 0x%08x",
157 ret, phase, offset);
158 return ret;
159 }
160 }
161 /* force new offset */
162 if (dfu_entity->offset != offset)
163 dfu_entity->offset = offset;
164 data->offset = offset;
165 data->read_phase = phase;
Patrick Delaunay2b15af52020-11-06 19:01:30 +0100166 log_debug("\nSTM32 download read %s offset=0x%x\n",
167 dfu_entity->name, offset);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100168 ret = dfu_read(dfu_entity, buffer, buffer_size,
169 dfu_entity->i_blk_seq_num);
170 if (ret < 0) {
171 stm32prog_err("DFU read failed [%d] phase = %d offset = 0x%08x",
172 ret, phase, offset);
173 return ret;
174 }
175
176 size = ret;
177
178 if (size < buffer_size) {
179 data->offset = 0;
180 data->read_phase = PHASE_END;
181 memset(buffer + size, 0, buffer_size - size);
182 } else {
183 data->offset += size;
184 }
185
186 return ret;
187}
188
189/* UART access ***************************************************/
190int stm32prog_serial_init(struct stm32prog_data *data, int link_dev)
191{
192 struct udevice *dev = NULL;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100193 struct dm_serial_ops *ops;
194 /* no parity, 8 bits, 1 stop */
195 u32 serial_config = SERIAL_DEFAULT_CONFIG;
196
197 down_serial_dev = NULL;
198
Patrick Delaunaye2592992021-02-25 13:37:03 +0100199 if (uclass_get_device_by_seq(UCLASS_SERIAL, link_dev, &dev)) {
200 log_err("serial %d device not found\n", link_dev);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100201 return -ENODEV;
202 }
Patrick Delaunaye2592992021-02-25 13:37:03 +0100203
204 down_serial_dev = dev;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100205
206 /* force silent console on uart only when used */
207 if (gd->cur_serial_dev == down_serial_dev)
208 gd->flags |= GD_FLG_DISABLE_CONSOLE | GD_FLG_SILENT;
209 else
210 gd->flags &= ~(GD_FLG_DISABLE_CONSOLE | GD_FLG_SILENT);
211
212 ops = serial_get_ops(down_serial_dev);
213
214 if (!ops) {
Patrick Delaunaye2592992021-02-25 13:37:03 +0100215 log_err("serial %d = %s missing ops\n", link_dev, dev->name);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100216 return -ENODEV;
217 }
218 if (!ops->setconfig) {
Patrick Delaunaye2592992021-02-25 13:37:03 +0100219 log_err("serial %d = %s missing setconfig\n", link_dev, dev->name);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100220 return -ENODEV;
221 }
222
223 clrsetbits_le32(&serial_config, SERIAL_PAR_MASK, SERIAL_PAR_EVEN);
224
225 data->buffer = memalign(CONFIG_SYS_CACHELINE_SIZE,
226 USART_RAM_BUFFER_SIZE);
227
228 return ops->setconfig(down_serial_dev, serial_config);
229}
230
231static void stm32prog_serial_flush(void)
232{
233 struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
234 int err;
235
236 do {
237 err = ops->getc(down_serial_dev);
238 } while (err != -EAGAIN);
239}
240
241static int stm32prog_serial_getc_err(void)
242{
243 struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
244 int err;
245
246 do {
247 err = ops->getc(down_serial_dev);
248 if (err == -EAGAIN) {
249 ctrlc();
Stefan Roese80877fa2022-09-02 14:10:46 +0200250 schedule();
Patrick Delaunayb823d992020-03-18 09:25:00 +0100251 }
252 } while ((err == -EAGAIN) && (!had_ctrlc()));
253
254 return err;
255}
256
257static u8 stm32prog_serial_getc(void)
258{
259 int err;
260
261 err = stm32prog_serial_getc_err();
262
263 return err >= 0 ? err : 0;
264}
265
266static bool stm32prog_serial_get_buffer(u8 *buffer, u32 *count)
267{
268 struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
269 int err;
Patrick Delaunay4daf9942021-05-18 15:12:05 +0200270 ulong start = get_timer(0);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100271
272 do {
273 err = ops->getc(down_serial_dev);
274 if (err >= 0) {
275 *buffer++ = err;
276 *count -= 1;
277 } else if (err == -EAGAIN) {
278 ctrlc();
Stefan Roese80877fa2022-09-02 14:10:46 +0200279 schedule();
Patrick Delaunay4daf9942021-05-18 15:12:05 +0200280 if (get_timer(start) > TIMEOUT_SERIAL_BUFFER) {
281 err = -ETIMEDOUT;
282 break;
283 }
Patrick Delaunayb823d992020-03-18 09:25:00 +0100284 } else {
285 break;
286 }
287 } while (*count && !had_ctrlc());
288
289 return !!(err < 0);
290}
291
292static void stm32prog_serial_putc(u8 w_byte)
293{
294 struct dm_serial_ops *ops = serial_get_ops(down_serial_dev);
295 int err;
296
297 do {
298 err = ops->putc(down_serial_dev, w_byte);
299 } while (err == -EAGAIN);
300}
301
302/* Helper function ************************************************/
Patrick Delaunay21ea4ef2022-09-06 18:53:19 +0200303static u8 stm32prog_start(struct stm32prog_data *data, uintptr_t address)
Patrick Delaunayb823d992020-03-18 09:25:00 +0100304{
305 u8 ret = 0;
306 struct dfu_entity *dfu_entity;
307
308 if (address < 0x100) {
309 if (address == PHASE_OTP)
310 return stm32prog_otp_start(data);
311
312 if (address == PHASE_PMIC)
313 return stm32prog_pmic_start(data);
314
315 if (address == PHASE_RESET || address == PHASE_END) {
316 data->cur_part = NULL;
317 data->dfu_seq = 0;
318 data->phase = address;
319 return 0;
320 }
321 if (address != data->phase) {
322 stm32prog_err("invalid received phase id %d, current phase is %d",
323 (u8)address, (u8)data->phase);
324 return -EINVAL;
325 }
326 }
327 /* check the last loaded partition */
328 if (address == DEFAULT_ADDRESS || address == data->phase) {
329 switch (data->phase) {
330 case PHASE_END:
331 case PHASE_RESET:
332 case PHASE_DO_RESET:
333 data->cur_part = NULL;
334 data->phase = PHASE_DO_RESET;
335 return 0;
336 }
337 dfu_entity = stm32prog_get_entity(data);
338 if (!dfu_entity)
339 return -ENODEV;
340
Patrick Delaunayefc7a3b2020-12-11 13:36:18 +0100341 ret = dfu_flush(dfu_entity, NULL, 0, data->dfu_seq);
342 if (ret) {
343 stm32prog_err("DFU flush failed [%d]", ret);
344 return ret;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100345 }
Patrick Delaunayefc7a3b2020-12-11 13:36:18 +0100346 data->dfu_seq = 0;
347
Patrick Delaunayb823d992020-03-18 09:25:00 +0100348 printf("\n received length = 0x%x\n", data->cursor);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100349
350 /* update DFU with received flashlayout */
351 if (data->phase == PHASE_FLASHLAYOUT)
352 stm32prog_dfu_init(data);
353 } else {
354 void (*entry)(void) = (void *)address;
355
Patrick Delaunay21ea4ef2022-09-06 18:53:19 +0200356 printf("## Starting application at 0x%p ...\n", (void *)address);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100357 (*entry)();
358 printf("## Application terminated\n");
359 ret = -ENOEXEC;
360 }
361
362 return ret;
363}
364
365/**
366 * get_address() - Get address if it is valid
367 *
368 * @tmp_xor: Current xor value to update
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100369 * Return: The address area
Patrick Delaunayb823d992020-03-18 09:25:00 +0100370 */
Patrick Delaunay21ea4ef2022-09-06 18:53:19 +0200371static uintptr_t get_address(u8 *tmp_xor)
Patrick Delaunayb823d992020-03-18 09:25:00 +0100372{
Patrick Delaunay21ea4ef2022-09-06 18:53:19 +0200373 uintptr_t address = 0x0;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100374 u8 data;
375
376 data = stm32prog_serial_getc();
377 *tmp_xor ^= data;
378 address |= ((u32)data) << 24;
379
380 data = stm32prog_serial_getc();
381 address |= ((u32)data) << 16;
382 *tmp_xor ^= data;
383
384 data = stm32prog_serial_getc();
385 address |= ((u32)data) << 8;
386 *tmp_xor ^= data;
387
388 data = stm32prog_serial_getc();
389 address |= ((u32)data);
390 *tmp_xor ^= data;
391
392 return address;
393}
394
395static void stm32prog_serial_result(u8 result)
396{
397 /* always flush fifo before to send result */
398 stm32prog_serial_flush();
399 stm32prog_serial_putc(result);
400}
401
402/* Command -----------------------------------------------*/
403/**
404 * get_cmd_command() - Respond to Get command
405 *
406 * @data: Current command context
407 */
408static void get_cmd_command(struct stm32prog_data *data)
409{
410 u32 counter = 0x0;
411
412 stm32prog_serial_putc(NB_CMD);
413 stm32prog_serial_putc(USART_BL_VERSION);
414
415 for (counter = 0; counter < NB_CMD; counter++)
416 stm32prog_serial_putc(cmd_id[counter]);
417
418 stm32prog_serial_result(ACK_BYTE);
419}
420
421/**
422 * get_version_command() - Respond to Get Version command
423 *
424 * @data: Current command context
425 */
426static void get_version_command(struct stm32prog_data *data)
427{
428 stm32prog_serial_putc(UBOOT_BL_VERSION);
429 stm32prog_serial_result(ACK_BYTE);
430}
431
432/**
433 * get_id_command() - Respond to Get ID command
434 *
435 * @data: Current command context
436 */
437static void get_id_command(struct stm32prog_data *data)
438{
Patrick Delaunay7ef09a32021-05-18 15:12:10 +0200439 u32 cpu = get_cpu_dev();
440
Patrick Delaunayb823d992020-03-18 09:25:00 +0100441 /* Send Device IDCode */
442 stm32prog_serial_putc(0x1);
Patrick Delaunay7ef09a32021-05-18 15:12:10 +0200443 stm32prog_serial_putc((cpu >> 8) & 0xFF);
444 stm32prog_serial_putc(cpu & 0xFF);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100445 stm32prog_serial_result(ACK_BYTE);
446}
447
448/**
449 * get_phase_command() - Respond to Get phase
450 *
451 * @data: Current command context
452 */
453static void get_phase_command(struct stm32prog_data *data)
454{
455 char *err_msg = NULL;
456 u8 i, length = 0;
457 u32 destination = DEFAULT_ADDRESS; /* destination address */
458 int phase = data->phase;
459
460 if (phase == PHASE_RESET || phase == PHASE_DO_RESET) {
461 err_msg = stm32prog_get_error(data);
462 length = strlen(err_msg);
463 }
464 if (phase == PHASE_FLASHLAYOUT)
Patrick Delaunaye334d322022-09-06 18:53:18 +0200465 destination = CONFIG_SYS_LOAD_ADDR;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100466
467 stm32prog_serial_putc(length + 5); /* Total length */
468 stm32prog_serial_putc(phase & 0xFF); /* partition ID */
469 stm32prog_serial_putc(destination); /* byte 1 of address */
470 stm32prog_serial_putc(destination >> 8); /* byte 2 of address */
471 stm32prog_serial_putc(destination >> 16); /* byte 3 of address */
472 stm32prog_serial_putc(destination >> 24); /* byte 4 of address */
473
474 stm32prog_serial_putc(length); /* Information length */
475 for (i = 0; i < length; i++)
476 stm32prog_serial_putc(err_msg[i]);
477 stm32prog_serial_result(ACK_BYTE);
478
479 if (phase == PHASE_RESET)
480 stm32prog_do_reset(data);
481}
482
483/**
484 * read_memory_command() - Read data from memory
485 *
486 * @data: Current command context
487 */
488static void read_memory_command(struct stm32prog_data *data)
489{
Patrick Delaunay21ea4ef2022-09-06 18:53:19 +0200490 uintptr_t address = 0x0;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100491 u8 rcv_data = 0x0, tmp_xor = 0x0;
492 u32 counter = 0x0;
493
494 /* Read memory address */
495 address = get_address(&tmp_xor);
496
497 /* If address memory is not received correctly */
498 rcv_data = stm32prog_serial_getc();
499 if (rcv_data != tmp_xor) {
500 stm32prog_serial_result(NACK_BYTE);
501 return;
502 }
503
504 stm32prog_serial_result(ACK_BYTE);
505
506 /* Read the number of bytes to be received:
507 * Max NbrOfData = Data + 1 = 256
508 */
509 rcv_data = stm32prog_serial_getc();
510 tmp_xor = ~rcv_data;
511 if (stm32prog_serial_getc() != tmp_xor) {
512 stm32prog_serial_result(NACK_BYTE);
513 return;
514 }
515
516 /* If checksum is correct send ACK */
517 stm32prog_serial_result(ACK_BYTE);
518
519 /* Send data to the host:
520 * Number of data to read = data + 1
521 */
522 for (counter = (rcv_data + 1); counter != 0; counter--)
523 stm32prog_serial_putc(*(u8 *)(address++));
524}
525
526/**
527 * start_command() - Respond to start command
528 *
529 * Jump to user application in RAM or partition check
530 *
531 * @data: Current command context
532 */
533static void start_command(struct stm32prog_data *data)
534{
Patrick Delaunay21ea4ef2022-09-06 18:53:19 +0200535 uintptr_t address = 0;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100536 u8 tmp_xor = 0x0;
537 u8 ret, rcv_data;
538
539 /* Read memory address */
540 address = get_address(&tmp_xor);
541
542 /* If address memory is not received correctly */
543 rcv_data = stm32prog_serial_getc();
544 if (rcv_data != tmp_xor) {
545 stm32prog_serial_result(NACK_BYTE);
546 return;
547 }
548 /* validate partition */
Patrick Delaunay21ea4ef2022-09-06 18:53:19 +0200549 ret = stm32prog_start(data, address);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100550
551 if (ret)
552 stm32prog_serial_result(ABORT_BYTE);
553 else
554 stm32prog_serial_result(ACK_BYTE);
555}
556
557/**
558 * download_command() - Respond to download command
559 *
560 * Write data to not volatile memory, Flash
561 *
562 * @data: Current command context
563 */
564static void download_command(struct stm32prog_data *data)
565{
566 u32 address = 0x0;
567 u8 my_xor = 0x0;
568 u8 rcv_xor;
569 u32 counter = 0x0, codesize = 0x0;
570 u8 *ramaddress = 0;
571 u8 rcv_data = 0x0;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100572 u32 cursor = data->cursor;
573 long size = 0;
574 u8 operation;
575 u32 packet_number;
576 u32 result = ACK_BYTE;
577 u8 ret;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100578 bool error;
579 int rcv;
580
581 address = get_address(&my_xor);
582
583 /* If address memory is not received correctly */
584 rcv_xor = stm32prog_serial_getc();
585 if (rcv_xor != my_xor) {
586 result = NACK_BYTE;
587 goto end;
588 }
589
590 /* If address valid send ACK */
591 stm32prog_serial_result(ACK_BYTE);
592
593 /* get packet number and operation type */
594 operation = (u8)((u32)address >> 24);
595 packet_number = ((u32)(((u32)address << 8))) >> 8;
596
597 switch (operation) {
598 /* supported operation */
599 case PHASE_FLASHLAYOUT:
600 case PHASE_OTP:
601 case PHASE_PMIC:
602 break;
603 default:
604 result = NACK_BYTE;
605 goto end;
606 }
607 /* check the packet number */
608 if (packet_number == 0) {
609 /* erase: re-initialize the image_header struct */
610 data->packet_number = 0;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100611 cursor = 0;
612 data->cursor = 0;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100613 /*idx = cursor;*/
614 } else {
615 data->packet_number++;
616 }
617
618 /* Check with the number of current packet if the device receive
619 * the true packet
620 */
621 if (packet_number != data->packet_number) {
622 data->packet_number--;
623 result = NACK_BYTE;
624 goto end;
625 }
626
627 /*-- Read number of bytes to be written and data -----------*/
628
629 /* Read the number of bytes to be written:
630 * Max NbrOfData = data + 1 <= 256
631 */
632 rcv_data = stm32prog_serial_getc();
633
634 /* NbrOfData to write = data + 1 */
635 codesize = rcv_data + 0x01;
636
637 if (codesize > USART_RAM_BUFFER_SIZE) {
638 result = NACK_BYTE;
639 goto end;
640 }
641
642 /* Checksum Initialization */
643 my_xor = rcv_data;
644
645 /* UART receive data and send to Buffer */
646 counter = codesize;
647 error = stm32prog_serial_get_buffer(data->buffer, &counter);
648
649 /* read checksum */
650 if (!error) {
651 rcv = stm32prog_serial_getc_err();
652 error = !!(rcv < 0);
653 rcv_xor = rcv;
654 }
655
656 if (error) {
657 printf("transmission error on packet %d, byte %d\n",
658 packet_number, codesize - counter);
659 /* waiting end of packet before flush & NACK */
Patrick Delaunay4daf9942021-05-18 15:12:05 +0200660 mdelay(TIMEOUT_SERIAL_BUFFER);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100661 data->packet_number--;
662 result = NACK_BYTE;
663 goto end;
664 }
665
666 /* Compute Checksum */
667 ramaddress = data->buffer;
668 for (counter = codesize; counter != 0; counter--)
669 my_xor ^= *(ramaddress++);
670
671 /* If Checksum is incorrect */
672 if (rcv_xor != my_xor) {
673 printf("checksum error on packet %d\n",
674 packet_number);
675 /* wait to be sure that all data are received
676 * in the FIFO before flush
677 */
Patrick Delaunay4daf9942021-05-18 15:12:05 +0200678 mdelay(TIMEOUT_SERIAL_BUFFER);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100679 data->packet_number--;
680 result = NACK_BYTE;
681 goto end;
682 }
683
Patrick Delaunayf67fd842021-05-18 15:12:04 +0200684 switch (operation) {
685 case PHASE_OTP:
686 size = codesize;
687 ret = stm32prog_otp_write(data, cursor, data->buffer, &size);
688 break;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100689
Patrick Delaunayf67fd842021-05-18 15:12:04 +0200690 case PHASE_PMIC:
691 size = codesize;
692 ret = stm32prog_pmic_write(data, cursor, data->buffer, &size);
693 break;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100694
Patrick Delaunayf67fd842021-05-18 15:12:04 +0200695 default:
696 ret = stm32prog_write(data, data->buffer, codesize);
697 break;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100698 }
699
Patrick Delaunayb823d992020-03-18 09:25:00 +0100700 if (ret)
701 result = ABORT_BYTE;
Patrick Delaunayf67fd842021-05-18 15:12:04 +0200702 else
703 /* Update current position in buffer */
704 data->cursor += codesize;
Patrick Delaunayb823d992020-03-18 09:25:00 +0100705
706end:
707 stm32prog_serial_result(result);
708}
709
710/**
711 * read_partition() - Respond to read command
712 *
713 * Read data from not volatile memory, Flash
714 *
715 * @data: Current command context
716 */
717static void read_partition_command(struct stm32prog_data *data)
718{
719 u32 i, part_id, codesize, offset = 0, rcv_data;
720 long size;
721 u8 tmp_xor;
722 int res;
723 u8 buffer[256];
724
725 part_id = stm32prog_serial_getc();
726 tmp_xor = part_id;
727
728 offset = get_address(&tmp_xor);
729
730 rcv_data = stm32prog_serial_getc();
731 if (rcv_data != tmp_xor) {
Patrick Delaunay2b15af52020-11-06 19:01:30 +0100732 log_debug("1st checksum received = %x, computed %x\n",
733 rcv_data, tmp_xor);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100734 goto error;
735 }
736 stm32prog_serial_putc(ACK_BYTE);
737
738 /* NbrOfData to read = data + 1 */
739 rcv_data = stm32prog_serial_getc();
740 codesize = rcv_data + 0x01;
741 tmp_xor = rcv_data;
742
743 rcv_data = stm32prog_serial_getc();
744 if ((rcv_data ^ tmp_xor) != 0xFF) {
Patrick Delaunay2b15af52020-11-06 19:01:30 +0100745 log_debug("2nd checksum received = %x, computed %x\n",
746 rcv_data, tmp_xor);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100747 goto error;
748 }
749
Patrick Delaunay2b15af52020-11-06 19:01:30 +0100750 log_debug("%s : %x\n", __func__, part_id);
Patrick Delaunayb823d992020-03-18 09:25:00 +0100751 rcv_data = 0;
752 switch (part_id) {
753 case PHASE_OTP:
754 size = codesize;
755 if (!stm32prog_otp_read(data, offset, buffer, &size))
756 rcv_data = size;
757 break;
758 case PHASE_PMIC:
759 size = codesize;
760 if (!stm32prog_pmic_read(data, offset, buffer, &size))
761 rcv_data = size;
762 break;
763 default:
764 res = stm32prog_read(data, part_id, offset,
765 buffer, codesize);
766 if (res > 0)
767 rcv_data = res;
768 break;
769 }
770 if (rcv_data > 0) {
771 stm32prog_serial_putc(ACK_BYTE);
772 /*----------- Send data to the host -----------*/
773 for (i = 0; i < rcv_data; i++)
774 stm32prog_serial_putc(buffer[i]);
775 /*----------- Send filler to the host -----------*/
776 for (; i < codesize; i++)
777 stm32prog_serial_putc(0x0);
778 return;
779 }
780 stm32prog_serial_result(ABORT_BYTE);
781 return;
782
783error:
784 stm32prog_serial_result(NACK_BYTE);
785}
786
787/* MAIN function = SERIAL LOOP ***********************************************/
788
789/**
790 * stm32prog_serial_loop() - USART bootloader Loop routine
791 *
792 * @data: Current command context
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100793 * Return: true if reset is needed after loop
Patrick Delaunayb823d992020-03-18 09:25:00 +0100794 */
795bool stm32prog_serial_loop(struct stm32prog_data *data)
796{
797 u32 counter = 0x0;
798 u8 command = 0x0;
799 u8 found;
800 int phase = data->phase;
801
802 /* element of cmd_func need to aligned with cmd_id[]*/
803 void (*cmd_func[NB_CMD])(struct stm32prog_data *) = {
804 /* GET_CMD_COMMAND */ get_cmd_command,
805 /* GET_VER_COMMAND */ get_version_command,
806 /* GET_ID_COMMAND */ get_id_command,
807 /* GET_PHASE_COMMAND */ get_phase_command,
808 /* RM_COMMAND */ read_memory_command,
809 /* READ_PART_COMMAND */ read_partition_command,
810 /* START_COMMAND */ start_command,
811 /* DOWNLOAD_COMMAND */ download_command
812 };
813
814 /* flush and NACK pending command received during u-boot init
815 * request command reemit
816 */
817 stm32prog_serial_result(NACK_BYTE);
818
819 clear_ctrlc(); /* forget any previous Control C */
820 while (!had_ctrlc()) {
821 phase = data->phase;
822
823 if (phase == PHASE_DO_RESET)
824 return true;
825
826 /* Get the user command: read first byte */
827 command = stm32prog_serial_getc();
828
829 if (command == INIT_BYTE) {
830 puts("\nConnected\n");
831 stm32prog_serial_result(ACK_BYTE);
832 continue;
833 }
834
835 found = 0;
836 for (counter = 0; counter < NB_CMD; counter++)
837 if (cmd_id[counter] == command) {
838 found = 1;
839 break;
840 }
841 if (found)
842 if ((command ^ stm32prog_serial_getc()) != 0xFF)
843 found = 0;
844 if (!found) {
845 /* wait to be sure that all data are received
846 * in the FIFO before flush (CMD and XOR)
847 */
848 mdelay(3);
849 stm32prog_serial_result(NACK_BYTE);
850 } else {
851 stm32prog_serial_result(ACK_BYTE);
852 cmd_func[counter](data);
853 }
Stefan Roese80877fa2022-09-02 14:10:46 +0200854 schedule();
Patrick Delaunayb823d992020-03-18 09:25:00 +0100855 }
856
857 /* clean device */
858 if (gd->cur_serial_dev == down_serial_dev) {
859 /* restore console on uart */
860 gd->flags &= ~(GD_FLG_DISABLE_CONSOLE | GD_FLG_SILENT);
861 }
862 down_serial_dev = NULL;
863
864 return false; /* no reset after ctrlc */
865}