blob: 883169442e1e61d39bca05d5f724da7eaddfcebb [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*******************************************************************************
2 * Copyright (C) 2016, ZIXC Corporation.
3 *
4 * File Name:cmd_set.c
5 * File Mark:
6 * Description:
7 * Others:
8 * Version: 1.0
9 * Author: zangxiaofeng
10 * Date: 2013-6-8
11 * History 1:
12 * Date:
13 * Version:
14 * Author:
15 * Modification:
16 * History 2:
17 ********************************************************************************/
18/****************************************************************************
19* Include files
20****************************************************************************/
21#include <common.h>
22#include <command.h>
23#include <net.h>
24#include <jffs2/load_kernel.h>
25#include <nand.h>
26#include <linux/mtd/spi-nor.h>
27#include <linux/mtd/nor_spifc.h>
28
29#include "downloader_config.h"
30#include "downloader_nand.h"
31#include "downloader_serial.h"
32#include "errno.h"
33#include "boot_mode.h"
34
35
36#define ZLOAD_PARTITION_SIZE 0x3000
37
38
39/****************************************************************************
40* Global Function Prototypes
41****************************************************************************/
42extern partition_table_t * g_partition_table;
43int set_partitions(unsigned int size);
44partition_entry_t * get_partitions(const char *partname, partition_table_t *table);
45
46partition_table_t * g_partition_table_dl = NULL;
47
48extern char *tsp_console_buffer;
49extern struct fsl_qspi spi_nor_flash;
50
51
52/*******************************************************************************
53 * Function:do_set
54 * Description:
55 * Parameters:
56 * Input:
57 *
58 * Output:
59 *
60 * Returns:
61 *
62 *
63 * Others:
64 ********************************************************************************/
65int do_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
66{
67
68 char *par = NULL;
69 unsigned int size = 0;
70 unsigned int ret = 0;
71
72 if(argc<3)
73 {
74 return cmd_usage(cmdtp);
75 }
76 par = argv[1];
77 size = (unsigned int)simple_strtoul (argv[2], NULL, 16);
78
79 if(strcmp(par,"partitions") == 0)
80 {
81 sprintf(tsp_console_buffer,"OKAY RECV_TABLES");
82 downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
83 ret = set_partitions(size);
84 return ret;
85 }
86 else
87 {
88 sprintf(tsp_console_buffer,"FAIL COMMAND ERROR");
89 downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
90 return -1;
91 }
92
93
94}
95U_BOOT_CMD(
96 set, CONFIG_SYS_MAXARGS, 0, do_set,
97 "set : set [module] [size]",
98 ""
99);
100
xf.li6c8fc1e2023-08-12 00:11:09 -0700101static unsigned int gen_crc(char *pInput, int InputLen)
102{
103
104 char pOutput[4];
105 unsigned int *pcrc = (unsigned int *)pOutput;
106 int OutputLen = 4;
107 char *check = pOutput;
108 int i, j;
109 memcpy(check, pInput, OutputLen);
110 pInput += OutputLen;
111
112 for(i = 0; i < InputLen; i += OutputLen)
113 {
114 for(j = 0; j < OutputLen; j++)
115 {
116 check[j] ^= pInput[i + j];
117 }
118 }
119
120 return *pcrc;
121
122}
123
lh9ed821d2023-04-07 01:36:19 -0700124/*******************************************************************************
125 * Function:set_partitions
126 * Description:
127 * Parameters:
128 * Input:
129 *
130 * Output:
131 *
132 * Returns:
133 *
134 *
135 * Others:
136 ********************************************************************************/
137 int set_partitions(unsigned int size)
138{
139 partition_entry_t *part_nvr = NULL;
140 partition_entry_t *part_nvr_dl = NULL;
141 partition_table_t *table_dl = NULL;
142 char *table_new = (char*)(CONFIG_USB_DMA_BUF_ADDR); /*USB DMA BUFFER*/
xf.li6c8fc1e2023-08-12 00:11:09 -0700143 uint32_t crc_cal = 0;
lh9ed821d2023-04-07 01:36:19 -0700144
145 /* UE´ÓPC»ñÈ¡·ÖÇø±í */
146 downloader_serial_read_actuallen((char *)table_new, size);
147 table_dl = (partition_table_t *)table_new;
148
149 g_partition_table_dl = kzalloc(4096, GFP_KERNEL);
150 if(g_partition_table_dl == NULL)
151 {
152 printf("set_partitions kzalloc failed.\n");
153 return -1;
154 }
xf.li6c8fc1e2023-08-12 00:11:09 -0700155 /*·ÖÇø±ícrcУÑé*/
156 crc_cal = gen_crc(((unsigned char*)table_dl) + 32, table_dl->entrys * sizeof(partition_entry_t));
157
lh9ed821d2023-04-07 01:36:19 -0700158 memcpy(g_partition_table_dl,table_dl,size);
xf.li6c8fc1e2023-08-12 00:11:09 -0700159 if((table_dl->magic != PARTITION_MAGIC) || crc_cal != table_dl->crc)
lh9ed821d2023-04-07 01:36:19 -0700160 {
161 sprintf(tsp_console_buffer,"FAIL INVALID_PARTITION_TABLE");
162 downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
163 return -1;
164 }
165
166 /* ·ÖÇø±íÆ¥Åä»òûÓзÖÇø±í */
167 if(memcmp( g_partition_table, table_dl, sizeof(partition_table_t))==0
168 || g_partition_table->magic != PARTITION_MAGIC)
169 {
170 g_partition_table = g_partition_table_dl;
171 sprintf(tsp_console_buffer,"OKAY");
172 downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
173 return 0;
174 }
175 else
176 {
177 /* UE´ÓPC»ñÈ¡NV·ÖÇøÐÅÏ¢ */
178 part_nvr_dl = get_partitions("nvrofs", table_dl);
179 if(part_nvr_dl == NULL)
180 {
181 printf("pc part nvrofs get failed.\n");
182 return -1;
183 }
184
185 /* ´ÓUEµÄNAND¶ÁÈ¡NV·ÖÇøÐÅÏ¢ */
186 part_nvr = get_partitions("nvrofs", g_partition_table);
187 if(part_nvr == NULL)
188 {
189 printf("part_nvrofs get failed.\n");
190 sprintf(tsp_console_buffer,"FAIL UNACCEPTABLE_PARTITION_CHANGE");
191 downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
192 return -1;
193 }
194
195 if((part_nvr->part_offset == part_nvr_dl->part_offset)
196 &&(part_nvr->part_size == part_nvr_dl->part_size))
197 {
198 sprintf(tsp_console_buffer,"FAIL ACCEPTABLE_PARTITION_CHANGE");
199 downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
200 return 0;
201 }
202 else
203 {
204 sprintf(tsp_console_buffer,"FAIL UNACCEPTABLE_PARTITION_CHANGE");
205 downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
206 return -1;
207 }
208 }
209}
210
211/*******************************************************************************
212 * Function:get_partitions
213 * Description:
214 * Parameters:
215 * Input:
216 *
217 * Output:
218 *
219 * Returns:
220 *
221 *
222 * Others:
223 ********************************************************************************/
224 partition_entry_t * get_partitions(const char *partname, partition_table_t *table)
225{
226
227 partition_entry_t *entry = &table->table[0];
228 uint32_t entry_nums = table->entrys;
229 while( entry_nums-- )
230 {
231 if ( strcmp((const char *)entry->part_name,partname) == 0 )
232 return entry;
233 entry++;
234 }
235 return NULL;
236}
237
238/*******************************************************************************
239 * Function:set_nand_dlflag
240 * Description: open or close USB DL PORT, based on nand
241 * dl on :open DL port ; dl off :close DL port
242 * Parameters:
243 * Input:
244 *
245 * Output:
246 *
247 * Returns:
248 *
249 *
250 * Others:
251 ********************************************************************************/
252 int set_nand_dlflag( char * sign)
253{
254 char value = 0;
255 int bootflag = 0;
256 int times = 0;
257 int i =0;
258 int ret = 0;
259 struct erase_info ei;
260 nand_info_t *nand = &nand_info[nand_curr_device];
261
262 u_char *buffer = kzalloc(6*(nand->writesize + nand->oobsize),GFP_KERNEL);
263 u_char *p_buffer = buffer;
264
265 if( buffer == NULL )
266 return 1;
267
268 times = 12*1024/nand->writesize;
269 for(i=0;i<times;i++)
270 {
271 nand_read_page_with_ecc(nand,
272 ((loff_t)i*nand->writesize),
273 0,
274 p_buffer);
275 p_buffer += nand->writesize;
276 }
277
278 if (strcmp((const char *)sign,"on") == 0)
279 {
280 bootflag = 0x00;
281 memset(&value, bootflag, 1);
282 }
283 else if (strcmp((const char *)sign,"off") == 0)
284 {
285 bootflag = 0x5a;
286 memset(&value, bootflag, 1);
287 }
288 memcpy(buffer+2, &value, 1);
289
290 memset(&ei, 0, sizeof(struct erase_info));
291 ei.mtd = nand;
292 ei.addr = (uint64_t)(0);
293 ei.len = (uint64_t)nand->erasesize;
294 ret = nand->erase(nand, &ei); /*²Á³ýµÚÒ»¿é*/
295
296 p_buffer = buffer;
297
298 for(i=0;i<times;i++)
299 {
300 nand_write_page_with_ecc(nand, ((loff_t)i*nand->writesize), p_buffer);
301 p_buffer += nand->writesize;
302 }
303
304 sprintf(tsp_console_buffer,"DL OKAY");
305 downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
306
307 kfree(buffer);
308
309 return 0;
310
311}
312
313
314/*******************************************************************************
315 * Function:set_nor_dlflag
316 * Description: open or close USB DL PORT, based on nand
317 * dl on :open DL port ; dl off :close DL port
318 * Parameters:
319 * Input:
320 *
321 * Output:
322 *
323 * Returns:
324 *
325 *
326 * Others:
327 ********************************************************************************/
328 int set_nor_dlflag(char *sign)
329{
330 int ret = 0;
331 char value = 0;
332 int bootflag = 0;
333 uint32_t load_addr = 0x0;
334 uint32_t size_read = ZLOAD_PARTITION_SIZE;
335 uint32_t size_write = ZLOAD_PARTITION_SIZE;
336 struct fsl_qspi *nor = &spi_nor_flash;
337 u_char *buffer = kzalloc(ZLOAD_PARTITION_SIZE,GFP_KERNEL);
338
339 if(buffer == NULL)
340 {
341 return -1;
342 }
343
344 ret = nand_read(&(nor->nor[0].mtd), load_addr, &size_read, buffer);
345 if(ret != 0)
346 {
347 printf("nand_read error.\n");
348 return -1;
349 }
350
351 if (strcmp((const char *)sign,"on") == 0)
352 {
353 bootflag = 0x00;
354 memset(&value, bootflag, 1);
355 }
356 else if (strcmp((const char *)sign,"off") == 0)
357 {
358 bootflag = 0x5a;
359 memset(&value, bootflag, 1);
360 }
361 memcpy(buffer+2, &value, 1);
362
363 ret = nand_erase(&(nor->nor[0].mtd), load_addr, nor->nor[0].mtd.erasesize);
364 if(ret != 0)
365 {
366 printf("nand_erase error.\n");
367 return -1;
368 }
369
370 ret = nand_write(&(nor->nor[0].mtd), load_addr, &size_write, buffer);
371 if(ret != 0)
372 {
373 printf("nand_write error.\n");
374 return -1;
375 }
376
377 sprintf(tsp_console_buffer,"DL OKAY");
378 downloader_serial_write(tsp_console_buffer, strlen(tsp_console_buffer)+1);
379
380 kfree(buffer);
381
382 return 0;
383}
384
385
386/*******************************************************************************
387 * Function:do_dlflag
388 * Description: open or close USB DL PORT,
389 * dl on :open DL port ; dl off :close DL port
390 * Parameters:
391 * Input:
392 *
393 * Output:
394 *
395 * Returns:
396 *
397 *
398 * Others:
399 ********************************************************************************/
400int do_dlflag(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
401{
402 int ret = 0;
403 u_char *sign = NULL;
404 int type = 0;
405
406 if(argc<2)
407 {
408 return cmd_usage(cmdtp);
409 }
410 sign = argv[1];
411 type = read_boot_flashtype();
412
413 if(type == IF_TYPE_NAND || type == IF_TYPE_SPI_NAND)
414 {
415 ret = set_nand_dlflag(sign);
416 }
417 else if(type == IF_TYPE_NOR)
418 {
419 ret = set_nor_dlflag(sign);
420 }
421
422 if(ret != 0)
423 {
424 return -1;
425 }
426
427 return 0;
428
429}
430U_BOOT_CMD(
431 dl, CONFIG_SYS_MAXARGS, 0, do_dlflag,
432 "dl : dl [sign]",
433 ""
434);