c3835a9c6e212d76d33919f4c91e4d2223e4f137
[keystone-rtos/mcsdk-tools.git] / writer / nor / src / norwriter.c
1 /*\r
2  * Copyright (c) 2011-2015, Texas Instruments Incorporated\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  * *  Redistributions of source code must retain the above copyright\r
10  *    notice, this list of conditions and the following disclaimer.\r
11  *\r
12  * *  Redistributions in binary form must reproduce the above copyright\r
13  *    notice, this list of conditions and the following disclaimer in the\r
14  *    documentation and/or other materials provided with the distribution.\r
15  *\r
16  * *  Neither the name of Texas Instruments Incorporated nor the names of\r
17  *    its contributors may be used to endorse or promote products derived\r
18  *    from this software without specific prior written permission.\r
19  *\r
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31  *\r
32  */\r
33 \r
34 /**************************************************************************************\r
35  * FILE PURPOSE: NOR writer utility\r
36  **************************************************************************************\r
37  * FILE NAME: norwriter.c\r
38  *\r
39  * DESCRIPTION: A simple nor writer using platform lib APIs to program the NOR flash\r
40  *              with an image that the ibl can read.\r
41  *\r
42  ***************************************************************************************/\r
43 #include <stdlib.h>\r
44 #include <stdio.h>\r
45 #include <string.h>\r
46 #include "platform.h"\r
47 #include "types.h"\r
48 \r
49 /* NOR writer utility version */\r
50 char version[] = "01.00.00.04";\r
51 \r
52 /* The input file name is hard coded */\r
53 char *input_file = "nor_writer_input.txt";\r
54 \r
55 uint32_t swap_byte = 0;\r
56 \r
57 /* Parameters defined in the input_file */\r
58 #define FILE_NAME      "file_name"\r
59 #define START_ADDR     "start_addr"\r
60 \r
61 /* Memory address to store the write data */\r
62 #define WRITE_DATA_ADDRESS     0x80000000\r
63 \r
64 /******************************************************************************\r
65  * Structure:   NOR_WRITER_INFO_T\r
66  *\r
67  *              NOR writer control data. This structure should be filled in\r
68  *              by the user before running\r
69  ******************************************************************************/\r
70 #define MAX_LINE_LENGTH 40\r
71 typedef struct NOR_WRITER_INFO_tag\r
72 {\r
73     char        file_name[MAX_LINE_LENGTH]; /* CCS format data file name */\r
74     uint32_t    blockSizeBytes;             /* The size of each sector */\r
75     uint32_t    deviceTotalBytes;           /* Total number of bytes available in the device */\r
76     uint32_t    startAddr;                  /* Start address to write */\r
77     uint32_t    writeBytes;                 /* Number of bytes to be written into the device */\r
78     uint8_t     *writeData;                 /* Address to store the write data */\r
79     uint8_t     *readData;                  /* Address to store the read data */\r
80 \r
81 } NOR_WRITER_INFO_T;\r
82 \r
83 NOR_WRITER_INFO_T norWriterInfo;\r
84 \r
85 /* OSAL functions for Platform Library */\r
86 uint8_t *Osal_platformMalloc (uint32_t num_bytes, uint32_t alignment)\r
87 {\r
88         return malloc(num_bytes);\r
89 }\r
90 \r
91 void Osal_platformFree (uint8_t *dataPtr, uint32_t num_bytes)\r
92 {\r
93     /* Free up the memory */\r
94     if (dataPtr)\r
95     {\r
96         free(dataPtr);\r
97     }\r
98 }\r
99 \r
100 void Osal_platformSpiCsEnter(void)\r
101 {\r
102     return;\r
103 }\r
104 \r
105 void Osal_platformSpiCsExit (void)\r
106 {\r
107     return;\r
108 }\r
109 \r
110 /******************************************************************************\r
111  * Function:    print_platform_errno\r
112  ******************************************************************************/\r
113 void\r
114 print_platform_errno\r
115 (\r
116     void\r
117 )\r
118 {\r
119     printf ("Returned platform error number is %d\n", platform_errno);\r
120 }\r
121 \r
122 /******************************************************************************\r
123  * Function:    formBlock\r
124  *\r
125  *      Form a block of data to write to the NOR. The block is\r
126  *      created as a byte stream from the 4 byte stream in which\r
127  *      the MSB is always sent first.\r
128  ******************************************************************************/\r
129 void\r
130 formBlock\r
131 (\r
132     uint32_t      *data,\r
133     uint32_t      blockSize,\r
134     uint8_t       *scratch\r
135 )\r
136 {\r
137     uint32_t i, j;\r
138     \r
139     /* Convert the data to a byte stream */\r
140     for (i = j = 0; j < blockSize; i++, j+=4)\r
141     {\r
142         scratch[j+0] = (data[i] >> 24) & 0xff;\r
143         scratch[j+1] = (data[i] >> 16) & 0xff;\r
144         scratch[j+2] = (data[i] >>  8) & 0xff;\r
145         scratch[j+3] = (data[i] >>  0) & 0xff;\r
146     }\r
147 }\r
148 \r
149 /******************************************************************************\r
150  * Function:    flash_nor\r
151  *\r
152  *              Write the image to flash.\r
153  *              Returns TRUE if the image is written successfully\r
154  *                      FALSE if the image write fails\r
155  ******************************************************************************/\r
156 Bool\r
157 flash_nor\r
158 (\r
159     PLATFORM_DEVICE_info    *p_device\r
160 )\r
161 {\r
162     uint32_t      wPos, wLen;\r
163     uint32_t      block, start_block;\r
164     uint8_t       *scrach_block;\r
165 \r
166     if (swap_byte)\r
167     {\r
168         scrach_block = malloc(norWriterInfo.blockSizeBytes);\r
169         if (scrach_block == NULL)\r
170         {\r
171             printf ("Can not allocate scratch block memory!\n");\r
172             return (FALSE);\r
173         }\r
174     }\r
175 \r
176     start_block = norWriterInfo.startAddr / norWriterInfo.blockSizeBytes;\r
177 \r
178     /* Program the NOR */\r
179     for (block = start_block, wPos = 0; wPos < norWriterInfo.writeBytes; block++, wPos += norWriterInfo.blockSizeBytes)\r
180     {\r
181         printf ("Flashing sector %d (%d bytes of %d)\n", block, wPos, norWriterInfo.writeBytes);\r
182 \r
183         wLen = norWriterInfo.blockSizeBytes;\r
184         if (norWriterInfo.writeBytes - wPos < norWriterInfo.blockSizeBytes)\r
185         {\r
186             wLen = norWriterInfo.writeBytes - wPos;\r
187         }\r
188 \r
189         if (swap_byte)\r
190         {\r
191             formBlock((uint32_t *)(&norWriterInfo.writeData[wPos]), norWriterInfo.blockSizeBytes, scrach_block);\r
192         }\r
193         else\r
194         {\r
195             scrach_block = &norWriterInfo.writeData[wPos];\r
196         }\r
197         if (platform_device_write(p_device->handle,\r
198                                   block*norWriterInfo.blockSizeBytes,\r
199                                   scrach_block,\r
200                                   wLen) != Platform_EOK)\r
201         {\r
202             printf ("platform_nor_write sector # %d failed!\n", block);\r
203             print_platform_errno();\r
204             if (swap_byte) free (scrach_block);\r
205             return (FALSE);\r
206         }\r
207     }\r
208 \r
209     if (swap_byte) free (scrach_block);\r
210     return (TRUE);\r
211 }\r
212 \r
213 /******************************************************************************\r
214  * Function:    flash_verify\r
215  *\r
216  *              Read back the data file that was just flashed. On errors mark the block as bad.\r
217  *              Returns TRUE if the image verified correctly.\r
218  *                      FALSE if the image verification failed\r
219  ******************************************************************************/\r
220 Bool\r
221 flash_verify\r
222 (\r
223     PLATFORM_DEVICE_info    *p_device\r
224 )\r
225 {\r
226     uint32_t      rPos, rLen;\r
227     uint32_t      i, j;\r
228     uint32_t      block, start_block;\r
229     uint8_t       *scrach_block;\r
230     uint32_t      *read_data_w;\r
231 \r
232     if (swap_byte) \r
233     {\r
234         scrach_block = malloc(norWriterInfo.blockSizeBytes);\r
235         if (scrach_block == NULL)\r
236         {\r
237             printf ("Can not allocate scratch block memory!\n");\r
238             return (FALSE);\r
239         }\r
240     }\r
241 \r
242     start_block = norWriterInfo.startAddr / norWriterInfo.blockSizeBytes;\r
243 \r
244     for (block = start_block, rPos = 0; rPos < norWriterInfo.writeBytes; block++, rPos += norWriterInfo.blockSizeBytes)\r
245     {\r
246         printf ("Reading and verifying sector %d (%d bytes of %d)\n", block, rPos, norWriterInfo.writeBytes);\r
247 \r
248         if (!swap_byte)\r
249         {\r
250             scrach_block = &norWriterInfo.readData[rPos];\r
251 \r
252         }\r
253         /* Read a sector of data */\r
254         if(platform_device_read(p_device->handle,\r
255                                 block*norWriterInfo.blockSizeBytes,\r
256                                 scrach_block,\r
257                                 norWriterInfo.blockSizeBytes) != Platform_EOK)\r
258         {\r
259             printf ("Failure in sector %d\n", block);\r
260             print_platform_errno();\r
261             if (swap_byte) free (scrach_block);\r
262             return (FALSE);\r
263         }\r
264 \r
265         /* Convert the packed data */\r
266         if (swap_byte)\r
267         {\r
268             read_data_w = (uint32_t *)(&norWriterInfo.readData[rPos]);\r
269             for  (i = 0, j = 0; i < norWriterInfo.blockSizeBytes; i += 4)\r
270                 read_data_w[j++] = (scrach_block[i+0] << 24) | (scrach_block[i+1] << 16) | (scrach_block[i+2] << 8) | scrach_block[i+3];\r
271         }\r
272 \r
273         /* Read the data from the file */\r
274         rLen = norWriterInfo.blockSizeBytes;\r
275         if (norWriterInfo.writeBytes - rPos < norWriterInfo.blockSizeBytes)\r
276         {\r
277             rLen = norWriterInfo.writeBytes - rPos;\r
278         }\r
279 \r
280         for (i = rPos; i < rLen; i++)\r
281         {\r
282             if (norWriterInfo.readData[i] != norWriterInfo.writeData[i])\r
283             {\r
284                 printf ("Failure in sector %d, at byte %d, (at byte %d in the data file) expected 0x%08x, read 0x%08x\n",\r
285                         block, i, rPos, norWriterInfo.writeData[i], norWriterInfo.readData[i]);\r
286                 if (swap_byte) free (scrach_block);\r
287                 return (FALSE);\r
288             }\r
289         }\r
290 \r
291     }\r
292 \r
293     if (swap_byte) free (scrach_block);\r
294     return (TRUE);\r
295 }\r
296 \r
297 /******************************************************************************\r
298  * Function:    parse_input_file\r
299  ******************************************************************************/\r
300 static Bool\r
301 parse_input_file\r
302 (\r
303     FILE*               fp\r
304 )\r
305 {\r
306     char line[MAX_LINE_LENGTH];\r
307     char tokens[] = " :=;\n\r";\r
308     char *key, *data;\r
309 \r
310     memset(line, 0, MAX_LINE_LENGTH);\r
311 \r
312     fgets(line, MAX_LINE_LENGTH, fp);\r
313     key  = (char *)strtok(line, tokens);\r
314     data = (char *)strtok(NULL, tokens);\r
315 \r
316     if(strlen(data) == 0)\r
317     {\r
318        return FALSE;\r
319     }\r
320 \r
321     if(strcmp(key, FILE_NAME) != 0)\r
322     {\r
323         return FALSE;\r
324     }\r
325 \r
326     strcpy (norWriterInfo.file_name, data);\r
327 \r
328     fgets(line, MAX_LINE_LENGTH, fp);\r
329     key  = (char *)strtok(line, tokens);\r
330     data = (char *)strtok(NULL, tokens);\r
331 \r
332     if(strlen(data) == 0)\r
333     {\r
334        return FALSE;\r
335     }\r
336 \r
337     if(strcmp(key, START_ADDR) != 0)\r
338     {\r
339         return FALSE;\r
340     }\r
341 \r
342     norWriterInfo.startAddr = (uint32_t)atoi(data);\r
343 \r
344     return TRUE;\r
345 }\r
346 \r
347 /******************************************************************************\r
348  * Function:    find_file_length\r
349  ******************************************************************************/\r
350 static Bool\r
351 find_file_length\r
352 (\r
353     FILE*               fp\r
354 )\r
355 {\r
356     char        line[MAX_LINE_LENGTH];\r
357     char        *pEnd;\r
358     char        *ext;\r
359     uint32_t    data_len, write_addr;\r
360 \r
361     memset(line, 0, MAX_LINE_LENGTH);\r
362 \r
363     ext = strrchr(norWriterInfo.file_name, '.');\r
364 \r
365 \r
366     if (ext && (strcmp(ext, ".dat") == 0))\r
367     {\r
368     fgets(line, MAX_LINE_LENGTH, fp);\r
369 \r
370     /* Read the write address from the CCS header */\r
371     strtoul (line,&pEnd,16);\r
372     strtoul (pEnd,&pEnd,16);\r
373     write_addr = strtoul (pEnd,&pEnd,16);\r
374     strtoul (pEnd,&pEnd,16);\r
375 \r
376     /* Read the data length */\r
377     data_len = (strtoul (pEnd,NULL,16)) * 4;\r
378     }\r
379     else\r
380     {\r
381         /* find the data length by seeking to the end and getting position */\r
382         fseek(fp, 0, SEEK_END);\r
383         data_len = ftell(fp);\r
384         fseek(fp, 0, SEEK_SET);\r
385     }\r
386 \r
387     if (data_len > (norWriterInfo.deviceTotalBytes - norWriterInfo.startAddr))\r
388     {\r
389         printf ("The data file is too big to fit into the device.\n");\r
390         return FALSE;\r
391     }\r
392 \r
393     norWriterInfo.writeBytes = data_len;\r
394     if (write_addr != WRITE_DATA_ADDRESS)\r
395         write_addr = WRITE_DATA_ADDRESS;\r
396     norWriterInfo.writeData  = (uint8_t *)write_addr;\r
397     norWriterInfo.readData   = (uint8_t *)(write_addr + norWriterInfo.deviceTotalBytes);\r
398 \r
399     return TRUE;\r
400 }\r
401 \r
402 /******************************************************************************\r
403  * Function:    main\r
404  ******************************************************************************/\r
405 void main ()\r
406 {\r
407     FILE                    *fp;\r
408     platform_init_flags     init_flags;\r
409     platform_init_config    init_config;\r
410     PLATFORM_DEVICE_info    *p_device;\r
411     Bool                    ret;\r
412 \r
413     printf("NOR Writer Utility Version %s\n\n", version);\r
414 \r
415     fp = fopen(input_file, "r");\r
416     if (fp == NULL)\r
417     {\r
418         printf("Error in opening %s input file\n", input_file);\r
419         return;\r
420     }\r
421 \r
422     ret = parse_input_file(fp);\r
423     fclose (fp);\r
424 \r
425     if (ret == FALSE)\r
426     {\r
427         printf("Error in parsing %s input file\n", input_file);\r
428         return;\r
429     }\r
430 \r
431     /* Initialize main Platform lib */\r
432     memset(&init_config, 0, sizeof(platform_init_config));\r
433     memset(&init_flags, 1, sizeof(platform_init_flags));\r
434     init_flags.pll = 0;\r
435     init_flags.ddr = 0;\r
436     init_flags.phy = 0;\r
437     if (platform_init(&init_flags, &init_config) != Platform_EOK)\r
438     {\r
439         printf ("Platform init failed!\n");\r
440         print_platform_errno();\r
441         return;\r
442     }\r
443 #if !(defined(_EVMC6657L_))\r
444 \r
445 #if (defined(DEVICE_K2G))\r
446     p_device = platform_device_open(PLATFORM_DEVID_NORN25Q128A13ESF40F, 0);\r
447 #else\r
448     p_device = platform_device_open(PLATFORM_DEVID_NORN25Q128, 0);\r
449 #endif\r
450 \r
451 #else\r
452     p_device = platform_device_open(PLATFORM_DEVID_NORN25Q032A, 0);\r
453 #endif\r
454     if (p_device == NULL)\r
455     {\r
456         printf ("NOR device open failed!\n");\r
457         print_platform_errno();\r
458         return;\r
459     }\r
460     norWriterInfo.deviceTotalBytes  = p_device->block_count * p_device->page_count * p_device->page_size;\r
461     norWriterInfo.blockSizeBytes    = p_device->page_count * p_device->page_size;\r
462 \r
463     if ((norWriterInfo.startAddr % norWriterInfo.blockSizeBytes) != 0)\r
464     {\r
465         printf ("The start programming address 0x%8x set in %s is not at the beginning of a block, block size = 0x%4x\n",\r
466                 norWriterInfo.startAddr,\r
467                 norWriterInfo.file_name,\r
468                 norWriterInfo.blockSizeBytes);\r
469         return;\r
470     }\r
471 \r
472     /* Open and find the length of the data file */\r
473     fp = fopen (norWriterInfo.file_name, "rb");\r
474     if (fp == NULL)\r
475     {\r
476       printf ("Failed to open file %s\n", norWriterInfo.file_name);\r
477       platform_device_close(p_device->handle);\r
478       return;\r
479     }\r
480 \r
481     /* Parse the CCS format file */\r
482     ret = find_file_length(fp);\r
483     fclose (fp);\r
484     \r
485     norWriterInfo.writeBytes += norWriterInfo.blockSizeBytes - 1;\r
486     norWriterInfo.writeBytes -= norWriterInfo.writeBytes % norWriterInfo.blockSizeBytes;\r
487     \r
488     if (ret == FALSE)\r
489     {\r
490         printf("Error in parsing CCS file %s\n", norWriterInfo.file_name);\r
491         platform_device_close(p_device->handle);\r
492         return;\r
493     }\r
494 \r
495     /* Write the flash */\r
496     if (flash_nor (p_device) == FALSE)\r
497     {\r
498         printf ("NOR write failed\n");\r
499         platform_device_close(p_device->handle);\r
500         return;\r
501     }\r
502 \r
503     /* verify the flash */\r
504     if(flash_verify (p_device) == FALSE)\r
505     {\r
506         printf ("NOR read verify failed\n");\r
507         platform_device_close(p_device->handle);\r
508         return;\r
509     }\r
510 \r
511 \r
512     printf ("NOR programming completed successfully\n");\r
513 \r
514     platform_device_close(p_device->handle);\r
515 \r
516     return;\r
517 }\r
518 \r
519 \r
520 \r
521 \r