usbboot/src/cmd.c |
31 | 31 | #include "ingenic_usb.h" |
32 | 32 | #include "usb_boot_defines.h" |
33 | 33 | |
34 | | extern int com_argc; |
35 | | extern char com_argv[MAX_ARGC][MAX_COMMAND_LENGTH]; |
36 | | |
37 | | struct ingenic_dev ingenic_dev; |
38 | 34 | struct hand hand; |
39 | 35 | struct sdram_in sdram_in; |
40 | | struct nand_in nand_in; |
41 | | static struct nand_out nand_out; |
42 | 36 | |
43 | 37 | unsigned int total_size; |
44 | | unsigned char code_buf[4 * 512 * 1024]; |
45 | | unsigned char check_buf[4 * 512 * 1024]; |
46 | | unsigned char cs[16]; |
47 | | unsigned char ret[8]; |
| 38 | static char code_buf[4 * 512 * 1024]; |
| 39 | static char ret[8]; |
48 | 40 | |
49 | | static const char IMAGE_TYPE[][30] = { |
50 | | "with oob and ecc", |
51 | | "with oob and without ecc", |
52 | | "without oob", |
53 | | }; |
54 | 41 | |
55 | 42 | static int load_file(struct ingenic_dev *ingenic_dev, const char *file_path) |
56 | 43 | { |
... | ... | |
78 | 65 | |
79 | 66 | status = read(fd, ingenic_dev->file_buff, ingenic_dev->file_len); |
80 | 67 | |
81 | | if (status < ingenic_dev->file_len) { |
| 68 | if (status < (int)ingenic_dev->file_len) { |
82 | 69 | fprintf(stderr, "Error - can't read file '%s': %s\n", |
83 | 70 | file_path, strerror(errno)); |
84 | 71 | goto close; |
... | ... | |
97 | 84 | } |
98 | 85 | |
99 | 86 | /* after upload stage2. must init device */ |
100 | | void init_cfg() |
| 87 | void init_cfg(struct ingenic_dev *dev) |
101 | 88 | { |
102 | | if (usb_get_ingenic_cpu(&ingenic_dev) < 3) { |
| 89 | if (usb_get_ingenic_cpu(dev) < 3) { |
103 | 90 | printf(" XBurst CPU not booted yet, boot it first!\n"); |
104 | 91 | return; |
105 | 92 | } |
106 | 93 | |
107 | | ingenic_dev.file_buff = &hand; |
108 | | ingenic_dev.file_len = sizeof(hand); |
109 | | if (usb_send_data_to_ingenic(&ingenic_dev) != 1) |
| 94 | if (usb_send_data_to_ingenic(dev, (char*)&hand, sizeof(hand)) != 1) |
110 | 95 | goto xout; |
111 | 96 | |
112 | | if (usb_ingenic_configration(&ingenic_dev, DS_hand) != 1) |
| 97 | if (usb_ingenic_configration(dev, DS_hand) != 1) |
113 | 98 | goto xout; |
114 | 99 | |
115 | | if (usb_read_data_from_ingenic(&ingenic_dev, ret, 8) != 1) |
| 100 | if (usb_read_data_from_ingenic(dev, ret, 8) != 1) |
116 | 101 | goto xout; |
117 | 102 | |
118 | 103 | printf(" Configuring XBurst CPU succeeded.\n"); |
... | ... | |
121 | 106 | printf("Configuring XBurst CPU failed.\n"); |
122 | 107 | } |
123 | 108 | |
124 | | int boot(char *stage1_path, char *stage2_path){ |
| 109 | int boot(struct ingenic_dev *dev, const char *stage1_path, const char *stage2_path) |
| 110 | { |
125 | 111 | int status; |
126 | 112 | |
127 | | status = usb_get_ingenic_cpu(&ingenic_dev); |
| 113 | status = usb_get_ingenic_cpu(dev); |
128 | 114 | switch (status) { |
129 | 115 | case 1: /* Jz4740v1 */ |
130 | 116 | status = 0; |
... | ... | |
154 | 140 | |
155 | 141 | /* now we upload the boot stage1 */ |
156 | 142 | printf(" Loading stage1 from '%s'\n", stage1_path); |
157 | | if (load_file(&ingenic_dev, stage1_path) < 1) |
| 143 | if (load_file(dev, stage1_path) < 1) |
158 | 144 | return -1; |
159 | 145 | |
160 | | if (usb_ingenic_upload(&ingenic_dev, 1) < 1) |
| 146 | if (usb_ingenic_upload(dev, 1) < 1) |
161 | 147 | return -1; |
162 | 148 | |
163 | 149 | /* now we upload the boot stage2 */ |
164 | 150 | usleep(100); |
165 | 151 | printf(" Loading stage2 from '%s'\n", stage2_path); |
166 | | if (load_file(&ingenic_dev, stage2_path) < 1) |
| 152 | if (load_file(dev, stage2_path) < 1) |
167 | 153 | return -1; |
168 | 154 | |
169 | | if (usb_ingenic_upload(&ingenic_dev, 2) < 1) |
| 155 | if (usb_ingenic_upload(dev, 2) < 1) |
170 | 156 | return -1; |
171 | 157 | |
172 | 158 | printf(" Booted successfully!\n"); |
173 | 159 | } |
174 | 160 | usleep(100); |
175 | | init_cfg(); |
| 161 | init_cfg(dev); |
176 | 162 | return 1; |
177 | 163 | } |
178 | 164 | |
179 | | /* nand function */ |
180 | | int error_check(unsigned char *org,unsigned char * obj,unsigned int size) |
181 | | { |
182 | | unsigned int i; |
183 | | printf(" Comparing %d bytes - ", size); |
184 | | for (i = 0; i < size; i++) { |
185 | | if (org[i] != obj[i]) { |
186 | | unsigned int s = (i < 8) ? i : i - 8; // start_dump |
187 | | printf("FAIL at off %d, wrote 0x%x, read 0x%x\n", i, org[i], obj[i]); |
188 | | printf(" off %d write: %02x %02x %02x %02x %02x %02x %02x %02x" |
189 | | " %02x %02x %02x %02x %02x %02x %02x %02x\n", s, |
190 | | org[s], org[s+1], org[s+2], org[s+3], org[s+4], org[s+5], org[s+6], org[s+7], |
191 | | org[s+8], org[s+9], org[s+10], org[s+11], org[s+12], org[s+13], org[s+14], org[s+15]); |
192 | | printf(" off %d read: %02x %02x %02x %02x %02x %02x %02x %02x" |
193 | | " %02x %02x %02x %02x %02x %02x %02x %02x\n", s, |
194 | | obj[s], obj[s+1], obj[s+2], obj[s+3], obj[s+4], obj[s+5], obj[s+6], obj[s+7], |
195 | | obj[s+8], obj[s+9], obj[s+10], obj[s+11], obj[s+12], obj[s+13], obj[s+14], obj[s+15]); |
196 | | return 0; |
197 | | } |
198 | | } |
199 | | printf("SUCCESS\n"); |
200 | | return 1; |
201 | | } |
202 | | |
203 | | int nand_markbad(struct nand_in *nand_in) |
204 | | { |
205 | | if (usb_get_ingenic_cpu(&ingenic_dev) < 3) { |
206 | | printf(" Device unboot! Boot it first!\n"); |
207 | | return -1; |
208 | | } |
209 | | printf(" mark bad block : %d\n",nand_in->start); |
210 | | usb_send_data_address_to_ingenic(&ingenic_dev, nand_in->start); |
211 | | usb_ingenic_nand_ops(&ingenic_dev, NAND_MARK_BAD); |
212 | | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
213 | | printf(" Mark bad block at %d\n",((ret[3] << 24) | |
214 | | (ret[2] << 16) | |
215 | | (ret[1] << 8) | |
216 | | (ret[0] << 0)) / hand.nand_ppb); |
217 | | return 0; |
218 | | } |
219 | | |
220 | | int nand_program_check(struct nand_in *nand_in, |
221 | | struct nand_out *nand_out, |
222 | | unsigned int *start_page) |
223 | | { |
224 | | unsigned int i, page_num, cur_page = -1; |
225 | | unsigned short temp; |
226 | | |
227 | | printf(" Writing NAND page %d len %d...\n", nand_in->start, nand_in->length); |
228 | | if (nand_in->length > (unsigned int)MAX_TRANSFER_SIZE) { |
229 | | printf(" Buffer size too long!\n"); |
230 | | return -1; |
231 | | } |
232 | | |
233 | | #ifdef CONFIG_NAND_OUT |
234 | | unsigned char status_buf[32]; |
235 | | nand_out->status = status_buf; |
236 | | for (i = 0; i < nand_in->max_chip; i++) |
237 | | (nand_out->status)[i] = 0; /* set all status to fail */ |
238 | | #endif |
239 | | |
240 | | if (usb_get_ingenic_cpu(&ingenic_dev) < 3) { |
241 | | printf(" Device unboot! Boot it first!\n"); |
242 | | return -1; |
243 | | } |
244 | | ingenic_dev.file_buff = nand_in->buf; |
245 | | ingenic_dev.file_len = nand_in->length; |
246 | | usb_send_data_to_ingenic(&ingenic_dev); |
247 | | for (i = 0; i < nand_in->max_chip; i++) { |
248 | | if ((nand_in->cs_map)[i]==0) |
249 | | continue; |
250 | | if (nand_in->option == NO_OOB) { |
251 | | page_num = nand_in->length / hand.nand_ps; |
252 | | if ((nand_in->length % hand.nand_ps) !=0) |
253 | | page_num++; |
254 | | } else { |
255 | | page_num = nand_in->length / |
256 | | (hand.nand_ps + hand.nand_os); |
257 | | if ((nand_in->length% (hand.nand_ps + hand.nand_os)) !=0) |
258 | | page_num++; |
259 | | } |
260 | | temp = ((nand_in->option << 12) & 0xf000) + |
261 | | ((i<<4) & 0xff0) + NAND_PROGRAM; |
262 | | usb_send_data_address_to_ingenic(&ingenic_dev, nand_in->start); |
263 | | usb_send_data_length_to_ingenic(&ingenic_dev, page_num); |
264 | | usb_ingenic_nand_ops(&ingenic_dev, temp); |
265 | | |
266 | | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
267 | | printf(" Finish! (len %d start_page %d page_num %d)\n", |
268 | | nand_in->length, nand_in->start, page_num); |
269 | | |
270 | | usb_send_data_address_to_ingenic(&ingenic_dev, nand_in->start); |
271 | | /* Read back to check! */ |
272 | | usb_send_data_length_to_ingenic(&ingenic_dev, page_num); |
273 | | |
274 | | switch (nand_in->option) { |
275 | | case OOB_ECC: |
276 | | temp = ((OOB_ECC << 12) & 0xf000) + |
277 | | ((i << 4) & 0xff0) + NAND_READ; |
278 | | usb_ingenic_nand_ops(&ingenic_dev, temp); |
279 | | printf(" Checking %d bytes...", nand_in->length); |
280 | | usb_read_data_from_ingenic(&ingenic_dev, check_buf, |
281 | | page_num * (hand.nand_ps + hand.nand_os)); |
282 | | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
283 | | break; |
284 | | case OOB_NO_ECC: /* do not support data verify */ |
285 | | temp = ((OOB_NO_ECC << 12) & 0xf000) + |
286 | | ((i << 4) & 0xff0) + NAND_READ; |
287 | | usb_ingenic_nand_ops(&ingenic_dev, temp); |
288 | | printf(" Checking %d bytes...", nand_in->length); |
289 | | usb_read_data_from_ingenic(&ingenic_dev, check_buf, |
290 | | page_num * (hand.nand_ps + hand.nand_os)); |
291 | | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
292 | | break; |
293 | | case NO_OOB: |
294 | | temp = ((NO_OOB << 12) & 0xf000) + |
295 | | ((i << 4) & 0xff0) + NAND_READ; |
296 | | usb_ingenic_nand_ops(&ingenic_dev, temp); |
297 | | printf(" Checking %d bytes...", nand_in->length); |
298 | | usb_read_data_from_ingenic(&ingenic_dev, check_buf, |
299 | | page_num * hand.nand_ps); |
300 | | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
301 | | break; |
302 | | default: |
303 | | ; |
304 | | } |
305 | | |
306 | | cur_page = (ret[3] << 24) | (ret[2] << 16) | (ret[1] << 8) | |
307 | | (ret[0] << 0); |
308 | | |
309 | | #ifdef CONFIG_NAND_OUT |
310 | | (nand_out->status)[i] = 1; |
311 | | #endif |
312 | | |
313 | | if (nand_in->start < 1 && |
314 | | hand.nand_ps == 4096 && |
315 | | hand.fw_args.cpu_id == 0x4740) { |
316 | | printf(" no check! End at Page: %d\n", cur_page); |
317 | | continue; |
318 | | } |
319 | 165 | |
320 | | if (!nand_in->check(nand_in->buf, check_buf, nand_in->length)) { |
321 | | #ifdef CONFIG_NAND_OUT |
322 | | (nand_out->status)[i] = 0; |
323 | | #endif |
324 | | struct nand_in bad; |
325 | | // tbd: doesn't the other side skip bad blocks too? Can we just deduct 1 from cur_page? |
326 | | // tbd: why do we only mark a block as bad if the last page in the block was written? |
327 | | bad.start = (cur_page - 1) / hand.nand_ppb; |
328 | | if (cur_page % hand.nand_ppb == 0) |
329 | | nand_markbad(&bad); |
330 | | } |
331 | | |
332 | | printf(" End at Page: %d\n",cur_page); |
333 | | } |
334 | | |
335 | | *start_page = cur_page; |
336 | | return 0; |
337 | | } |
338 | | |
339 | | int nand_erase(struct nand_in *nand_in) |
| 166 | int debug_memory(struct ingenic_dev *dev, int obj, unsigned int start, unsigned int size) |
340 | 167 | { |
341 | | unsigned int start_blk, blk_num, end_block; |
342 | | int i; |
| 168 | char buffer[8], tmp; |
343 | 169 | |
344 | | start_blk = nand_in->start; |
345 | | blk_num = nand_in->length; |
346 | | if (start_blk > (unsigned int)NAND_MAX_BLK_NUM) { |
347 | | printf(" Start block number overflow!\n"); |
348 | | return -1; |
349 | | } |
350 | | if (blk_num > (unsigned int)NAND_MAX_BLK_NUM) { |
351 | | printf(" Length block number overflow!\n"); |
352 | | return -1; |
353 | | } |
354 | | |
355 | | if (usb_get_ingenic_cpu(&ingenic_dev) < 3) { |
356 | | printf(" Device unboot! Boot it first!\n"); |
357 | | return -1; |
358 | | } |
359 | | |
360 | | for (i = 0; i < nand_in->max_chip; i++) { |
361 | | if ((nand_in->cs_map)[i]==0) |
362 | | continue; |
363 | | printf(" Erasing No.%d device No.%d flash (start_blk %u blk_num %u)......\n", |
364 | | nand_in->dev, i, start_blk, blk_num); |
365 | | |
366 | | usb_send_data_address_to_ingenic(&ingenic_dev, start_blk); |
367 | | usb_send_data_length_to_ingenic(&ingenic_dev, blk_num); |
368 | | |
369 | | unsigned short temp = ((i << 4) & 0xff0) + NAND_ERASE; |
370 | | usb_ingenic_nand_ops(&ingenic_dev, temp); |
371 | | |
372 | | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
373 | | printf(" Finish!"); |
374 | | } |
375 | | end_block = ((ret[3] << 24) | |
376 | | (ret[2] << 16) | |
377 | | (ret[1] << 8) | |
378 | | (ret[0] << 0)) / hand.nand_ppb; |
379 | | printf(" Return: %02x %02x %02x %02x %02x %02x %02x %02x (position %d)\n", |
380 | | ret[0], ret[1], ret[2], ret[3], ret[4], ret[5], ret[6], ret[7], end_block); |
381 | | if (!hand.nand_force_erase) { |
382 | | /* not force erase, show bad block infomation */ |
383 | | printf(" There are marked bad blocks: %d\n", |
384 | | end_block - start_blk - blk_num ); |
385 | | } else { |
386 | | /* force erase, no bad block infomation can show */ |
387 | | printf(" Force erase, no bad block infomation!\n" ); |
388 | | } |
| 170 | (void)obj; |
389 | 171 | |
390 | | return 1; |
391 | | } |
392 | | |
393 | | int nand_program_file(struct nand_in *nand_in, |
394 | | struct nand_out *nand_out, |
395 | | char *fname) |
396 | | { |
397 | | |
398 | | int flen, m, j, k; |
399 | | unsigned int start_page = 0, page_num, code_len, offset, transfer_size; |
400 | | int fd, status; |
401 | | struct stat fstat; |
402 | | struct nand_in n_in; |
403 | | struct nand_out n_out; |
404 | | |
405 | | #ifdef CONFIG_NAND_OUT |
406 | | unsigned char status_buf[32]; |
407 | | nand_out->status = status_buf; |
408 | | for (i=0; i<nand_in->max_chip; i++) |
409 | | (nand_out->status)[i] = 0; /* set all status to fail */ |
410 | | #endif |
411 | | status = stat(fname, &fstat); |
412 | | |
413 | | if (status < 0) { |
414 | | fprintf(stderr, "Error - can't get file size from '%s': %s\n", |
415 | | fname, strerror(errno)); |
416 | | return -1; |
417 | | } |
418 | | flen = fstat.st_size; |
419 | | |
420 | | fd = open(fname, O_RDONLY); |
421 | | if (fd < 0) { |
422 | | fprintf(stderr, "Error - can't open file '%s': %s\n", |
423 | | fname, strerror(errno)); |
424 | | return -1; |
425 | | } |
426 | | |
427 | | printf(" Programing No.%d device, flen %d, start page %d...\n",nand_in->dev, flen, nand_in->start); |
428 | | n_in.start = nand_in->start / hand.nand_ppb; |
429 | | if (nand_in->option == NO_OOB) { |
430 | | if (flen % (hand.nand_ppb * hand.nand_ps) == 0) |
431 | | n_in.length = flen / (hand.nand_ps * hand.nand_ppb); |
432 | | else |
433 | | n_in.length = flen / (hand.nand_ps * hand.nand_ppb) + 1; |
434 | | } else { |
435 | | if (flen % (hand.nand_ppb * (hand.nand_ps + hand.nand_os)) == 0) |
436 | | n_in.length = flen / |
437 | | ((hand.nand_ps + hand.nand_os) * hand.nand_ppb); |
438 | | else |
439 | | n_in.length = flen / |
440 | | ((hand.nand_ps + hand.nand_os) * hand.nand_ppb) |
441 | | + 1; |
442 | | } |
443 | | /* printf(" length %d flen %d\n", n_in.length, flen); */ |
444 | | n_in.cs_map = nand_in->cs_map; |
445 | | n_in.dev = nand_in->dev; |
446 | | n_in.max_chip = nand_in->max_chip; |
447 | | if (nand_erase(&n_in) != 1) |
448 | | return -1; |
449 | | if (nand_in->option == NO_OOB) |
450 | | transfer_size = (hand.nand_ppb * hand.nand_ps); |
451 | | else |
452 | | transfer_size = (hand.nand_ppb * (hand.nand_ps + hand.nand_os)); |
453 | | |
454 | | m = flen / transfer_size; |
455 | | j = flen % transfer_size; |
456 | | printf(" Size to send %d, transfer_size %d\n", flen, transfer_size); |
457 | | printf(" Image type : %s\n", IMAGE_TYPE[nand_in->option]); |
458 | | printf(" It will cause %d times buffer transfer.\n", j == 0 ? m : m + 1); |
459 | | |
460 | | #ifdef CONFIG_NAND_OUT |
461 | | for (i = 0; i < nand_in->max_chip; i++) |
462 | | (nand_out->status)[i] = 1; /* set all status to success! */ |
463 | | #endif |
464 | | |
465 | | offset = 0; |
466 | | for (k = 0; k < m; k++) { |
467 | | if (nand_in->option == NO_OOB) |
468 | | page_num = transfer_size / hand.nand_ps; |
469 | | else |
470 | | page_num = transfer_size / (hand.nand_ps + hand.nand_os); |
471 | | |
472 | | code_len = transfer_size; |
473 | | status = read(fd, code_buf, code_len); |
474 | | if (status < code_len) { |
475 | | fprintf(stderr, "Error - can't read file '%s': %s\n", |
476 | | fname, strerror(errno)); |
477 | | return -1; |
478 | | } |
479 | | |
480 | | nand_in->length = code_len; /* code length,not page number! */ |
481 | | nand_in->buf = code_buf; |
482 | | if (nand_program_check(nand_in, &n_out, &start_page) == -1) |
483 | | return -1; |
484 | | |
485 | | if (start_page - nand_in->start > hand.nand_ppb) |
486 | | printf(" Skip a old bad block !\n"); |
487 | | nand_in->start = start_page; |
488 | | |
489 | | #ifdef CONFIG_NAND_OUT |
490 | | for (i = 0; i < nand_in->max_chip; i++) { |
491 | | (nand_out->status)[i] = (nand_out->status)[i] * |
492 | | (n_out.status)[i]; |
493 | | } |
494 | | #endif |
495 | | offset += code_len ; |
496 | | } |
497 | | |
498 | | if (j) { |
499 | | code_len = j; |
500 | | if (j % hand.nand_ps) |
501 | | j += hand.nand_ps - (j % hand.nand_ps); |
502 | | memset(code_buf, 0, j); /* set all to null */ |
503 | | |
504 | | status = read(fd, code_buf, code_len); |
505 | | |
506 | | if (status < code_len) { |
507 | | fprintf(stderr, "Error - can't read file '%s': %s\n", |
508 | | fname, strerror(errno)); |
509 | | return -1; |
510 | | } |
511 | | |
512 | | nand_in->length = j; |
513 | | nand_in->buf = code_buf; |
514 | | if (nand_program_check(nand_in, &n_out, &start_page) == -1) |
515 | | return -1; |
516 | | |
517 | | if (start_page - nand_in->start > hand.nand_ppb) |
518 | | printf(" Skip a old bad block !"); |
519 | | |
520 | | #ifdef CONFIG_NAND_OUT |
521 | | for (i=0; i < nand_in->max_chip; i++) { |
522 | | (nand_out->status)[i] = (nand_out->status)[i] * |
523 | | (n_out.status)[i]; |
524 | | } |
525 | | #endif |
526 | | } |
527 | | |
528 | | close(fd); |
529 | | return 1; |
530 | | } |
531 | | |
532 | | int nand_program_file_planes(struct nand_in *nand_in, |
533 | | struct nand_out *nand_out, |
534 | | char *fname) |
535 | | { |
536 | | printf(" not implement yet !\n"); |
537 | | return -1; |
538 | | } |
539 | | |
540 | | int init_nand_in(void) |
541 | | { |
542 | | nand_in.buf = code_buf; |
543 | | nand_in.check = error_check; |
544 | | nand_in.dev = 0; |
545 | | nand_in.cs_map = cs; |
546 | | memset(nand_in.cs_map, 0, MAX_DEV_NUM); |
547 | | |
548 | | nand_in.max_chip = 16; |
549 | | return 0; |
550 | | } |
551 | | |
552 | | int nand_prog(void) |
553 | | { |
554 | | char *image_file; |
555 | | char *help = " Usage: nprog (1) (2) (3) (4) (5)\n" |
556 | | " (1)\tstart page number\n" |
557 | | " (2)\timage file name\n" |
558 | | " (3)\tdevice index number\n" |
559 | | " (4)\tflash index number\n" |
560 | | " (5) image type must be:\n" |
561 | | " \t-n:\tno oob\n" |
562 | | " \t-o:\twith oob no ecc\n" |
563 | | " \t-e:\twith oob and ecc\n"; |
564 | | |
565 | | if (com_argc != 6) { |
566 | | printf(" not enough argument.\n"); |
567 | | printf("%s", help); |
568 | | return 0; |
569 | | } |
570 | | |
571 | | init_nand_in(); |
572 | | |
573 | | nand_in.start = atoi(com_argv[1]); |
574 | | image_file = com_argv[2]; |
575 | | nand_in.dev = atoi(com_argv[3]); |
576 | | (nand_in.cs_map)[atoi(com_argv[4])] = 1; |
577 | | if (!strcmp(com_argv[5], "-e")) |
578 | | nand_in.option = OOB_ECC; |
579 | | else if (!strcmp(com_argv[5], "-o")) |
580 | | nand_in.option = OOB_NO_ECC; |
581 | | else if (!strcmp(com_argv[5], "-n")) |
582 | | nand_in.option = NO_OOB; |
583 | | else |
584 | | printf("%s", help); |
585 | | |
586 | | if (hand.nand_plane > 1) |
587 | | nand_program_file_planes(&nand_in, &nand_out, image_file); |
588 | | else |
589 | | nand_program_file(&nand_in, &nand_out, image_file); |
590 | | |
591 | | #ifdef CONFIG_NAND_OUT |
592 | | printf(" Flash check result:\n"); |
593 | | int i; |
594 | | for (i = 0; i < 16; i++) |
595 | | printf(" %d", (nand_out.status)[i]); |
596 | | #endif |
597 | | |
598 | | return 1; |
599 | | } |
600 | | |
601 | | int nand_query(void) |
602 | | { |
603 | | int i; |
604 | | unsigned char csn; |
605 | | |
606 | | if (com_argc < 3) { |
607 | | printf(" Usage: nquery (1) (2)\n" |
608 | | " (1):device index number\n" |
609 | | " (2):flash index number\n"); |
610 | | return -1; |
611 | | } |
612 | | init_nand_in(); |
613 | | |
614 | | nand_in.dev = atoi(com_argv[1]); |
615 | | (nand_in.cs_map)[atoi(com_argv[2])] = 1; |
616 | | |
617 | | for (i = 0; i < nand_in.max_chip; i++) { |
618 | | if ((nand_in.cs_map)[i] != 0) |
619 | | break; |
620 | | } |
621 | | if (i >= nand_in.max_chip) |
622 | | return -1; |
623 | | |
624 | | if (usb_get_ingenic_cpu(&ingenic_dev) < 3) { |
625 | | printf(" Device unboot! Boot it first!\n"); |
626 | | return -1; |
627 | | } |
628 | | |
629 | | csn = i; |
630 | | printf(" ID of No.%d device No.%d flash: \n", nand_in.dev, csn); |
631 | | |
632 | | unsigned short ops = ((csn << 4) & 0xff0) + NAND_QUERY; |
633 | | usb_ingenic_nand_ops(&ingenic_dev, ops); |
634 | | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
635 | | printf(" Vendor ID :0x%x \n",(unsigned char)ret[0]); |
636 | | printf(" Product ID :0x%x \n",(unsigned char)ret[1]); |
637 | | printf(" Chip ID :0x%x \n",(unsigned char)ret[2]); |
638 | | printf(" Page ID :0x%x \n",(unsigned char)ret[3]); |
639 | | printf(" Plane ID :0x%x \n",(unsigned char)ret[4]); |
640 | | |
641 | | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
642 | | printf(" Operation status: Success!\n"); |
643 | | |
644 | | return 1; |
645 | | } |
646 | | |
647 | | int nand_read(int mode) |
648 | | { |
649 | | unsigned int i,j; |
650 | | unsigned int start_addr, length, page_num; |
651 | | unsigned char csn; |
652 | | unsigned short temp = 0; |
653 | | unsigned ram_addr = 0; |
654 | | |
655 | | if (com_argc < 5) { |
656 | | printf(" Usage: nread (1) (2) (3) (4)\n" |
657 | | " 1:start page number\n" |
658 | | " 2:length in byte\n" |
659 | | " 3:device index number\n" |
660 | | " 4:flash index number\n" |
661 | | " 5:start SDRAM address\n"); |
662 | | return -1; |
663 | | } |
664 | | init_nand_in(); |
665 | | |
666 | | if (atoi(com_argv[4]) >= MAX_DEV_NUM) { |
667 | | printf(" Flash index number overflow!\n"); |
668 | | return -1; |
669 | | } |
670 | | (nand_in.cs_map)[atoi(com_argv[4])] = 1; |
671 | | nand_in.start = atoi(com_argv[1]); |
672 | | nand_in.length= atoi(com_argv[2]); |
673 | | nand_in.dev = atoi(com_argv[3]); |
674 | | |
675 | | if (com_argc = 6) { |
676 | | ram_addr = strtoul(com_argv[5], NULL, 0); |
677 | | printf("==%s==", com_argv[5]); |
678 | | } |
679 | | start_addr = nand_in.start; |
680 | | length = nand_in.length; |
681 | | |
682 | | if (start_addr > NAND_MAX_PAGE_NUM || length > NAND_MAX_PAGE_NUM ) { |
683 | | printf(" Page number overflow!\n"); |
684 | | return -1; |
685 | | } |
686 | | if (usb_get_ingenic_cpu(&ingenic_dev) < 3) { |
687 | | printf(" Device unboot! Boot it first!\n"); |
688 | | return -1; |
689 | | } |
690 | | for (i = 0; i < nand_in.max_chip; i++) |
691 | | if ((nand_in.cs_map)[i] != 0) |
692 | | break; |
693 | | if (i >= nand_in.max_chip) return 1; |
694 | | csn = i; |
695 | | printf(" Reading from No.%d device No.%d flash....\n",nand_in.dev,csn); |
696 | | |
697 | | page_num = length / hand.nand_ps +1; |
698 | | |
699 | | switch(mode) { |
700 | | case NAND_READ: |
701 | | temp = ((NO_OOB<<12) & 0xf000) + ((csn<<4) & 0xff0) + NAND_READ; |
702 | | break; |
703 | | case NAND_READ_OOB: |
704 | | temp = ((csn<<4) & 0xff0) + NAND_READ_OOB; |
705 | | break; |
706 | | case NAND_READ_RAW: |
707 | | temp = ((NO_OOB<<12) & 0xf000) + ((csn<<4) & 0xff0) + |
708 | | NAND_READ_RAW; |
709 | | break; |
710 | | case NAND_READ_TO_RAM: |
711 | | temp = ((NO_OOB<<12) & 0xf000) + ((csn<<4) & 0xff0) + |
712 | | NAND_READ_TO_RAM; |
713 | | printf(" Reading nand to RAM: 0x%x\n", ram_addr); |
714 | | usb_ingenic_start(&ingenic_dev, VR_PROGRAM_START1, ram_addr); |
715 | | break; |
716 | | default: |
717 | | printf(" unknow mode!\n"); |
718 | | return -1; |
719 | | } |
720 | | |
721 | | usb_send_data_address_to_ingenic(&ingenic_dev, start_addr); |
722 | | usb_send_data_length_to_ingenic(&ingenic_dev, page_num); |
723 | | |
724 | | usb_ingenic_nand_ops(&ingenic_dev, temp); |
725 | | |
726 | | usb_read_data_from_ingenic(&ingenic_dev, nand_in.buf, page_num * hand.nand_ps); |
727 | | |
728 | | for (j = 0; j < length; j++) { |
729 | | if (j % 16 == 0) |
730 | | printf("\n 0x%08x : ",j); |
731 | | printf("%02x ",(nand_in.buf)[j]); |
732 | | } |
733 | | printf("\n"); |
734 | | |
735 | | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
736 | | printf(" Operation end position : %d \n", |
737 | | (ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0)); |
738 | | |
739 | | return 1; |
740 | | } |
741 | | |
742 | | int debug_memory(int obj, unsigned int start, unsigned int size) |
743 | | { |
744 | | unsigned int buffer[8],tmp; |
745 | | |
746 | | tmp = usb_get_ingenic_cpu(&ingenic_dev); |
| 172 | tmp = usb_get_ingenic_cpu(dev); |
747 | 173 | if (tmp > 2) { |
748 | 174 | printf(" This command only run under UNBOOT state!\n"); |
749 | 175 | return -1; |
... | ... | |
771 | 197 | printf(" Now test memory from 0x%x to 0x%x: \n", |
772 | 198 | start, start + hand.fw_args.size); |
773 | 199 | |
774 | | if (load_file(&ingenic_dev, STAGE1_FILE_PATH) < 1) |
| 200 | if (load_file(dev, STAGE1_FILE_PATH) < 1) |
775 | 201 | return -1; |
776 | | if (usb_ingenic_upload(&ingenic_dev, 1) < 1) |
| 202 | if (usb_ingenic_upload(dev, 1) < 1) |
777 | 203 | return -1; |
778 | 204 | |
779 | 205 | usleep(100); |
780 | | usb_read_data_from_ingenic(&ingenic_dev, buffer, 8); |
| 206 | usb_read_data_from_ingenic(dev, buffer, 8); |
781 | 207 | if (buffer[0] != 0) |
782 | 208 | printf(" Test memory fail! Last error address is 0x%x !\n", |
783 | 209 | buffer[0]); |
... | ... | |
787 | 213 | return 1; |
788 | 214 | } |
789 | 215 | |
790 | | int debug_gpio(int obj, unsigned char ops, unsigned char pin) |
791 | | { |
792 | | unsigned int tmp; |
793 | | |
794 | | tmp = usb_get_ingenic_cpu(&ingenic_dev); |
795 | | if (tmp > 2) { |
796 | | printf(" This command only run under UNBOOT state!\n"); |
797 | | return -1; |
798 | | } |
799 | | |
800 | | switch (tmp) { |
801 | | case 1: |
802 | | tmp = 0; |
803 | | hand.fw_args.cpu_id = 0x4740; |
804 | | if (pin > 124) { |
805 | | printf(" Jz4740 has 124 GPIO pin in all!\n"); |
806 | | return -1; |
807 | | } |
808 | | break; |
809 | | case 2: |
810 | | tmp = 0; |
811 | | hand.fw_args.cpu_id = 0x4750; |
812 | | if (pin > 178) { |
813 | | printf(" Jz4750 has 178 GPIO pin in all!\n"); |
814 | | return -1; |
815 | | } |
816 | | break; |
817 | | } |
818 | | |
819 | | hand.fw_args.debug_ops = ops;/* tell device it's memory debug */ |
820 | | hand.fw_args.pin_num = pin; |
821 | | |
822 | | if (ops == 2) |
823 | | printf(" GPIO %d set!\n",pin); |
824 | | else |
825 | | printf(" GPIO %d clear!\n",pin); |
826 | | |
827 | | if (load_file(&ingenic_dev, STAGE1_FILE_PATH) < 1) |
828 | | return -1; |
829 | | if (usb_ingenic_upload(&ingenic_dev, 1) < 1) |
830 | | return -1; |
831 | | |
832 | | return 0; |
833 | | } |
834 | | |
835 | | int debug_go(void) |
| 216 | int debug_go(struct ingenic_dev *dev, size_t argc, char *argv[]) |
836 | 217 | { |
837 | 218 | unsigned int addr,obj; |
838 | | if (com_argc<3) { |
| 219 | if (argc < 3) { |
839 | 220 | printf(" Usage: go (1) (2) \n" |
840 | 221 | " 1:start SDRAM address\n" |
841 | 222 | " 2:device index number\n"); |
842 | 223 | return 0; |
843 | 224 | } |
844 | 225 | |
845 | | addr = strtoul(com_argv[1], NULL, 0); |
846 | | obj = atoi(com_argv[2]); |
| 226 | addr = strtoul(argv[1], NULL, 0); |
| 227 | obj = atoi(argv[2]); |
847 | 228 | |
848 | 229 | printf(" Executing No.%d device at address 0x%x\n", obj, addr); |
849 | 230 | |
850 | | if (usb_ingenic_start(&ingenic_dev, VR_PROGRAM_START2, addr) < 1) |
| 231 | if (usb_ingenic_start(dev, VR_PROGRAM_START2, addr) < 1) |
851 | 232 | return -1; |
852 | 233 | |
853 | 234 | return 1; |
854 | 235 | } |
855 | 236 | |
856 | | int sdram_load(struct sdram_in *sdram_in) |
| 237 | int sdram_load(struct ingenic_dev *dev, struct sdram_in *sdram_in) |
857 | 238 | { |
858 | | if (usb_get_ingenic_cpu(&ingenic_dev) < 3) { |
| 239 | if (usb_get_ingenic_cpu(dev) < 3) { |
859 | 240 | printf(" Device unboot! Boot it first!\n"); |
860 | 241 | return -1; |
861 | 242 | } |
... | ... | |
865 | 246 | return -1; |
866 | 247 | } |
867 | 248 | |
868 | | ingenic_dev.file_buff = sdram_in->buf; |
869 | | ingenic_dev.file_len = sdram_in->length; |
870 | | usb_send_data_to_ingenic(&ingenic_dev); |
871 | | usb_send_data_address_to_ingenic(&ingenic_dev, sdram_in->start); |
872 | | usb_send_data_length_to_ingenic(&ingenic_dev, sdram_in->length); |
873 | | usb_ingenic_sdram_ops(&ingenic_dev, sdram_in); |
| 249 | usb_send_data_to_ingenic(dev, sdram_in->buf, sdram_in->length); |
| 250 | usb_send_data_address_to_ingenic(dev, sdram_in->start); |
| 251 | usb_send_data_length_to_ingenic(dev, sdram_in->length); |
| 252 | /* usb_ingenic_sdram_ops(dev, sdram_in);*/ |
874 | 253 | |
875 | | usb_read_data_from_ingenic(&ingenic_dev, ret, 8); |
| 254 | usb_read_data_from_ingenic(dev, ret, 8); |
876 | 255 | printf(" Load last address at 0x%x\n", |
877 | 256 | ((ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0))); |
878 | 257 | |
879 | 258 | return 1; |
880 | 259 | } |
881 | 260 | |
882 | | int sdram_load_file(struct sdram_in *sdram_in, char *file_path) |
| 261 | int sdram_load_file(struct ingenic_dev *dev, struct sdram_in *sdram_in, char *file_path) |
883 | 262 | { |
884 | 263 | struct stat fstat; |
885 | 264 | unsigned int flen,m,j,offset,k; |
... | ... | |
895 | 274 | |
896 | 275 | fd = open(file_path, O_RDONLY); |
897 | 276 | if (fd < 0) { |
898 | | fprintf(stderr, "Error - can't open file '%s': %s\n", |
| 277 | fprintf(stderr, "Error - can't open file '%s': %s\n", |
899 | 278 | file_path, strerror(errno)); |
900 | 279 | goto out; |
901 | 280 | } |
... | ... | |
910 | 289 | for (k = 0; k < m; k++) { |
911 | 290 | status = read(fd, sdram_in->buf, MAX_LOAD_SIZE); |
912 | 291 | if (status < MAX_LOAD_SIZE) { |
913 | | fprintf(stderr, "Error - can't read file '%s': %s\n", |
| 292 | fprintf(stderr, "Error - can't read file '%s': %s\n", |
914 | 293 | file_path, strerror(errno)); |
915 | 294 | goto close; |
916 | 295 | } |
917 | 296 | |
918 | 297 | sdram_in->length = MAX_LOAD_SIZE; |
919 | | if (sdram_load(sdram_in) < 1) |
| 298 | if (sdram_load(dev, sdram_in) < 1) |
920 | 299 | goto close; |
921 | 300 | |
922 | 301 | sdram_in->start += MAX_LOAD_SIZE; |
... | ... | |
925 | 304 | } |
926 | 305 | |
927 | 306 | if (j) { |
928 | | if (j % 4 !=0) |
| 307 | if (j % 4 !=0) |
929 | 308 | j += 4 - (j % 4); |
930 | 309 | status = read(fd, sdram_in->buf, j); |
931 | | if (status < j) { |
932 | | fprintf(stderr, "Error - can't read file '%s': %s\n", |
| 310 | if (status < (int)j) { |
| 311 | fprintf(stderr, "Error - can't read file '%s': %s\n", |
933 | 312 | file_path, strerror(errno)); |
934 | 313 | goto close; |
935 | 314 | } |
936 | 315 | |
937 | 316 | sdram_in->length = j; |
938 | | if (sdram_load(sdram_in) < 1) |
| 317 | if (sdram_load(dev, sdram_in) < 1) |
939 | 318 | goto close; |
940 | 319 | } |
941 | 320 | |
usbboot/src/command_line.c |
19 | 19 | #include <stdio.h> |
20 | 20 | #include <stdlib.h> |
21 | 21 | #include <string.h> |
| 22 | #include <ctype.h> |
22 | 23 | #include "usb_boot_defines.h" |
23 | 24 | #include "ingenic_usb.h" |
24 | 25 | #include "cmd.h" |
25 | 26 | #include "xburst-tools_version.h" |
26 | | |
| 27 | #include "nand.h" |
| 28 | #include "mem.h" |
| 29 | |
27 | 30 | extern struct nand_in nand_in; |
28 | 31 | extern struct sdram_in sdram_in; |
29 | | extern unsigned char code_buf[4 * 512 * 1024]; |
| 32 | static char code_buf[4 * 512 * 1024]; |
| 33 | extern struct ingenic_dev ingenic_dev; |
| 34 | typedef int (*command_callback_t)(size_t argc, char *argv[]); |
| 35 | |
| 36 | struct command { |
| 37 | const char *name; |
| 38 | command_callback_t callback; |
| 39 | }; |
30 | 40 | |
31 | | int com_argc; |
32 | | char com_argv[MAX_ARGC][MAX_COMMAND_LENGTH]; |
| 41 | #define COMMAND(_name, _callback) {\ |
| 42 | .name = _name, \ |
| 43 | .callback = (command_callback_t)_callback, \ |
| 44 | } |
33 | 45 | |
34 | | static const char COMMAND[][COMMAND_NUM]= |
| 46 | static const char COMMANDS[][COMMAND_NUM]= |
35 | 47 | { |
36 | | "", |
37 | | "query", |
38 | | "querya", |
39 | | "erase", |
40 | | "read", |
41 | | "prog", |
42 | | "nquery", |
43 | | "nerase", |
44 | | "nread", |
45 | | "nreadraw", |
46 | | "nreadoob", /* index 10 */ |
47 | | "nprog", |
48 | | "help", |
49 | | "version", |
50 | 48 | "go", |
51 | 49 | "fconfig", |
52 | | "exit", |
53 | | "readnand", |
54 | | "gpios", |
55 | | "gpioc", |
56 | 50 | "boot", /* index 20 */ |
57 | 51 | "list", |
58 | 52 | "select", |
... | ... | |
63 | 57 | "nmake", |
64 | 58 | "load", |
65 | 59 | "memtest", |
66 | | "run" |
| 60 | "run", |
67 | 61 | }; |
68 | 62 | |
69 | | static int handle_help(void) |
| 63 | static unsigned long parse_number(const char *s, int *err) |
| 64 | { |
| 65 | unsigned long val = 0; |
| 66 | unsigned int base = 10; |
| 67 | char *endptr; |
| 68 | |
| 69 | if (s == 0 || *s == 0) { |
| 70 | if (err) |
| 71 | *err = 1; |
| 72 | return 0; |
| 73 | } |
| 74 | |
| 75 | if (*s == '0') { |
| 76 | ++s; |
| 77 | if (*s == 'x') { |
| 78 | base = 16; |
| 79 | ++s; |
| 80 | } else if (*s != 0) { |
| 81 | base = 8; |
| 82 | } |
| 83 | } else if (*s == 'b') { |
| 84 | ++s; |
| 85 | base = 2; |
| 86 | } |
| 87 | |
| 88 | val = strtoul(s, &endptr, base); |
| 89 | |
| 90 | if (*endptr) { |
| 91 | if (err) |
| 92 | *err = 1; |
| 93 | return 0; |
| 94 | } |
| 95 | |
| 96 | if (err) |
| 97 | *err = 0; |
| 98 | |
| 99 | return val; |
| 100 | } |
| 101 | |
| 102 | static unsigned long parse_number_print_error(const char *s, int *err) |
| 103 | { |
| 104 | unsigned long value; |
| 105 | int err2 = 0; |
| 106 | value = parse_number(s, &err2); |
| 107 | if (err2) { |
| 108 | fprintf(stderr, "Error: %s is not a number\n", s); |
| 109 | if (err) |
| 110 | ++err; |
| 111 | } |
| 112 | |
| 113 | return value; |
| 114 | } |
| 115 | |
| 116 | static int handle_exit() |
| 117 | { |
| 118 | exit(0); |
| 119 | return 0; |
| 120 | } |
| 121 | |
| 122 | static int handle_help() |
70 | 123 | { |
71 | 124 | printf(" command support in current version:\n" |
72 | 125 | /* " query" */ |
... | ... | |
74 | 127 | /* " erase" */ |
75 | 128 | /* " read" */ |
76 | 129 | /* " prog" */ |
77 | | " nquery query NAND flash info\n" |
78 | | " nerase erase NAND flash\n" |
79 | | " nread read NAND flash data with checking bad block and ECC\n" |
80 | | " nreadraw read NAND flash data without checking bad block and ECC\n" |
81 | | " nreadoo read NAND flash oob without checking bad block and ECC\n" /* index 10 */ |
82 | | " nprog program NAND flash with data and ECC\n" |
83 | | " help print this help\n" |
84 | | " version show current USB Boot software version\n" |
85 | | " go execute program in SDRAM\n" |
86 | | " fconfig set USB Boot config file(not implement)\n" |
87 | | " exit quit from telnet session\n" |
88 | | " readnand read data from nand flash and store to SDRAM\n" |
89 | | " gpios set one GPIO to high level\n" |
90 | | " gpioc set one GPIO to low level\n" |
91 | | " boot boot device and make it in stage2\n" /* index 20 */ |
92 | | " list show current device number can connect(not implement)\n" |
| 130 | " nquery query NAND flash info\n" |
| 131 | " nerase erase NAND flash\n" |
| 132 | " nread read NAND flash data with checking bad block and ECC\n" |
| 133 | " nreadraw read NAND flash data without checking bad block and ECC\n" |
| 134 | " nreadoo read NAND flash oob without checking bad block and ECC\n" /* index 10 */ |
| 135 | " nprog program NAND flash with data and ECC\n" |
| 136 | " ndump dump NAND flash data to file\n" |
| 137 | " help print this help\n" |
| 138 | " version show current USB Boot software version\n" |
| 139 | " go execute program in SDRAM\n" |
| 140 | " fconfig set USB Boot config file(not implement)\n" |
| 141 | " exit quit from current session\n" |
| 142 | " readnand read data from nand flash and store to SDRAM\n" |
| 143 | " boot boot device and make it in stage2\n" /* index 20 */ |
| 144 | " list show current device number can connect(not implement)\n" |
93 | 145 | /* " select" */ |
94 | 146 | /* " unselect" */ |
95 | 147 | /* " chip" */ |
96 | 148 | /* " unchip" */ |
97 | | " nmark mark a bad block in NAND flash\n" |
98 | | " nmake read all data from nand flash and store to file(not implement)\n" |
99 | | " load load file data to SDRAM\n" |
100 | | " memtest do SDRAM test\n" |
101 | | " run run command script in file(implement by -c args)\n" |
102 | | " sdprog program SD card(not implement)\n" |
103 | | " sdread read data from SD card(not implement)\n"); |
104 | | return 1; |
| 149 | " nmark mark a bad block in NAND flash\n" |
| 150 | " nmake read all data from nand flash and store to file(not implement)\n" |
| 151 | " load load file data to SDRAM\n" |
| 152 | " memtest do SDRAM test\n" |
| 153 | " run run command script in file(implement by -c args)\n" |
| 154 | " sdprog program SD card(not implement)\n" |
| 155 | " sdread read data from SD card(not implement)\n"); |
| 156 | |
| 157 | return 0; |
| 158 | } |
| 159 | |
| 160 | static int handle_version() |
| 161 | { |
| 162 | printf("USB Boot Software current version: %s\n", XBURST_TOOLS_VERSION); |
| 163 | |
| 164 | return 0; |
105 | 165 | } |
106 | 166 | |
107 | | static int handle_version(void) |
| 167 | static int handle_boot() |
108 | 168 | { |
109 | | printf(" USB Boot Software current version: %s\n", XBURST_TOOLS_VERSION); |
110 | | return 1; |
| 169 | boot(&ingenic_dev, STAGE1_FILE_PATH, STAGE2_FILE_PATH); |
| 170 | |
| 171 | return 0; |
111 | 172 | } |
112 | 173 | |
113 | | /* need transfer two para :blk_num ,start_blk */ |
114 | | int handle_nerase(void) |
| 174 | static int handle_nand_erase(size_t argc, char *argv[]) |
115 | 175 | { |
116 | | if (com_argc < 5) { |
| 176 | uint32_t start_block, num_blocks; |
| 177 | unsigned int device_idx; |
| 178 | uint8_t nand_idx; |
| 179 | int err; |
| 180 | |
| 181 | if (argc < 5) { |
117 | 182 | printf(" Usage: nerase (1) (2) (3) (4)\n" |
118 | | " 1:start block number\n" |
119 | | " 2:block length\n" |
120 | | " 3:device index number\n" |
121 | | " 4:flash chip index number\n"); |
| 183 | " 1:start block number\n" |
| 184 | " 2:block length\n" |
| 185 | " 3:device index number\n" |
| 186 | " 4:flash chip index number\n"); |
122 | 187 | return -1; |
123 | 188 | } |
124 | 189 | |
125 | | init_nand_in(); |
| 190 | start_block = parse_number_print_error(argv[1], &err); |
| 191 | num_blocks = parse_number_print_error(argv[2], &err); |
| 192 | device_idx = parse_number_print_error(argv[3], &err); |
| 193 | nand_idx = parse_number_print_error(argv[4], &err); |
| 194 | if (err) |
| 195 | return err; |
126 | 196 | |
127 | | nand_in.start = atoi(com_argv[1]); |
128 | | nand_in.length = atoi(com_argv[2]); |
129 | | nand_in.dev = atoi(com_argv[3]); |
130 | | if (atoi(com_argv[4]) >= MAX_DEV_NUM) { |
| 197 | if (nand_idx >= MAX_DEV_NUM) { |
131 | 198 | printf(" Flash index number overflow!\n"); |
132 | 199 | return -1; |
133 | 200 | } |
134 | | (nand_in.cs_map)[atoi(com_argv[4])] = 1; |
135 | 201 | |
136 | | if (nand_erase(&nand_in) < 1) |
| 202 | if (nand_erase(&ingenic_dev, nand_idx, start_block, num_blocks)) |
137 | 203 | return -1; |
138 | 204 | |
139 | | return 1; |
| 205 | return 0; |
140 | 206 | } |
141 | 207 | |
142 | | int handle_nmark(void) |
| 208 | static int handle_nand_mark(size_t argc, char *argv[]) |
143 | 209 | { |
144 | | if (com_argc < 4) { |
145 | | printf(" Usage: nerase (1) (2) (3)\n" |
146 | | " 1:bad block number\n" |
147 | | " 2:device index number\n" |
148 | | " 3:flash chip index number\n"); |
| 210 | uint32_t block; |
| 211 | unsigned int device_idx; |
| 212 | uint8_t nand_idx; |
| 213 | int err = 0; |
| 214 | |
| 215 | if (argc < 4) { |
| 216 | printf("Usage: nerase (1) (2) (3)\n" |
| 217 | "1: bad block number\n" |
| 218 | "2: device index number\n" |
| 219 | "3: flash chip index number\n"); |
149 | 220 | return -1; |
150 | 221 | } |
151 | | init_nand_in(); |
152 | 222 | |
153 | | nand_in.start = atoi(com_argv[1]); |
154 | | nand_in.dev = atoi(com_argv[2]); |
| 223 | block = parse_number_print_error(argv[1], &err); |
| 224 | device_idx = parse_number_print_error(argv[2], &err); |
| 225 | nand_idx = parse_number_print_error(argv[3], &err); |
| 226 | if (err) |
| 227 | return err; |
155 | 228 | |
156 | | if (atoi(com_argv[3])>=MAX_DEV_NUM) { |
157 | | printf(" Flash index number overflow!\n"); |
| 229 | if (nand_idx >= MAX_DEV_NUM) { |
| 230 | printf("Flash index number overflow!\n"); |
158 | 231 | return -1; |
159 | 232 | } |
160 | | (nand_in.cs_map)[atoi(com_argv[3])] = 1; |
161 | 233 | |
162 | | nand_markbad(&nand_in); |
163 | | return 1; |
| 234 | nand_markbad(&ingenic_dev, nand_idx, block); |
| 235 | |
| 236 | return 0; |
164 | 237 | } |
165 | 238 | |
166 | | int handle_memtest(void) |
| 239 | static int handle_memtest(size_t argc, char *argv[]) |
167 | 240 | { |
| 241 | unsigned int device_idx; |
168 | 242 | unsigned int start, size; |
169 | | if (com_argc != 2 && com_argc != 4) |
| 243 | int err = 0; |
| 244 | |
| 245 | if (argc != 2 && argc != 4) |
170 | 246 | { |
171 | 247 | printf(" Usage: memtest (1) [2] [3]\n" |
172 | | " 1:device index number\n" |
173 | | " 2:SDRAM start address\n" |
174 | | " 3:test size\n"); |
| 248 | " 1: device index number\n" |
| 249 | " 2: SDRAM start address\n" |
| 250 | " 3: test size\n"); |
175 | 251 | return -1; |
176 | 252 | } |
177 | 253 | |
178 | | if (com_argc == 4) { |
179 | | start = strtoul(com_argv[2], NULL, 0); |
180 | | size = strtoul(com_argv[3], NULL, 0); |
| 254 | if (argc == 4) { |
| 255 | start = parse_number_print_error(argv[2], &err); |
| 256 | size = parse_number_print_error(argv[3], &err); |
181 | 257 | } else { |
182 | 258 | start = 0; |
183 | 259 | size = 0; |
184 | 260 | } |
185 | | debug_memory(atoi(com_argv[1]), start, size); |
186 | | return 1; |
| 261 | device_idx = parse_number_print_error(argv[1], &err); |
| 262 | if (err) |
| 263 | return err; |
| 264 | |
| 265 | debug_memory(&ingenic_dev, device_idx, start, size); |
| 266 | return 0; |
187 | 267 | } |
188 | 268 | |
189 | | int handle_gpio(int mode) |
| 269 | static int handle_load(size_t argc, char *argv[]) |
190 | 270 | { |
191 | | if (com_argc < 3) { |
| 271 | if (argc != 4) { |
192 | 272 | printf(" Usage:" |
193 | | " gpios (1) (2)\n" |
194 | | " 1:GPIO pin number\n" |
195 | | " 2:device index number\n"); |
| 273 | " load (1) (2) (3) \n" |
| 274 | " 1:SDRAM start address\n" |
| 275 | " 2:image file name\n" |
| 276 | " 3:device index number\n"); |
| 277 | |
196 | 278 | return -1; |
197 | 279 | } |
198 | 280 | |
199 | | debug_gpio(atoi(com_argv[2]), mode, atoi(com_argv[1])); |
200 | | return 1; |
| 281 | sdram_in.start=strtoul(argv[1], NULL, 0); |
| 282 | printf(" start:::::: 0x%x\n", sdram_in.start); |
| 283 | |
| 284 | sdram_in.dev = atoi(argv[3]); |
| 285 | sdram_in.buf = code_buf; |
| 286 | sdram_load_file(&ingenic_dev, &sdram_in, argv[2]); |
| 287 | return 0; |
201 | 288 | } |
202 | 289 | |
203 | | int handle_load(void) |
| 290 | static size_t command_parse(char *cmd, char *argv[]) |
204 | 291 | { |
205 | | if (com_argc<4) { |
206 | | printf(" Usage:" |
207 | | " load (1) (2) (3) \n" |
208 | | " 1:SDRAM start address\n" |
209 | | " 2:image file name\n" |
210 | | " 3:device index number\n"); |
| 292 | size_t argc = 0; |
211 | 293 | |
212 | | return -1; |
| 294 | if (cmd == 0 || *cmd == 0) |
| 295 | return 0; |
| 296 | |
| 297 | |
| 298 | while (isspace(*cmd)) { |
| 299 | ++cmd; |
213 | 300 | } |
214 | 301 | |
215 | | sdram_in.start=strtoul(com_argv[1], NULL, 0); |
216 | | printf(" start:::::: 0x%x\n", sdram_in.start); |
| 302 | argv[0] = cmd; |
| 303 | argc = 1; |
217 | 304 | |
218 | | sdram_in.dev = atoi(com_argv[3]); |
219 | | sdram_in.buf = code_buf; |
220 | | sdram_load_file(&sdram_in, com_argv[2]); |
221 | | return 1; |
| 305 | while (*cmd) { |
| 306 | if (isspace(*cmd)) { |
| 307 | *cmd = 0; |
| 308 | |
| 309 | do { |
| 310 | ++cmd; |
| 311 | } while (isspace(*cmd)); |
| 312 | |
| 313 | if (*cmd == 0 || argc >= MAX_ARGC) |
| 314 | break; |
| 315 | |
| 316 | argv[argc] = cmd; |
| 317 | ++argc; |
| 318 | } |
| 319 | |
| 320 | ++cmd; |
| 321 | } |
| 322 | |
| 323 | return argc; |
| 324 | } |
| 325 | |
| 326 | static int handle_nand_read(size_t argc, char *argv[]) |
| 327 | { |
| 328 | int mode; |
| 329 | uint32_t start_page, num_pages; |
| 330 | unsigned int device_idx; |
| 331 | uint8_t nand_idx; |
| 332 | int err = 0; |
| 333 | |
| 334 | if (argc != 5) { |
| 335 | printf("Usage: %s <start page> <length> <device index> " |
| 336 | "<nand chip index>\n", argv[0]); |
| 337 | return -1; |
| 338 | } |
| 339 | |
| 340 | if (strcmp(argv[0], "nread") == 0) { |
| 341 | mode = NAND_READ; |
| 342 | } else if (strcmp(argv[0], "nreadraw") == 0) { |
| 343 | mode = NAND_READ_RAW; |
| 344 | } else if (strcmp(argv[0], "nreadoob") == 0) { |
| 345 | mode = NAND_READ_OOB; |
| 346 | } else { |
| 347 | return -1; |
| 348 | } |
| 349 | |
| 350 | start_page = parse_number_print_error(argv[1], &err); |
| 351 | num_pages = parse_number_print_error(argv[2], &err); |
| 352 | device_idx = parse_number_print_error(argv[3], &err); |
| 353 | nand_idx = parse_number_print_error(argv[4], &err); |
| 354 | if (err) |
| 355 | return err; |
| 356 | |
| 357 | return nand_read(&ingenic_dev, nand_idx, mode, start_page, num_pages, 0); |
| 358 | } |
| 359 | |
| 360 | static int handle_nand_dump(size_t argc, char *argv[]) |
| 361 | { |
| 362 | int mode; |
| 363 | uint32_t start_page, num_pages; |
| 364 | unsigned int device_idx; |
| 365 | uint8_t nand_idx; |
| 366 | int err = 0; |
| 367 | |
| 368 | if (argc != 5) { |
| 369 | printf("Usage: %s <start page> <length> <filename> <mode>\n", argv[0]); |
| 370 | return -1; |
| 371 | } |
| 372 | |
| 373 | if (strcmp(argv[5], "-n") == 0) { |
| 374 | mode = NAND_READ; |
| 375 | } else if (strcmp(argv[5], "-e") == 0) { |
| 376 | mode = NAND_READ_RAW; |
| 377 | } else if (strcmp(argv[5], "-o") == 0) { |
| 378 | mode = NAND_READ_OOB; |
| 379 | } else { |
| 380 | return -1; |
| 381 | } |
| 382 | |
| 383 | start_page = parse_number_print_error(argv[1], &err); |
| 384 | num_pages = parse_number_print_error(argv[2], &err); |
| 385 | device_idx = parse_number_print_error(argv[3], &err); |
| 386 | nand_idx = parse_number_print_error(argv[4], &err); |
| 387 | if (err) |
| 388 | return err; |
| 389 | |
| 390 | return nand_read(&ingenic_dev, nand_idx, mode, start_page, num_pages, 0); |
| 391 | |
| 392 | } |
| 393 | |
| 394 | static int handle_nand_query(size_t argc, char *argv[]) |
| 395 | { |
| 396 | unsigned int device_idx; |
| 397 | uint8_t nand_idx; |
| 398 | int err = 0; |
| 399 | |
| 400 | if (argc != 3) { |
| 401 | printf("Usage: %s <device index> <nand chip index>\n", argv[0]); |
| 402 | return -1; |
| 403 | } |
| 404 | |
| 405 | device_idx = parse_number_print_error(argv[1], &err); |
| 406 | nand_idx = parse_number_print_error(argv[2], &err); |
| 407 | if (err) |
| 408 | return err; |
| 409 | |
| 410 | return nand_query(&ingenic_dev, nand_idx); |
222 | 411 | } |
223 | 412 | |
224 | | int command_interpret(char * com_buf) |
| 413 | static int handle_nand_prog(size_t argc, char *argv[]) |
225 | 414 | { |
226 | | char *buf = com_buf; |
227 | | int k, L, i = 0, j = 0; |
228 | | |
229 | | L = (int)strlen(buf); |
230 | | buf[L]=' '; |
231 | | |
232 | | if (buf[0] == '\n') |
233 | | return 0; |
234 | | |
235 | | for (k = 0; k <= L; k++) { |
236 | | if (*buf == ' ' || *buf == '\n') { |
237 | | while ( *(++buf) == ' ' ); |
238 | | com_argv[i][j] = '\0'; |
239 | | i++; |
240 | | if (i > MAX_ARGC) |
241 | | return COMMAND_NUM + 1; |
242 | | j = 0; |
243 | | continue; |
244 | | } else { |
245 | | com_argv[i][j] = *buf; |
246 | | j++; |
247 | | if (j > MAX_COMMAND_LENGTH) |
248 | | return COMMAND_NUM + 1; |
| 415 | uint32_t start_page; |
| 416 | unsigned int device_idx; |
| 417 | uint8_t nand_idx, mode = -1; |
| 418 | int err = 0; |
| 419 | |
| 420 | if (argc != 5) { |
| 421 | printf("Usage: %s <start page> <filename> <device index> <nand chip index> <mode>\n", argv[0]); |
| 422 | return -1; |
| 423 | } |
| 424 | |
| 425 | start_page = parse_number_print_error(argv[1], &err); |
| 426 | device_idx = parse_number_print_error(argv[3], &err); |
| 427 | nand_idx = parse_number_print_error(argv[4], &err); |
| 428 | |
| 429 | if (argv[5][0] == '-') { |
| 430 | switch (argv[5][1]) { |
| 431 | case 'e': |
| 432 | mode = NO_OOB; |
| 433 | break; |
| 434 | case 'o': |
| 435 | mode = OOB_NO_ECC; |
| 436 | break; |
| 437 | case 'r': |
| 438 | mode = OOB_ECC; |
| 439 | break; |
| 440 | default: |
| 441 | break; |
249 | 442 | } |
250 | | buf++; |
251 | 443 | } |
| 444 | if (mode == -1) { |
| 445 | printf("%s: Invalid mode '%s'\n", argv[0], argv[5]); |
| 446 | err = -1; |
| 447 | } |
| 448 | |
| 449 | if (err) |
| 450 | return err; |
252 | 451 | |
253 | | com_argc = i; |
254 | 452 | |
255 | | for (i = 1; i <= COMMAND_NUM; i++) |
256 | | if (!strcmp(COMMAND[i], com_argv[0])) |
257 | | return i; |
258 | | return COMMAND_NUM + 1; |
| 453 | nand_prog(&ingenic_dev, nand_idx, start_page, argv[2], mode); |
| 454 | |
| 455 | return 0; |
259 | 456 | } |
260 | 457 | |
261 | | int command_handle(char *buf) |
| 458 | static int handle_mem_read(size_t argc, char *argv[]) |
262 | 459 | { |
263 | | int cmd = command_interpret(buf); /* get the command index */ |
| 460 | uint32_t addr; |
| 461 | uint32_t val; |
| 462 | int err = 0; |
| 463 | if (argc != 2) |
| 464 | printf("Usage: %s <addr>\n", argv[0]); |
264 | 465 | |
265 | | switch (cmd) { |
266 | | case 0: |
267 | | break; |
268 | | case 6: |
269 | | nand_query(); |
270 | | break; |
271 | | case 7: |
272 | | handle_nerase(); |
273 | | break; |
274 | | case 8: /* nread */ |
275 | | nand_read(NAND_READ); |
276 | | break; |
277 | | case 9: /* nreadraw */ |
278 | | nand_read(NAND_READ_RAW); |
279 | | break; |
280 | | case 10: /* nreadoob */ |
281 | | nand_read(NAND_READ_OOB); |
282 | | break; |
283 | | case 11: |
284 | | nand_prog(); |
285 | | break; |
286 | | case 12: |
287 | | handle_help(); |
288 | | break; |
289 | | case 13: |
290 | | handle_version(); |
291 | | break; |
292 | | case 14: |
293 | | debug_go(); |
294 | | break; |
295 | | case 16: /* exit */ |
296 | | printf(" exiting usbboot software\n"); |
297 | | return -1; /* return -1 to break the main.c while |
298 | | * then run usb_ingenic_cleanup*/ |
299 | | /*case 17: |
300 | | nand_read(NAND_READ_TO_RAM); */ |
301 | | break; |
302 | | case 18: |
303 | | handle_gpio(2); |
304 | | break; |
305 | | case 19: |
306 | | handle_gpio(3); |
| 466 | addr = parse_number_print_error(argv[1], &err); |
| 467 | if (err) |
| 468 | return err; |
| 469 | |
| 470 | switch (argv[0][7]) { |
| 471 | case '8': |
| 472 | val = mem_read8(&ingenic_dev, addr); |
307 | 473 | break; |
308 | | case 20: |
309 | | boot(STAGE1_FILE_PATH, STAGE2_FILE_PATH); |
| 474 | case '1': |
| 475 | val = mem_read16(&ingenic_dev, addr); |
310 | 476 | break; |
311 | | case 26: |
312 | | handle_nmark(); |
| 477 | default: |
| 478 | val = mem_read32(&ingenic_dev, addr); |
313 | 479 | break; |
314 | | case 28: |
315 | | handle_load(); |
| 480 | } |
| 481 | |
| 482 | printf("0x%x = 0x%x\n", addr, val); |
| 483 | |
| 484 | return 0; |
| 485 | } |
| 486 | |
| 487 | static int handle_mem_write(size_t argc, char *argv[]) |
| 488 | { |
| 489 | uint32_t addr; |
| 490 | uint32_t val; |
| 491 | int err = 0; |
| 492 | |
| 493 | if (argc != 3) |
| 494 | printf("Usage: %s <addr> <value>\n", argv[0]); |
| 495 | |
| 496 | addr = parse_number_print_error(argv[1], &err); |
| 497 | val = parse_number_print_error(argv[2], &err); |
| 498 | if (err) |
| 499 | return err; |
| 500 | |
| 501 | switch (argv[0][8]) { |
| 502 | case '8': |
| 503 | mem_write8(&ingenic_dev, addr, val); |
316 | 504 | break; |
317 | | case 29: |
318 | | handle_memtest(); |
| 505 | case '1': |
| 506 | mem_write16(&ingenic_dev, addr, val); |
319 | 507 | break; |
320 | 508 | default: |
321 | | printf(" command not support or input error!\n"); |
| 509 | mem_write32(&ingenic_dev, addr, val); |
322 | 510 | break; |
323 | 511 | } |
324 | 512 | |
325 | | return 1; |
| 513 | printf("0x%x = 0x%x\n", addr, val); |
| 514 | |
| 515 | return 0; |
| 516 | } |
| 517 | |
| 518 | |
| 519 | static const struct command commands[] = { |
| 520 | COMMAND("version", handle_version), |
| 521 | COMMAND("help", handle_help), |
| 522 | COMMAND("nquery", handle_nand_query), |
| 523 | COMMAND("nerase", handle_nand_erase), |
| 524 | COMMAND("nread", handle_nand_read), |
| 525 | COMMAND("nreadraw", handle_nand_read), |
| 526 | COMMAND("nreadoo", handle_nand_read), |
| 527 | COMMAND("nprog", handle_nand_prog), |
| 528 | COMMAND("nwrite", handle_nand_prog), |
| 529 | COMMAND("nmark", handle_nand_mark), |
| 530 | COMMAND("ndump", handle_nand_dump), |
| 531 | COMMAND("exit", handle_exit), |
| 532 | COMMAND("boot", handle_boot), |
| 533 | COMMAND("memread", handle_mem_read), |
| 534 | COMMAND("memwrite", handle_mem_write), |
| 535 | COMMAND("memread16", handle_mem_read), |
| 536 | COMMAND("memwrite16", handle_mem_write), |
| 537 | COMMAND("memread8", handle_mem_read), |
| 538 | COMMAND("memwrite8", handle_mem_write), |
| 539 | COMMAND("memtest", handle_memtest), |
| 540 | COMMAND("load", handle_load), |
| 541 | }; |
| 542 | |
| 543 | int command_handle(char *buf) |
| 544 | { |
| 545 | size_t argc; |
| 546 | char *argv[MAX_ARGC]; |
| 547 | size_t i; |
| 548 | |
| 549 | argc = command_parse(buf, argv); |
| 550 | |
| 551 | if (argc == 0) |
| 552 | return 0; |
| 553 | |
| 554 | for (i = 0; i < ARRAY_SIZE(commands); ++i) { |
| 555 | if (strcmp(commands[i].name, argv[0]) == 0) |
| 556 | return commands[i].callback(argc, argv); |
| 557 | } |
| 558 | |
| 559 | printf("Unknow command \"%s\"\n", argv[0]); |
| 560 | |
| 561 | return -1; |
326 | 562 | } |
usbboot/src/ingenic_usb.c |
2 | 2 | * Copyright(C) 2009 Qi Hardware Inc., |
3 | 3 | * Authors: Xiangfu Liu <xiangfu@qi-hardware.com> |
4 | 4 | * Marek Lindner <lindner_marek@yahoo.de> |
5 | | * |
| 5 | * |
6 | 6 | * This program is free software: you can redistribute it and/or modify |
7 | 7 | * it under the terms of the GNU General Public License as published by |
8 | 8 | * the Free Software Foundation, either version 3 of the License, or |
... | ... | |
34 | 34 | usb_busses = usb_get_busses(); |
35 | 35 | |
36 | 36 | for (usb_bus = usb_busses; usb_bus != NULL; usb_bus = usb_bus->next) { |
37 | | for (usb_dev = usb_bus->devices; usb_dev != NULL; |
| 37 | for (usb_dev = usb_bus->devices; usb_dev != NULL; |
38 | 38 | usb_dev = usb_dev->next) { |
39 | 39 | |
40 | 40 | if ((usb_dev->descriptor.idVendor == VENDOR_ID) && |
41 | 41 | (usb_dev->descriptor.idProduct == PRODUCT_ID)) { |
42 | 42 | ingenic_dev->usb_dev = usb_dev; |
43 | 43 | count++; |
| 44 | break; |
44 | 45 | } |
45 | 46 | |
46 | 47 | } |
... | ... | |
56 | 57 | struct usb_interface *usb_if; |
57 | 58 | int config_index, if_index, alt_index; |
58 | 59 | |
59 | | for (config_index = 0; |
60 | | config_index < ingenic_dev->usb_dev->descriptor.bNumConfigurations; |
| 60 | for (config_index = 0; |
| 61 | config_index < ingenic_dev->usb_dev->descriptor.bNumConfigurations; |
61 | 62 | config_index++) { |
62 | 63 | usb_config_desc = &ingenic_dev->usb_dev->config[config_index]; |
63 | 64 | |
64 | 65 | if (!usb_config_desc) |
65 | 66 | return 0; |
66 | 67 | |
67 | | for (if_index = 0; if_index < usb_config_desc->bNumInterfaces; |
| 68 | for (if_index = 0; if_index < usb_config_desc->bNumInterfaces; |
68 | 69 | if_index++) { |
69 | 70 | usb_if = &usb_config_desc->interface[if_index]; |
70 | 71 | |
... | ... | |
80 | 81 | |
81 | 82 | if ((usb_if_desc->bInterfaceClass == 0xff) && |
82 | 83 | (usb_if_desc->bInterfaceSubClass == 0)) { |
83 | | ingenic_dev->interface = |
| 84 | ingenic_dev->interface = |
84 | 85 | usb_if_desc->bInterfaceNumber; |
85 | 86 | return 1; |
86 | 87 | } |
... | ... | |
144 | 145 | { |
145 | 146 | int status; |
146 | 147 | |
147 | | memset(&ingenic_dev->cpu_info_buff, 0, |
| 148 | memset(&ingenic_dev->cpu_info_buff, 0, |
148 | 149 | ARRAY_SIZE(ingenic_dev->cpu_info_buff)); |
149 | 150 | |
150 | 151 | sleep(1); |
... | ... | |
195 | 196 | return 1; |
196 | 197 | } |
197 | 198 | |
198 | | int usb_send_data_length_to_ingenic(struct ingenic_dev *ingenic_dev, int len) |
| 199 | int usb_send_data_length_to_ingenic(struct ingenic_dev *ingenic_dev, unsigned int len) |
199 | 200 | { |
200 | 201 | int status; |
| 202 | |
201 | 203 | /* tell the device the length of the file to be uploaded */ |
202 | 204 | status = usb_control_msg(ingenic_dev->usb_handle, |
203 | 205 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
... | ... | |
217 | 219 | return 1; |
218 | 220 | } |
219 | 221 | |
220 | | int usb_send_data_address_to_ingenic(struct ingenic_dev *ingenic_dev, |
221 | | unsigned int stage_addr) |
| 222 | int usb_send_data_address_to_ingenic(struct ingenic_dev *ingenic_dev, uint32_t addr) |
222 | 223 | { |
223 | 224 | int status; |
224 | 225 | /* tell the device the RAM address to store the file */ |
225 | 226 | status = usb_control_msg(ingenic_dev->usb_handle, |
226 | 227 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
227 | 228 | /* bRequest */ VR_SET_DATA_ADDRESS, |
228 | | /* wValue */ STAGE_ADDR_MSB(stage_addr), |
229 | | /* wIndex */ STAGE_ADDR_LSB(stage_addr), |
| 229 | /* wValue */ STAGE_ADDR_MSB(addr), |
| 230 | /* wIndex */ STAGE_ADDR_LSB(addr), |
230 | 231 | /* Data */ 0, |
231 | 232 | /* wLength */ 0, |
232 | 233 | USB_TIMEOUT); |
... | ... | |
240 | 241 | return 1; |
241 | 242 | } |
242 | 243 | |
243 | | int usb_send_data_to_ingenic(struct ingenic_dev *ingenic_dev) |
| 244 | int usb_send_data_to_ingenic(struct ingenic_dev *ingenic_dev, const char *data, |
| 245 | int size) |
244 | 246 | { |
245 | 247 | int status; |
246 | 248 | status = usb_bulk_write(ingenic_dev->usb_handle, |
247 | 249 | /* endpoint */ INGENIC_OUT_ENDPOINT, |
248 | | /* bulk data */ ingenic_dev->file_buff, |
249 | | /* bulk data length */ ingenic_dev->file_len, |
| 250 | /* bulk data */ data, |
| 251 | /* bulk data length */ size, |
250 | 252 | USB_TIMEOUT); |
251 | | if (status < ingenic_dev->file_len) { |
| 253 | if (status < size) { |
252 | 254 | fprintf(stderr, "Error - " |
253 | 255 | "can't send bulk data to Ingenic CPU: %i\n", status); |
254 | 256 | return -1; |
... | ... | |
258 | 260 | } |
259 | 261 | |
260 | 262 | int usb_read_data_from_ingenic(struct ingenic_dev *ingenic_dev, |
261 | | unsigned char *buff, unsigned int len) |
| 263 | char *data, int size) |
262 | 264 | { |
263 | 265 | int status; |
264 | 266 | status = usb_bulk_read(ingenic_dev->usb_handle, |
265 | 267 | /* endpoint */ INGENIC_IN_ENDPOINT, |
266 | | /* bulk data */ buff, |
267 | | /* bulk data length */ len, |
| 268 | /* bulk data */ data, |
| 269 | /* bulk data length */ size, |
268 | 270 | USB_TIMEOUT); |
269 | | if (status < len) { |
| 271 | if (status < size) { |
270 | 272 | fprintf(stderr, "Error - " |
271 | 273 | "can't read bulk data from Ingenic device:%i\n", status); |
272 | 274 | return -1; |
... | ... | |
299 | 301 | |
300 | 302 | int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage) |
301 | 303 | { |
302 | | int status; |
303 | | |
304 | 304 | unsigned int stage2_addr; |
305 | 305 | stage2_addr = total_size + 0x80000000; |
306 | 306 | stage2_addr -= CODE_SIZE; |
... | ... | |
309 | 309 | int rqst = VR_PROGRAM_START1; |
310 | 310 | |
311 | 311 | usb_send_data_address_to_ingenic(ingenic_dev, stage_addr); |
312 | | printf(" Download stage %d program and execute at 0x%08x\n", |
| 312 | printf(" Download stage %d program and execute at 0x%08x\n", |
313 | 313 | stage, (stage_addr)); |
314 | | usb_send_data_to_ingenic(ingenic_dev); |
| 314 | usb_send_data_to_ingenic(ingenic_dev, ingenic_dev->file_buff, |
| 315 | ingenic_dev->file_len); |
315 | 316 | |
316 | 317 | if (stage == 2) { |
317 | | if (usb_get_ingenic_cpu(ingenic_dev) < 1) |
| 318 | if (usb_get_ingenic_cpu(ingenic_dev) < 1) |
318 | 319 | return -1; |
319 | 320 | usb_ingenic_flush_cache(ingenic_dev); |
320 | 321 | rqst = VR_PROGRAM_START2; |
... | ... | |
331 | 332 | void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev) |
332 | 333 | { |
333 | 334 | if ((ingenic_dev->usb_handle) && (ingenic_dev->interface)) |
334 | | usb_release_interface(ingenic_dev->usb_handle, |
| 335 | usb_release_interface(ingenic_dev->usb_handle, |
335 | 336 | ingenic_dev->interface); |
336 | 337 | |
337 | 338 | if (ingenic_dev->usb_handle) |
... | ... | |
359 | 360 | return 1; |
360 | 361 | } |
361 | 362 | |
| 363 | int usb_ingenic_mem_ops(struct ingenic_dev *ingenic_dev, int ops) |
| 364 | { |
| 365 | int status; |
| 366 | status = usb_control_msg(ingenic_dev->usb_handle, |
| 367 | /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 368 | /* bRequest */ VR_MEM_OPS, |
| 369 | /* wValue */ ops & 0xffff, |
| 370 | /* wIndex */ 0, |
| 371 | /* Data */ 0, |
| 372 | /* wLength */ 0, |
| 373 | USB_TIMEOUT); |
| 374 | |
| 375 | if (status != 0) { |
| 376 | fprintf(stderr, "Error - " |
| 377 | "can't set Ingenic device nand ops: %i\n", status); |
| 378 | return -1; |
| 379 | } |
| 380 | |
| 381 | return 1; |
| 382 | } |
| 383 | |
| 384 | |
362 | 385 | int usb_ingenic_configration(struct ingenic_dev *ingenic_dev, int ops) |
363 | 386 | { |
364 | 387 | int status; |
usbboot/src/nand.c |
| 1 | #include <stdlib.h> |
| 2 | #include <stdio.h> |
| 3 | #include <fcntl.h> |
| 4 | #include <unistd.h> |
| 5 | #include <errno.h> |
| 6 | #include <sys/stat.h> |
| 7 | #include <string.h> |
| 8 | |
| 9 | #include "nand.h" |
| 10 | #include "ingenic_usb.h" |
| 11 | #include "usb_boot_defines.h" |
| 12 | |
| 13 | extern struct hand hand; |
| 14 | |
| 15 | #define NAND_OP(idx, op, mode) (((mode << 12) & 0xf000) | ((idx << 4) & 0xff0) | op) |
| 16 | |
| 17 | #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) |
| 18 | |
| 19 | static const char IMAGE_TYPE[][30] = { |
| 20 | "with oob and ecc", |
| 21 | "with oob and without ecc", |
| 22 | "without oob", |
| 23 | }; |
| 24 | |
| 25 | static int error_check(const char *org, const char *obj, unsigned int size) |
| 26 | { |
| 27 | unsigned int i; |
| 28 | printf("Comparing %d bytes - ", size); |
| 29 | for (i = 0; i < size; i++) { |
| 30 | if (org[i] != obj[i]) { |
| 31 | unsigned int s = (i < 8) ? i : i - 8; // start_dump |
| 32 | printf("FAIL at off %d, wrote 0x%x, read 0x%x\n", i, org[i], obj[i]); |
| 33 | printf(" off %d write: %02x %02x %02x %02x %02x %02x %02x %02x" |
| 34 | " %02x %02x %02x %02x %02x %02x %02x %02x\n", s, |
| 35 | org[s], org[s+1], org[s+2], org[s+3], org[s+4], org[s+5], org[s+6], org[s+7], |
| 36 | org[s+8], org[s+9], org[s+10], org[s+11], org[s+12], org[s+13], org[s+14], org[s+15]); |
| 37 | printf(" off %d read: %02x %02x %02x %02x %02x %02x %02x %02x" |
| 38 | " %02x %02x %02x %02x %02x %02x %02x %02x\n", s, |
| 39 | obj[s], obj[s+1], obj[s+2], obj[s+3], obj[s+4], obj[s+5], obj[s+6], obj[s+7], |
| 40 | obj[s+8], obj[s+9], obj[s+10], obj[s+11], obj[s+12], obj[s+13], obj[s+14], obj[s+15]); |
| 41 | return 0; |
| 42 | } |
| 43 | } |
| 44 | printf("SUCCESS\n"); |
| 45 | return 1; |
| 46 | } |
| 47 | |
| 48 | static int nand_read_pages(struct ingenic_dev *dev, unsigned int start_page, int num_pages, char *buf, |
| 49 | int length, uint16_t op, char *ret) |
| 50 | { |
| 51 | usb_send_data_address_to_ingenic(dev, start_page); |
| 52 | usb_send_data_length_to_ingenic(dev, num_pages); |
| 53 | |
| 54 | usb_ingenic_nand_ops(dev, op); |
| 55 | |
| 56 | usb_read_data_from_ingenic(dev, buf, length); |
| 57 | |
| 58 | usb_read_data_from_ingenic(dev, ret, 8); |
| 59 | |
| 60 | return 0; |
| 61 | } |
| 62 | int nand_markbad(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t block) |
| 63 | { |
| 64 | char ret[8]; |
| 65 | (void)nand_idx; |
| 66 | |
| 67 | if (usb_get_ingenic_cpu(dev) < 3) { |
| 68 | printf("Device unboot! Boot it first!\n"); |
| 69 | return -1; |
| 70 | } |
| 71 | printf("Mark bad block : %d\n", block); |
| 72 | usb_send_data_address_to_ingenic(dev, block); |
| 73 | usb_ingenic_nand_ops(dev, NAND_MARK_BAD); |
| 74 | usb_read_data_from_ingenic(dev, ret, ARRAY_SIZE(ret)); |
| 75 | printf("Mark bad block at %d\n",((ret[3] << 24) | |
| 76 | (ret[2] << 16) | |
| 77 | (ret[1] << 8) | |
| 78 | (ret[0] << 0)) / hand.nand_ppb); |
| 79 | |
| 80 | return 0; |
| 81 | } |
| 82 | |
| 83 | int nand_program_check(struct ingenic_dev *dev, uint8_t nand_idx, |
| 84 | unsigned int start_page, const char *data, |
| 85 | uint32_t length, unsigned int mode) |
| 86 | { |
| 87 | unsigned int page_num, cur_page = -1; |
| 88 | unsigned short op; |
| 89 | static char read_back_buf[MAX_TRANSFER_SIZE]; |
| 90 | char ret[8]; |
| 91 | |
| 92 | printf("Writing NAND page %u len %u...\n", start_page, length); |
| 93 | if (length > (unsigned int)MAX_TRANSFER_SIZE) { |
| 94 | printf("Buffer size too long!\n"); |
| 95 | return -ENOMEM; |
| 96 | } |
| 97 | |
| 98 | if (usb_get_ingenic_cpu(dev) < 3) { |
| 99 | printf("Device unboot! Boot it first!\n"); |
| 100 | return -ENODEV; |
| 101 | } |
| 102 | usb_send_data_to_ingenic(dev, data, length); |
| 103 | |
| 104 | if (mode == NO_OOB) |
| 105 | page_num = DIV_ROUND_UP(length, hand.nand_ps); |
| 106 | else |
| 107 | page_num = DIV_ROUND_UP(length, hand.nand_ps + hand.nand_os); |
| 108 | |
| 109 | op = NAND_OP(nand_idx, NAND_PROGRAM, mode); |
| 110 | |
| 111 | usb_send_data_address_to_ingenic(dev, start_page); |
| 112 | usb_send_data_length_to_ingenic(dev, page_num); |
| 113 | usb_ingenic_nand_ops(dev, op); |
| 114 | |
| 115 | usb_read_data_from_ingenic(dev, ret, 8); |
| 116 | printf("Finish! (len %d start_page %d page_num %d)\n", |
| 117 | length, start_page, page_num); |
| 118 | |
| 119 | switch(mode) { |
| 120 | case NAND_READ: |
| 121 | op = NAND_OP(nand_idx, NAND_READ, NO_OOB); |
| 122 | break; |
| 123 | case NAND_READ_OOB: |
| 124 | op = NAND_OP(nand_idx, NAND_READ_OOB, 0); |
| 125 | break; |
| 126 | case NAND_READ_RAW: |
| 127 | op = NAND_OP(nand_idx, NAND_READ_RAW, NO_OOB); |
| 128 | break; |
| 129 | } |
| 130 | |
| 131 | nand_read_pages(dev, start_page, page_num, read_back_buf, length, op, ret); |
| 132 | printf("Checking %d bytes...", length); |
| 133 | |
| 134 | cur_page = (ret[3] << 24) | (ret[2] << 16) | (ret[1] << 8) | |
| 135 | (ret[0] << 0); |
| 136 | |
| 137 | if (start_page < 1 && |
| 138 | hand.nand_ps == 4096 && |
| 139 | hand.fw_args.cpu_id == 0x4740) { |
| 140 | printf("no check! End at Page: %d\n", cur_page); |
| 141 | } |
| 142 | |
| 143 | if (!error_check(data, read_back_buf, length)) { |
| 144 | // tbd: doesn't the other side skip bad blocks too? Can we just deduct 1 from cur_page? |
| 145 | // tbd: why do we only mark a block as bad if the last page in the block was written? |
| 146 | if (cur_page % hand.nand_ppb == 0) |
| 147 | nand_markbad(dev, nand_idx, (cur_page - 1) / hand.nand_ppb); |
| 148 | } |
| 149 | |
| 150 | printf("End at Page: %d\n", cur_page); |
| 151 | |
| 152 | /* *start_page = cur_page;*/ |
| 153 | return 0; |
| 154 | } |
| 155 | |
| 156 | int nand_erase(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t start_block, |
| 157 | uint32_t num_blocks) |
| 158 | { |
| 159 | uint32_t end_block; |
| 160 | uint16_t op; |
| 161 | static char ret[8]; |
| 162 | |
| 163 | if (start_block > (unsigned int)NAND_MAX_BLK_NUM) { |
| 164 | printf("Start block number overflow!\n"); |
| 165 | return -1; |
| 166 | } |
| 167 | if (num_blocks > (unsigned int)NAND_MAX_BLK_NUM) { |
| 168 | printf("Length block number overflow!\n"); |
| 169 | return -1; |
| 170 | } |
| 171 | |
| 172 | if (usb_get_ingenic_cpu(dev) < 3) { |
| 173 | printf("Device unboot! Boot it first!\n"); |
| 174 | return -1; |
| 175 | } |
| 176 | |
| 177 | printf("Erasing No.%d device No.%d flash (start_blk %u blk_num %u)......\n", |
| 178 | 0, nand_idx, start_block, num_blocks); |
| 179 | |
| 180 | usb_send_data_address_to_ingenic(dev, start_block); |
| 181 | usb_send_data_length_to_ingenic(dev, num_blocks); |
| 182 | |
| 183 | op = NAND_OP(nand_idx, NAND_ERASE, 0); |
| 184 | usb_ingenic_nand_ops(dev, op); |
| 185 | |
| 186 | usb_read_data_from_ingenic(dev, ret, 8); |
| 187 | printf("Finish!"); |
| 188 | |
| 189 | end_block = ((ret[3] << 24) | (ret[2] << 16) | |
| 190 | (ret[1] << 8) | (ret[0] << 0)) / hand.nand_ppb; |
| 191 | printf("Return: %02x %02x %02x %02x %02x %02x %02x %02x (position %d)\n", |
| 192 | ret[0], ret[1], ret[2], ret[3], ret[4], ret[5], ret[6], ret[7], end_block); |
| 193 | if (!hand.nand_force_erase) { |
| 194 | /* not force erase, show bad block infomation */ |
| 195 | printf("There are marked bad blocks: %d\n", |
| 196 | end_block - start_block - num_blocks ); |
| 197 | } else { |
| 198 | /* force erase, no bad block infomation can show */ |
| 199 | printf("Force erase, no bad block infomation!\n" ); |
| 200 | } |
| 201 | |
| 202 | return 0; |
| 203 | } |
| 204 | |
| 205 | int nand_program_file(struct ingenic_dev *dev, uint8_t nand_idx, |
| 206 | uint32_t start_page, const char *filename, int mode) |
| 207 | { |
| 208 | uint32_t start_block, num_blocks; |
| 209 | int flen, m, j, k; |
| 210 | unsigned int page_num, code_len, offset, transfer_size; |
| 211 | int fd, status; |
| 212 | struct stat fstat; |
| 213 | static char code_buf[MAX_TRANSFER_SIZE]; |
| 214 | |
| 215 | status = stat(filename, &fstat); |
| 216 | |
| 217 | if (status < 0) { |
| 218 | fprintf(stderr, "Error - can't get file size from '%s': %s\n", |
| 219 | filename, strerror(errno)); |
| 220 | return -1; |
| 221 | } |
| 222 | flen = fstat.st_size; |
| 223 | |
| 224 | fd = open(filename, O_RDONLY); |
| 225 | if (fd < 0) { |
| 226 | fprintf(stderr, "Error - can't open file '%s': %s\n", |
| 227 | filename, strerror(errno)); |
| 228 | return -1; |
| 229 | } |
| 230 | |
| 231 | printf("Programing No.%d device, flen %d, start page %d...\n", 0, |
| 232 | flen, start_page); |
| 233 | |
| 234 | /* printf("length %d flen %d\n", n_in.length, flen); */ |
| 235 | if (mode == NO_OOB) |
| 236 | transfer_size = (hand.nand_ppb * hand.nand_ps); |
| 237 | else |
| 238 | transfer_size = (hand.nand_ppb * (hand.nand_ps + hand.nand_os)); |
| 239 | |
| 240 | start_block = start_page / hand.nand_ppb; |
| 241 | num_blocks = flen / (transfer_size - 1) + 1; |
| 242 | |
| 243 | if (nand_erase(dev, nand_idx, start_block, num_blocks)) |
| 244 | return -1; |
| 245 | |
| 246 | m = flen / transfer_size; |
| 247 | j = flen % transfer_size; |
| 248 | |
| 249 | printf("Size to send %d, transfer_size %d\n", flen, transfer_size); |
| 250 | printf("Image type : %s\n", IMAGE_TYPE[mode]); |
| 251 | printf("It will cause %d times buffer transfer.\n", j == 0 ? m : m + 1); |
| 252 | |
| 253 | if (mode == NO_OOB) |
| 254 | page_num = transfer_size / hand.nand_ps; |
| 255 | else |
| 256 | page_num = transfer_size / (hand.nand_ps + hand.nand_os); |
| 257 | |
| 258 | |
| 259 | offset = 0; |
| 260 | for (k = 0; k < m; k++) { |
| 261 | code_len = transfer_size; |
| 262 | status = read(fd, code_buf, code_len); |
| 263 | if (status < (int)code_len) { |
| 264 | fprintf(stderr, "Error - can't read file '%s': %s\n", |
| 265 | filename, strerror(errno)); |
| 266 | goto close; |
| 267 | } |
| 268 | |
| 269 | if (nand_program_check(dev, nand_idx, start_page, code_buf, code_len, mode) == -1) |
| 270 | goto close; |
| 271 | |
| 272 | /* if (start_page - nand_in->start > hand.nand_ppb) |
| 273 | printf("Skip a old bad block !\n");*/ |
| 274 | |
| 275 | offset += code_len ; |
| 276 | } |
| 277 | |
| 278 | if (j) { |
| 279 | code_len = j; |
| 280 | if (j % hand.nand_ps) |
| 281 | j += hand.nand_ps - (j % hand.nand_ps); |
| 282 | memset(code_buf, 0, j); /* set all to null */ |
| 283 | |
| 284 | status = read(fd, code_buf, code_len); |
| 285 | |
| 286 | if (status < (int)code_len) { |
| 287 | fprintf(stderr, "Error - can't read file '%s': %s\n", |
| 288 | filename, strerror(errno)); |
| 289 | goto close; |
| 290 | } |
| 291 | |
| 292 | if (nand_program_check(dev, nand_idx, start_page, code_buf, j, mode) == -1) |
| 293 | goto close; |
| 294 | |
| 295 | /* |
| 296 | if (start_page - nand_in->start > hand.nand_ppb) |
| 297 | printf("Skip a old bad block !"); |
| 298 | */ |
| 299 | } |
| 300 | close: |
| 301 | close(fd); |
| 302 | return 0; |
| 303 | } |
| 304 | |
| 305 | int nand_prog(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t start_page, |
| 306 | const char *filename, int mode) |
| 307 | { |
| 308 | if (hand.nand_plane > 1) |
| 309 | printf("ERROR"); |
| 310 | else |
| 311 | nand_program_file(dev, nand_idx, start_page, filename, mode); |
| 312 | |
| 313 | return 0; |
| 314 | } |
| 315 | |
| 316 | int nand_query(struct ingenic_dev *dev, uint8_t nand_idx) |
| 317 | { |
| 318 | uint16_t op; |
| 319 | char ret[8]; |
| 320 | |
| 321 | if (usb_get_ingenic_cpu(dev) < 3) { |
| 322 | printf("Device unboot! Boot it first!\n"); |
| 323 | return -1; |
| 324 | } |
| 325 | |
| 326 | printf("ID of No.%u device No.%u flash: \n", 0, nand_idx); |
| 327 | |
| 328 | op = NAND_OP(nand_idx, NAND_QUERY, 0); |
| 329 | |
| 330 | usb_ingenic_nand_ops(dev, op); |
| 331 | usb_read_data_from_ingenic(dev, ret, ARRAY_SIZE(ret)); |
| 332 | printf("Vendor ID :0x%x \n", (unsigned char)ret[0]); |
| 333 | printf("Product ID :0x%x \n", (unsigned char)ret[1]); |
| 334 | printf("Chip ID :0x%x \n", (unsigned char)ret[2]); |
| 335 | printf("Page ID :0x%x \n", (unsigned char)ret[3]); |
| 336 | printf("Plane ID :0x%x \n", (unsigned char)ret[4]); |
| 337 | |
| 338 | usb_read_data_from_ingenic(dev, ret, ARRAY_SIZE(ret)); |
| 339 | printf("Operation status: Success!\n"); |
| 340 | |
| 341 | return 0; |
| 342 | } |
| 343 | |
| 344 | int nand_read(struct ingenic_dev *dev, uint8_t nand_idx, int mode, |
| 345 | uint32_t start_page, uint32_t length, uint32_t ram_addr) |
| 346 | { |
| 347 | uint16_t op; |
| 348 | uint32_t page; |
| 349 | uint32_t request_length; |
| 350 | uint32_t pages_per_request; |
| 351 | char ret[8]; |
| 352 | char *buf; |
| 353 | int fd; |
| 354 | |
| 355 | if (start_page > NAND_MAX_PAGE_NUM) { |
| 356 | printf("Page number overflow!\n"); |
| 357 | return -1; |
| 358 | } |
| 359 | if (usb_get_ingenic_cpu(dev) < 3) { |
| 360 | printf("Device unboot! Boot it first!\n"); |
| 361 | return -1; |
| 362 | } |
| 363 | if (nand_idx >= 16) |
| 364 | return -1; |
| 365 | |
| 366 | printf("Reading from No.%u device No.%u flash....\n", 0, nand_idx); |
| 367 | |
| 368 | |
| 369 | switch(mode) { |
| 370 | case NAND_READ: |
| 371 | op = NAND_OP(nand_idx, NAND_READ, NO_OOB); |
| 372 | break; |
| 373 | case NAND_READ_OOB: |
| 374 | op = NAND_OP(nand_idx, NAND_READ_OOB, 0); |
| 375 | break; |
| 376 | case NAND_READ_RAW: |
| 377 | op = NAND_OP(nand_idx, NAND_READ_RAW, NO_OOB); |
| 378 | break; |
| 379 | case NAND_READ_TO_RAM: |
| 380 | op = NAND_OP(nand_idx, NAND_READ_TO_RAM, NO_OOB); |
| 381 | printf("Reading nand to RAM: 0x%x\n", ram_addr); |
| 382 | usb_ingenic_start(dev, VR_PROGRAM_START1, ram_addr); |
| 383 | break; |
| 384 | default: |
| 385 | printf("unknow mode!\n"); |
| 386 | return -1; |
| 387 | } |
| 388 | |
| 389 | pages_per_request = 1; |
| 390 | request_length = hand.nand_ps * pages_per_request; |
| 391 | |
| 392 | page = start_page; |
| 393 | |
| 394 | buf = malloc(request_length); |
| 395 | |
| 396 | fd = open("/tmp/dump.bin", O_WRONLY | O_TRUNC | O_CREAT); |
| 397 | if (fd < 0) { |
| 398 | printf("Failed to open file\n"); |
| 399 | return errno; |
| 400 | } |
| 401 | |
| 402 | while (length > 0) { |
| 403 | if (request_length > length) |
| 404 | request_length = length; |
| 405 | |
| 406 | nand_read_pages(dev, page, pages_per_request, buf, request_length, op, ret); |
| 407 | |
| 408 | write(fd, buf, request_length); |
| 409 | |
| 410 | length -= request_length; |
| 411 | page += pages_per_request; |
| 412 | } |
| 413 | close(fd); |
| 414 | printf("Operation end position : %u \n", |
| 415 | (ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0)); |
| 416 | free(buf); |
| 417 | |
| 418 | return 1; |
| 419 | } |
usbboot/xburst_stage2/boothandler.c |
20 | 20 | */ |
21 | 21 | |
22 | 22 | #include "jz4740.h" |
23 | | #include "usb.h" |
| 23 | #include "usb.h" |
24 | 24 | #include "error.h" |
25 | 25 | #include "usb_boot.h" |
26 | 26 | #include "usb_boot_defines.h" |
... | ... | |
28 | 28 | #include "udc.h" |
29 | 29 | #define dprintf(x) serial_puts(x) |
30 | 30 | |
| 31 | #define MEM_WRITE 0 |
| 32 | #define MEM_READ 1 |
| 33 | |
| 34 | #define MEM_8BIT (0 << 1) |
| 35 | #define MEM_16BIT (1 << 1) |
| 36 | #define MEM_32BIT (2 << 1) |
| 37 | |
| 38 | #define MEM_WRITE8 (MEM_WRITE | MEM_8BIT) |
| 39 | #define MEM_WRITE16 (MEM_WRITE | MEM_16BIT) |
| 40 | #define MEM_WRITE32 (MEM_WRITE | MEM_32BIT) |
| 41 | #define MEM_READ8 (MEM_READ | MEM_8BIT) |
| 42 | #define MEM_READ16 (MEM_READ | MEM_16BIT) |
| 43 | #define MEM_READ32 (MEM_READ | MEM_32BIT) |
| 44 | |
| 45 | |
| 46 | |
31 | 47 | unsigned int (*nand_query)(u8 *); |
32 | 48 | int (*nand_init)(int bus_width, int row_cycle, int page_size, int page_per_block, |
33 | 49 | int,int,int,int); |
... | ... | |
42 | 58 | void (*nand_disable) (unsigned int csn); |
43 | 59 | |
44 | 60 | struct hand Hand,*Hand_p; |
45 | | extern u32 Bulk_out_buf[BULK_OUT_BUF_SIZE]; |
46 | | extern u32 Bulk_in_buf[BULK_IN_BUF_SIZE]; |
| 61 | extern u32 Bulk_buf[BULK_BUF_SIZE]; |
47 | 62 | extern u16 handshake_PKT[4]; |
48 | 63 | extern udc_state; |
49 | 64 | extern void *memset(void *s, int c, size_t count); |
... | ... | |
68 | 83 | void config_hand() |
69 | 84 | { |
70 | 85 | struct hand *hand_p; |
71 | | hand_p=(struct hand *)Bulk_out_buf; |
72 | | memcpy(&Hand, (unsigned char *)Bulk_out_buf, sizeof(struct hand)); |
| 86 | hand_p=(struct hand *)Bulk_buf; |
| 87 | memcpy(&Hand, (unsigned char *)Bulk_buf, sizeof(struct hand)); |
73 | 88 | |
74 | 89 | #if 0 |
75 | 90 | Hand.nand_bw=hand_p->nand_bw; |
... | ... | |
104 | 119 | else |
105 | 120 | HW_SendPKT(0,temp2,8); |
106 | 121 | udc_state = IDLE; |
107 | | return ERR_OK; |
| 122 | return ERR_OK; |
108 | 123 | } |
109 | | |
| 124 | |
110 | 125 | int SET_DATA_ADDERSS_Handle(u8 *buf) |
111 | 126 | { |
112 | 127 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
... | ... | |
115 | 130 | serial_put_hex(start_addr); |
116 | 131 | return ERR_OK; |
117 | 132 | } |
118 | | |
| 133 | |
119 | 134 | int SET_DATA_LENGTH_Handle(u8 *buf) |
120 | 135 | { |
121 | 136 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
... | ... | |
129 | 144 | { |
130 | 145 | return ERR_OK; |
131 | 146 | } |
132 | | |
| 147 | |
133 | 148 | int PROGRAM_START1_Handle(u8 *buf) |
134 | 149 | { |
135 | 150 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
... | ... | |
150 | 165 | f(); |
151 | 166 | return ERR_OK; |
152 | 167 | } |
153 | | |
| 168 | |
| 169 | int MEM_OPS_Handle(u8 *buf) |
| 170 | { |
| 171 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
| 172 | u32 val; |
| 173 | |
| 174 | switch (dreq->wValue) { |
| 175 | case MEM_WRITE8: |
| 176 | *((volatile u8*)(start_addr)) = (u8)ops_length; |
| 177 | handshake_PKT[0] = ops_length & 0xff; |
| 178 | handshake_PKT[1] = 8; |
| 179 | break; |
| 180 | case MEM_WRITE16: |
| 181 | *((volatile u16*)(start_addr)) = (u16)ops_length; |
| 182 | handshake_PKT[0] = ops_length & 0xffff; |
| 183 | handshake_PKT[1] = 16; |
| 184 | break; |
| 185 | case MEM_WRITE32: |
| 186 | *((volatile u32*)(start_addr)) = ops_length; |
| 187 | handshake_PKT[0] = ops_length; |
| 188 | handshake_PKT[1] = ops_length >> 16; |
| 189 | break; |
| 190 | case MEM_READ8: |
| 191 | val = *((volatile u8*)(start_addr)); |
| 192 | handshake_PKT[0] = (u16)val; |
| 193 | handshake_PKT[1] = (u16)(val >> 16); |
| 194 | break; |
| 195 | case MEM_READ16: |
| 196 | val = *((volatile u16*)(start_addr)); |
| 197 | handshake_PKT[0] = (u16)val; |
| 198 | handshake_PKT[1] = (u16)(val >> 16); |
| 199 | break; |
| 200 | case MEM_READ32: |
| 201 | val = *((volatile u32*)(start_addr)); |
| 202 | handshake_PKT[0] = (u16)val; |
| 203 | handshake_PKT[1] = (u16)(val >> 16); |
| 204 | break; |
| 205 | default: |
| 206 | handshake_PKT[0] = 0xDEAD; |
| 207 | handshake_PKT[1] = 0xC0DE; |
| 208 | break; |
| 209 | } |
| 210 | handshake_PKT[2] = 0; |
| 211 | handshake_PKT[3] = 0; |
| 212 | HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT)); |
| 213 | return ERR_OK; |
| 214 | } |
| 215 | |
154 | 216 | int NOR_OPS_Handle(u8 *buf) |
155 | 217 | { |
156 | 218 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
| 219 | udc_state = IDLE; |
157 | 220 | return ERR_OK; |
158 | 221 | } |
159 | 222 | |
... | ... | |
171 | 234 | { |
172 | 235 | case NAND_QUERY: |
173 | 236 | dprintf("\n Request : NAND_QUERY!"); |
174 | | nand_query((u8 *)Bulk_in_buf); |
175 | | HW_SendPKT(1, Bulk_in_buf, 8); |
| 237 | nand_query((u8 *)Bulk_buf); |
| 238 | HW_SendPKT(1, Bulk_buf, 8); |
176 | 239 | handshake_PKT[3]=(u16)ERR_OK; |
177 | 240 | udc_state = BULK_IN; |
178 | 241 | break; |
... | ... | |
186 | 249 | handshake_PKT[0] = (u16) ret_dat; |
187 | 250 | handshake_PKT[1] = (u16) (ret_dat>>16); |
188 | 251 | HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT)); |
189 | | udc_state = IDLE; |
| 252 | udc_state = IDLE; |
190 | 253 | |
191 | 254 | break; |
192 | 255 | case NAND_READ_OOB: |
193 | 256 | dprintf("\n Request : NAND_READ_OOB!"); |
194 | | memset(Bulk_in_buf,0,ops_length*Hand.nand_ps); |
195 | | ret_dat = nand_read_oob(Bulk_in_buf,start_addr,ops_length); |
| 257 | memset(Bulk_buf,0,ops_length*Hand.nand_ps); |
| 258 | ret_dat = nand_read_oob(Bulk_buf,start_addr,ops_length); |
196 | 259 | handshake_PKT[0] = (u16) ret_dat; |
197 | 260 | handshake_PKT[1] = (u16) (ret_dat>>16); |
198 | | HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps); |
199 | | udc_state = BULK_IN; |
| 261 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps); |
| 262 | udc_state = BULK_IN; |
200 | 263 | break; |
201 | 264 | case NAND_READ_RAW: |
202 | 265 | dprintf("\n Request : NAND_READ_RAW!"); |
203 | 266 | switch (option) |
204 | 267 | { |
205 | 268 | case OOB_ECC: |
206 | | nand_read_raw(Bulk_in_buf,start_addr,ops_length,option); |
207 | | HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os)); |
| 269 | nand_read_raw(Bulk_buf,start_addr,ops_length,option); |
| 270 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os)); |
208 | 271 | handshake_PKT[0] = (u16) ret_dat; |
209 | 272 | handshake_PKT[1] = (u16) (ret_dat>>16); |
210 | 273 | udc_state = BULK_IN; |
211 | 274 | break; |
212 | 275 | default: |
213 | | nand_read_raw(Bulk_in_buf,start_addr,ops_length,option); |
214 | | HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps); |
| 276 | nand_read_raw(Bulk_buf,start_addr,ops_length,option); |
| 277 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps); |
215 | 278 | handshake_PKT[0] = (u16) ret_dat; |
216 | 279 | handshake_PKT[1] = (u16) (ret_dat>>16); |
217 | 280 | udc_state = BULK_IN; |
... | ... | |
234 | 297 | switch (option) |
235 | 298 | { |
236 | 299 | case OOB_ECC: |
237 | | ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_ECC); |
| 300 | ret_dat = nand_read(Bulk_buf,start_addr,ops_length,OOB_ECC); |
238 | 301 | handshake_PKT[0] = (u16) ret_dat; |
239 | 302 | handshake_PKT[1] = (u16) (ret_dat>>16); |
240 | | HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os )); |
| 303 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os )); |
241 | 304 | udc_state = BULK_IN; |
242 | 305 | break; |
243 | 306 | case OOB_NO_ECC: |
244 | | ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_NO_ECC); |
| 307 | ret_dat = nand_read(Bulk_buf,start_addr,ops_length,OOB_NO_ECC); |
245 | 308 | handshake_PKT[0] = (u16) ret_dat; |
246 | 309 | handshake_PKT[1] = (u16) (ret_dat>>16); |
247 | | HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os)); |
| 310 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os)); |
248 | 311 | udc_state = BULK_IN; |
249 | 312 | break; |
250 | 313 | case NO_OOB: |
251 | | ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,NO_OOB); |
| 314 | ret_dat = nand_read(Bulk_buf,start_addr,ops_length,NO_OOB); |
252 | 315 | handshake_PKT[0] = (u16) ret_dat; |
253 | 316 | handshake_PKT[1] = (u16) (ret_dat>>16); |
254 | | HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps); |
| 317 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps); |
255 | 318 | udc_state = BULK_IN; |
256 | 319 | break; |
257 | 320 | } |
... | ... | |
260 | 323 | case NAND_PROGRAM: |
261 | 324 | dprintf("\n Request : NAND_PROGRAM!"); |
262 | 325 | // dprintf("\n Option : %x",option); |
263 | | ret_dat = nand_program((void *)Bulk_out_buf, |
| 326 | ret_dat = nand_program((void *)Bulk_buf, |
264 | 327 | start_addr,ops_length,option); |
265 | 328 | dprintf("\n NAND_PROGRAM finish!"); |
266 | 329 | handshake_PKT[0] = (u16) ret_dat; |
... | ... | |
294 | 357 | { |
295 | 358 | case SDRAM_LOAD: |
296 | 359 | // dprintf("\n Request : SDRAM_LOAD!"); |
297 | | ret_dat = (u32)memcpy((u8 *)start_addr,Bulk_out_buf,ops_length); |
| 360 | ret_dat = (u32)memcpy((u8 *)start_addr,Bulk_buf,ops_length); |
298 | 361 | handshake_PKT[0] = (u16) ret_dat; |
299 | 362 | handshake_PKT[1] = (u16) (ret_dat>>16); |
300 | 363 | HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT)); |
... | ... | |
314 | 377 | //Init nand flash |
315 | 378 | nand_init_4740(Hand.nand_bw,Hand.nand_rc,Hand.nand_ps,Hand.nand_ppb, |
316 | 379 | Hand.nand_bbpage,Hand.nand_bbpos,Hand.nand_force_erase,Hand.nand_eccpos); |
317 | | |
| 380 | |
318 | 381 | dprintf("\nnand_ps, nand_ppb, nand_bbpage, nand_bbpos, nand_eccpos\n"); |
319 | 382 | serial_put_hex(Hand.nand_ps); |
320 | 383 | serial_put_hex(Hand.nand_ppb); |
... | ... | |
368 | 431 | config_hand(); |
369 | 432 | break; |
370 | 433 | default:; |
371 | | |
372 | 434 | } |
373 | 435 | Borad_Init(); |
374 | 436 | return ERR_OK; |