[Tutorial] Actualiza el XBRebooter sin usas el nanddumper

1, 2, 3, 4
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?


La que flashea sin leer. Para minimizar daños. XD EDIT: Mi nand es de 256 megas: ¿tiene soporte para todos los tamaños?

Por otra parte, había leído que al trabajar desde la ram y no desde el pendrive, la nueva versión no se colgaba, o se colgaba menos al escribir: ¿tiene esto alguna base? En fin, a ver cuando es el día que podemos actualizar la consola desde pendrive... [carcajad]

Si al final te animas, estará muy bien saber cómo te fue con el minimal. Si no, ya me animaré yo la próxima vez que toque flashear.

Muchas gracias por todo.
Don y Daz, teneis un mp con las versiones modificadas.
RastaMan escribió:Don y Daz, teneis un mp con las versiones modificadas.

Gracias.
No me entero de nada [triston]

Al inicio dice "No disponible para Jasper" y todos hablan de que ya lo consiguieron en 512 y 256mb xD

Que es "XBRFLASH", cual es esa nueva versión del Iflash, es mas estable, soporta USB 2.0???. :-?

Por que nadie se curra un Tuto para Jasperianos [mamaaaaa]

Yo soy un noob peo estaría dispuesto hacer un tuto paso a paso con todo lo necesario para hacer el trabajo completo con lujos y detalles, pero necesitaría ayuda.

Lo que mas me interesa es saber que hacer cuando saltan errores en las extracciones de la nand, he oído de badblock no se que, nandcompare, pero no he visto en ningún tuto que lo utilice [agggtt]

Estaría de PM hacer un hilo recopilatorio de todos los programas que hay para lo referido con la nand y decir para que sirve cada uno y en que ocasiones utilizarlo, claro solo nombres, sin links de descarga al menos que sea legal.

Edito: hilo_tutorial-actualiza-el-xbrebooter-sin-usas-el-nanddumper_1356403_s100#p1718674557
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;
}
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
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 &amp;&amp; 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 (&amp;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 &amp; 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 (&amp;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 (&amp;start);
    for ( i = 0; i < sfc.size_bytes; i += sfc.block_sz )
    {
        if ( !(i &amp; 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 &amp; 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 (&amp;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(&amp;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 &amp; 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 &amp;= 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(&amp;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 &amp; ~pgmask;
    ofs_addr = physaddr &amp; 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 &amp; (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 &amp;~ (4|8|0x3c0));

    switch ((config >> 17) &amp; 0x03)
    {
    case 0: // Small block original SFC (pre jasper)
        switch ((config >> 4) &amp; 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) &amp; 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) &amp; 0x3) + ((config >> 21) &amp; 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) &amp; 0x3) + ((config >> 21) &amp; 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 &amp;= 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)) &amp; 1);

    if (status != 0x200)
    {
        if (status &amp; 0x40)
            printf("Bad block found (index: 0x%x)                 \n", address / sfc.block_sz);
        else if (status &amp; 0x1c)
      {
            //printf(" ! SFCX: (Corrected) ECC error at address %08x: %08x\n", address, status);
      }
        else if (!raw &amp;&amp; (status &amp; 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 &amp;= 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) &amp; 1);

    // Command the write
    sfcx_writereg(SFCX_COMMAND, WRITE_PAGE_TO_PHY);

    // Wait Busy
    while (sfcx_readreg(SFCX_STATUS) &amp; 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) &amp; ~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(&amp;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(&amp;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 &amp;= 0x3fffe00; // Align to page
    sfcx_writereg(SFCX_ADDRESS, address);

    // Wait Busy
    while (sfcx_readreg(SFCX_STATUS) &amp; 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) &amp; 1);

    // Command the block erase
    sfcx_writereg(SFCX_COMMAND, BLOCK_ERASE);

    // Wait Busy
    while (sfcx_readreg(SFCX_STATUS) &amp; 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) &amp; ~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 &amp; 31))
            v = ~bswap_32(*data++);
        val ^= v &amp; 1;
        v>>=1;
        if (val &amp; 1)
            val ^= 0x6954559;
        val >>= 1;
    }

    val = ~val;

    // 26 bit ecc data
    edc[0xC] |= (val << 6) &amp; 0xC0;
    edc[0xD] = (val >> 2) &amp; 0xFF;
    edc[0xE] = (val >> 10) &amp; 0xFF;
    edc[0xF] = (val >> 18) &amp; 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) &amp; 0xFF;
        data[sfc.page_sz + 0x1] = (num >> 0) &amp; 0xFF;
    }
    else
    {
        data[sfc.page_sz + 0x1] = (num >> 8) &amp; 0xFF;
        data[sfc.page_sz + 0x0] = (num >> 0) &amp; 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)  &amp; 0xFF;
        data[sfc.page_sz + 0x3] = (ver >> 8)  &amp; 0xFF;
        data[sfc.page_sz + 0x4] = (ver >> 16) &amp; 0xFF;
        data[sfc.page_sz + 0x6] = (ver >> 24) &amp; 0xFF;
    }
    else
    {
        data[sfc.page_sz + 0x2] = (ver >> 0)  &amp; 0xFF;
        data[sfc.page_sz + 0x3] = (ver >> 8)  &amp; 0xFF;
        data[sfc.page_sz + 0x4] = (ver >> 16) &amp; 0xFF;
        data[sfc.page_sz + 0x6] = (ver >> 24) &amp; 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&amp;t=1356403&amp;p=1718671262#p1718671262



Por si alguno no se lee el hilo de forma completa, que haberlos haylos :)
Pues si, tienes razon que haylos y mas de lo que parece :)
Don Pelayo, como haces para que solo lea la nand? Por lo que entiendo el iflash lee, compara y escribe. Ya tengo el XBR_3 escrito en la nand de mi Xenon pero me gustaria hacer unas pruebas para ver que tan fiable es esto de leer/escribir con Gentoo.

Gracias y un saludo!!
don pelayo creo que no me di a entender como dios manda. mi problema era que al flashear el xbr lo hacia correcto.la primera ves lo hice por lpt, la consola arrancaba y todo bien pero al intentar actualizar con los avatares (ya quite la r6t3) al reinicio solo quedaba la luz central en verde y no hacia nada mas ni video ni nada.tampoco arrancaba el xell pero al flashear el original mediante gentoo si que podia hacer todo, formatear instalar avatares (7371) etc etc

solo una ves flashee por ltp y las demas ya lo hice por medio de gentoo y el xbrflash.c . comento tambien que la forma en que saque mi orig.bin fue primero leer las primeras dos megas por lpt y flashear el xell. despues mediante gentoo hice backup completo de mi nand de 512,pero siempre se me trababa el gentoo al verificar.asi que lo que hice fue sacar tres dumps sin verificacion del gentoo y con el total commander y el nandcomparer 1.3 fue comparar esos tres dumps y todos eran identicos y sin errores asi que di por hecho de que eran buenos dumpeos.
despues inyecte los primeros dos megas que saque al backup de 512 de gentoo y al parecer con eso ya tengo la nand original.

mi problema se soluciono hasta que borre toda la nand (o eso creo con el comando 0x000000) y flashee el xbr 3 (con kv y config) ya pude formatear la memoria interna e instalar los avatares sin que muriera mi consola,este proceso de borrar la memoria interna y de instalar avatares lo he hecho tres veces para confirmar que todo quedara bien y al parecer ya quedo bien la consola.

solo una duda mas: la consola que compre para el jtag es una arcade de 512 con fecha de fabricacion de abril del 2009. en este momento la tengo abierta y me puedo dar cuenta que se calienta mucho el disipador del vga y los ventiladores no funcionan mas rapido, mientras el disipa del cpu esta frio frio el del vga quema si tocas con el dedo el pipe de cobre ¿¿ es normal en estas consolas que suba tanto la temperatura de la vga?? no he podido medir la temperatura por que en este momento no dispongo de una sonda
pero si le quito el tunel de plastico y prendo la consola al ponerse mas caliente si veo que los ventiladores empiesan a revolucionar mas y mas. asi que ya descarto la posibilidad de que no haya metido bien mi config que fue lo que pense en principio

¿¿ a que temperatura es normal que este la vga en las jasper??
no tiro mas rollo.

saludos y reitero mis gracias a todos aquellos que estan para ayudar
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.
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.

Hay distintas versiones del xbrflash, una de las cuales creo que te permite hacer todo. Pero claro, hay que meter los comandos adecuados. Te recomiendo que leas un poco más este hilo para aclararte.

Lo de los 66 megas es verídico.

Saludos.
mirad lo que ha salido hoy:
http://www.xbox-scene.com/xbox1data/sep ... DvlWwX.php
XBR-Flash for Linux v0.2 beta
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 beta
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


Me alegra. Quiere decir que se trabaja en serio en este método de lectura y escritura, que al parecer ya hace el trabajo del Nandpro. Lo próximo es trabajar un poco más en la estabilidad, aunque eso ya es cosa de gentoo, y no de esta aplicación.
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.
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.
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.


¿¿Osea que descartamos la cuestión de la config de una 256?? Pues ahí lo tienes central98, al parecer no es del todo raro. Pero a ver si alguien más os confirma el dato.
Se os queda en menos la memoria porque parece ser que en la imagen del XBR va incluida la info de cuanta memoria le quedaba libre a la consola donde la montaron.

Si quereis recuperar toda la memoria que os falta debereis formatear la memoria interna y ya apareceran todos los megas fantasmas
pues yo confirmo la falta de espacio en la memoria interna

despues del flasheo del xbr tengo 359 megas o algo asi,formateo la memoria y siguen quedando los 359 y despues de instalar los avatares se queda en 229 megas libres.

lo gracioso es que antes de flashear. la consola en el 7371 con avatares tenia libres trecientos cincuenta y tantos megas
a ver si puedo poner unas fotos para confirmarles el dato

saludo
Yo no lo puedo probar porque cerrando la ultima caja se me ha soltado el db1f1, y ya llevo mas de 2 horas tiradas [maszz]

Mañana veremos a ver...
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 [maszz]

Mañana veremos a ver...


Cola caliente y arreando... Yo en cuanto conseguí una soldadura decente de ese punto le aplique la pistola. Después me embarqué en una vorágine de aplicar cola aquí y allá, de modo que cuando vaya a desoldar el nandumper las voy a pasar algo canutas... Pero bueno, los puntos del JTAG quedaron bien soldados y asegurados. XD
Confirmo que formateando la memoria vuelven los 100 megas. 325 megas me deja a mi libres, aun los veo pocos pero creo que es lo que habia antes o muy poco menos.
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
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!.
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!.


Ok gracias compi voy a ver
Pues ahora me dice esto con este comando mount /dev/sda /mnt/usb.
mount: you must specify the filessystem type
El pen esta en sda
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.
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.


Bueno como dige yo lo he echo con el Debian XD

hilo_xbrflash-0-3-6-como-usar-ayuda-hack-conseguido-d_1367841_s10#p1718842819

Has lo que te dice RastaMan.

Un saludo!.
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?
Bueno pues ya se lo trago a la segunda va la vencida ya lo tengo [oki] .
Y garcias por echarme una manita
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.

Lo mas recomendable es XBRflsh 0.3.6 mas gentoo beta 2.
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.

Es falcon pero ya se lo trago,la primera vez me dio error pero la segunda ok.
Gracias por la ayuda
Edito para comentar que después de probar la consola con juegos pelis,apagarla y toda la parafernalia para ver que funciona al pelo. [sonrisa]
La desenchufo para quitar todo el tema del jtag y al encenderla putadon e-79. [mamaaaaa] [buuuaaaa]
Alguien tiene idea de por que?
Las soldaduras no tienen ningun contacto raro.

Edito ya ta solucionado [jaja]
179 respuestas
1, 2, 3, 4