PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
romwrite.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "irx_imports.h"
12#include <loadcore.h>
13#include <s147_mmio_hwport.h>
14#include <sys/fcntl.h>
15
16IRX_ID("ROMWRITE", 7, 1);
17// Text section hash:
18// 6674c59e79963dd4c1d7f6fccfecbf70
19
20typedef struct nand_id_desc_info_
21{
22 u32 m_id[5];
23 const char *m_nand_name;
24 const char *m_nand_desc;
25 int m_page_size_noecc;
26 int m_page_size_withecc;
27 int m_pages_per_block;
28 int m_block_size;
30
31typedef union romwrite_part_buf_
32{
33 u8 m_buf[0x20000];
35 s147nand_dir_t m_dir;
36 s147nand_direntry_t m_direntry[64];
38
39static void thread_proc(void *userdata);
40static void do_toggle_dev9addr_inner(int len, int cnt);
41static void set_boot_video_mode(int flg);
42static void do_set_flag(int flg);
43static void do_set_secr_code(char code1, char code2);
44static void do_handle_atfile_image(int part, const char *str);
45static void do_set_atfile_147_dir(const char *str);
46static int do_start_write_proc(void);
47static int do_format_device(int abspart);
48static int do_write_partition(int part);
49static int check_badblock_count(void);
50static int get_nand_partition_offset(int part, int abspart);
51static int get_nand_partition_size(int part, int abspart);
52static int get_nand_block_size_div_32_div_64(void);
53static int get_nand_block_size_div_32(void);
54static void do_dma_write_bytes_multi(void *ptr, int pageoffs, int pagecnt);
55static int do_list_files(int part);
56static void do_output_bb_info(int blocksd, int abspart, int bboffs);
57static int do_verify(void *buf1, void *buf2, int len);
58static const nand_id_desc_info_t *do_parse_device_info(const char *nandid);
59// Unofficial: printf to IOP Kprintf instead of EE
60#define USER_PRINTF(...) Kprintf(__VA_ARGS__)
61// Unofficial: printf to EE is omitted
62#define STATUS_PRINTF(...) Kprintf(__VA_ARGS__)
63
64static const nand_id_desc_info_t g_nand_type_info[4] = {
65 {
66 {0xEC, 0xDA, 0xFFFFFFFF, 0x15, 0xFFFFFFFF},
67 "SAMSUNG K9F2G08U0M",
68 "8bit width, 256MBytes",
69 0x800,
70 0x840,
71 0x40,
72 0x800,
73 },
74 {
75 {0xEC, 0xDC, 0x10, 0x95, 0x54},
76 "SAMSUNG K9F4G08U0M",
77 "8bit width, 512MBytes",
78 0x800,
79 0x840,
80 0x40,
81 0x1000,
82 },
83 {
84 {0xEC, 0xD3, 0x51, 0x95, 0x58},
85 "SAMSUNG K9K8G08U0M",
86 "8bit width, 1GBytes",
87 0x800,
88 0x840,
89 0x40,
90 0x2000,
91 },
92 {{0x0, 0x0, 0x0, 0x0, 0x0}, NULL, NULL, 0, 0, 0, 0}};
93// Unofficial: move to bss
94static char g_secr_code[2];
95// Unofficial: move to bss
96static int g_curflag;
97// Unofficial: move to bss
98static int g_boot_video_mode;
99// Unofficial: move to bss
100static char *g_page_buf;
101// Unofficial: move to bss
102static int g_badblock_count;
103static char g_product_code_tmp[32];
104static u8 *g_blockinfo_str_buf;
105static u16 *g_blockinfo_dat_buf;
106static const nand_id_desc_info_t *g_device_info;
107static char g_atfile_part_image[8][0x100];
108static char g_atfile_info_image[0x100];
109static char g_atfile_147_dir[0x100];
110static romwrite_part_buf_t g_nand_partbuf __attribute__((__aligned__(16)));
111
112static void do_format_nand_device(char devindchr)
113{
114 switch ( devindchr )
115 {
116 case '2':
117 do_set_flag(0x10000);
118 break;
119 case '4':
120 do_set_flag(0x20000);
121 break;
122 case '8':
123 do_set_flag(0x30000);
124 break;
125 default:
126 do_set_flag(0xF0000);
127 devindchr = ' ';
128 break;
129 }
130 STATUS_PRINTF(" -f%c: Format NAND(atfile:) device\n", devindchr);
131}
132
133static char *do_read_product_code(int fd)
134{
135 read(fd, g_product_code_tmp, sizeof(g_product_code_tmp));
136 STATUS_PRINTF(" ---> OK, set product code - \"%s\"\n", &g_product_code_tmp[16]);
137 // Unofficial: omit Blowfish hashing S147NBGI
138 return &g_product_code_tmp[4];
139}
140
141int _start(int ac, char **av)
142{
143 iop_thread_t thparam;
144 int thid;
145 int i;
146 char secrcode1;
147 char secrcode2;
148 int fd;
149 const char *product_code;
150 int image_file_idx;
151
152 // Unofficial: omit SIF output command set to 30
153 if ( ac < 2 )
154 {
155 USER_PRINTF("SYS147 ROM Writer (version 0x%04x)\n\n", 0x701);
156 DelayThread(10000);
157 USER_PRINTF("usage: %s [OPTION]... [FILE]...\n", "romwrite.irx");
158 DelayThread(10000);
159 USER_PRINTF(" -m, --main ............. MainPCB mode (Send PRINTF to EE)\n");
160 DelayThread(10000);
161 USER_PRINTF(" -s0 .................... Set default security code\n");
162 DelayThread(10000);
163 USER_PRINTF(" -sr .................... Read \"s147secr.147\" and set security code\n");
164 DelayThread(10000);
165 USER_PRINTF(" -f(f2, f4, f8) ......... Format NAND(atfile:) device\n");
166 DelayThread(10000);
167 USER_PRINTF(" -0([1..7]) filename .... Write \"atfile[0..7]:\" image file\n");
168 DelayThread(10000);
169 USER_PRINTF(" -d directory ........... Search \"atfile*.147\" in the directory and Write\n");
170 DelayThread(10000);
171 USER_PRINTF(" -i filename ............ Write \"atfile9:info\" image from file\n");
172 DelayThread(10000);
173 USER_PRINTF(" -l ..................... Read NAND device and Display all file list\n");
174 DelayThread(10000);
175 USER_PRINTF(" -v, --vga .............. Set boot video mode (VGA)\n");
176 DelayThread(10000);
177 return MODULE_NO_RESIDENT_END;
178 }
179 // Unofficial: init var here instead
180 g_badblock_count = 1;
181 USER_PRINTF("\n====== romwrite(version 0x%04x): Check argument ======\n", 0x701);
182 DelayThread(10000);
183 for ( i = 1; i < ac; i += 1 )
184 {
185 if ( !strcmp(av[i], "-m") || !strcmp(av[i], "--main") )
186 {
187 USER_PRINTF(" -m, --main : MainPCB mode (Send PRINTF to EE)\n");
188 DelayThread(10000);
189 // Unofficial: Flag setting omitted
190 break;
191 }
192 if ( !strcmp(av[i], "-v") || !strcmp(av[i], "--vga") )
193 {
194 USER_PRINTF(" -v, --vga : Set boot video mode (VGA)\n");
195 DelayThread(10000);
196 set_boot_video_mode(2);
197 break;
198 }
199 }
200 for ( i = 1; i < ac; i += 1 )
201 {
202 if ( av[i][0] != '-' )
203 continue;
204 switch ( av[i][1] )
205 {
206 case '0':
207 case '1':
208 case '2':
209 case '3':
210 case '4':
211 case '5':
212 case '6':
213 case '7':
214 image_file_idx = strtol(av[i] + 1, 0, 10);
215 STATUS_PRINTF(" -%d : Write \"atfile%d:\" image file\n", image_file_idx, image_file_idx);
216 do_set_flag(1 << image_file_idx);
217 i += 1;
218 do_handle_atfile_image(image_file_idx, av[i]);
219 break;
220 case 'd':
221 STATUS_PRINTF(" -d : Search \"atfile*.147\" in the directory and Write\n");
222 i += 1;
223 do_set_flag(0x2000000);
224 do_set_atfile_147_dir(av[i]);
225 break;
226 case 'f':
227 do_format_nand_device(av[i][2]);
228 break;
229 case 'i':
230 STATUS_PRINTF(" -i : Write \"atfile9:info\" image\n");
231 do_set_flag(0x200);
232 i += 1;
233 do_handle_atfile_image(9, av[i]);
234 break;
235 case 'l':
236 STATUS_PRINTF(" -l : Read NAND device and Display all file list\n");
237 do_set_flag(0x4000000);
238 break;
239 case 's':
240 switch ( av[i][2] )
241 {
242 case '0':
243 STATUS_PRINTF(" -s0: Set default security code\n");
244 do_set_flag(0x1000000);
245 do_set_secr_code(0xFF, 0xFF);
246 break;
247 case 'r':
248 STATUS_PRINTF(" -sr: Read \"s147secr.147\" file\n");
249 do_set_flag(0x1000000);
250 i += 1;
251 fd = open(av[i], O_RDONLY);
252 if ( fd < 0 )
253 {
254 STATUS_PRINTF(" ---> File not found, set default code\n");
255 do_set_secr_code(0xFF, 0xFF);
256 break;
257 }
258 product_code = do_read_product_code(fd);
259 do_set_secr_code(product_code[0], product_code[1]);
260 close(fd);
261 break;
262 default:
263 STATUS_PRINTF(" -s : Set immediate secrity code\n");
264 i += 1;
265 secrcode1 = strtol(av[i], 0, 10);
266 i += 1;
267 secrcode2 = strtol(av[i], 0, 10);
268 do_set_flag(0x1000000);
269 do_set_secr_code(secrcode1, secrcode2);
270 break;
271 }
272 break;
273 default:
274 break;
275 }
276 }
277 STATUS_PRINTF("\n");
278 thparam.attr = TH_C;
279 thparam.thread = thread_proc;
280 thparam.priority = 0x7A;
281 thparam.stacksize = 0x80000;
282 thparam.option = 0;
283 thid = CreateThread(&thparam);
284 if ( thid <= 0 )
285 return MODULE_NO_RESIDENT_END;
286 StartThread(thid, 0);
287 return MODULE_RESIDENT_END;
288}
289
290static void thread_proc(void *userdata)
291{
292 int i;
293 USE_S147_DEV9_MEM_MMIO();
294
295 (void)userdata;
296 if ( do_start_write_proc() )
297 {
298 STATUS_PRINTF("\n****** Aborted ******\n\n");
299 for ( ;; )
300 {
301 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
302 s147_dev9_mem_mmio->m_led = 1;
303 DelayThread(250000);
304 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
305 s147_dev9_mem_mmio->m_led = 0;
306 DelayThread(250000);
307 }
308 }
309 STATUS_PRINTF("====== Completed ======\n\n");
310 for ( ;; )
311 {
312 for ( i = 1; i < 20; i += 1 )
313 {
314 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
315 do_toggle_dev9addr_inner(5 * i, 50);
316 }
317 for ( i = 20; i > 0; i -= 1 )
318 {
319 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
320 do_toggle_dev9addr_inner(5 * i, 50);
321 }
322 }
323}
324
325static void do_toggle_dev9addr_inner(int len, int cnt)
326{
327 int i;
328 USE_S147_DEV9_MEM_MMIO();
329
330 for ( i = 0; i < cnt; i += 1 )
331 {
332 if ( len > 0 )
333 {
334 s147_dev9_mem_mmio->m_led = 3;
335 DelayThread(10 * len);
336 }
337 if ( len < 100 )
338 {
339 s147_dev9_mem_mmio->m_led = 0;
340 DelayThread(10 * (100 - len));
341 }
342 }
343}
344
345// Unused function omitted
346
347static unsigned int generate_acio_delay_val(char dmat_val, char rddl_val, char wrdl_val)
348{
349 return (((dmat_val - 1) & 0xF) << 24) | (((rddl_val - 1) & 0xF) << 4) | 0xA01A0100 | ((wrdl_val - 1) & 0xF);
350}
351
352// Unused function omitted
353
354// Send print to OSDSYS related omitted
355
356static void set_boot_video_mode(int flg)
357{
358 g_boot_video_mode = flg;
359}
360
361static void do_set_flag(int flg)
362{
363 g_curflag |= flg;
364}
365
366static void do_set_secr_code(char code1, char code2)
367{
368 g_secr_code[0] = code1;
369 g_secr_code[1] = code2;
370}
371
372static void do_handle_atfile_image(int part, const char *str)
373{
374 if ( part == 9 )
375 {
376 strcpy(g_atfile_info_image, str);
377 return;
378 }
379 if ( part >= 0 && part < 8 && g_atfile_part_image[part] != str )
380 {
381 // Unofficial: check if pointer is different
382 strcpy(g_atfile_part_image[part], str);
383 }
384}
385
386static void do_set_atfile_147_dir(const char *str)
387{
388 strcpy(g_atfile_147_dir, str);
389}
390
391static int do_start_write_proc(void)
392{
393 s147nand_info_t *nandinf;
394 int state;
395 int part;
396 int logaddrtable;
397 u8 nandid[5];
398 USE_S147_DEV9_MEM_MMIO();
399
400 close(open("ctrl99:watchdog-stop", O_RDONLY));
401 if ( (g_curflag & 0x1000000) != 0 )
402 {
403 STATUS_PRINTF("====== Set security code ======\n");
404 s147_dev9_mem_mmio->m_security_unlock_set1 = g_secr_code[0];
405 s147_dev9_mem_mmio->m_security_unlock_set2 = g_secr_code[1];
406 STATUS_PRINTF("\n");
407 }
408 STATUS_PRINTF("====== Device information ======\n");
409 s147nand_26_nand_readid(nandid);
410 g_device_info = do_parse_device_info((char *)nandid);
411 if ( !g_device_info )
412 {
413 STATUS_PRINTF(" ID = %02X/%02X/%02X/%02X/%02X\n", nandid[0], nandid[1], nandid[2], nandid[3], nandid[4]);
414 STATUS_PRINTF("\nError: Unknown Device\n");
415 return -1;
416 }
417 STATUS_PRINTF(" ID = %02X/%02X/%02X/%02X/%02X\n", nandid[0], nandid[1], nandid[2], nandid[3], nandid[4]);
418 STATUS_PRINTF(" \"%s\", %s\n", g_device_info->m_nand_name, g_device_info->m_nand_desc);
419 STATUS_PRINTF(
420 " PageSize = %d + %d (Bytes)\n",
421 g_device_info->m_page_size_noecc,
422 g_device_info->m_page_size_withecc - g_device_info->m_page_size_noecc);
423 STATUS_PRINTF(" Pages/Block = %d (Pages)\n", g_device_info->m_pages_per_block);
424 STATUS_PRINTF(" BlockSize = %d (Blocks)\n", g_device_info->m_block_size);
425 STATUS_PRINTF("\n");
426 CpuSuspendIntr(&state);
427 g_blockinfo_str_buf = (u8 *)AllocSysMemory(ALLOC_FIRST, g_device_info->m_block_size, 0);
428 g_blockinfo_dat_buf = (u16 *)AllocSysMemory(ALLOC_FIRST, sizeof(u16) * g_device_info->m_block_size, 0);
429 CpuResumeIntr(state);
430 if ( !g_blockinfo_str_buf || !g_blockinfo_dat_buf )
431 {
432 STATUS_PRINTF("\nError: AllocSysMemory failed\n\n");
433 return -1;
434 }
435 nandinf = s147nand_16_getnandinfo();
436 CpuSuspendIntr(&state);
437 nandinf->m_page_size_noecc = g_device_info->m_page_size_noecc;
438 nandinf->m_page_size_withecc = g_device_info->m_page_size_withecc;
439 nandinf->m_pages_per_block = g_device_info->m_pages_per_block;
440 nandinf->m_block_size = g_device_info->m_block_size;
441 nandinf->m_page_count = g_device_info->m_block_size * g_device_info->m_pages_per_block;
442 CpuResumeIntr(state);
443 logaddrtable = 0;
444 switch ( g_curflag & 0xFF0000 )
445 {
446 case 0x10000:
447 logaddrtable = do_format_device(2);
448 break;
449 case 0x20000:
450 logaddrtable = do_format_device(4);
451 break;
452 case 0x30000:
453 logaddrtable = do_format_device(8);
454 break;
455 case 0xF0000:
456 logaddrtable = do_format_device(0);
457 break;
458 default:
459 break;
460 }
461 if ( logaddrtable )
462 return logaddrtable;
463 s147nand_6_checkformat();
464 close(open("atfile9:acdelay", O_RDONLY));
465 if ( (g_curflag & 0x2000000) != 0 )
466 {
467 STATUS_PRINTF("====== Search directory ======\n");
468 for ( part = 0; part < 8; part += 1 )
469 {
470 int fd;
471
472 if ( s147nand_10_get_nand_partition_size(part) <= 0 )
473 {
474 STATUS_PRINTF(" atfile%d: Unformatted - Do nothing\n", part);
475 continue;
476 }
477 sprintf(g_atfile_part_image[part], "%satfile%d.147", g_atfile_147_dir, part);
478 fd = open(g_atfile_part_image[part], O_RDONLY);
479 if ( fd < 0 )
480 {
481 DelayThread(10000);
482 continue;
483 }
484 do_set_flag(1 << part);
485 do_handle_atfile_image(part, g_atfile_part_image[part]);
486 close(fd);
487 STATUS_PRINTF(" \"%s\" is found\n", g_atfile_part_image[part]);
488 }
489 STATUS_PRINTF(" \n");
490 }
491 for ( part = 0; part < 8; part += 1 )
492 {
493 if ( ((1 << part) & g_curflag) == 0 )
494 continue;
495 STATUS_PRINTF("====== Write \"%s\" to atfile%d: ======\n", g_atfile_part_image[part], part);
496 logaddrtable = do_write_partition(part);
497 if ( logaddrtable )
498 return logaddrtable;
499 STATUS_PRINTF(" \n");
500 }
501 if ( (g_curflag & 0x200) != 0 )
502 {
503 STATUS_PRINTF("====== Write \"%s\" to \"atfile9:info\" ======\n", g_atfile_info_image);
504 logaddrtable = do_write_partition(9);
505 if ( logaddrtable )
506 return logaddrtable;
507 STATUS_PRINTF(" \n");
508 }
509 if ( (g_curflag & 0x4000000) != 0 )
510 {
511 STATUS_PRINTF("====== Display file list ======\n");
512 logaddrtable = s147nand_12_load_logaddrtable();
513 if ( logaddrtable )
514 {
515 STATUS_PRINTF(" Error: Unformatted device (%d)\n", logaddrtable);
516 return logaddrtable;
517 }
518 for ( part = 0; part < 8; part += 1 )
519 do_list_files(part);
520 }
521 return 0;
522}
523
524static int do_format_device(int abspart)
525{
526 int blocks;
527 int bboffs;
528 int nand_partition_offset;
529 int bbcnt1;
530 int i;
531 USE_S147_DEV9_MEM_MMIO();
532
533 STATUS_PRINTF("====== Format NAND device ======\n");
534 STATUS_PRINTF(" [1/3]Block Erase and Check Bad Blocks\n");
535 STATUS_PRINTF(" BadBlock =");
536 for ( blocks = 0; blocks < g_device_info->m_block_size; blocks += 1 )
537 {
538 int eraseres;
539
540 s147_dev9_mem_mmio->m_led = (blocks >> 4) & 3;
541 eraseres = blocks ? s147nand_24_eraseoffset(s147nand_27_blocks2pages(blocks)) :
542 s147nand_25_nand_blockerase(s147nand_27_blocks2pages(0));
543 switch ( eraseres )
544 {
545 case -1470020:
546 g_blockinfo_str_buf[blocks] = 'X';
547 STATUS_PRINTF(" %d", blocks);
548 break;
549 case 0:
550 g_blockinfo_str_buf[blocks] = '=';
551 break;
552 default:
553 STATUS_PRINTF(" %d*(%d)", blocks, eraseres);
554 break;
555 }
556 }
557 STATUS_PRINTF("\n\n");
558 STATUS_PRINTF(" [2/3]Replace Bad Blocks ('B':Boot, 'I':Info, 'X':Broken, 'R':Reserved, '@':Occupied)\n");
559 g_blockinfo_dat_buf[0] = 0xEEEE;
560 g_blockinfo_str_buf[0] = 'B';
561 nand_partition_offset = get_nand_partition_offset(8, 8);
562 for ( blocks = 1; blocks < nand_partition_offset - 1; blocks += 1 )
563 {
564 if ( g_blockinfo_str_buf[blocks] != '=' )
565 continue;
566 g_blockinfo_dat_buf[blocks] = 0xEEEE;
567 g_blockinfo_str_buf[blocks] = 'R';
568 }
569 bbcnt1 = 0;
570 if ( g_blockinfo_str_buf[nand_partition_offset - 1] == 'X' )
571 {
572 bbcnt1 = check_badblock_count();
573 if ( bbcnt1 >= 0 )
574 {
575 g_blockinfo_dat_buf[nand_partition_offset - 1] = bbcnt1;
576 g_blockinfo_dat_buf[bbcnt1] = 0xCCCC;
577 g_blockinfo_str_buf[bbcnt1] = '@';
578 bboffs = bbcnt1;
579 }
580 }
581 else
582 {
583 g_blockinfo_dat_buf[nand_partition_offset - 1] = 0xAAAA;
584 bboffs = nand_partition_offset - 1;
585 }
586 if ( bbcnt1 >= 0 )
587 {
588 for ( blocks = nand_partition_offset; blocks < g_device_info->m_block_size; blocks += 1 )
589 {
590 if ( g_blockinfo_str_buf[blocks] != 'X' )
591 {
592 g_blockinfo_dat_buf[blocks] = 0xAAAA;
593 continue;
594 }
595 bbcnt1 = check_badblock_count();
596 if ( bbcnt1 < 0 )
597 break;
598 g_blockinfo_dat_buf[blocks] = bbcnt1;
599 g_blockinfo_dat_buf[bbcnt1] = 0xCCCC;
600 g_blockinfo_str_buf[bbcnt1] = '@';
601 }
602 }
603 if ( bbcnt1 < 0 )
604 {
605 STATUS_PRINTF(" Error: Too many bad blocks to replace\n");
606 return -1;
607 }
608 for ( blocks = 0; blocks < g_device_info->m_block_size; blocks += 1 )
609 {
610 do_output_bb_info(blocks, abspart, bboffs);
611 s147_dev9_mem_mmio->m_watchdog_flag2 = 0;
612 }
613 STATUS_PRINTF("\n");
614 STATUS_PRINTF(" [3/3]Write Boot Sector and Logical Address Table\n");
615 memset(&g_nand_partbuf.m_hdr, 0, sizeof(g_nand_partbuf.m_hdr));
616 strncpy(g_nand_partbuf.m_hdr.m_sig, "S147NAND", 9);
617 g_nand_partbuf.m_hdr.m_bootsector_ver_1 = 3;
618 g_nand_partbuf.m_hdr.m_bootsector_ver_2 = 0;
619 for ( i = 0; i < 8; i += 1 )
620 {
621 g_nand_partbuf.m_hdr.m_nand_partition_info[i].m_offset = get_nand_partition_offset(i, abspart);
622 g_nand_partbuf.m_hdr.m_nand_partition_info[i].m_size = get_nand_partition_size(i, abspart);
623 STATUS_PRINTF(
624 " atfile%d: StartBlock = 0x%04x(%4d) / BlockSize = 0x%04x(%4d)\n",
625 i,
626 g_nand_partbuf.m_hdr.m_nand_partition_info[i].m_offset,
627 g_nand_partbuf.m_hdr.m_nand_partition_info[i].m_offset,
628 g_nand_partbuf.m_hdr.m_nand_partition_info[i].m_size,
629 g_nand_partbuf.m_hdr.m_nand_partition_info[i].m_size);
630 }
631 g_nand_partbuf.m_hdr.m_nand_partition_8_info.m_offset = get_nand_partition_offset(8, abspart);
632 g_nand_partbuf.m_hdr.m_nand_partition_8_info.m_size = get_nand_partition_size(8, abspart);
633 STATUS_PRINTF(
634 " system : StartBlock = 0x%04x(%4d) / BlockSize = 0x%04x(%4d)\n",
635 g_nand_partbuf.m_hdr.m_nand_partition_8_info.m_offset,
636 g_nand_partbuf.m_hdr.m_nand_partition_8_info.m_offset,
637 g_nand_partbuf.m_hdr.m_nand_partition_8_info.m_size,
638 g_nand_partbuf.m_hdr.m_nand_partition_8_info.m_size);
639 STATUS_PRINTF("\n");
640 g_nand_partbuf.m_hdr.m_nand_seccode[0] = g_secr_code[0];
641 g_nand_partbuf.m_hdr.m_nand_seccode[1] = g_secr_code[1];
642 g_nand_partbuf.m_hdr.m_nand_vidmode[0] = g_boot_video_mode;
643 strncpy(g_nand_partbuf.m_hdr.m_nand_desc, g_device_info->m_nand_name, sizeof(g_nand_partbuf.m_hdr.m_nand_desc));
644 g_nand_partbuf.m_hdr.m_page_size_noecc = g_device_info->m_page_size_noecc;
645 g_nand_partbuf.m_hdr.m_page_size_withecc = g_device_info->m_page_size_withecc;
646 g_nand_partbuf.m_hdr.m_pages_per_block = g_device_info->m_pages_per_block;
647 g_nand_partbuf.m_hdr.m_block_size = g_device_info->m_block_size;
648 g_nand_partbuf.m_hdr.m_acmem_delay_val = 0;
649 g_nand_partbuf.m_hdr.m_acio_delay_val = generate_acio_delay_val(3, 3, 3);
650 s147nand_22_nand_write_dma(&g_nand_partbuf.m_hdr, 0, 0, sizeof(g_nand_partbuf.m_hdr));
651 do_dma_write_bytes_multi(g_blockinfo_dat_buf, 1, sizeof(u16) * g_device_info->m_block_size);
652 return 0;
653}
654
655static int do_write_partition(int part)
656{
657 int fd;
658 int state;
659 int bytes;
660 int pages;
661 int blocks;
662 int partblocks1;
663 int actual_readres;
664 int expected_readres;
665 int err;
666 USE_S147_DEV9_MEM_MMIO();
667
668 actual_readres = 0;
669 expected_readres = 0;
670 err = 0;
671 if ( part == 9 )
672 {
673 partblocks1 = (s147nand_9_get_nand_partition(8) - 1) * g_device_info->m_pages_per_block;
674 if ( partblocks1 < 0 )
675 {
676 STATUS_PRINTF(" Error: No partition #0 table\n");
677 return -1;
678 }
679 fd = open(g_atfile_info_image, O_RDONLY);
680 if ( fd < 0 )
681 {
682 STATUS_PRINTF(" Error: File not found - \"%s\"\n", g_atfile_info_image);
683 return -1;
684 }
685 }
686 else
687 {
688 partblocks1 = s147nand_9_get_nand_partition(part) * g_device_info->m_pages_per_block;
689 if ( partblocks1 < 0 )
690 {
691 STATUS_PRINTF(" Error: Invalid unit number\n");
692 return -1;
693 }
694 fd = open(g_atfile_part_image[part], O_RDONLY);
695 if ( fd < 0 )
696 {
697 STATUS_PRINTF(" Error: File not found - \"%s\"\n", g_atfile_part_image[part]);
698 return -1;
699 }
700 }
701 CpuSuspendIntr(&state);
702 g_page_buf = (char *)AllocSysMemory(ALLOC_FIRST, g_device_info->m_page_size_noecc, 0);
703 CpuResumeIntr(state);
704 if ( !g_page_buf )
705 {
706 STATUS_PRINTF("\nError: AllocSysMemory failed\n\n");
707 err = 1;
708 }
709 if ( !err )
710 {
711 if ( part == 9 )
712 {
713 bytes = lseek(fd, 0, SEEK_END);
714 if ( g_device_info->m_page_size_noecc < bytes )
715 {
716 STATUS_PRINTF(" Error: INFO image file is too large - \"%s\"\n", g_atfile_info_image);
717 STATUS_PRINTF(" FileSize(%d) > info(%d)\n", bytes, g_device_info->m_page_size_noecc);
718 err = 1;
719 }
720 if ( !err )
721 {
722 lseek(fd, 0, SEEK_SET);
723 expected_readres = 8;
724 actual_readres = read(fd, g_page_buf, expected_readres);
725 if ( actual_readres < expected_readres )
726 err = 1;
727 if ( !err )
728 {
729 if ( strncmp(g_page_buf, "S147INFO", 8) )
730 {
731 STATUS_PRINTF(" Error: \"%s\" is not a S147INFO-image file\n", g_atfile_info_image);
732 err = 1;
733 }
734 if ( !err )
735 {
736 pages = 1;
737 blocks = 1;
738 }
739 }
740 }
741 }
742 else
743 {
744 int partsizebytes;
745
746 bytes = lseek(fd, 0, SEEK_END);
747 partsizebytes =
748 s147nand_10_get_nand_partition_size(part) * g_device_info->m_pages_per_block * g_device_info->m_page_size_noecc;
749 if ( partsizebytes < bytes )
750 {
751 STATUS_PRINTF(" Error: ROM image file is too large - \"%s\"\n", g_atfile_part_image[part]);
752 STATUS_PRINTF(" FileSize(%d) > atfile%d(%d)\n", bytes, part, partsizebytes);
753 err = 1;
754 }
755 if ( !err )
756 {
757 lseek(fd, 0, SEEK_SET);
758 expected_readres = 0x20;
759 actual_readres = read(fd, g_page_buf, expected_readres);
760 if ( actual_readres < expected_readres )
761 err = 1;
762 if ( !err )
763 {
764 if ( strncmp(g_page_buf, "S147ROM", 8) )
765 {
766 STATUS_PRINTF(" Error: \"%s\" is not a S147ROM-image file\n", g_atfile_part_image[part]);
767 err = 1;
768 }
769 if ( !err )
770 {
771 pages = s147nand_30_bytes2pagesnoeccround(bytes);
772 blocks = s147nand_29_pages2blockround(pages);
773 }
774 }
775 }
776 }
777 }
778 if ( !err )
779 {
780 int xind2;
781 int xind1;
782 int pageoffs;
783 int finished;
784
785 STATUS_PRINTF(" FileSize = %dbytes SectorSize=%dsectors BlockSize=%dblocks\n", bytes, pages, blocks);
786 lseek(fd, 0, SEEK_SET);
787 xind2 = 0;
788 pageoffs = partblocks1;
789 finished = 0;
790 for ( xind1 = 0; xind1 < blocks; xind1 += 1 )
791 {
792 int xind3;
793
794 STATUS_PRINTF(
795 " atfile%d(%d/%d): LogBlock=%d (PhyBlock=%d) ",
796 part,
797 xind1,
798 blocks - 1,
799 s147nand_28_pages2blocks(pageoffs),
800 s147nand_13_translate_blockoffs(s147nand_28_pages2blocks(pageoffs)));
801 s147_dev9_mem_mmio->m_led = s147nand_28_pages2blocks(pageoffs) & 3;
802 if ( (g_curflag & 0xFF0000) == 0 )
803 {
804 STATUS_PRINTF("Erase -> ");
805 if ( s147nand_11_erasetranslatepageoffs(pageoffs) == -1470020 )
806 {
807 STATUS_PRINTF("\nromwrite: Bad block error, use \"-f\" option.\n");
808 err = 1;
809 break;
810 }
811 }
812 STATUS_PRINTF("Write -> Verify\n");
813 for ( xind3 = 0; xind3 < g_device_info->m_pages_per_block; )
814 {
815 int i;
816
817 // Unofficial: don't use global variable for partition buffer
818 if ( part != 9 )
819 {
820 int xindbytes;
821
822 xindbytes = bytes - xind2 * g_device_info->m_page_size_noecc;
823 expected_readres = (xindbytes > 0x20000) ? 0x20000 : xindbytes;
824 }
825 else
826 {
827 memset(g_nand_partbuf.m_buf, 0, g_device_info->m_page_size_noecc);
828 expected_readres = (g_device_info->m_page_size_noecc < bytes) ? g_device_info->m_page_size_noecc : bytes;
829 }
830 // Unofficial: check against read bytes instead of 0
831 actual_readres = read(fd, g_nand_partbuf.m_buf, expected_readres);
832 if ( actual_readres < expected_readres )
833 {
834 err = 1;
835 finished = 1;
836 break;
837 }
838 for ( i = 0; i <= 0x1FFFF; i += g_device_info->m_page_size_noecc )
839 {
840 s147nand_8_multi_write_dma(((char *)g_nand_partbuf.m_buf) + i, pageoffs, 1);
841 s147nand_7_multi_read_dma(g_page_buf, pageoffs, 1);
842 if ( do_verify(((char *)g_nand_partbuf.m_buf) + i, g_page_buf, g_device_info->m_page_size_noecc) )
843 {
844 STATUS_PRINTF(
845 "romwrite: Verify error - LogBlock=%d LogPage=%d\n", s147nand_28_pages2blocks(pageoffs), pageoffs);
846 err = 1;
847 finished = 1;
848 break;
849 }
850 pageoffs += 1;
851 xind2 += 1;
852 xind3 += 1;
853 if ( xind2 >= pages )
854 {
855 finished = 1;
856 break;
857 }
858 }
859 if ( finished )
860 break;
861 }
862 if ( finished )
863 break;
864 }
865 }
866 if ( actual_readres < expected_readres )
867 STATUS_PRINTF(" Error: File-I/O fault (%d)\n", actual_readres);
868 if ( fd >= 0 )
869 close(fd);
870 if ( err )
871 {
872 CpuSuspendIntr(&state);
873 // Unofficial: don't free partition buffer
874 if ( g_page_buf )
875 FreeSysMemory(g_page_buf);
876 CpuResumeIntr(state);
877 }
878 return err ? -1 : 0;
879}
880
881static int check_badblock_count(void)
882{
883 int retval;
884
885 retval = -1;
886 for ( ; g_badblock_count < get_nand_partition_offset(8, 8) - 1; g_badblock_count += 1 )
887 {
888 if ( g_blockinfo_str_buf[g_badblock_count] == 'R' )
889 {
890 retval = g_badblock_count;
891 g_badblock_count += 1;
892 break;
893 }
894 }
895 return retval;
896}
897
898static int get_nand_partition_offset(int part, int abspart)
899{
900 if ( part == 8 )
901 return get_nand_block_size_div_32();
902 if ( abspart )
903 {
904 if ( part < 0 || part >= abspart )
905 return -1;
906 if ( abspart == -1 && g_device_info->m_block_size == (int)0x80000000 )
907 __builtin_trap();
908 }
909 if ( !part )
910 return get_nand_block_size_div_32_div_64();
911 if ( abspart )
912 return g_device_info->m_block_size / abspart * part;
913 if ( part != 1 )
914 return -1;
915 return g_device_info->m_block_size / 4;
916}
917
918static int get_nand_partition_size(int part, int abspart)
919{
920 if ( part == 8 )
921 return get_nand_block_size_div_32_div_64() - get_nand_block_size_div_32();
922 if ( abspart )
923 {
924 if ( part < 0 || part >= abspart )
925 return 0;
926 if ( abspart == -1 && g_device_info->m_block_size == (int)0x80000000 )
927 __builtin_trap();
928 return g_device_info->m_block_size / abspart - (part ? 0 : get_nand_block_size_div_32_div_64());
929 }
930 if ( part )
931 return (part == 1) ? (3 * (g_device_info->m_block_size / 4)) : 0;
932 return g_device_info->m_block_size / 4 - get_nand_block_size_div_32_div_64();
933}
934
935static int get_nand_block_size_div_32_div_64(void)
936{
937 return get_nand_block_size_div_32() + g_device_info->m_block_size / 64;
938}
939
940static int get_nand_block_size_div_32(void)
941{
942 return g_device_info->m_block_size / 32;
943}
944
945static void do_dma_write_bytes_multi(void *ptr, int pageoffs, int pagecnt)
946{
947 int i;
948 int bytecnt;
949
950 bytecnt = s147nand_30_bytes2pagesnoeccround(pagecnt);
951 for ( i = 0; i < bytecnt; i += 1 )
952 s147nand_22_nand_write_dma(
953 (char *)ptr + ((g_device_info->m_page_size_noecc >> 2) << 2) * i,
954 pageoffs + i,
955 0,
956 g_device_info->m_page_size_noecc);
957}
958
959static int do_list_files(int part)
960{
961 int hdrret;
962 int pageoffs;
963 int xind1;
964 int i;
965 int dircnt;
966 int filcnt;
967 int finished;
968 char pathtmp[18];
969
970 hdrret = -1;
971 dircnt = 0;
972 filcnt = 0;
973 finished = 0;
974 pageoffs = s147nand_9_get_nand_partition(part) * g_device_info->m_pages_per_block;
975 if ( pageoffs < 0 )
976 return -19;
977 for ( xind1 = 0; xind1 < 64; xind1 += 1 )
978 {
979 s147nand_7_multi_read_dma(g_nand_partbuf.m_buf, pageoffs + xind1, 1);
980 for ( i = 0; i < 64; i += 1 )
981 {
982 if ( (xind1 << 6) - 1 + i == -1 )
983 {
984 if ( strncmp(g_nand_partbuf.m_dir.m_sig, "S147ROM", 8) )
985 {
986 STATUS_PRINTF(" \"%s%d:\" ... No data\n", "atfile", part);
987 STATUS_PRINTF(" -----------------------------\n\n");
988 return -19;
989 }
990 hdrret = g_nand_partbuf.m_dir.m_entrycnt;
991 STATUS_PRINTF(" \"%s%d:\"\n", "atfile", part);
992 STATUS_PRINTF(" -----------------------------\n");
993 }
994 else
995 {
996 if ( (xind1 << 6) - 1 + i >= hdrret )
997 {
998 finished = 1;
999 break;
1000 }
1001 strcpy(pathtmp, g_nand_partbuf.m_direntry[i].m_name);
1002 if ( g_nand_partbuf.m_direntry[i].m_type == 'D' )
1003 {
1004 strcat(pathtmp, "/");
1005 dircnt += 1;
1006 }
1007 else
1008 {
1009 filcnt += 1;
1010 }
1011 STATUS_PRINTF(" %9d %s\n", g_nand_partbuf.m_direntry[i].m_size, pathtmp);
1012 DelayThread(20000);
1013 }
1014 }
1015 if ( finished )
1016 break;
1017 }
1018 STATUS_PRINTF(" -----------------------------\n");
1019 STATUS_PRINTF(" %d directories, %d files\n", dircnt, filcnt);
1020 STATUS_PRINTF("\n");
1021 return hdrret;
1022}
1023
1024static void do_output_bb_info(int blocksd, int abspart, int bboffs)
1025{
1026 (void)abspart;
1027 if ( (blocksd & 0x3F) == 0 )
1028 STATUS_PRINTF(" %04X(%4d):", blocksd, blocksd);
1029 STATUS_PRINTF("%c", (blocksd == bboffs) ? 'I' : g_blockinfo_str_buf[blocksd]);
1030 if ( (blocksd & 0xF) == 15 )
1031 STATUS_PRINTF(" ");
1032 if ( (blocksd & 0x3F) == '?' )
1033 STATUS_PRINTF("\n");
1034}
1035
1036static int do_verify(void *buf1, void *buf2, int len)
1037{
1038 int i;
1039
1040 for ( i = 0; i < len / 4; i += 1 )
1041 if ( ((u32 *)buf1)[i] != ((u32 *)buf2)[i] )
1042 return ((u32 *)buf1)[i] - ((u32 *)buf2)[i];
1043 return 0;
1044}
1045
1046static const nand_id_desc_info_t *do_parse_device_info(const char *nandid)
1047{
1048 int i;
1049 int j;
1050
1051 for ( i = 0; g_nand_type_info[i].m_nand_name; i += 1 )
1052 {
1053 int cmpval;
1054
1055 cmpval = 0;
1056 for ( j = 0; j < 5; j += 1 )
1057 if ( ((int)g_nand_type_info[i].m_id[j] == -1) || ((u8)g_nand_type_info[i].m_id[j] == (u8)nandid[j]) )
1058 cmpval += 1;
1059 if ( cmpval == 5 )
1060 return &g_nand_type_info[i];
1061 }
1062 return 0;
1063}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
typedef __attribute__
Definition tlbfunc.c:60