1 /*********************************************************************
2  *
3  *   LPC ISP Commands for flash tool
4  *
5  *
6  *  Copyright (C) 2012 Nathael Pajani <nathael.pajani@nathael.net>
7  *
8  *  This program is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  *********************************************************************/
23 #include <stdlib.h> /* strtoul */
24 #include <stdio.h> /* printf, snprintf */
25 #include <stdint.h>
26 #include <unistd.h>
27 #include <string.h> /* strncmp, memset */
28 #include <ctype.h>
29 #include <errno.h>
31 #include <unistd.h> /* for open, close */
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
36 #include "isp_utils.h"
37 #include "isp_commands.h"
38 #include "parts.h"
40 #define REP_BUFSIZE 40
42 extern int trace_on;
45 int get_ids(void)
46 {
47         int ret = 0;
49         isp_cmd_part_id(0);
50         isp_cmd_read_uid();
51         isp_cmd_boot_version();
53         return ret;
54 }
57 int dump_to_file(struct part_desc* part, char* filename)
58 {
59         int ret = 0, len = 0;
60         char* data;
62         /* Allocate buffer */
63         data = malloc(part->flash_size);
64         if (data == NULL) {
65                 printf("Unable to allocate read buffer, asked %u.\n", part->flash_size);
66                 return -10;
67         }
69         /* Read data */
70         len = isp_read_memory(data, part->flash_base, part->flash_size, part->uuencode);
71         if (len != (int)(part->flash_size)) {
72                 printf("Read returned %d bytes instead of %u.\n", len, part->flash_size);
73         }
75         /* Write data to file */
76         ret = isp_buff_to_file(data, part->flash_size, filename);
78         /* Free memory */
79         free(data);
81         return ret;
82 }
85 int erase_flash(struct part_desc* part)
86 {
87         int ret = 0;
88         int i = 0;
90         /* Unlock device */
91         ret = isp_cmd_unlock(1);
92         if (ret != 0) {
93                 printf("Unable to unlock device, aborting.\n");
94                 return -1;
95         }
97         for (i=0; i<(int)(part->flash_nb_sectors); i++) {
98                 ret = isp_send_cmd_sectors("blank-check", 'I', i, i, 1);
99                 if (ret == CMD_SUCCESS) {
100                         /* sector already blank, preserve the flash, skip to next one :) */
101                         continue;
102                 }
103                 if (ret < 0) {
104                         /* Error ? */
105                         printf("Initial blank check error (%d) at sector %d!\n", ret, i);
106                         return ret;
107                 } else {
108                         /* Controller replyed with first non blank offset and data, remove it from buffer */
109                         char buf[REP_BUFSIZE];
110                         usleep( 5000 ); /* Some devices are slow to scan flash, give them some time */
111                         isp_serial_read(buf, REP_BUFSIZE, 3);
112                 }
113                 /* Sector not blank, perform erase */
114                 ret = isp_send_cmd_sectors("prepare-for-write", 'P', i, i, 1);
115                 if (ret != 0) {
116                         printf("Error (%d) when trying to prepare sector %d for erase operation!\n", ret, i);
117                         return ret;
118                 }
119                 ret = isp_send_cmd_sectors("erase", 'E', i, i, 1);
120                 if (ret != 0) {
121                         printf("Error (%d) when trying to erase sector %d!\n", ret, i);
122                         return ret;
123                 }
124         }
125         printf("Flash now all blank.\n");
127         return 0;
130 int start_prog(struct part_desc* part)
132         int ret = 0, len = 0;
133         uint32_t addr = 0;
135         len = isp_read_memory((char*)&addr, (part->flash_base + part->reset_vector_offset), sizeof(addr), part->uuencode);
136         if (len != sizeof(addr)) {
137                 printf("Unable to read reset address from flash.\n");
138                 return len;
139         }
140         /* FIXME : the following value (0x200) may be LPC111x specific */
141         if (addr < 0x200) {
142                 printf("Actual reset address is 0x%08x, which is under the lowest allowed address of 0x200.\n", addr);
143         }
144         /* Unlock device */
145         ret = isp_cmd_unlock(1);
146         if (ret != 0) {
147                 printf("Unable to unlock device, aborting.\n");
148                 return -1;
149         }
150         /* Read address in thumb or arm mode ? */
151         if (addr & 0x01) {
152                 addr &= ~1UL;
153                 ret = isp_send_cmd_go(addr, 'T');
154         } else {
155                 ret = isp_send_cmd_go(addr, 'A');
156         }
158         /* FIXME : start terminal */
160         return ret;
164 static unsigned int calc_write_size(unsigned int sector_size, unsigned int ram_buff_size)
166         unsigned int write_size = 0;
168         write_size = ((sector_size < ram_buff_size) ? sector_size : ram_buff_size);
169         /* According to section 21.5.7 of LPC11xx user's manual (UM10398), number of bytes
170          * written should be 256 | 512 | 1024 | 4096 */
171         if (write_size >= 4096) {
172                 write_size = 4096;
173         } else if (write_size >= 1024) {
174                 write_size = 1024;
175         } else if (write_size >= 512) {
176                 write_size = 512;
177         } else if (write_size >= 256) {
178                 write_size = 256;
179         } else if (write_size >= 64) {
180                 write_size = 64;
181         } else {
182                 write_size = 0;
183         }
184         return write_size;
187 int flash_target(struct part_desc* part, char* filename, int calc_user_code)
189         int ret = 0;
190         char* data = NULL;
191         int size = 0;
192         int i = 0, blocks = 0;
193         unsigned int write_size = 0;
194         unsigned int sector_size = (part->flash_size / part->flash_nb_sectors);
195         uint32_t ram_addr = (part->ram_base + part->ram_buff_offset);
196         uint32_t uuencode = part->uuencode;
197         uint32_t* v = NULL; /* Used for checksum computing */
198         uint32_t cksum = 0;
199         uint32_t crp = 0;
201         /**  Sanity checks  *********************************/
202         /* RAM buffer address within RAM */
203         if (ram_addr > (part->ram_base + part->ram_size)) {
204                 printf("Invalid configuration, asked to use buffer out of RAM, aborting.\n");
205                 return -1;
206         }
207         if (trace_on) {
208                 printf("flash size : 0x%08x, nb sectors : %d\n", part->flash_size, part->flash_nb_sectors);
209         }
210         /* Calc write block size */
211         write_size = calc_write_size(sector_size, part->ram_buff_size);
212         if (write_size == 0) {
213                 printf("Config error, I cannot flash using blocks of nul size !\nAborted.\n");
214                 return -2;
215         } else if (trace_on) {
216                 printf("write size : %d\n", write_size);
217         }
219         /* Just make sure flash is erased */
220         ret = erase_flash(part);
221         if (ret != 0) {
222                 printf("Unable to erase device, aborting.\n");
223                 return -3;
224         }
226         /* Allocate a buffer as big as the flash */
227         data = malloc(part->flash_size);
228         if (data == NULL) {
229                 printf("Unable to get a buffer to load the image!");
230                 return -4;
231         }
232         /* And fill the buffer with the image */
233         size = isp_file_to_buff(data, part->flash_size, filename);
234         if (size <= 0){
235                 free(data);
236                 return -5;
237         }
238         /* Fill unused buffer with 0's so we can flash blocks of data of "write_size" */
239         memset(&data[size], 0, (part->flash_size - size));
240         /* And check checksum of first 7 vectors if asked, according to section 21.3.3 of
241          * LPC11xx user's manual (UM10398) */
242         v = (uint32_t *)data;
243         cksum = 0 - v[0] - v[1] - v[2] - v[3] - v[4] - v[5] - v[6];
244         if (calc_user_code == 1) {
245                 v[7] = cksum;
246         } else if (cksum != v[7]) {
247                 printf("Checksum is 0x%08x, should be 0x%08x\n", v[7], cksum);
248                 free(data);
249                 return -5;
250         }
251         printf("Checksum check OK\n");
253         crp = v[(CRP_OFFSET / 4)];
254         if ((crp == CRP_NO_ISP) || (crp == CRP_CRP1) || (crp == CRP_CRP2) || (crp == CRP_CRP3)) {
255                 printf("CRP : 0x%08x\n", crp);
256                 printf("The binary has CRP protection ativated, which violates GPLv3.\n");
257                 printf("Check the licence for the software you are using, and if this is allowed,\n");
258                 printf(" then modify this software to allow flashing of code with CRP protection\n");
259                 printf(" activated. (Or use another software).\n");
260                 return -6;
261         }
263         blocks = (size / write_size) + ((size % write_size) ? 1 : 0);
264         /* Gonna write out of flash ? */
265         if ((blocks * write_size) > part->flash_size) {
266                 printf("Config error, I cannot flash beyond end of flash !\n");
267                 printf("Flash size : %d, trying to flash %d blocks of %d bytes : %d\n",
268                                 part->flash_size, blocks, write_size, (blocks * write_size));
269                 free(data);
270                 return -7;
271         }
272         printf("Flash size : %d, trying to flash %d blocks of %d bytes : %d\n",
273                         part->flash_size, blocks, write_size, (blocks * write_size));
275         /* Now flash the device */
276         printf("Writing started, %d blocks of %d bytes ...\n", blocks, write_size);
277         for (i=0; i<blocks; i++) {
278                 unsigned int current_sector = (i * write_size) / sector_size;
279                 uint32_t flash_addr = part->flash_base + (i * write_size);
280                 /* Prepare sector for writting (must be done before each write) */
281                 ret = isp_send_cmd_sectors("prepare-for-write", 'P', current_sector, current_sector, 1);
282                 if (ret != 0) {
283                         printf("Error (%d) when trying to prepare sector %d for erase operation!\n", ret, i);
284                         free(data);
285                         return ret;
286                 }
287                 /* Send data to RAM */
288                 ret = isp_send_buf_to_ram(&data[i * write_size], ram_addr, write_size, uuencode);
289                 if (ret != 0) {
290                         printf("Unable to perform write-to-ram operation for block %d (block size: %d)\n",
291                                         i, write_size);
292                         free(data);
293                         return ret;
294                 }
295                 /* Copy from RAM to FLASH */
296                 ret = isp_send_cmd_address('C', flash_addr, ram_addr, write_size, "write_to_ram");
297                 if (ret != 0) {
298                         printf("Unable to copy data to flash for block %d (block size: %d)\n", i, write_size);
299                         free(data);
300                         return ret;
301                 }
302         }
304         if (ret == 0) {
305                 printf("Done, binary has been written to internal flash.\n");
306         }
308         free(data);
309         return ret;