int sfcx_DMAread_block(unsigned char *data, unsigned char *meta, int raw, unsigned long rawlength, unsigned long length) { int status; sfcx_writereg(SFCX_STATUS, sfcx_readreg(SFCX_STATUS)); sfcx_writereg(SFCX_CONFIG, (sfcx_readreg(SFCX_CONFIG)|CONFIG_DMA_LEN)); // Set flash address (logical) //address &= 0x3fffe00; // Align to page sfcx_writereg(SFCX_ADDRESS, 0); // Set the target address for data sfcx_writereg(SFCX_DPHYSADDR,data-BASE_ADDRESS); // Set the target address for meta sfcx_writereg(SFCX_MPHYSADDR,meta-BASE_ADDRESS); // Command the read // Either a logical read (0x200 bytes, no meta data) // or a Physical read (0x210 bytes with meta data) sfcx_writereg(SFCX_COMMAND, raw ? DMA_PHY_TO_RAM : DMA_LOG_TO_RAM); // Wait Busy while ((status = sfcx_readreg(SFCX_STATUS)) & STATUS_BUSY); if (!SFCX_SUCCESS(status)) { if (status & STATUS_BB_ER) printf(" ! SFCX: Bad block found at %08X\n"); else if (status & STATUS_ECC_ER) // printf(" ! SFCX: (Corrected) ECC error at address %08X: %08X\n", address, status); status = status; else if (!raw && (status & STATUS_ILL_LOG)) printf(" ! SFCX: Illegal logical block at %08X (status: %08X)\n", status); else printf(" ! SFCX: Unknown error at address %08X: %08X. Please worry.\n", status); } // Set internal page buffer pointer to 0 sfcx_writereg(SFCX_ADDRESS, 0); int i; //int page_sz = raw ? sfc.page_sz_phys : sfc.page_sz; for (i = 0; i < length; i += 4) { // Byteswap the data *(int*)(&data[i]) = __builtin_bswap32(read32(&data[i])); } for (i = 0; i < (rawlength - length); i += 4) // sfc.block_sz_phys - sfc.block_sz == META SIZE { // Byteswap the data *(int*)(&meta[i]) = __builtin_bswap32(read32(&meta[i])); } return status; }
int main(void) { xenos_init(VIDEO_MODE_AUTO); console_set_colors(0xD8444E00,0xFF96A300); console_init(); usb_init(); usb_do_poll(); printf("SFCX Init.\n"); flashconfig = sfcx_readreg(SFCX_CONFIG); sfcx_init(); if (sfc.initialized != SFCX_INITIALIZED) { printf(" ! Flashconfig: 0x%08X\n", flashconfig); printf(" ! sfcx initialization failure\n"); printf(" ! nand related features will not be available\n"); waitforexit(); } printf("Xenon_config_init.\n"); xenon_config_init(); prompt(MAIN_MENU); return 0; }
int flash_from_file(const char *filename, int raw) { int i, logic_pos, status = 0x200; unsigned char *block, *block_flash, *bad_block; float pct = 0.f; FILE *f = fopen(filename, "rb"); if (!f) { printf("\nError: Failed to open file: %s\n", filename); return -1; } printf("\nFlashing from %s...\n", filename); printf("0x%x block's to write...\n", sfc.size_blocks); if (!f) return -1; if (raw == -1) /* auto */ { fseek(f, 0, SEEK_END); raw = detect_read_write_modus(ftell(f)); if (raw == -1) return -1; fseek(f, 0, SEEK_SET); } block = (unsigned char*) malloc(sfc.block_sz_phys); block_flash = (unsigned char*) malloc(sfc.block_sz_phys); bad_block = (unsigned char*) malloc(sfc.block_sz_phys); unsigned nand_size = sfc.size_bytes; // Dump only 64mb on big nand if ((nand_size == NAND_SIZE_512MB) | (nand_size == NAND_SIZE_256MB)) { nand_size = NAND_SIZE_64MB; } for (i = 0; i < nand_size; i += sfc.block_sz) { memset(block, 0xFF, sizeof (block)); if (!fread(block, 1, sfc.page_sz_phys * sfc.pages_in_block, f)) { printf("Error reading ...\r\n"); return i; } pct = ((float) i / (float) (nand_size)); App.SetProgressValue(pct); // printf("Writing block: 0x%x of 0x%x (%iMB/%iMB)\r\n", sfcx_address_to_block(i) +1 , sfc.size_blocks , (i + sfc.block_sz) >> 20, nand_size >> 20); //Check for bad block sfcx_writereg(SFCX_STATUS, sfcx_readreg(SFCX_STATUS)); sfcx_writereg(SFCX_ADDRESS, i); sfcx_writereg(SFCX_COMMAND, raw ? PHY_PAGE_TO_BUF : LOG_PAGE_TO_BUF); // Wait Busy while ((status = sfcx_readreg(SFCX_STATUS)) & 1); if ((!raw)) { logic_pos = sfcx_readreg(SFCX_PHYSICAL); if (!(logic_pos & 0x04000000)) /* shouldn't happen, unless the existing image is broken. just assume the block is okay. */ { printf("Error: Uh, oh, don't know. Reading @ block %08x failed. logic_pos: %i\r\n", i, sfcx_address_to_block(logic_pos)); logic_pos = i; } logic_pos &= 0x3fffe00; if (logic_pos != i) { printf("Relocating/moving bad block from position 0x%x to 0x%x\r\n", sfcx_address_to_block(i), sfcx_address_to_block(logic_pos)); } } else if (status & 0x40) //Bad Block Management { printf("Bad block ...\r\n"); #if 0 logic_pos = sfc.last_bad_block_pos * sfc.block_sz; sfc.last_bad_block_pos--; sfcx_set_blocknumber(block, sfcx_address_to_block(i)); sfcx_calcecc((int*) block); if (logic_pos != i) { printf("Relocating/moving bad block from position 0x%x to 0x%x\n", sfcx_address_to_block(i), sfcx_address_to_block(logic_pos)); } #endif } else { logic_pos = i; } #if 0 if (sfc.last_bad_block_pos == sfcx_address_to_block(i)) { //We reach the the last entry bad block in reserved area printf("\nWriting only to last entry bad block in the reserved area."); break; } #endif //Erase block in Nand sfcx_erase_block(logic_pos); //Write block to Nand sfcx_write_block(block, logic_pos); } printf("\nWrite done\n"); fclose(f); free(block); free(block_flash); free(bad_block); if (App.Warning("Flashing is complete, reboot the console?") == TRUE) { xenon_smc_power_reboot(); } return 0; }
void dmatest() { int i; unsigned long j,k; // unsigned char block_raw[sfc.block_sz_phys]; //unsigned char edc[3]; int size_blocks; unsigned long size_bytes, size_bytes_raw; FILE *f; char *path = "uda:/dmatest2.bin"; f = fopen(path, "wb"); if (!f){ printf(" ! Can't open %s\n",path); waitforexit(); } if (sfc.size_bytes == NAND_SIZE_256MB || sfc.size_bytes == NAND_SIZE_256MB){ size_blocks = 0x200; //Only 64MB dumps supported on Big Block consoles size_bytes = 0x4000000; size_bytes_raw = 0x4200000; } unsigned char dma_user[size_bytes]; unsigned char dma_spare[size_bytes_raw-size_bytes]; unsigned char dma_merge[size_bytes_raw]; printf("DMA Length: %10X\n",(sfcx_readreg(SFCX_CONFIG)|CONFIG_DMA_LEN)); //sfcx_read_block(block_raw,i*sfc.block_sz,1); sfcx_DMAread_block(dma_user,dma_spare,1,size_bytes_raw,size_bytes); k = 0; for (j=0; j<size_bytes_raw; j += sfc.page_sz_phys) { memcpy(&dma_merge[j], &dma_user[k*sfc.page_sz],sfc.page_sz); memcpy(&dma_merge[j+sfc.page_sz],&dma_spare[k*sfc.meta_sz],sfc.meta_sz); k++; } //printf("Comparing Block (bytes %02X %02X %02X) %04X: ",dma_merge[0],dma_merge[1],dma_merge[2], i); // if (!memcmp(&dma_merge[0],&block_raw[0],sfc.block_sz_phys)) // printf("OK!\n"); // else // printf("FAIL !\n"); /* for (j=0; j<sfc.block_sz_phys; j += sfc.page_sz_phys) { memcpy(edc,&dma_merge[(j+sfc.page_sz_phys)-3],3); sfcx_calcecc(&dma_merge[j]); if (!memcmp(edc,&dma_merge[(j+sfc.page_sz_phys)-3],3)) printf("EDC OK!\n"); else printf("EDC FAIL!\n"); } */ if (!(fwrite(dma_merge,1,size_bytes_raw,f))); printf("fwrite fail!\n"); fclose(f); printf("DONE!!!!\n"); }