› Foros › Xbox 360 › Exploits y homebrew
RastaMan escribió:Los problemas son inherentes al gentoo y la 360, no influye si lees o escribes.
Lo que se hace al flashear sin leer es estar el menor tiempo posible en el gentoo asi le quitas oportunidades de colgarse.
Queria probar el gentoo minimal a ver si es mas estable, pero una vez booteado me he dado cuenta de que no tiene soporte de FAT asi que tendria que prepararme un pen flasheado en ext2 o ext3 para esto y me daba pereza.
Por otra parte... que version del xbrflash quieres? La que lee los 512? La que flashea sin leer?
/*
XBR-Flash for Linux by trancy
Thanks goes to tmbinc and Redline99
History
-------
v0.1 initial by tmbinc
v0.1.x modified by Redline99
v0.1.1 modified by trancy
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <byteswap.h>
#include <string.h>
#include <time.h>
volatile unsigned int *flash;
time_t start,end;
double time_dif;
//****** Defines ****************************************************************************
//NAND SIZES
#define NAND_SIZE_16MB 0x1000000
#define NAND_SIZE_64MB 0x4000000
#define NAND_SIZE_256MB 0x10000000
#define NAND_SIZE_512MB 0x20000000
//Registers
/*
#define SFCX_CONFIG 0x00
#define SFCX_STATUS 0x04
#define SFCX_COMMAND 0x08
#define SFCX_ADDRESS 0x0C
#define SFCX_DATA 0x10
#define SFCX_LOGICAL 0x14
#define SFCX_PHYSICAL 0x18
#define SFCX_DPHYSADDR 0x1C
#define SFCX_MPHYSADDR 0x20
*/
#define SFCX_CONFIG 0x00
#define SFCX_STATUS 0x01
#define SFCX_COMMAND 0x02
#define SFCX_ADDRESS 0x03
#define SFCX_DATA 0x04
#define SFCX_LOGICAL 0x05
#define SFCX_PHYSICAL 0x06
#define SFCX_DPHYSADDR 0x07
#define SFCX_MPHYSADDR 0x08
//Commands for Command Register
#define PAGE_BUF_TO_REG 0x00 //Read page buffer to data register
#define REG_TO_PAGE_BUF 0x01 //Write data register to page buffer
#define LOG_PAGE_TO_BUF 0x02 //Read logical page into page buffer
#define PHY_PAGE_TO_BUF 0x03 //Read physical page into page buffer
#define WRITE_PAGE_TO_PHY 0x04 //Write page buffer to physical page
#define BLOCK_ERASE 0x05 //Block Erase
#define DMA_LOG_TO_RAM 0x06 //DMA logical flash to main memory
#define DMA_PHY_TO_RAM 0x07 //DMA physical flash to main memory
#define DMA_RAM_TO_PHY 0x08 //DMA main memory to physical flash
#define UNLOCK_CMD_0 0x55 //Unlock command 0; Kernel does 0x5500
#define UNLOCK_CMD_1 0xAA //Unlock command 1; Kernel does 0xAA00
// API Consumers should use these two defines to
// use for creating static buffers at compile time
#define MAX_PAGE_SZ 0x210 //Max known hardware physical page size
#define MAX_BLOCK_SZ 0x42000 //Max known hardware physical block size
struct sfc
{
int initialized;
int large_block;
int page_sz;
int meta_sz;
int page_sz_phys;
int pages_in_block;
int block_sz;
int block_sz_phys;
int size_mb;
int size_bytes;
int size_bytes_phys;
int size_pages;
int size_blocks;
};
//****** Prototypes ****************************************************************************
unsigned int sfcx_init(void);
void sfcx_writereg( int reg, unsigned long value );
unsigned int sfcx_readreg( int reg );
int sfcx_erase_block(int address);
int sfcx_read_page(unsigned char *data, int sector, int raw);
int sfcx_write_page(unsigned char *data, int address);
int sfcx_read_block(unsigned char *data, int address, int raw);
int sfcx_write_block(unsigned char *data, int address);
void sfcx_calcecc(unsigned int *data);
int sfcx_get_blocknumber(unsigned char *data);
void sfcx_set_blocknumber(unsigned char *data, int num);
int sfcx_get_blockversion(unsigned char *data);
void sfcx_set_blockversion(unsigned char *data, int ver);
void sfcx_set_pagevalid(unsigned char *data);
void sfcx_set_pageinvalid(unsigned char *data);
int sfcx_is_pagevalid(unsigned char *data);
int sfcx_block_to_address(int block);
int sfcx_address_to_block(int address);
extern void *mmap64( void *__addr, size_t __len, int __prot, int __flags, int __fd, __off64_t __offset) __THROW;
extern volatile void * ioremap( unsigned long long physaddr, unsigned size, int sync );
extern int iounmap( volatile void *start, size_t length );
int flash_from_file( const char *filename, int raw );
int dump_flash_to_file( const char *filename );
int verify_flash_with_file( const char *filename, int raw );
struct sfc sfc;
int main( int argc, char **argv )
{
const char *orig = argv[1];
int res;
printf("XBR-Flash for Linux v0.1.1 beta by trancy\nThanks goes to tmbinc and Redline99\n\n");
flash = ioremap(0xea00c000, 0x1000, 1);
sfcx_init();
if ( argc != 2 && argc != 3 )
{
printf("usage: %s <current> [<new>]\n", *argv);
return 2;
}
res = verify_flash_with_file(orig, 1);
if ( res == -1 )
{
dump_flash_to_file(orig);
res = verify_flash_with_file(orig, 1);
}
if ( res != sfc.size_bytes )
{
if ( res == -2 )
printf("Verify failed!\n");
else
if ( res > 0 )
printf("Verified correctly, but only %d bytes.\n", res);
else
printf("Error: Original image invalid\n");
printf("Info: I won't flash if you don't have a full, working backup, sorry.\n");
return 1;
}
printf("Verify ok.\n");
//Write from file to flash
if ( argc > 2 )
{
const char *image = argv[2];
flash_from_file(image, -1);
res = verify_flash_with_file(image, -1);
if ( res > 0 )
printf("Verified %d bytes ok :)\n", res);
else
printf("Error: Verify failed! (%d)\n", res);
}
return 0;
}
int dump_flash_to_file( const char *filename )
{
int i;
unsigned char *block;
block = (unsigned char*) malloc (sfc.block_sz_phys);
printf("\nDumping to %s...\n", filename);
printf("0x%x block's to dump...\n", sfc.size_blocks );
time (&start);
FILE *f = fopen(filename, "wb");
for ( i = 0; i < sfc.size_bytes; i += sfc.block_sz )
{
sfcx_read_block(block, i, 1);
if ( !(i & 0x3fff) )
{
printf("Reading block: 0x%x of 0x%x\r", i / sfc.block_sz + 1 , sfc.size_blocks );
fflush(stdout);
}
if ( fwrite(block, 1, sfc.block_sz_phys, f) != sfc.block_sz_phys )
return -1;
}
time (&end);
time_dif = difftime (end,start);
printf("\nReading done in %.2lf sec.\nSpeed: %.2lf MB/s\n", time_dif, sfc.size_bytes / time_dif / 1024 / 1024);
fclose(f);
free(block);
return 0;
}
int verify_flash_with_file( const char *filename, int raw )
{
int i, status;
unsigned char *block, *block_flash;
FILE *f = fopen(filename, "rb");
if ( !f )
return -1;
printf("\nVerifying flash with %s...\n", filename);
printf("0x%x block's to verify...\n", sfc.size_blocks);
if ( raw == -1 ) /* auto */
{
fseek(f, 0, SEEK_END);
//64MB XBR-File
if( ftell(f) == NAND_SIZE_64MB / sfc.page_sz * sfc.page_sz_phys )
sfc.size_bytes = NAND_SIZE_64MB;
if ( ftell(f) == sfc.size_bytes / sfc.page_sz * sfc.page_sz_phys )
{
raw = 1;
printf("Detected RAW nand file, verifying in raw mode.\n");
}
else
{
raw = 0;
printf("Detected short nand file, verifying in cooked mode.\n");
}
fseek(f, 0, SEEK_SET);
}
block = (unsigned char*) malloc (sfc.block_sz_phys);
block_flash = (unsigned char*) malloc (sfc.block_sz_phys);
time (&start);
for ( i = 0; i < sfc.size_bytes; i += sfc.block_sz )
{
if ( !(i & 0x3fff) )
{
printf("Verifying block: 0x%x of 0x%x\r", i / sfc.block_sz + 1, sfc.size_blocks);
fflush(stdout);
}
if ( fread(block, 1, sfc.block_sz_phys, f) != sfc.block_sz_phys )
return i;
status = sfcx_read_block(block_flash, i, raw);
if (status & 0x40)
{
printf("Ignoring bad block at 0x%x\n", i / sfc.block_sz );
continue;
}
if ( memcmp(block, block_flash, sfc.block_sz_phys) )
{
printf("Verify error at block: 0x%x\n", i / sfc.block_sz );
return -2;
}
}
time (&end);
time_dif = difftime (end,start);
printf("\nVerify done in %.2lf sec.\nSpeed: %.2lf MB/s\n", time_dif, sfc.size_bytes / time_dif / 1024 / 1024);
fclose(f);
free(block);
free(block_flash);
return i;
}
int flash_from_file( const char *filename, int raw )
{
int i, j, phys_pos;
unsigned char *block, *block_flash;
FILE *f = fopen(filename, "rb");
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);
//64MB XBR-File
if( ftell(f) == NAND_SIZE_64MB / sfc.page_sz * sfc.page_sz_phys )
sfc.size_bytes = NAND_SIZE_64MB;
if ( ftell(f) == sfc.size_bytes / sfc.page_sz * sfc.page_sz_phys )
{
raw = 1;
printf("Detected RAW nand file, flashing in raw mode.\n");
}
else
{
raw = 0;
printf("Detected short nand file, flashing in cooked mode.\n");
}
fseek(f, 0, SEEK_SET);
}
block = (unsigned char*) malloc (sfc.block_sz_phys);
block_flash = (unsigned char*) malloc (sfc.block_sz_phys);
time(&start);
for ( i = 0; i < sfc.size_bytes; i += sfc.block_sz )
{
memset(block, 0xFF, sizeof(block));
if ( !fread(block, 1, sfc.page_sz_phys * sfc.pages_in_block, f) )
return i;
printf("Writing block: 0x%x of 0x%x\r", i / sfc.block_sz + 1, sfc.size_blocks );
fflush(stdout);
if ( !raw )
{
sfcx_read_page(block_flash, i, 0);
phys_pos = sfcx_readreg(SFCX_PHYSICAL);
if ( !(phys_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 at %08x failed.\n", i);
phys_pos = i;
}
phys_pos &= 0x3fffe00;
if ( phys_pos != i )
printf("Relocating block 0x%x to 0x%x...\n", i / sfc.block_sz , phys_pos / sfc.block_sz);
}
else
phys_pos = i;
//Erase block in Nand
sfcx_erase_block(phys_pos);
//Write block to Nand
sfcx_write_block(block, phys_pos);
}
time(&end);
time_dif = difftime(end,start);
printf("\nWrite done in %.2lf sec.\nSpeed: %.2lf MB/s\n", time_dif, sfc.size_bytes / time_dif / 1024 / 1024);
free(block);
free(block_flash);
return 0;
}
volatile void * ioremap( unsigned long long physaddr, unsigned size, int sync )
{
int axs_mem_fd = -1;
unsigned long long page_addr, ofs_addr, reg, pgmask;
void* reg_mem = NULL;
/*
* looks like mmap wants aligned addresses?
*/
pgmask = getpagesize() - 1;
page_addr = physaddr & ~pgmask;
ofs_addr = physaddr & pgmask;
/*
* Don't forget O_SYNC, esp. if address is in RAM region.
* Note: if you do know you'll access in Read Only mode,
* pass O_RDONLY to open, and PROT_READ only to mmap
*/
if ( axs_mem_fd == -1 )
{
axs_mem_fd = open("/dev/mem", O_RDWR | (sync ? O_SYNC : 0));
if ( axs_mem_fd < 0 )
{
perror("AXS: can't open /dev/mem");
return NULL;
}
}
/* memory map */
reg_mem = mmap64((caddr_t) reg_mem, size + ofs_addr, PROT_READ | PROT_WRITE, MAP_SHARED, axs_mem_fd, page_addr);
if ( reg_mem == MAP_FAILED )
{
perror("AXS: mmap error");
close(axs_mem_fd);
return NULL;
}
reg = (unsigned long) reg_mem + ofs_addr;
return (volatile void *) reg;
}
int iounmap( volatile void *start, size_t length )
{
unsigned long ofs_addr;
ofs_addr = (unsigned long) start & (getpagesize() - 1);
/* do some cleanup when you're done with it */
return munmap((unsigned char*) start - ofs_addr, length + ofs_addr);
}
void sfcx_writereg( int reg, unsigned long value )
{
flash[reg] = bswap_32(value);
}
unsigned int sfcx_readreg( int reg )
{
return bswap_32(flash[reg]);
}
unsigned int sfcx_init(void)
{
sfc.initialized = 0;
sfc.large_block = 0;
sfc.page_sz = 0x200;
sfc.meta_sz = 0x10;
sfc.page_sz_phys = sfc.page_sz + sfc.meta_sz;
unsigned int config = sfcx_readreg(SFCX_CONFIG);
//Turn off interrupts, turn off WP_EN, and set DMA pages to 0
sfcx_writereg(SFCX_CONFIG, config &~ (4|8|0x3c0));
switch ((config >> 17) & 0x03)
{
case 0: // Small block original SFC (pre jasper)
switch ((config >> 4) & 0x3)
{
case 0: // Unsupported 8MB?
printf("Error: Unsupported Type A-0\n");
return -1;
//sfc.block_sz = 0x4000; // 16 KB
//sfc.size_blocks = 0x200;
//sfc.size_bytes = sfc.size_blocks << 0xE;
case 1: // 16MB
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x400;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
case 2: // 32MB
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x800;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
case 3: // 64MB
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x1000;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
}
break;
case 1: // New SFC/Southbridge: Codename "Panda"?
switch ((config >> 4) & 0x3)
{
case 0: // Unsupported
printf("Error: Unsupported Type B-0\n");
return -2;
case 1: // Small block 16MB setup
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x400;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
case 2: // Large Block: Current Jasper 256MB and 512MB
sfc.block_sz = 0x20000; // 128KB
//sfc.size_bytes = 0x1 << (((config >> 19) & 0x3) + ((config >> 21) & 0xF) + 0x17);
sfc.size_bytes = 1024 * 1024 * 64;
sfc.size_blocks = sfc.size_bytes >> 0x11;
sfc.large_block = 2;
break;
case 3: // Large Block: Future or unknown hardware
sfc.block_sz = 0x40000; // 256KB
sfc.size_bytes = 0x1 << (((config >> 19) & 0x3) + ((config >> 21) & 0xF) + 0x17);
sfc.size_blocks = sfc.size_bytes >> 0x12;
sfc.large_block = 3;
break;
}
break;
default:
printf("Error: Unsupported Type\n");
return -3;
}
sfc.pages_in_block = sfc.block_sz / sfc.page_sz;
sfc.block_sz_phys = sfc.pages_in_block * sfc.page_sz_phys;
sfc.size_pages = sfc.size_bytes / sfc.page_sz;
sfc.size_blocks = sfc.size_bytes / sfc.block_sz;
sfc.size_bytes_phys = sfc.block_sz_phys * sfc.size_blocks;
sfc.size_mb = sfc.size_bytes >> 20;
printf("Nandsize: %d MB\n", sfc.size_mb);
#if 0
printf(" config register = %08X\n", config);
printf(" sfc:page_sz = %08X\n", sfc.page_sz);
printf(" sfc:meta_sz = %08X\n", sfc.meta_sz);
printf(" sfc:page_sz_phys = %08X\n", sfc.page_sz_phys);
printf(" sfc:pages_in_block = %08X\n", sfc.pages_in_block);
printf(" sfc:block_sz = %08X\n", sfc.block_sz);
printf(" sfc:block_sz_phys = %08X\n", sfc.block_sz_phys);
printf(" sfc:size_mb = %dMB\n", sfc.size_mb);
printf(" sfc:size_bytes = %08X\n", sfc.size_bytes);
printf(" sfc:size_bytes_phys = %08X\n", sfc.size_bytes_phys);
printf(" sfc:size_pages = %08X\n", sfc.size_pages);
printf(" sfc:size_blocks = %08X\n", sfc.size_blocks);
printf("\n");
#endif
sfc.initialized = 1;
return config;
}
int sfcx_read_page(unsigned char *data, int address, int raw)
{
int status;
sfcx_writereg(SFCX_STATUS, sfcx_readreg(SFCX_STATUS));
// Set flash address (logical)
//address &= 0x3fffe00; // Align to page
sfcx_writereg(SFCX_ADDRESS, 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 ? PHY_PAGE_TO_BUF : LOG_PAGE_TO_BUF);
// Wait Busy
while ((status = sfcx_readreg(SFCX_STATUS)) & 1);
if (status != 0x200)
{
if (status & 0x40)
printf("Bad block found (index: 0x%x) \n", address / sfc.block_sz);
else if (status & 0x1c)
{
//printf(" ! SFCX: (Corrected) ECC error at address %08x: %08x\n", address, status);
}
else if (!raw && (status & 0x800))
{
//printf(" ! SFCX: Illegal logical block at %08x (status: %08x)\n", address / sfc.block_sz, status);
}
else
{
printf("Error: Unknown error at address 0x%x: 0x%x. Please worry.\n", address, 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 < page_sz ; i += 4)
{
// Transfer data from buffer to register
sfcx_writereg(SFCX_COMMAND, PAGE_BUF_TO_REG);
// Read out our data through the register
*(int*)(data + i) = bswap_32(sfcx_readreg(SFCX_DATA));
}
return status;
}
int sfcx_write_page(unsigned char *data, int address)
{
sfcx_writereg(SFCX_STATUS, 0xFF);
// Enable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) | 8);
// Set internal page buffer pointer to 0
sfcx_writereg(SFCX_ADDRESS, 0);
int i;
for (i = 0; i < sfc.page_sz_phys; i+=4)
{
// Write out our data through the register
sfcx_writereg(SFCX_DATA, bswap_32(*(int*)(data + i)));
// Transfer data from register to buffer
sfcx_writereg(SFCX_COMMAND, REG_TO_PAGE_BUF);
}
// Set flash address (logical)
//address &= 0x3fffe00; // Align to page
sfcx_writereg(SFCX_ADDRESS, address);
// Unlock sequence (for write)
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_0);
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_1);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
// Command the write
sfcx_writereg(SFCX_COMMAND, WRITE_PAGE_TO_PHY);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
int status = sfcx_readreg(SFCX_STATUS);
if (status != 0x200)
printf("Unexpected sfcx_write_page status 0x%x\n", status);
// Disable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) & ~8);
return status;
}
int sfcx_read_block(unsigned char *data, int address, int raw)
{
int p;
int status = 0;
int page_sz = raw ? sfc.page_sz_phys : sfc.page_sz;
for (p = 0; p < sfc.pages_in_block; p++)
{
status |= sfcx_read_page(&data[p * page_sz], address + (p * sfc.page_sz), raw);
//if (status != 0x200)
// break;
}
return status;
}
int sfcx_write_block(unsigned char *data, int address)
{
int p;
int status = 0;
for (p = 0; p < sfc.pages_in_block; p++)
{
status |= sfcx_write_page(&data[p * sfc.page_sz_phys], address + (p * sfc.page_sz));
//if (status != 0x200)
// break;
}
return status;
}
int sfcx_erase_block(int address)
{
// Enable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) | 8);
sfcx_writereg(SFCX_STATUS, 0xFF);
// Set flash address (logical)
//address &= 0x3fffe00; // Align to page
sfcx_writereg(SFCX_ADDRESS, address);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
// Unlock sequence (for erase)
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_1);
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_0);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
// Command the block erase
sfcx_writereg(SFCX_COMMAND, BLOCK_ERASE);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
int status = sfcx_readreg(SFCX_STATUS);
if (status != 0x200)
printf("Unexpected erase at block 0x%x with status 0x%x\n", address / sfc.block_sz, status);
sfcx_writereg(SFCX_STATUS, 0xFF);
// Disable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) & ~8);
return status;
}
void sfcx_calcecc(unsigned int *data)
{
unsigned int i=0, val=0;
unsigned char *edc = ((unsigned char*)data) + sfc.page_sz;
unsigned int v=0;
for (i = 0; i < 0x1066; i++)
{
if (!(i & 31))
v = ~bswap_32(*data++);
val ^= v & 1;
v>>=1;
if (val & 1)
val ^= 0x6954559;
val >>= 1;
}
val = ~val;
// 26 bit ecc data
edc[0xC] |= (val << 6) & 0xC0;
edc[0xD] = (val >> 2) & 0xFF;
edc[0xE] = (val >> 10) & 0xFF;
edc[0xF] = (val >> 18) & 0xFF;
}
int sfcx_get_blocknumber(unsigned char *data)
{
if(sfc.large_block)
{
return (data[sfc.page_sz + 0x2] << 8) | (data[sfc.page_sz + 0x1]);
}
else
{
return (data[sfc.page_sz + 0x1] << 8) | (data[sfc.page_sz + 0x0]);
}
}
void sfcx_set_blocknumber(unsigned char *data, int num)
{
if(sfc.large_block)
{
data[sfc.page_sz + 0x2] = (num >> 8) & 0xFF;
data[sfc.page_sz + 0x1] = (num >> 0) & 0xFF;
}
else
{
data[sfc.page_sz + 0x1] = (num >> 8) & 0xFF;
data[sfc.page_sz + 0x0] = (num >> 0) & 0xFF;
}
}
int sfcx_get_blockversion(unsigned char *data)
{
if(sfc.large_block)
{
return (data[sfc.page_sz + 0x6] << 24) | (data[sfc.page_sz + 0x4] << 16) |
(data[sfc.page_sz + 0x3] << 8) | (data[sfc.page_sz + 0x5]);
}
else
{
return (data[sfc.page_sz + 0x6] << 24) | (data[sfc.page_sz + 0x4] << 16) |
(data[sfc.page_sz + 0x3] << 8) | (data[sfc.page_sz + 0x2]);
}
}
void sfcx_set_blockversion(unsigned char *data, int ver)
{
// NOTE This is only doing a single page
if(sfc.large_block)
{
data[sfc.page_sz + 0x5] = (ver >> 0) & 0xFF;
data[sfc.page_sz + 0x3] = (ver >> 8) & 0xFF;
data[sfc.page_sz + 0x4] = (ver >> 16) & 0xFF;
data[sfc.page_sz + 0x6] = (ver >> 24) & 0xFF;
}
else
{
data[sfc.page_sz + 0x2] = (ver >> 0) & 0xFF;
data[sfc.page_sz + 0x3] = (ver >> 8) & 0xFF;
data[sfc.page_sz + 0x4] = (ver >> 16) & 0xFF;
data[sfc.page_sz + 0x6] = (ver >> 24) & 0xFF;
}
}
void sfcx_set_pagevalid(unsigned char *data)
{
if(sfc.large_block)
{
data[sfc.page_sz + 0x0] = 0xFF;
}
else
{
data[sfc.page_sz + 0x5] = 0xFF;
}
}
void sfcx_set_pageinvalid(unsigned char *data)
{
if(sfc.large_block)
{
data[sfc.page_sz + 0x0] = 0x00;
}
else
{
data[sfc.page_sz + 0x5] = 0x00;
}
}
int sfcx_is_pagevalid(unsigned char *data)
{
if(sfc.large_block)
{
return data[sfc.page_sz + 0x0] == 0xFF;
}
else
{
return data[sfc.page_sz + 0x5] == 0xFF;
}
}
// TODO: Some sort of block/file system driver to make use of
// the block allocation table and the rest of the nand
int sfcx_block_to_address(int block)
{
return block * sfc.block_sz;
}
int sfcx_address_to_block(int address)
{
return address / sfc.block_sz;
}
Hail_Mary escribió:Xbrflash.c Jasper 256/512mb:/*
XBR-Flash for Linux by trancy
Thanks goes to tmbinc and Redline99
History
-------
v0.1 initial by tmbinc
v0.1.x modified by Redline99
v0.1.1 modified by trancy
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <byteswap.h>
#include <string.h>
#include <time.h>
volatile unsigned int *flash;
time_t start,end;
double time_dif;
//****** Defines ****************************************************************************
//NAND SIZES
#define NAND_SIZE_16MB 0x1000000
#define NAND_SIZE_64MB 0x4000000
#define NAND_SIZE_256MB 0x10000000
#define NAND_SIZE_512MB 0x20000000
//Registers
/*
#define SFCX_CONFIG 0x00
#define SFCX_STATUS 0x04
#define SFCX_COMMAND 0x08
#define SFCX_ADDRESS 0x0C
#define SFCX_DATA 0x10
#define SFCX_LOGICAL 0x14
#define SFCX_PHYSICAL 0x18
#define SFCX_DPHYSADDR 0x1C
#define SFCX_MPHYSADDR 0x20
*/
#define SFCX_CONFIG 0x00
#define SFCX_STATUS 0x01
#define SFCX_COMMAND 0x02
#define SFCX_ADDRESS 0x03
#define SFCX_DATA 0x04
#define SFCX_LOGICAL 0x05
#define SFCX_PHYSICAL 0x06
#define SFCX_DPHYSADDR 0x07
#define SFCX_MPHYSADDR 0x08
//Commands for Command Register
#define PAGE_BUF_TO_REG 0x00 //Read page buffer to data register
#define REG_TO_PAGE_BUF 0x01 //Write data register to page buffer
#define LOG_PAGE_TO_BUF 0x02 //Read logical page into page buffer
#define PHY_PAGE_TO_BUF 0x03 //Read physical page into page buffer
#define WRITE_PAGE_TO_PHY 0x04 //Write page buffer to physical page
#define BLOCK_ERASE 0x05 //Block Erase
#define DMA_LOG_TO_RAM 0x06 //DMA logical flash to main memory
#define DMA_PHY_TO_RAM 0x07 //DMA physical flash to main memory
#define DMA_RAM_TO_PHY 0x08 //DMA main memory to physical flash
#define UNLOCK_CMD_0 0x55 //Unlock command 0; Kernel does 0x5500
#define UNLOCK_CMD_1 0xAA //Unlock command 1; Kernel does 0xAA00
// API Consumers should use these two defines to
// use for creating static buffers at compile time
#define MAX_PAGE_SZ 0x210 //Max known hardware physical page size
#define MAX_BLOCK_SZ 0x42000 //Max known hardware physical block size
struct sfc
{
int initialized;
int large_block;
int page_sz;
int meta_sz;
int page_sz_phys;
int pages_in_block;
int block_sz;
int block_sz_phys;
int size_mb;
int size_bytes;
int size_bytes_phys;
int size_pages;
int size_blocks;
};
//****** Prototypes ****************************************************************************
unsigned int sfcx_init(void);
void sfcx_writereg( int reg, unsigned long value );
unsigned int sfcx_readreg( int reg );
int sfcx_erase_block(int address);
int sfcx_read_page(unsigned char *data, int sector, int raw);
int sfcx_write_page(unsigned char *data, int address);
int sfcx_read_block(unsigned char *data, int address, int raw);
int sfcx_write_block(unsigned char *data, int address);
void sfcx_calcecc(unsigned int *data);
int sfcx_get_blocknumber(unsigned char *data);
void sfcx_set_blocknumber(unsigned char *data, int num);
int sfcx_get_blockversion(unsigned char *data);
void sfcx_set_blockversion(unsigned char *data, int ver);
void sfcx_set_pagevalid(unsigned char *data);
void sfcx_set_pageinvalid(unsigned char *data);
int sfcx_is_pagevalid(unsigned char *data);
int sfcx_block_to_address(int block);
int sfcx_address_to_block(int address);
extern void *mmap64( void *__addr, size_t __len, int __prot, int __flags, int __fd, __off64_t __offset) __THROW;
extern volatile void * ioremap( unsigned long long physaddr, unsigned size, int sync );
extern int iounmap( volatile void *start, size_t length );
int flash_from_file( const char *filename, int raw );
int dump_flash_to_file( const char *filename );
int verify_flash_with_file( const char *filename, int raw );
struct sfc sfc;
int main( int argc, char **argv )
{
const char *orig = argv[1];
int res;
printf("XBR-Flash for Linux v0.1.1 beta by trancy\nThanks goes to tmbinc and Redline99\n\n");
flash = ioremap(0xea00c000, 0x1000, 1);
sfcx_init();
if ( argc != 2 && argc != 3 )
{
printf("usage: %s <current> [<new>]\n", *argv);
return 2;
}
res = verify_flash_with_file(orig, 1);
if ( res == -1 )
{
dump_flash_to_file(orig);
res = verify_flash_with_file(orig, 1);
}
if ( res != sfc.size_bytes )
{
if ( res == -2 )
printf("Verify failed!\n");
else
if ( res > 0 )
printf("Verified correctly, but only %d bytes.\n", res);
else
printf("Error: Original image invalid\n");
printf("Info: I won't flash if you don't have a full, working backup, sorry.\n");
return 1;
}
printf("Verify ok.\n");
//Write from file to flash
if ( argc > 2 )
{
const char *image = argv[2];
flash_from_file(image, -1);
res = verify_flash_with_file(image, -1);
if ( res > 0 )
printf("Verified %d bytes ok :)\n", res);
else
printf("Error: Verify failed! (%d)\n", res);
}
return 0;
}
int dump_flash_to_file( const char *filename )
{
int i;
unsigned char *block;
block = (unsigned char*) malloc (sfc.block_sz_phys);
printf("\nDumping to %s...\n", filename);
printf("0x%x block's to dump...\n", sfc.size_blocks );
time (&start);
FILE *f = fopen(filename, "wb");
for ( i = 0; i < sfc.size_bytes; i += sfc.block_sz )
{
sfcx_read_block(block, i, 1);
if ( !(i & 0x3fff) )
{
printf("Reading block: 0x%x of 0x%x\r", i / sfc.block_sz + 1 , sfc.size_blocks );
fflush(stdout);
}
if ( fwrite(block, 1, sfc.block_sz_phys, f) != sfc.block_sz_phys )
return -1;
}
time (&end);
time_dif = difftime (end,start);
printf("\nReading done in %.2lf sec.\nSpeed: %.2lf MB/s\n", time_dif, sfc.size_bytes / time_dif / 1024 / 1024);
fclose(f);
free(block);
return 0;
}
int verify_flash_with_file( const char *filename, int raw )
{
int i, status;
unsigned char *block, *block_flash;
FILE *f = fopen(filename, "rb");
if ( !f )
return -1;
printf("\nVerifying flash with %s...\n", filename);
printf("0x%x block's to verify...\n", sfc.size_blocks);
if ( raw == -1 ) /* auto */
{
fseek(f, 0, SEEK_END);
//64MB XBR-File
if( ftell(f) == NAND_SIZE_64MB / sfc.page_sz * sfc.page_sz_phys )
sfc.size_bytes = NAND_SIZE_64MB;
if ( ftell(f) == sfc.size_bytes / sfc.page_sz * sfc.page_sz_phys )
{
raw = 1;
printf("Detected RAW nand file, verifying in raw mode.\n");
}
else
{
raw = 0;
printf("Detected short nand file, verifying in cooked mode.\n");
}
fseek(f, 0, SEEK_SET);
}
block = (unsigned char*) malloc (sfc.block_sz_phys);
block_flash = (unsigned char*) malloc (sfc.block_sz_phys);
time (&start);
for ( i = 0; i < sfc.size_bytes; i += sfc.block_sz )
{
if ( !(i & 0x3fff) )
{
printf("Verifying block: 0x%x of 0x%x\r", i / sfc.block_sz + 1, sfc.size_blocks);
fflush(stdout);
}
if ( fread(block, 1, sfc.block_sz_phys, f) != sfc.block_sz_phys )
return i;
status = sfcx_read_block(block_flash, i, raw);
if (status & 0x40)
{
printf("Ignoring bad block at 0x%x\n", i / sfc.block_sz );
continue;
}
if ( memcmp(block, block_flash, sfc.block_sz_phys) )
{
printf("Verify error at block: 0x%x\n", i / sfc.block_sz );
return -2;
}
}
time (&end);
time_dif = difftime (end,start);
printf("\nVerify done in %.2lf sec.\nSpeed: %.2lf MB/s\n", time_dif, sfc.size_bytes / time_dif / 1024 / 1024);
fclose(f);
free(block);
free(block_flash);
return i;
}
int flash_from_file( const char *filename, int raw )
{
int i, j, phys_pos;
unsigned char *block, *block_flash;
FILE *f = fopen(filename, "rb");
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);
//64MB XBR-File
if( ftell(f) == NAND_SIZE_64MB / sfc.page_sz * sfc.page_sz_phys )
sfc.size_bytes = NAND_SIZE_64MB;
if ( ftell(f) == sfc.size_bytes / sfc.page_sz * sfc.page_sz_phys )
{
raw = 1;
printf("Detected RAW nand file, flashing in raw mode.\n");
}
else
{
raw = 0;
printf("Detected short nand file, flashing in cooked mode.\n");
}
fseek(f, 0, SEEK_SET);
}
block = (unsigned char*) malloc (sfc.block_sz_phys);
block_flash = (unsigned char*) malloc (sfc.block_sz_phys);
time(&start);
for ( i = 0; i < sfc.size_bytes; i += sfc.block_sz )
{
memset(block, 0xFF, sizeof(block));
if ( !fread(block, 1, sfc.page_sz_phys * sfc.pages_in_block, f) )
return i;
printf("Writing block: 0x%x of 0x%x\r", i / sfc.block_sz + 1, sfc.size_blocks );
fflush(stdout);
if ( !raw )
{
sfcx_read_page(block_flash, i, 0);
phys_pos = sfcx_readreg(SFCX_PHYSICAL);
if ( !(phys_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 at %08x failed.\n", i);
phys_pos = i;
}
phys_pos &= 0x3fffe00;
if ( phys_pos != i )
printf("Relocating block 0x%x to 0x%x...\n", i / sfc.block_sz , phys_pos / sfc.block_sz);
}
else
phys_pos = i;
//Erase block in Nand
sfcx_erase_block(phys_pos);
//Write block to Nand
sfcx_write_block(block, phys_pos);
}
time(&end);
time_dif = difftime(end,start);
printf("\nWrite done in %.2lf sec.\nSpeed: %.2lf MB/s\n", time_dif, sfc.size_bytes / time_dif / 1024 / 1024);
free(block);
free(block_flash);
return 0;
}
volatile void * ioremap( unsigned long long physaddr, unsigned size, int sync )
{
int axs_mem_fd = -1;
unsigned long long page_addr, ofs_addr, reg, pgmask;
void* reg_mem = NULL;
/*
* looks like mmap wants aligned addresses?
*/
pgmask = getpagesize() - 1;
page_addr = physaddr & ~pgmask;
ofs_addr = physaddr & pgmask;
/*
* Don't forget O_SYNC, esp. if address is in RAM region.
* Note: if you do know you'll access in Read Only mode,
* pass O_RDONLY to open, and PROT_READ only to mmap
*/
if ( axs_mem_fd == -1 )
{
axs_mem_fd = open("/dev/mem", O_RDWR | (sync ? O_SYNC : 0));
if ( axs_mem_fd < 0 )
{
perror("AXS: can't open /dev/mem");
return NULL;
}
}
/* memory map */
reg_mem = mmap64((caddr_t) reg_mem, size + ofs_addr, PROT_READ | PROT_WRITE, MAP_SHARED, axs_mem_fd, page_addr);
if ( reg_mem == MAP_FAILED )
{
perror("AXS: mmap error");
close(axs_mem_fd);
return NULL;
}
reg = (unsigned long) reg_mem + ofs_addr;
return (volatile void *) reg;
}
int iounmap( volatile void *start, size_t length )
{
unsigned long ofs_addr;
ofs_addr = (unsigned long) start & (getpagesize() - 1);
/* do some cleanup when you're done with it */
return munmap((unsigned char*) start - ofs_addr, length + ofs_addr);
}
void sfcx_writereg( int reg, unsigned long value )
{
flash[reg] = bswap_32(value);
}
unsigned int sfcx_readreg( int reg )
{
return bswap_32(flash[reg]);
}
unsigned int sfcx_init(void)
{
sfc.initialized = 0;
sfc.large_block = 0;
sfc.page_sz = 0x200;
sfc.meta_sz = 0x10;
sfc.page_sz_phys = sfc.page_sz + sfc.meta_sz;
unsigned int config = sfcx_readreg(SFCX_CONFIG);
//Turn off interrupts, turn off WP_EN, and set DMA pages to 0
sfcx_writereg(SFCX_CONFIG, config &~ (4|8|0x3c0));
switch ((config >> 17) & 0x03)
{
case 0: // Small block original SFC (pre jasper)
switch ((config >> 4) & 0x3)
{
case 0: // Unsupported 8MB?
printf("Error: Unsupported Type A-0\n");
return -1;
//sfc.block_sz = 0x4000; // 16 KB
//sfc.size_blocks = 0x200;
//sfc.size_bytes = sfc.size_blocks << 0xE;
case 1: // 16MB
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x400;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
case 2: // 32MB
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x800;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
case 3: // 64MB
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x1000;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
}
break;
case 1: // New SFC/Southbridge: Codename "Panda"?
switch ((config >> 4) & 0x3)
{
case 0: // Unsupported
printf("Error: Unsupported Type B-0\n");
return -2;
case 1: // Small block 16MB setup
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x400;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
case 2: // Large Block: Current Jasper 256MB and 512MB
sfc.block_sz = 0x20000; // 128KB
//sfc.size_bytes = 0x1 << (((config >> 19) & 0x3) + ((config >> 21) & 0xF) + 0x17);
sfc.size_bytes = 1024 * 1024 * 64;
sfc.size_blocks = sfc.size_bytes >> 0x11;
sfc.large_block = 2;
break;
case 3: // Large Block: Future or unknown hardware
sfc.block_sz = 0x40000; // 256KB
sfc.size_bytes = 0x1 << (((config >> 19) & 0x3) + ((config >> 21) & 0xF) + 0x17);
sfc.size_blocks = sfc.size_bytes >> 0x12;
sfc.large_block = 3;
break;
}
break;
default:
printf("Error: Unsupported Type\n");
return -3;
}
sfc.pages_in_block = sfc.block_sz / sfc.page_sz;
sfc.block_sz_phys = sfc.pages_in_block * sfc.page_sz_phys;
sfc.size_pages = sfc.size_bytes / sfc.page_sz;
sfc.size_blocks = sfc.size_bytes / sfc.block_sz;
sfc.size_bytes_phys = sfc.block_sz_phys * sfc.size_blocks;
sfc.size_mb = sfc.size_bytes >> 20;
printf("Nandsize: %d MB\n", sfc.size_mb);
#if 0
printf(" config register = %08X\n", config);
printf(" sfc:page_sz = %08X\n", sfc.page_sz);
printf(" sfc:meta_sz = %08X\n", sfc.meta_sz);
printf(" sfc:page_sz_phys = %08X\n", sfc.page_sz_phys);
printf(" sfc:pages_in_block = %08X\n", sfc.pages_in_block);
printf(" sfc:block_sz = %08X\n", sfc.block_sz);
printf(" sfc:block_sz_phys = %08X\n", sfc.block_sz_phys);
printf(" sfc:size_mb = %dMB\n", sfc.size_mb);
printf(" sfc:size_bytes = %08X\n", sfc.size_bytes);
printf(" sfc:size_bytes_phys = %08X\n", sfc.size_bytes_phys);
printf(" sfc:size_pages = %08X\n", sfc.size_pages);
printf(" sfc:size_blocks = %08X\n", sfc.size_blocks);
printf("\n");
#endif
sfc.initialized = 1;
return config;
}
int sfcx_read_page(unsigned char *data, int address, int raw)
{
int status;
sfcx_writereg(SFCX_STATUS, sfcx_readreg(SFCX_STATUS));
// Set flash address (logical)
//address &= 0x3fffe00; // Align to page
sfcx_writereg(SFCX_ADDRESS, 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 ? PHY_PAGE_TO_BUF : LOG_PAGE_TO_BUF);
// Wait Busy
while ((status = sfcx_readreg(SFCX_STATUS)) & 1);
if (status != 0x200)
{
if (status & 0x40)
printf("Bad block found (index: 0x%x) \n", address / sfc.block_sz);
else if (status & 0x1c)
{
//printf(" ! SFCX: (Corrected) ECC error at address %08x: %08x\n", address, status);
}
else if (!raw && (status & 0x800))
{
//printf(" ! SFCX: Illegal logical block at %08x (status: %08x)\n", address / sfc.block_sz, status);
}
else
{
printf("Error: Unknown error at address 0x%x: 0x%x. Please worry.\n", address, 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 < page_sz ; i += 4)
{
// Transfer data from buffer to register
sfcx_writereg(SFCX_COMMAND, PAGE_BUF_TO_REG);
// Read out our data through the register
*(int*)(data + i) = bswap_32(sfcx_readreg(SFCX_DATA));
}
return status;
}
int sfcx_write_page(unsigned char *data, int address)
{
sfcx_writereg(SFCX_STATUS, 0xFF);
// Enable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) | 8);
// Set internal page buffer pointer to 0
sfcx_writereg(SFCX_ADDRESS, 0);
int i;
for (i = 0; i < sfc.page_sz_phys; i+=4)
{
// Write out our data through the register
sfcx_writereg(SFCX_DATA, bswap_32(*(int*)(data + i)));
// Transfer data from register to buffer
sfcx_writereg(SFCX_COMMAND, REG_TO_PAGE_BUF);
}
// Set flash address (logical)
//address &= 0x3fffe00; // Align to page
sfcx_writereg(SFCX_ADDRESS, address);
// Unlock sequence (for write)
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_0);
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_1);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
// Command the write
sfcx_writereg(SFCX_COMMAND, WRITE_PAGE_TO_PHY);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
int status = sfcx_readreg(SFCX_STATUS);
if (status != 0x200)
printf("Unexpected sfcx_write_page status 0x%x\n", status);
// Disable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) & ~8);
return status;
}
int sfcx_read_block(unsigned char *data, int address, int raw)
{
int p;
int status = 0;
int page_sz = raw ? sfc.page_sz_phys : sfc.page_sz;
for (p = 0; p < sfc.pages_in_block; p++)
{
status |= sfcx_read_page(&data[p * page_sz], address + (p * sfc.page_sz), raw);
//if (status != 0x200)
// break;
}
return status;
}
int sfcx_write_block(unsigned char *data, int address)
{
int p;
int status = 0;
for (p = 0; p < sfc.pages_in_block; p++)
{
status |= sfcx_write_page(&data[p * sfc.page_sz_phys], address + (p * sfc.page_sz));
//if (status != 0x200)
// break;
}
return status;
}
int sfcx_erase_block(int address)
{
// Enable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) | 8);
sfcx_writereg(SFCX_STATUS, 0xFF);
// Set flash address (logical)
//address &= 0x3fffe00; // Align to page
sfcx_writereg(SFCX_ADDRESS, address);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
// Unlock sequence (for erase)
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_1);
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_0);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
// Command the block erase
sfcx_writereg(SFCX_COMMAND, BLOCK_ERASE);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
int status = sfcx_readreg(SFCX_STATUS);
if (status != 0x200)
printf("Unexpected erase at block 0x%x with status 0x%x\n", address / sfc.block_sz, status);
sfcx_writereg(SFCX_STATUS, 0xFF);
// Disable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) & ~8);
return status;
}
void sfcx_calcecc(unsigned int *data)
{
unsigned int i=0, val=0;
unsigned char *edc = ((unsigned char*)data) + sfc.page_sz;
unsigned int v=0;
for (i = 0; i < 0x1066; i++)
{
if (!(i & 31))
v = ~bswap_32(*data++);
val ^= v & 1;
v>>=1;
if (val & 1)
val ^= 0x6954559;
val >>= 1;
}
val = ~val;
// 26 bit ecc data
edc[0xC] |= (val << 6) & 0xC0;
edc[0xD] = (val >> 2) & 0xFF;
edc[0xE] = (val >> 10) & 0xFF;
edc[0xF] = (val >> 18) & 0xFF;
}
int sfcx_get_blocknumber(unsigned char *data)
{
if(sfc.large_block)
{
return (data[sfc.page_sz + 0x2] << 8) | (data[sfc.page_sz + 0x1]);
}
else
{
return (data[sfc.page_sz + 0x1] << 8) | (data[sfc.page_sz + 0x0]);
}
}
void sfcx_set_blocknumber(unsigned char *data, int num)
{
if(sfc.large_block)
{
data[sfc.page_sz + 0x2] = (num >> 8) & 0xFF;
data[sfc.page_sz + 0x1] = (num >> 0) & 0xFF;
}
else
{
data[sfc.page_sz + 0x1] = (num >> 8) & 0xFF;
data[sfc.page_sz + 0x0] = (num >> 0) & 0xFF;
}
}
int sfcx_get_blockversion(unsigned char *data)
{
if(sfc.large_block)
{
return (data[sfc.page_sz + 0x6] << 24) | (data[sfc.page_sz + 0x4] << 16) |
(data[sfc.page_sz + 0x3] << 8) | (data[sfc.page_sz + 0x5]);
}
else
{
return (data[sfc.page_sz + 0x6] << 24) | (data[sfc.page_sz + 0x4] << 16) |
(data[sfc.page_sz + 0x3] << 8) | (data[sfc.page_sz + 0x2]);
}
}
void sfcx_set_blockversion(unsigned char *data, int ver)
{
// NOTE This is only doing a single page
if(sfc.large_block)
{
data[sfc.page_sz + 0x5] = (ver >> 0) & 0xFF;
data[sfc.page_sz + 0x3] = (ver >> 8) & 0xFF;
data[sfc.page_sz + 0x4] = (ver >> 16) & 0xFF;
data[sfc.page_sz + 0x6] = (ver >> 24) & 0xFF;
}
else
{
data[sfc.page_sz + 0x2] = (ver >> 0) & 0xFF;
data[sfc.page_sz + 0x3] = (ver >> 8) & 0xFF;
data[sfc.page_sz + 0x4] = (ver >> 16) & 0xFF;
data[sfc.page_sz + 0x6] = (ver >> 24) & 0xFF;
}
}
void sfcx_set_pagevalid(unsigned char *data)
{
if(sfc.large_block)
{
data[sfc.page_sz + 0x0] = 0xFF;
}
else
{
data[sfc.page_sz + 0x5] = 0xFF;
}
}
void sfcx_set_pageinvalid(unsigned char *data)
{
if(sfc.large_block)
{
data[sfc.page_sz + 0x0] = 0x00;
}
else
{
data[sfc.page_sz + 0x5] = 0x00;
}
}
int sfcx_is_pagevalid(unsigned char *data)
{
if(sfc.large_block)
{
return data[sfc.page_sz + 0x0] == 0xFF;
}
else
{
return data[sfc.page_sz + 0x5] == 0xFF;
}
}
// TODO: Some sort of block/file system driver to make use of
// the block allocation table and the rest of the nand
int sfcx_block_to_address(int block)
{
return block * sfc.block_sz;
}
int sfcx_address_to_block(int address)
{
return address / sfc.block_sz;
}
RastaMan escribió:Hail_Mary escribió:Xbrflash.c Jasper 256/512mb:/*
XBR-Flash for Linux by trancy
Thanks goes to tmbinc and Redline99
History
-------
v0.1 initial by tmbinc
v0.1.x modified by Redline99
v0.1.1 modified by trancy
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <byteswap.h>
#include <string.h>
#include <time.h>
volatile unsigned int *flash;
time_t start,end;
double time_dif;
//****** Defines ****************************************************************************
//NAND SIZES
#define NAND_SIZE_16MB 0x1000000
#define NAND_SIZE_64MB 0x4000000
#define NAND_SIZE_256MB 0x10000000
#define NAND_SIZE_512MB 0x20000000
//Registers
/*
#define SFCX_CONFIG 0x00
#define SFCX_STATUS 0x04
#define SFCX_COMMAND 0x08
#define SFCX_ADDRESS 0x0C
#define SFCX_DATA 0x10
#define SFCX_LOGICAL 0x14
#define SFCX_PHYSICAL 0x18
#define SFCX_DPHYSADDR 0x1C
#define SFCX_MPHYSADDR 0x20
*/
#define SFCX_CONFIG 0x00
#define SFCX_STATUS 0x01
#define SFCX_COMMAND 0x02
#define SFCX_ADDRESS 0x03
#define SFCX_DATA 0x04
#define SFCX_LOGICAL 0x05
#define SFCX_PHYSICAL 0x06
#define SFCX_DPHYSADDR 0x07
#define SFCX_MPHYSADDR 0x08
//Commands for Command Register
#define PAGE_BUF_TO_REG 0x00 //Read page buffer to data register
#define REG_TO_PAGE_BUF 0x01 //Write data register to page buffer
#define LOG_PAGE_TO_BUF 0x02 //Read logical page into page buffer
#define PHY_PAGE_TO_BUF 0x03 //Read physical page into page buffer
#define WRITE_PAGE_TO_PHY 0x04 //Write page buffer to physical page
#define BLOCK_ERASE 0x05 //Block Erase
#define DMA_LOG_TO_RAM 0x06 //DMA logical flash to main memory
#define DMA_PHY_TO_RAM 0x07 //DMA physical flash to main memory
#define DMA_RAM_TO_PHY 0x08 //DMA main memory to physical flash
#define UNLOCK_CMD_0 0x55 //Unlock command 0; Kernel does 0x5500
#define UNLOCK_CMD_1 0xAA //Unlock command 1; Kernel does 0xAA00
// API Consumers should use these two defines to
// use for creating static buffers at compile time
#define MAX_PAGE_SZ 0x210 //Max known hardware physical page size
#define MAX_BLOCK_SZ 0x42000 //Max known hardware physical block size
struct sfc
{
int initialized;
int large_block;
int page_sz;
int meta_sz;
int page_sz_phys;
int pages_in_block;
int block_sz;
int block_sz_phys;
int size_mb;
int size_bytes;
int size_bytes_phys;
int size_pages;
int size_blocks;
};
//****** Prototypes ****************************************************************************
unsigned int sfcx_init(void);
void sfcx_writereg( int reg, unsigned long value );
unsigned int sfcx_readreg( int reg );
int sfcx_erase_block(int address);
int sfcx_read_page(unsigned char *data, int sector, int raw);
int sfcx_write_page(unsigned char *data, int address);
int sfcx_read_block(unsigned char *data, int address, int raw);
int sfcx_write_block(unsigned char *data, int address);
void sfcx_calcecc(unsigned int *data);
int sfcx_get_blocknumber(unsigned char *data);
void sfcx_set_blocknumber(unsigned char *data, int num);
int sfcx_get_blockversion(unsigned char *data);
void sfcx_set_blockversion(unsigned char *data, int ver);
void sfcx_set_pagevalid(unsigned char *data);
void sfcx_set_pageinvalid(unsigned char *data);
int sfcx_is_pagevalid(unsigned char *data);
int sfcx_block_to_address(int block);
int sfcx_address_to_block(int address);
extern void *mmap64( void *__addr, size_t __len, int __prot, int __flags, int __fd, __off64_t __offset) __THROW;
extern volatile void * ioremap( unsigned long long physaddr, unsigned size, int sync );
extern int iounmap( volatile void *start, size_t length );
int flash_from_file( const char *filename, int raw );
int dump_flash_to_file( const char *filename );
int verify_flash_with_file( const char *filename, int raw );
struct sfc sfc;
int main( int argc, char **argv )
{
const char *orig = argv[1];
int res;
printf("XBR-Flash for Linux v0.1.1 beta by trancy\nThanks goes to tmbinc and Redline99\n\n");
flash = ioremap(0xea00c000, 0x1000, 1);
sfcx_init();
if ( argc != 2 && argc != 3 )
{
printf("usage: %s <current> [<new>]\n", *argv);
return 2;
}
res = verify_flash_with_file(orig, 1);
if ( res == -1 )
{
dump_flash_to_file(orig);
res = verify_flash_with_file(orig, 1);
}
if ( res != sfc.size_bytes )
{
if ( res == -2 )
printf("Verify failed!\n");
else
if ( res > 0 )
printf("Verified correctly, but only %d bytes.\n", res);
else
printf("Error: Original image invalid\n");
printf("Info: I won't flash if you don't have a full, working backup, sorry.\n");
return 1;
}
printf("Verify ok.\n");
//Write from file to flash
if ( argc > 2 )
{
const char *image = argv[2];
flash_from_file(image, -1);
res = verify_flash_with_file(image, -1);
if ( res > 0 )
printf("Verified %d bytes ok :)\n", res);
else
printf("Error: Verify failed! (%d)\n", res);
}
return 0;
}
int dump_flash_to_file( const char *filename )
{
int i;
unsigned char *block;
block = (unsigned char*) malloc (sfc.block_sz_phys);
printf("\nDumping to %s...\n", filename);
printf("0x%x block's to dump...\n", sfc.size_blocks );
time (&start);
FILE *f = fopen(filename, "wb");
for ( i = 0; i < sfc.size_bytes; i += sfc.block_sz )
{
sfcx_read_block(block, i, 1);
if ( !(i & 0x3fff) )
{
printf("Reading block: 0x%x of 0x%x\r", i / sfc.block_sz + 1 , sfc.size_blocks );
fflush(stdout);
}
if ( fwrite(block, 1, sfc.block_sz_phys, f) != sfc.block_sz_phys )
return -1;
}
time (&end);
time_dif = difftime (end,start);
printf("\nReading done in %.2lf sec.\nSpeed: %.2lf MB/s\n", time_dif, sfc.size_bytes / time_dif / 1024 / 1024);
fclose(f);
free(block);
return 0;
}
int verify_flash_with_file( const char *filename, int raw )
{
int i, status;
unsigned char *block, *block_flash;
FILE *f = fopen(filename, "rb");
if ( !f )
return -1;
printf("\nVerifying flash with %s...\n", filename);
printf("0x%x block's to verify...\n", sfc.size_blocks);
if ( raw == -1 ) /* auto */
{
fseek(f, 0, SEEK_END);
//64MB XBR-File
if( ftell(f) == NAND_SIZE_64MB / sfc.page_sz * sfc.page_sz_phys )
sfc.size_bytes = NAND_SIZE_64MB;
if ( ftell(f) == sfc.size_bytes / sfc.page_sz * sfc.page_sz_phys )
{
raw = 1;
printf("Detected RAW nand file, verifying in raw mode.\n");
}
else
{
raw = 0;
printf("Detected short nand file, verifying in cooked mode.\n");
}
fseek(f, 0, SEEK_SET);
}
block = (unsigned char*) malloc (sfc.block_sz_phys);
block_flash = (unsigned char*) malloc (sfc.block_sz_phys);
time (&start);
for ( i = 0; i < sfc.size_bytes; i += sfc.block_sz )
{
if ( !(i & 0x3fff) )
{
printf("Verifying block: 0x%x of 0x%x\r", i / sfc.block_sz + 1, sfc.size_blocks);
fflush(stdout);
}
if ( fread(block, 1, sfc.block_sz_phys, f) != sfc.block_sz_phys )
return i;
status = sfcx_read_block(block_flash, i, raw);
if (status & 0x40)
{
printf("Ignoring bad block at 0x%x\n", i / sfc.block_sz );
continue;
}
if ( memcmp(block, block_flash, sfc.block_sz_phys) )
{
printf("Verify error at block: 0x%x\n", i / sfc.block_sz );
return -2;
}
}
time (&end);
time_dif = difftime (end,start);
printf("\nVerify done in %.2lf sec.\nSpeed: %.2lf MB/s\n", time_dif, sfc.size_bytes / time_dif / 1024 / 1024);
fclose(f);
free(block);
free(block_flash);
return i;
}
int flash_from_file( const char *filename, int raw )
{
int i, j, phys_pos;
unsigned char *block, *block_flash;
FILE *f = fopen(filename, "rb");
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);
//64MB XBR-File
if( ftell(f) == NAND_SIZE_64MB / sfc.page_sz * sfc.page_sz_phys )
sfc.size_bytes = NAND_SIZE_64MB;
if ( ftell(f) == sfc.size_bytes / sfc.page_sz * sfc.page_sz_phys )
{
raw = 1;
printf("Detected RAW nand file, flashing in raw mode.\n");
}
else
{
raw = 0;
printf("Detected short nand file, flashing in cooked mode.\n");
}
fseek(f, 0, SEEK_SET);
}
block = (unsigned char*) malloc (sfc.block_sz_phys);
block_flash = (unsigned char*) malloc (sfc.block_sz_phys);
time(&start);
for ( i = 0; i < sfc.size_bytes; i += sfc.block_sz )
{
memset(block, 0xFF, sizeof(block));
if ( !fread(block, 1, sfc.page_sz_phys * sfc.pages_in_block, f) )
return i;
printf("Writing block: 0x%x of 0x%x\r", i / sfc.block_sz + 1, sfc.size_blocks );
fflush(stdout);
if ( !raw )
{
sfcx_read_page(block_flash, i, 0);
phys_pos = sfcx_readreg(SFCX_PHYSICAL);
if ( !(phys_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 at %08x failed.\n", i);
phys_pos = i;
}
phys_pos &= 0x3fffe00;
if ( phys_pos != i )
printf("Relocating block 0x%x to 0x%x...\n", i / sfc.block_sz , phys_pos / sfc.block_sz);
}
else
phys_pos = i;
//Erase block in Nand
sfcx_erase_block(phys_pos);
//Write block to Nand
sfcx_write_block(block, phys_pos);
}
time(&end);
time_dif = difftime(end,start);
printf("\nWrite done in %.2lf sec.\nSpeed: %.2lf MB/s\n", time_dif, sfc.size_bytes / time_dif / 1024 / 1024);
free(block);
free(block_flash);
return 0;
}
volatile void * ioremap( unsigned long long physaddr, unsigned size, int sync )
{
int axs_mem_fd = -1;
unsigned long long page_addr, ofs_addr, reg, pgmask;
void* reg_mem = NULL;
/*
* looks like mmap wants aligned addresses?
*/
pgmask = getpagesize() - 1;
page_addr = physaddr & ~pgmask;
ofs_addr = physaddr & pgmask;
/*
* Don't forget O_SYNC, esp. if address is in RAM region.
* Note: if you do know you'll access in Read Only mode,
* pass O_RDONLY to open, and PROT_READ only to mmap
*/
if ( axs_mem_fd == -1 )
{
axs_mem_fd = open("/dev/mem", O_RDWR | (sync ? O_SYNC : 0));
if ( axs_mem_fd < 0 )
{
perror("AXS: can't open /dev/mem");
return NULL;
}
}
/* memory map */
reg_mem = mmap64((caddr_t) reg_mem, size + ofs_addr, PROT_READ | PROT_WRITE, MAP_SHARED, axs_mem_fd, page_addr);
if ( reg_mem == MAP_FAILED )
{
perror("AXS: mmap error");
close(axs_mem_fd);
return NULL;
}
reg = (unsigned long) reg_mem + ofs_addr;
return (volatile void *) reg;
}
int iounmap( volatile void *start, size_t length )
{
unsigned long ofs_addr;
ofs_addr = (unsigned long) start & (getpagesize() - 1);
/* do some cleanup when you're done with it */
return munmap((unsigned char*) start - ofs_addr, length + ofs_addr);
}
void sfcx_writereg( int reg, unsigned long value )
{
flash[reg] = bswap_32(value);
}
unsigned int sfcx_readreg( int reg )
{
return bswap_32(flash[reg]);
}
unsigned int sfcx_init(void)
{
sfc.initialized = 0;
sfc.large_block = 0;
sfc.page_sz = 0x200;
sfc.meta_sz = 0x10;
sfc.page_sz_phys = sfc.page_sz + sfc.meta_sz;
unsigned int config = sfcx_readreg(SFCX_CONFIG);
//Turn off interrupts, turn off WP_EN, and set DMA pages to 0
sfcx_writereg(SFCX_CONFIG, config &~ (4|8|0x3c0));
switch ((config >> 17) & 0x03)
{
case 0: // Small block original SFC (pre jasper)
switch ((config >> 4) & 0x3)
{
case 0: // Unsupported 8MB?
printf("Error: Unsupported Type A-0\n");
return -1;
//sfc.block_sz = 0x4000; // 16 KB
//sfc.size_blocks = 0x200;
//sfc.size_bytes = sfc.size_blocks << 0xE;
case 1: // 16MB
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x400;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
case 2: // 32MB
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x800;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
case 3: // 64MB
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x1000;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
}
break;
case 1: // New SFC/Southbridge: Codename "Panda"?
switch ((config >> 4) & 0x3)
{
case 0: // Unsupported
printf("Error: Unsupported Type B-0\n");
return -2;
case 1: // Small block 16MB setup
sfc.block_sz = 0x4000; // 16 KB
sfc.size_blocks = 0x400;
sfc.size_bytes = sfc.size_blocks << 0xE;
break;
case 2: // Large Block: Current Jasper 256MB and 512MB
sfc.block_sz = 0x20000; // 128KB
//sfc.size_bytes = 0x1 << (((config >> 19) & 0x3) + ((config >> 21) & 0xF) + 0x17);
sfc.size_bytes = 1024 * 1024 * 64;
sfc.size_blocks = sfc.size_bytes >> 0x11;
sfc.large_block = 2;
break;
case 3: // Large Block: Future or unknown hardware
sfc.block_sz = 0x40000; // 256KB
sfc.size_bytes = 0x1 << (((config >> 19) & 0x3) + ((config >> 21) & 0xF) + 0x17);
sfc.size_blocks = sfc.size_bytes >> 0x12;
sfc.large_block = 3;
break;
}
break;
default:
printf("Error: Unsupported Type\n");
return -3;
}
sfc.pages_in_block = sfc.block_sz / sfc.page_sz;
sfc.block_sz_phys = sfc.pages_in_block * sfc.page_sz_phys;
sfc.size_pages = sfc.size_bytes / sfc.page_sz;
sfc.size_blocks = sfc.size_bytes / sfc.block_sz;
sfc.size_bytes_phys = sfc.block_sz_phys * sfc.size_blocks;
sfc.size_mb = sfc.size_bytes >> 20;
printf("Nandsize: %d MB\n", sfc.size_mb);
#if 0
printf(" config register = %08X\n", config);
printf(" sfc:page_sz = %08X\n", sfc.page_sz);
printf(" sfc:meta_sz = %08X\n", sfc.meta_sz);
printf(" sfc:page_sz_phys = %08X\n", sfc.page_sz_phys);
printf(" sfc:pages_in_block = %08X\n", sfc.pages_in_block);
printf(" sfc:block_sz = %08X\n", sfc.block_sz);
printf(" sfc:block_sz_phys = %08X\n", sfc.block_sz_phys);
printf(" sfc:size_mb = %dMB\n", sfc.size_mb);
printf(" sfc:size_bytes = %08X\n", sfc.size_bytes);
printf(" sfc:size_bytes_phys = %08X\n", sfc.size_bytes_phys);
printf(" sfc:size_pages = %08X\n", sfc.size_pages);
printf(" sfc:size_blocks = %08X\n", sfc.size_blocks);
printf("\n");
#endif
sfc.initialized = 1;
return config;
}
int sfcx_read_page(unsigned char *data, int address, int raw)
{
int status;
sfcx_writereg(SFCX_STATUS, sfcx_readreg(SFCX_STATUS));
// Set flash address (logical)
//address &= 0x3fffe00; // Align to page
sfcx_writereg(SFCX_ADDRESS, 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 ? PHY_PAGE_TO_BUF : LOG_PAGE_TO_BUF);
// Wait Busy
while ((status = sfcx_readreg(SFCX_STATUS)) & 1);
if (status != 0x200)
{
if (status & 0x40)
printf("Bad block found (index: 0x%x) \n", address / sfc.block_sz);
else if (status & 0x1c)
{
//printf(" ! SFCX: (Corrected) ECC error at address %08x: %08x\n", address, status);
}
else if (!raw && (status & 0x800))
{
//printf(" ! SFCX: Illegal logical block at %08x (status: %08x)\n", address / sfc.block_sz, status);
}
else
{
printf("Error: Unknown error at address 0x%x: 0x%x. Please worry.\n", address, 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 < page_sz ; i += 4)
{
// Transfer data from buffer to register
sfcx_writereg(SFCX_COMMAND, PAGE_BUF_TO_REG);
// Read out our data through the register
*(int*)(data + i) = bswap_32(sfcx_readreg(SFCX_DATA));
}
return status;
}
int sfcx_write_page(unsigned char *data, int address)
{
sfcx_writereg(SFCX_STATUS, 0xFF);
// Enable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) | 8);
// Set internal page buffer pointer to 0
sfcx_writereg(SFCX_ADDRESS, 0);
int i;
for (i = 0; i < sfc.page_sz_phys; i+=4)
{
// Write out our data through the register
sfcx_writereg(SFCX_DATA, bswap_32(*(int*)(data + i)));
// Transfer data from register to buffer
sfcx_writereg(SFCX_COMMAND, REG_TO_PAGE_BUF);
}
// Set flash address (logical)
//address &= 0x3fffe00; // Align to page
sfcx_writereg(SFCX_ADDRESS, address);
// Unlock sequence (for write)
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_0);
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_1);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
// Command the write
sfcx_writereg(SFCX_COMMAND, WRITE_PAGE_TO_PHY);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
int status = sfcx_readreg(SFCX_STATUS);
if (status != 0x200)
printf("Unexpected sfcx_write_page status 0x%x\n", status);
// Disable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) & ~8);
return status;
}
int sfcx_read_block(unsigned char *data, int address, int raw)
{
int p;
int status = 0;
int page_sz = raw ? sfc.page_sz_phys : sfc.page_sz;
for (p = 0; p < sfc.pages_in_block; p++)
{
status |= sfcx_read_page(&data[p * page_sz], address + (p * sfc.page_sz), raw);
//if (status != 0x200)
// break;
}
return status;
}
int sfcx_write_block(unsigned char *data, int address)
{
int p;
int status = 0;
for (p = 0; p < sfc.pages_in_block; p++)
{
status |= sfcx_write_page(&data[p * sfc.page_sz_phys], address + (p * sfc.page_sz));
//if (status != 0x200)
// break;
}
return status;
}
int sfcx_erase_block(int address)
{
// Enable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) | 8);
sfcx_writereg(SFCX_STATUS, 0xFF);
// Set flash address (logical)
//address &= 0x3fffe00; // Align to page
sfcx_writereg(SFCX_ADDRESS, address);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
// Unlock sequence (for erase)
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_1);
sfcx_writereg(SFCX_COMMAND, UNLOCK_CMD_0);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
// Command the block erase
sfcx_writereg(SFCX_COMMAND, BLOCK_ERASE);
// Wait Busy
while (sfcx_readreg(SFCX_STATUS) & 1);
int status = sfcx_readreg(SFCX_STATUS);
if (status != 0x200)
printf("Unexpected erase at block 0x%x with status 0x%x\n", address / sfc.block_sz, status);
sfcx_writereg(SFCX_STATUS, 0xFF);
// Disable Writes
sfcx_writereg(SFCX_CONFIG, sfcx_readreg(SFCX_CONFIG) & ~8);
return status;
}
void sfcx_calcecc(unsigned int *data)
{
unsigned int i=0, val=0;
unsigned char *edc = ((unsigned char*)data) + sfc.page_sz;
unsigned int v=0;
for (i = 0; i < 0x1066; i++)
{
if (!(i & 31))
v = ~bswap_32(*data++);
val ^= v & 1;
v>>=1;
if (val & 1)
val ^= 0x6954559;
val >>= 1;
}
val = ~val;
// 26 bit ecc data
edc[0xC] |= (val << 6) & 0xC0;
edc[0xD] = (val >> 2) & 0xFF;
edc[0xE] = (val >> 10) & 0xFF;
edc[0xF] = (val >> 18) & 0xFF;
}
int sfcx_get_blocknumber(unsigned char *data)
{
if(sfc.large_block)
{
return (data[sfc.page_sz + 0x2] << 8) | (data[sfc.page_sz + 0x1]);
}
else
{
return (data[sfc.page_sz + 0x1] << 8) | (data[sfc.page_sz + 0x0]);
}
}
void sfcx_set_blocknumber(unsigned char *data, int num)
{
if(sfc.large_block)
{
data[sfc.page_sz + 0x2] = (num >> 8) & 0xFF;
data[sfc.page_sz + 0x1] = (num >> 0) & 0xFF;
}
else
{
data[sfc.page_sz + 0x1] = (num >> 8) & 0xFF;
data[sfc.page_sz + 0x0] = (num >> 0) & 0xFF;
}
}
int sfcx_get_blockversion(unsigned char *data)
{
if(sfc.large_block)
{
return (data[sfc.page_sz + 0x6] << 24) | (data[sfc.page_sz + 0x4] << 16) |
(data[sfc.page_sz + 0x3] << 8) | (data[sfc.page_sz + 0x5]);
}
else
{
return (data[sfc.page_sz + 0x6] << 24) | (data[sfc.page_sz + 0x4] << 16) |
(data[sfc.page_sz + 0x3] << 8) | (data[sfc.page_sz + 0x2]);
}
}
void sfcx_set_blockversion(unsigned char *data, int ver)
{
// NOTE This is only doing a single page
if(sfc.large_block)
{
data[sfc.page_sz + 0x5] = (ver >> 0) & 0xFF;
data[sfc.page_sz + 0x3] = (ver >> 8) & 0xFF;
data[sfc.page_sz + 0x4] = (ver >> 16) & 0xFF;
data[sfc.page_sz + 0x6] = (ver >> 24) & 0xFF;
}
else
{
data[sfc.page_sz + 0x2] = (ver >> 0) & 0xFF;
data[sfc.page_sz + 0x3] = (ver >> 8) & 0xFF;
data[sfc.page_sz + 0x4] = (ver >> 16) & 0xFF;
data[sfc.page_sz + 0x6] = (ver >> 24) & 0xFF;
}
}
void sfcx_set_pagevalid(unsigned char *data)
{
if(sfc.large_block)
{
data[sfc.page_sz + 0x0] = 0xFF;
}
else
{
data[sfc.page_sz + 0x5] = 0xFF;
}
}
void sfcx_set_pageinvalid(unsigned char *data)
{
if(sfc.large_block)
{
data[sfc.page_sz + 0x0] = 0x00;
}
else
{
data[sfc.page_sz + 0x5] = 0x00;
}
}
int sfcx_is_pagevalid(unsigned char *data)
{
if(sfc.large_block)
{
return data[sfc.page_sz + 0x0] == 0xFF;
}
else
{
return data[sfc.page_sz + 0x5] == 0xFF;
}
}
// TODO: Some sort of block/file system driver to make use of
// the block allocation table and the rest of the nand
int sfcx_block_to_address(int block)
{
return block * sfc.block_sz;
}
int sfcx_address_to_block(int address)
{
return address / sfc.block_sz;
}
Y esto?
Estaba ya posteado en el mismo hilo viewtopic.php?f=178&t=1356403&p=1718671262#p1718671262
marceono escribió:Respecto al "Xbrflash.c" he leido que sirve para leer y escribir desde gentoo, a mí me interesa hacer un respaldo de mi nand de 512m, se podría utilizar sólo para leer, es decir, ¿lleva algún menú en el que elijas las distintas opciones para leer, verificar y escribir?.
Alguno ha podido comprobar si eso que se comenta de que son necesarios únicamente los primeros 66 mb es cierto, vamos, que si al restaurar esos primeros 66 mb, la consola ha quedado funcional.
Llevo un par de semanas pasando diariamente por estos hilos y creo que ya tengo claro el proceso completo, a falta de unos pequeños puntos. A ver si el fin de semana que viene me decido y aplico el xploit.
Gracias a todos por compartir vuestras experiencias.
USE THIS SOFTWARE AT OWN RISK.
Two new features must be tested for 16/256/512MB Nands, so I need some more Beta-tester again
- Bad Block Management (BBM)
- KV and Config Injection
usage: ./a backup.bin xbr_virgin.bin -i
backup.bin Backup from your current Nand
xbr.bin XBReboot file
-i [optional] Injecting KV and Config from the current Nand to XBR-File
If you want to use -i (Injecting KV and Config), KV and Config must be valid in the current Nand, because XBR-Flash read the current Nand out and inject this to the XBR-file
Thanks goes to tmbinc, Redline99 and other I forgot
History
v0.1 initial by tmbinc
v0.1.x used sources from Redline99 (Xell mods)
v0.1.1 modified by trancy
v0.2 Added Bad Block Management (BBM)
Added KV and Config Injection
eXPerience83 escribió:mirad lo que ha salido hoy:
http://www.xbox-scene.com/xbox1data/sep ... DvlWwX.php
XBR-Flash for Linux v0.2 betaUSE THIS SOFTWARE AT OWN RISK.
Two new features must be tested for 16/256/512MB Nands, so I need some more Beta-tester again
- Bad Block Management (BBM)
- KV and Config Injection
usage: ./a backup.bin xbr_virgin.bin -i
backup.bin Backup from your current Nand
xbr.bin XBReboot file
-i [optional] Injecting KV and Config from the current Nand to XBR-File
If you want to use -i (Injecting KV and Config), KV and Config must be valid in the current Nand, because XBR-Flash read the current Nand out and inject this to the XBR-file
Thanks goes to tmbinc, Redline99 and other I forgot
History
v0.1 initial by tmbinc
v0.1.x used sources from Redline99 (Xell mods)
v0.1.1 modified by trancy
v0.2 Added Bad Block Management (BBM)
Added KV and Config Injection
central98 escribió:Pregunto aqui porque veo mas actividad que en otros hilos:
Alguno con 512 ha perdido un monton de espacio disponible al flashear el xbr3?
La mia es de las que en la caja ponia 256 pero luego tenia 512.
Analisa escribió:central98 escribió:Pregunto aqui porque veo mas actividad que en otros hilos:
Alguno con 512 ha perdido un monton de espacio disponible al flashear el xbr3?
La mia es de las que en la caja ponia 256 pero luego tenia 512.
Es normal centrl98 la mia es 512 y se queda en 230mb o por ahi libres, es una lastima que se quede en tan poco, yo tampoco lo entiendo.
central98 escribió:Yo no lo puedo probar porque cerrando la ultima caja se me ha soltado el db1f1, y ya llevo mas de 2 horas tiradas
Mañana veremos a ver...
tyno escribió:A ver si alguien me asesora,
Cuando llego al punto de montar el usb
mount /dev/sda1/mnt/ueb.
Me contesta esto
mount: cant find /dev/sda1/mnt/usb in /etc/fstab or /etc/mtab
Alguien me dice si tiene que salir esto,por que después de entrar en usb no me reconoce el lflash
JOSEunit10 escribió:tyno escribió:A ver si alguien me asesora,
Cuando llego al punto de montar el usb
mount /dev/sda1/mnt/ueb.
Me contesta esto
mount: cant find /dev/sda1/mnt/usb in /etc/fstab or /etc/mtab
Alguien me dice si tiene que salir esto,por que después de entrar en usb no me reconoce el lflash
Hola, a mi me pasaba exactamente lo mismo, justo ayer estaba en eso pero extrayendo la nand.
Bueno, yo utilice Debian v5.0, lo dejaba arrancar y luego metía el pendrive, en eso, el mismo Debian lo reconocía automáticamente y me lanzaba los datos del pendrive y la ubicación, que en mi caso con pendrive introducido en la parte de atrás de la consola era "sda".
Entonces en el comando lo que hice fue eliminar el "1" y anotar solo "sda".
ejemplo: mount /dev/sda /mnt/usb
Tal cual como esta anotado, con los espacios y todo, a lo mejor tu error también puede ser los espacios que veo no los has puesto.
Pruebalo, cuando lo haces no tiene que pasar nada, simplemente pasa a la siguiente linea, si esta mal te mandara el mismo mensaje que has anotado.
Suerte un saludo!.
RastaMan escribió:te falto el -t vfat
algo asi deberia quedar
mount -t vfat /dev/sda1 /mnt/usb
aunque es raro que el mount no te detecte automaticamente el filesystem al leer el superblock de la particion del pendrive.
tyno escribió:Ya lo he conseguido pero me sale esto en gcc lflash.c -o lflash.
lflash.c:in function "ioremap":
lflash.c:55:warning: cast to pointer fron integer of different size.
Esto es normal?
JOSEunit10 escribió:tyno escribió:Ya lo he conseguido pero me sale esto en gcc lflash.c -o lflash.
lflash.c:in function "ioremap":
lflash.c:55:warning: cast to pointer fron integer of different size.
Esto es normal?
Que placa tienes???, este tuto No sirve para Jasper!.
Tienes que hacer algo parecido pero con otra versión del Iflash compatible con Jasper, de tener esta placa.