ADDRESS_MAP_END void namcos10_state::memn_driver_init( ) { UINT8 *BIOS = (UINT8 *)memregion( "maincpu:rom" )->base(); nand_base = (UINT8 *)memregion( "user2" )->base(); decrypter = static_cast<ns10_decrypter_device*>(machine().root_device().subdevice("decrypter")); nand_copy( (UINT32 *)( BIOS + 0x0000000 ), 0x08000, 0x001c000 ); nand_copy( (UINT32 *)( BIOS + 0x0020000 ), 0x24000, 0x03e0000 ); }
static void memn_driver_init( running_machine &machine ) { UINT8 *BIOS = (UINT8 *)machine.region( "user1" )->base(); nand_base = (UINT8 *)machine.region( "user2" )->base(); nand_copy( (UINT32 *)( BIOS + 0x0000000 ), 0x08000, 0x001c000 ); nand_copy( (UINT32 *)( BIOS + 0x0020000 ), 0x24000, 0x03e0000 ); machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler( 0x1f400000, 0x1f400003, FUNC(nand_status_r) ); machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler( 0x1f410000, 0x1f410003, FUNC(nand_address1_w) ); machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler( 0x1f420000, 0x1f420003, FUNC(nand_address2_w) ); machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler( 0x1f430000, 0x1f430003, FUNC(nand_address3_w) ); machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler( 0x1f440000, 0x1f440003, FUNC(nand_address4_w) ); machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler( 0x1f450000, 0x1f450003, FUNC(nand_data_r) ); machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler( 0x1fb60000, 0x1fb60003, FUNC(watchdog_w) ); machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler( 0xbf500000, 0xbf5007d7, FUNC(nand_block_w) ); machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler( 0xbf500000, 0xbf5007d7, FUNC(nand_block_r) ); psx_driver_init(machine); }
s8 RemovePriiloader ( void ) { s32 fd = 0; Nand_Permissions SysPerm; memset(&SysPerm,0,sizeof(Nand_Permissions)); SysPerm.otherperm = 3; SysPerm.groupperm = 3; SysPerm.ownerperm = 3; printf("Restoring System menu app..."); s32 ret = nand_copy(copy_app,original_app,SysPerm); if (ret < 0) { if(ret == -80) { //checksum issues printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING!!\n Installer could not calculate the Checksum when coping the System menu app\n"); printf("back! the app however was copied...\n"); printf("Do you want to Continue ?\n"); printf("A = Yes B = No\n "); printf("\x1b[%u;%dm", 37, 1); if(!UserYesNoStop()) { printf("reverting changes...\n"); ISFS_Close(fd); ISFS_CreateFile(original_app,0,3,3,3); fd = ISFS_Open(original_app,ISFS_OPEN_RW); ISFS_Write(fd,priiloader_app,priiloader_app_size); ISFS_Close(fd); abort("System Menu Copying Failure"); } } else { ISFS_CreateFile(original_app,0,3,3,3); fd = ISFS_Open(original_app,ISFS_OPEN_RW); ISFS_Write(fd,priiloader_app,priiloader_app_size); ISFS_Close(fd); abort("\nUnable to restore the system menu! (ret = %d)",ret); } } ret = ISFS_Delete(copy_app); printf("Done!\n"); return 1; }
s8 CopyTicket ( ) { s32 fd = 0; char TIK_Path_dest[64]; char TIK_Path_org[64]; memset(TIK_Path_dest,0,64); memset(TIK_Path_org,0,64); sprintf(TIK_Path_dest, "/title/%08x/%08x/content/ticket",TITLE_UPPER(title_id),TITLE_LOWER(title_id)); sprintf(TIK_Path_org, "/ticket/%08x/%08x.tik",TITLE_UPPER(title_id),TITLE_LOWER(title_id)); gprintf("Checking for copy ticket...\n"); fd = ISFS_Open(TIK_Path_dest,ISFS_OPEN_READ); if (fd >= 0) { ISFS_Close(fd); printf("Skipping copy of system menu ticket...\n"); return 1; } switch(fd) { case ISFS_EINVAL: abort("Unable to read ticket.path is wrong/too long or ISFS isn't init yet?"); break; case ISFS_ENOMEM: abort("Unable to read ticket.(Out of memory)"); break; case -102: abort("Unauthorised to get ticket. is ios%d trucha signed?",IOS_GetVersion()); break; default: if(fd < 0) abort("Unable to read ticket. error %d. ",fd); case -106: printf("Priiloader system menu ticket not found.\n\tTrying to read original ticket...\n"); break; } fd = ISFS_Open(TIK_Path_org,ISFS_OPEN_READ); //"/ticket/00000001/00000002.tik" -> original path which should be there on every wii. if (fd < 0) { switch(fd) { case ISFS_EINVAL: abort("Unable to read ticket.path is wrong/too long or ISFS isn't init yet?"); break; case ISFS_ENOMEM: abort("Unable to read ticket.(Out of memory)"); break; case -106: abort("Ticket not found"); break; case -102: abort("Unauthorised to get ticket. is ios%d trucha signed?",IOS_GetVersion()); break; default: abort("Unable to read ticket. error %d. ",fd); break; } } ISFS_Close(fd); printf("Copying system menu ticket..."); Nand_Permissions TikPerm; memset(&TikPerm,0,sizeof(Nand_Permissions)); TikPerm.otherperm = 3; TikPerm.groupperm = 3; TikPerm.ownerperm = 3; if (nand_copy(TIK_Path_org,TIK_Path_dest,TikPerm) < 0) { abort("Unable to copy the system menu ticket"); } printf("Done!\n"); return 1; }
s8 PatchTMD( u8 delete_mode ) { Nand_Permissions Perm; memset(&Perm,0,sizeof(Nand_Permissions)); u8 SaveTmd = 0; SHA1 sha; // SHA-1 class sha.Reset(); u32 FileHash[5]; u8 *TMD_chk = NULL; s32 fd = 0; s32 r = 0; #ifdef _DEBUG gprintf("Path : %s\n",TMD_Path); #endif r = ISFS_GetAttr(TMD_Path, &Perm.owner, &Perm.group, &Perm.attributes, &Perm.ownerperm, &Perm.groupperm, &Perm.otherperm); if(r < 0 ) { //attribute getting failed. returning to default printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING : failed to get file's permissions. using defaults\n"); printf("\x1b[%u;%dm", 37, 1); gprintf("permission failure on desination! error %d\n",r); gprintf("writing with max permissions\n"); Perm.ownerperm = 3; Perm.groupperm = 3; Perm.otherperm = 0; } else { gprintf("r %d owner %d group %d attributes %X perm:%X-%X-%X\n", r, Perm.owner, Perm.group, Perm.attributes, Perm.ownerperm, Perm.groupperm, Perm.otherperm); } if(delete_mode == 0) { gprintf("patching TMD...\n"); printf("Patching TMD..."); } else { //return 1; gprintf("restoring TMD...\n"); printf("Restoring System Menu TMD...\n"); } fd = ISFS_Open(TMD_Path2,ISFS_OPEN_READ); if(fd < 0) { if(delete_mode) { printf("TMD backup not found. leaving TMD alone...\n"); return 1; } else { //got to make tmd copy :) gprintf("Making tmd backup...\n"); r = nand_copy(TMD_Path2,tmd_buf,tmd_size,Perm); if ( r < 0) { gprintf("Failure making TMD backup.error %d\n",r); printf("TMD backup/Patching Failure : error %d",r); goto _return; } } fd = 0; } ISFS_Close(fd); gprintf("TMD backup found\n"); //not so sure why we'd want to delete the tmd modification but ok... if(delete_mode) { if ( nand_copy(TMD_Path2,TMD_Path,Perm) < 0) { if(r == -80) { //checksum issues printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING!!\nInstaller could not calculate the Checksum when restoring the TMD back!\n"); printf("the TMD however was copied...\n"); printf("Do you want to Continue ?\n"); printf("A = Yes B = No\n "); printf("\x1b[%u;%dm", 37, 1); if(!UserYesNoStop()) { nand_copy(TMD_Path,TMD_Path2,Perm); abort("TMD restoring failure."); } } else { printf("\x1b[%u;%dm", 33, 1); printf("UNABLE TO RESTORE THE SYSTEM MENU TMD!!!\n\nTHIS COULD BRICK THE WII SO PLEASE REINSTALL SYSTEM MENU\nWHEN RETURNING TO THE HOMEBREW CHANNEL!!!\n\n"); printf("\x1b[%u;%dm", 37, 1); printf("press A to return to the homebrew channel\n"); nand_copy(TMD_Path,TMD_Path2,Perm); UserYesNoStop(); exit(0); } } else ISFS_Delete(TMD_Path2); return 1; } else { //check if version is the same STACK_ALIGN(fstats,TMDb_status,sizeof(fstats),32); static u8 tmdb_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); static signed_blob *mbTMD; static tmd* pbTMD; fd = ISFS_Open(TMD_Path2,ISFS_OPEN_READ); if (fd < 0) { gprintf("TMD bCheck : failed to open source : %s\n",TMD_Path2); goto patch_tmd; } r = ISFS_GetFileStats(fd,TMDb_status); if (r < 0) { gprintf("TMD bCheck : Failed to get information about %s!\n",TMD_Path2); ISFS_Close(fd); goto patch_tmd; } memset(tmdb_buf,0,MAX_SIGNED_TMD_SIZE); r = ISFS_Read(fd,tmdb_buf,TMDb_status->file_length); if (r < 0) { gprintf("TMD bCheck : Failed to Read Data from %s!\n",TMD_Path2); ISFS_Close(fd); goto patch_tmd; } ISFS_Close(fd); mbTMD = (signed_blob *)tmdb_buf; pbTMD = (tmd*)SIGNATURE_PAYLOAD(mbTMD); if (pbTMD->title_version != rTMD->title_version) { gprintf("TMD bCheck : backup TMD version mismatch: %d & %d\n",rTMD->title_version,pbTMD->title_version); //got to make tmd copy :) r = nand_copy(TMD_Path2,tmd_buf,tmd_size,Perm); if ( r < 0) { gprintf("TMD bCheck : Failure making TMD backup.error %d\n",r); printf("TMD backup/Patching Failure : error %d",r); goto _return; } } else gprintf("TMD bCheck : backup TMD is correct\n"); r = 0; } patch_tmd: gprintf("detected access rights : 0x%08X\n",rTMD->access_rights); if(rTMD->access_rights == 0x03) { gprintf("no AHBPROT modification needed\n"); } else { rTMD->access_rights = 0x03; DCFlushRange(rTMD,sizeof(tmd)); if(rTMD->access_rights != 0x03) { gprintf("rights change failure.\n"); goto _return; } SaveTmd++; } gprintf("checking Boot app SHA1 hash...\n"); gprintf("bootapp ( %d ) SHA1 hash = %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x\n",rTMD->boot_index ,rTMD->contents[rTMD->boot_index].hash[0],rTMD->contents[rTMD->boot_index].hash[1],rTMD->contents[rTMD->boot_index].hash[2],rTMD->contents[rTMD->boot_index].hash[3] ,rTMD->contents[rTMD->boot_index].hash[4],rTMD->contents[rTMD->boot_index].hash[5],rTMD->contents[rTMD->boot_index].hash[6],rTMD->contents[rTMD->boot_index].hash[7] ,rTMD->contents[rTMD->boot_index].hash[8],rTMD->contents[rTMD->boot_index].hash[9],rTMD->contents[rTMD->boot_index].hash[10],rTMD->contents[rTMD->boot_index].hash[11] ,rTMD->contents[rTMD->boot_index].hash[12],rTMD->contents[rTMD->boot_index].hash[13],rTMD->contents[rTMD->boot_index].hash[14],rTMD->contents[rTMD->boot_index].hash[15] ,rTMD->contents[rTMD->boot_index].hash[16],rTMD->contents[rTMD->boot_index].hash[17],rTMD->contents[rTMD->boot_index].hash[18],rTMD->contents[rTMD->boot_index].hash[19]); gprintf("generated priiloader SHA1 : "); sha.Reset(); sha.Input(priiloader_app,priiloader_app_size); if (!sha.Result(FileHash)) { gprintf("could not compute Hash of Priiloader!\n"); r = -1; goto _return; } if (!memcmp(rTMD->contents[rTMD->boot_index].hash, FileHash, sizeof(FileHash) ) ) { gprintf("no SHA hash change needed\n"); } else { memcpy(rTMD->contents[rTMD->boot_index].hash,FileHash,sizeof(FileHash)); gprintf("%08x %08x %08x %08x %08x\n",FileHash[0],FileHash[1],FileHash[2],FileHash[3],FileHash[4]); DCFlushRange(rTMD,sizeof(tmd)); SaveTmd++; } if(SaveTmd > 0) { gprintf("saving TMD\n"); r = nand_copy(TMD_Path,tmd_buf,tmd_size,Perm); if(r < 0 ) { gprintf("nand_copy failure. error %d\n",r); if(r == -80) goto _checkreturn; else goto _return; } } else { gprintf("no TMD mod's needed\n"); printf("no TMD modifications needed\n"); goto _return; } printf("Done\n"); _return: if (fd < r) { r = fd; } if(fd) { ISFS_Close(fd); } if (r < 0) { printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING!!\nInstaller couldn't Patch the system menu TMD.\n"); printf("Priiloader could still end up being installed but could end up working differently\n"); printf("Do you want the Continue ?\n"); printf("A = Yes B = No\n "); printf("\x1b[%u;%dm", 37, 1); if(!UserYesNoStop()) { fd = ISFS_Open(TMD_Path2,ISFS_OPEN_RW); if(fd >= 0) { //the backup is there. as safety lets copy it back. ISFS_Close(fd); nand_copy(TMD_Path2,TMD_Path,Perm); } abort("TMD failure"); return -1; } else { nand_copy(TMD_Path2,TMD_Path,Perm); printf("\nDone!\n"); return 1; } return r; } else return 1; _checkreturn: if(fd) { ISFS_Close(fd); } if(TMD_chk) { free(TMD_chk); TMD_chk = NULL; } printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING!!\n Installer could not calculate the Checksum for the TMD!"); printf("\nbut Patch write was successfull.\n"); printf("Do you want the Continue ?\n"); printf("A = Yes B = No\n "); printf("\x1b[%u;%dm", 37, 1); if(!UserYesNoStop()) { printf("reverting changes...\n"); nand_copy(TMD_Path2,TMD_Path,Perm); abort("TMD Patch failure\n"); } else { printf("\nDone!\n"); } return -80; }
s8 WritePriiloader( bool priiloader_found ) { s32 ret = 0; s32 fd = 0; Nand_Permissions SysPerm; if(priiloader_found == false) { memset(&SysPerm,0,sizeof(Nand_Permissions)); SysPerm.otherperm = 3; SysPerm.groupperm = 3; SysPerm.ownerperm = 3; //system menu coping printf("Moving System Menu app..."); ret = nand_copy(original_app,copy_app,SysPerm); if (ret < 0) { if (ret == -80) { //checksum issues printf("\x1b[%u;%dm", 33, 1); printf("\nWARNING!!\n Installer could not calculate the Checksum for the System menu app"); printf("\nbut Copy was successfull.\n"); printf("Do you want the Continue ?\n"); printf("A = Yes B = No\n "); printf("\x1b[%u;%dm", 37, 1); if(!UserYesNoStop()) { printf("reverting changes...\n"); ISFS_Delete(copy_app); abort("System Menu Copying Failure"); } else printf("\nDone!\n"); } else abort("\nUnable to move the system menu. error %d",ret); } else { gprintf("Moving System Menu Done\n"); printf("Done!\n"); } } ret = 0; //sys_menu app moved. lets write priiloader STACK_ALIGN(fstats,status,sizeof(fstats),32); memset(&SysPerm,0,sizeof(Nand_Permissions)); SysPerm.otherperm = 3; SysPerm.groupperm = 3; SysPerm.ownerperm = 3; printf("Writing Priiloader app..."); gprintf("Writing Priiloader\n"); char temp_dest[ISFS_MAXPATH]; memset(temp_dest,0,ISFS_MAXPATH); char *ptemp = NULL; ptemp = strstr(original_app,"/"); while(ptemp != NULL && strstr(ptemp+1,"/") != NULL) { ptemp = strstr(ptemp+1,"/"); } if(ptemp[0] == '/') { ptemp = ptemp+1; } memset(temp_dest,0,ISFS_MAXPATH); sprintf(temp_dest,"/tmp/%s",ptemp); ISFS_Delete(temp_dest); ret = ISFS_CreateFile(temp_dest,SysPerm.attributes,SysPerm.ownerperm,SysPerm.groupperm,SysPerm.otherperm); fd = ISFS_Open(temp_dest,ISFS_OPEN_RW); if (fd < 0) { gprintf("error %d\n",fd); abort("\nFailed to open file for Priiloader writing"); } ret = ISFS_Write(fd,priiloader_app,priiloader_app_size); if (ret < 0 ) //check if the app was writen correctly { ISFS_Close(fd); ISFS_Delete(copy_app); ISFS_Delete(temp_dest); gprintf("Write failed. ret %d\n",ret); abort("\nWrite of Priiloader app failed"); } ISFS_Close(fd); //SHA1 check here fd = ISFS_Open(temp_dest,ISFS_OPEN_READ); if (fd < 0) { ISFS_Delete(copy_app); abort("\nFailed to open file for Priiloader checking"); } if (ISFS_GetFileStats(fd,status) < 0) { ISFS_Close(fd); ISFS_Delete(copy_app); abort("Failed to get stats of %s. System Menu Recovered",temp_dest); } else { if ( status->file_length != priiloader_app_size ) { ISFS_Close(fd); ISFS_Delete(copy_app); abort("Written Priiloader app isn't the correct size.System Menu Recovered"); } else { gprintf("Size Check Success\n"); printf("Size Check Success!\n"); } } u8 *AppData = (u8 *)memalign(32,ALIGN32(status->file_length)); if (AppData) ret = ISFS_Read(fd,AppData,status->file_length); else { ISFS_Close(fd); ISFS_Delete(copy_app); abort("Checksum comparison Failure! MemAlign Failure of AppData\n"); } ISFS_Close(fd); if (ret < 0) { if (AppData) { free(AppData); AppData = NULL; } ISFS_Delete(copy_app); abort("Checksum comparison Failure! read of priiloader app returned %u\n",ret); } if(CompareSha1Hash((u8*)priiloader_app,priiloader_app_size,AppData,status->file_length)) printf("Checksum comparison Success!\n"); else { if (AppData) { free(AppData); AppData = NULL; } ISFS_Delete(copy_app); abort("Checksum comparison Failure!\n"); } if (AppData) { free(AppData); AppData = NULL; } // rename and do a final SHA1 chezck ISFS_Delete(original_app); ret = ISFS_Rename(temp_dest,original_app); if(ret < 0 ) { gprintf("WritePriiloader : rename returned %d\n",ret); nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("\nFailed to Write Priiloader : error Ren %d",ret); } printf("Done!!\n"); gprintf("Wrote Priiloader App.Checking Installation\n"); printf("\nChecking Priiloader Installation...\n"); memset(status,0,sizeof(fstats)); fd = ISFS_Open(original_app,ISFS_OPEN_READ); if (fd < 0) { nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("\nFailed to open file for Priiloader checking"); } if (ISFS_GetFileStats(fd,status) < 0) { ISFS_Close(fd); nand_copy(copy_app,original_app,SysPerm); abort("Failed to get stats of %s. System Menu Recovered",original_app); } else { if ( status->file_length != priiloader_app_size ) { ISFS_Close(fd); nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("Written Priiloader app isn't the correct size.System Menu Recovered"); } else { gprintf("Size Check Success\n"); printf("Size Check Success!\n"); } } AppData = (u8 *)memalign(32,ALIGN32(status->file_length)); if (AppData != NULL) ret = ISFS_Read(fd,AppData,status->file_length); else { ISFS_Close(fd); nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("Checksum comparison Failure! MemAlign Failure of AppData\n"); } ISFS_Close(fd); if (ret < 0) { if (AppData) { free(AppData); AppData = NULL; } nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("Checksum comparison Failure! read of priiloader app returned %u\n",ret); } if(CompareSha1Hash((u8*)priiloader_app,priiloader_app_size,AppData,status->file_length)) printf("Checksum comparison Success!\n"); else { if (AppData) { free(AppData); AppData = NULL; } nand_copy(copy_app,original_app,SysPerm); ISFS_Delete(copy_app); abort("Checksum comparison Failure!\n"); } if (AppData) { free(AppData); AppData = NULL; } gprintf("Priiloader Update Complete\n"); printf("Done!\n\n"); return 1; }
void rd_maintain(void) { //#define BURN_IN // #define VERBOSE #define ECC_BIT_LIMIT 2 int i=0,j=0; int rt; int total_page; #ifdef BURN_IN for(;;) #endif { if (nand_copy("progcv", SECT1_ROOT_START, SECT2_ROOT_START, ROOT_SIZE)) { //s/w update will only change sect1, we need to copy sect1 rd to sect 2 //coz sect 2 is logical mtd2 for cramfs //so, this case will only happen after s/w update #ifdef VERBOSE printf("root disk update from spare copy..."); #endif nand_copy("progc", SECT2_ROOT_START, SECT1_ROOT_START, ROOT_SIZE); } else { #ifdef VERBOSE printf("sect1 & sect2 root disk identical\n"); #endif } #ifdef BURN_IN #ifdef VERBOSE printf("burn-in count = %d\n",j++); #endif nand_copy("progc", SECT2_ROOT_START, SECT1_ROOT_START, ROOT_SIZE); nand_copy("progc", SECT1_ROOT_START, SECT2_ROOT_START, ROOT_SIZE); for(i=0;i<10;i++) #endif { rt = nand_check(SECT1_ROOT_START,ROOT_SIZE,&total_page); #ifdef VERBOSE printf("nand check on sect 1 rd, max ecc corr bit = %d, total err page = %d\n",rt,total_page); #endif if(rt>ECC_BIT_LIMIT) { printf("ecc corr bit exceed limit, re-flashing setc1 rd\n"); nand_copy("progc", SECT1_ROOT_START, SECT2_ROOT_START, ROOT_SIZE); } rt = nand_check(SECT2_ROOT_START,ROOT_SIZE,&total_page); #ifdef VERBOSE printf("nand check on sect 2 rd, max ecc corr bit = %d, total err page = %d\n",rt,total_page); #endif if(rt>ECC_BIT_LIMIT) { printf("ecc corr bit exceed limit, re-flashing setc2 rd\n"); nand_copy("progc", SECT2_ROOT_START, SECT1_ROOT_START, ROOT_SIZE); } } } }
void ec_maintain() { // int ec1_update_flag = 1, ec2_update_flag = 1; uint32_t magic = ec_hdr_section_get(HDR_MAGIC_OFFSET, 4); if (magic == EC_MAGIC) { uint16_t ec1 = ec_hdr_section_get(HDR_EC1_OFFSET, 2); printf("ec1 = %d\n", ec1); if (ec1 >= EC_BACKUP) { uint16_t ec2 = ec_hdr_section_get(HDR_EC2_OFFSET, 2); printf("ec2 = %d\n", ec2); if (ec2 >= EC_BACKUP) { printf("The 2nd level mirror maintaining:\n"); //A. Handle Bootloader if (!nand_copy("progv", SECT2_BOOT_START, SECT3_BOOT_START, BOOT_SIZE)) { //rewrite 2 if 2&3 are identical nand_copy("prog", SECT2_BOOT_START, SECT3_BOOT_START, BOOT_SIZE); } else { //copy 1 to 2 if 2&3 are different nand_copy("prog", SECT2_BOOT_START, SECT1_BOOT_START, BOOT_SIZE); } //B. Handle Kernel if (!nand_copy("progcv", SECT2_KERN_START, SECT3_KERN_START, KERN_SIZE)) { nand_copy("progc", SECT2_KERN_START, SECT3_KERN_START, KERN_SIZE); } else { nand_copy("progc", SECT2_KERN_START, SECT1_KERN_START, KERN_SIZE); } //C. Handle Rootdisk if (!nand_copy("progcv", SECT2_ROOT_START, SECT3_ROOT_START, ROOT_SIZE)) { nand_copy("progc", SECT2_ROOT_START, SECT3_ROOT_START, ROOT_SIZE); } else { nand_copy("progc", SECT2_ROOT_START, SECT1_ROOT_START, ROOT_SIZE); } #if 0 if (ec2_update_flag) { ec2 = 0; ec_hdr_section_set(HDR_EC2_OFFSET, ec2, 2); } #endif ec2 = 0; ec_hdr_section_set(HDR_EC2_OFFSET, ec2, 2); } printf("The 1st level mirror maintaining:\n"); //A. Handle Bootloader if (!nand_copy("progv", SECT1_BOOT_START, SECT2_BOOT_START, BOOT_SIZE)) { nand_copy("prog", SECT1_BOOT_START, SECT2_BOOT_START, BOOT_SIZE); } else { if (!nand_copy("progv", SECT1_BOOT_START, SECT3_BOOT_START, BOOT_SIZE)) { nand_copy("prog", SECT1_BOOT_START, SECT3_BOOT_START, BOOT_SIZE); //nand_copy("prog", SECT2_BOOT_START, SECT3_BOOT_START, BOOT_SIZE); } else { printf("restore backup1&2 from primary nboot!\n"); nand_copy("prog", SECT2_BOOT_START, SECT1_BOOT_START, BOOT_SIZE); nand_copy("prog", SECT3_BOOT_START, SECT1_BOOT_START, BOOT_SIZE); //nand_copy("prog", SECT1_BOOT_START, SECT2_BOOT_START, BOOT_SIZE); } } //B. Handle Kernel if (!nand_copy("progcv", SECT1_KERN_START, SECT2_KERN_START, KERN_SIZE)) { nand_copy("progc", SECT1_KERN_START, SECT2_KERN_START, KERN_SIZE); } else { if (!nand_copy("progcv", SECT1_KERN_START, SECT3_KERN_START, KERN_SIZE)) { nand_copy("progc", SECT1_KERN_START, SECT3_KERN_START, KERN_SIZE); //nand_copy("progc", SECT2_KERN_START, SECT3_KERN_START, KERN_SIZE); } else { printf("restore backup1&2 from primary kernel!\n"); nand_copy("progc", SECT2_KERN_START, SECT1_KERN_START, KERN_SIZE); nand_copy("progc", SECT3_KERN_START, SECT1_KERN_START, KERN_SIZE); //nand_copy("progc", SECT1_KERN_START, SECT2_KERN_START, KERN_SIZE); } } //C. Handle Rootdisk if (!nand_copy("progcv", SECT1_ROOT_START, SECT2_ROOT_START, ROOT_SIZE)) { //rewrite 1 if 1&2 identical nand_copy("progc", SECT1_ROOT_START, SECT2_ROOT_START, ROOT_SIZE); } else { if (!nand_copy("progcv", SECT1_ROOT_START, SECT3_ROOT_START, ROOT_SIZE)) { //rewrite 1 if 1&3 identical nand_copy("progc", SECT1_ROOT_START, SECT3_ROOT_START, ROOT_SIZE); //nand_copy("progc", SECT2_ROOT_START, SECT3_ROOT_START, ROOT_SIZE); } else { //both 2&3 are different from 1, copy 1 to 2&3, //case of after s/w update printf("restore backup1&2 from primary rootdisk!\n"); nand_copy("progc", SECT2_ROOT_START, SECT1_ROOT_START, ROOT_SIZE); nand_copy("progc", SECT3_ROOT_START, SECT1_ROOT_START, ROOT_SIZE); //nand_copy("progc", SECT1_ROOT_START, SECT2_ROOT_START, ROOT_SIZE); } } #if 0 if (ec1_update_flag) ec1 = 0; ec2++; ec_hdr_section_set(HDR_EC2_OFFSET, ec2, 2); #endif ec1 = 0; ec2++; ec_hdr_section_set(HDR_EC2_OFFSET, ec2, 2); } ec1++; ec_hdr_section_set(HDR_EC1_OFFSET, ec1, 2); } else { ec_hdr_create(); } }