[Tutorial] Dumpea tu NAND 256/512Mb Jasper en 10 minutos

1, 2, 3, 4
queria preguntaros, yo que tengo una jasper 512 esperando, si este metodo es mejor que el de usb spi, o si es recomendable hacer los dos....
tvillaje1 escribió:queria preguntaros, yo que tengo una jasper 512 esperando, si este metodo es mejor que el de usb spi, o si es recomendable hacer los dos....


Recomendable hacer los dos. ¿Por qué?, porque si un mismo método no funciona correctamente podría darte dos nand idénticas con errores de lectura. Si dos métodos distintos te dan el mismo resultado es más probable que la lectura haya sido satisfactoria en ambos casos.

ekanemore escribió:Bueno, si me podeis echar una mano, mañana tengo que montar todo esto y quiero tener los comandos claros.

Tengo una Jasper 256MB y lo primero que quiero hacer es obtener la nand por LPT, como me imagino que me dara algun error, me gustaria hacerlo tambien por gentoo para comprobar que al menos por los 2 metodos (LPT y Gentoo) me da la misma NAND y aunque tengan errores, no sera por el NandDumper.

Entonces con los cambios que han habido del ultimo XBR_JasperBB_8955_3.rar, para hacerlo con gentoo, ¿seria algo asi?

1 - Obtener los 2 primeros megas de mi nand por LPT

nandpro.exe lpt: -r2 mis2MB.bin

2 - Hacer varias copias y comprobar que son iguales y que el CB es correcto.

3 - Descomprimir el fichero en XBR_JasperBB_8955_3.rar e instalar los 2 primeros megas.

nandpro lpt: -w2 XBR_JasperBB_8955_3.bin

Ahora seria arrancar el Gentoo como el tutorial y... ¿seria asi?

1 - Ya teniendo todo preparado en Gento obtener la NAND. (bueno, varias y comprobar que son iguales)

./a.out backupnand.bin

2- Irme al ordenador y añado mis2MB.bin al inicio de los extraidos por gentoo

nandpro.exe backupnand.bin: -w2 mis2MB.bin

3 - Comprobar que el fichero backupnand.bin, es igual al obtenido por LPT.

Si lo hago de esta manera y compruebo que tanto por Gentoo como por LPT me da errores, pero son iguales, ¿podria decir que tengo una copia correcta de la NAND?.

¿seria asi con el nuevo XBR?.

Don Pelayo, ¿es correcto el comando asi: nandpro.exe backupnand.bin: -w2 mis2MB.bin?

Un saludo y gracias por leerme.


El comando es correcto. De hecho, revisando el mío puse dos puntos (:) después de "nandpro.exe" (el .exe al parecer no influye). Es tal y como tu lo tienes. Si no funcionase quita ".exe" a "nandpro"--> nandpro

Pero vamos, que seguro que funciona.
No es correcto, o almenos no te aseguro que funcione.

Lo que tienes que escribir es el Xell, no los primeros 2mb del XBR que no te aseguro que arranquen Xell por que no lo he probado.

Para ir 100% sobre seguro deberías escribir el "jasper_6723_hack_for_256mb_512mb.bin", que ocupa algo menos de dos megas.

Si ya ha probado alguien que escribiendo los 2 primeros megas del XBR funciona entonces no he dicho nada XD

Un saludo.
SanPedro_ escribió:No es correcto, o almenos no te aseguro que funcione.

Lo que tienes que escribir es el Xell, no los primeros 2mb del XBR que no te aseguro que arranquen Xell por que no lo he probado.

Para ir 100% sobre seguro deberías escribir el "jasper_6723_hack_for_256mb_512mb.bin", que ocupa algo menos de dos megas.

Si ya ha probado alguien que escribiendo los 2 primeros megas del XBR funciona entonces no he dicho nada XD

Un saludo.


No creo que nadie lo haya probado, y no creo que sea aconsejable hacerlo. Yo la verdad es que no había reparado en esa parte. Y sólo para que quede claro, yo sólo hablo por el comando que me pregunta, el de inyectar los dos primeros megas sacados mediante lpt en la copia de la nand extraída con el gentoo.

Sigue el consejo de Sanpedro con respecto al proceder para grabar el xell, por favor, no vayamos a tener un disgusto.
Esa impresión me daba a mi, que solo le estabas respondiendo al comando y no habías visto el fichero, pero como lo habías afirmado con tanta seguridad me habías hecho dudar de si alguien lo había probado y se podía hacer y yo no me había enterado xD
En ese caso lo afirmo, graba el Xell y no el XBR.

Un saludo.
SanPedro_ escribió:Esa impresión me daba a mi, que solo le estabas respondiendo al comando y no habías visto el fichero, pero como lo habías afirmado con tanta seguridad me habías hecho dudar de si alguien lo había probado y se podía hacer y yo no me había enterado xD
En ese caso lo afirmo, graba el Xell y no el XBR.

Un saludo.


+1
no consigo hacer un solo dump de la nand desde gentoo, siempre se me cuelga en la lectura, en diferentes puntos, me estoy empezando a desesperar. Por cierto es normal que tire errores de nand donde pone corrected y sea de error 210? porque en la lectura me tira bastantes errores de estos.

Es normal que al ejecutar el lflash.c de unos errores? yo pego tal cual esta aqui en un txt y lo renombro a .c, en gento parece que se ejecuta pero da algun tipo de error noseque integer.
Yo ahora mismo tengo la maquina con todo soldado enganchada al pc y 5 copias iguales de los 2 primeros megas extraidas.
Con esto aun no puedo comprobar si el CB es valido, no?
El siguiente paso seria seguir el tutorial, tal cual esta, los rebooter nuevos no afectan nada aqui, no?
Una vez la monte para arrancar el xell, sino me equivoco no necesitare mas el nanddumper ni la maquina abierta, no?
Entonces habra que seguir el tutorial para comprobar la copia de nand entera. Pero una vez haya una copia entera y valida de la nand, cual es el siguiente paso? Se flashea el ultimo rebooter entero? Se flashea el jasper_6723_hack_for_256mb_512mb.bin entero?
central98 escribió:Yo ahora mismo tengo la maquina con todo soldado enganchada al pc y 5 copias iguales de los 2 primeros megas extraidas.
Con esto aun no puedo comprobar si el CB es valido, no?
El siguiente paso seria seguir el tutorial, tal cual esta, los rebooter nuevos no afectan nada aqui, no?
Una vez la monte para arrancar el xell, sino me equivoco no necesitare mas el nanddumper ni la maquina abierta, no?
Entonces habra que seguir el tutorial para comprobar la copia de nand entera. Pero una vez haya una copia entera y valida de la nand, cual es el siguiente paso? Se flashea el ultimo rebooter entero? Se flashea el jasper_6723_hack_for_256mb_512mb.bin entero?


Yo no encontré modo de comprobar ni con 2 megas ni con 256. El degraded y el flashtool no son compatibles tgodavía con big nands, por lo menos no lo eran hace un mes, ni pueden abrir nands "a medias".

Los rebooter no afectan en nada los pasos que estás dando.

Dices que una vez montado el xell (yo creo que antes deberías hacer una copia completa con nandumper) podrás desoldar el nandumper... ¿¿De qué tamaño es tu nand?? Porque si es de 256/512 ya me dirás como vas a flashear sin el nandumper. ¿¿Con lflash?? Existe una versión para jasper big nand pero su fiabilidad a la hora de escribir no está comprobada. De hecho yo no conozco testimonios ni para bien ni para mal.

Concluyendo, saca una copia de la nand completa por lpt. Después otra con gentoo a la que le tendrás que inyectar el respaldo de 2 megas y las comparas. Si son idénticas, flashea el XBR_3 con tu config.bin y tu kv.bin inyectados y a ver si hay suerte.

Saludos.
Bueno, ya voy descubriendo cosas. Con un lflash.c que he encontrado me hace una copia de la nand de los primeros 66 mb que son lo que contienen toda la informacion de la consola. los he hecho desde gento sin ningun problema. Por otro lado quiero sacar un dump completo de 512 mb que por lo que he leido en otros foros si se cuelga en la verificacion no pasa nada porque el dump esta completo.

central98 yo hice dumps de los 2 primeros megas con nandumper y tenia varios dumps diferentes, pero segui haciendo dumps hasta que comprobe que 5 eran identicos, asi que supuse que estaba bien. Luego inyecte el xell y me cargo a la primera, entonces el gentoo ya me carga. Al principio gentoo no me cargaba porque lo gravaba en un cd, lo grave en dvd-r y me carga a la primera.

espero que te sirva de ayuda.
Es de 512.

A ver aver, entonces primero saco una con "nandpro.ese lpt: -r512 nand512.bin" tal cual la tengo.

A ver montado el xell, se puede leer y escribir la nand por linux, no? Entonces ya no necesitaria mas el lpt, es lo que tenia entendido. Entonces segun te entiendo, el gentoo sirve para leer pero no para escribir.

Que es lo que nos afecta no poder usar el degraded exactamente? Solo no saber si el cb es valido aun?

Respecto a lo de Analisa, pues en eso estaba ahora, meter el xell en esos 2 megas e intentar todo lo demas por gentoo, pero es que tengo un lio de conceptos considerable.
central98 escribió:Es de 512.

A ver aver, entonces primero saco una con "nandpro.ese lpt: -r512 nand512.bin" tal cual la tengo.

A ver montado el xell, se puede leer y escribir la nand por linux, no? Entonces ya no necesitaria mas el lpt, es lo que tenia entendido. Entonces segun te entiendo, el gentoo sirve para leer pero no para escribir.

Que es lo que nos afecta no poder usar el degraded exactamente? Solo no saber si el cb es valido aun?

Respecto a lo de Analisa, pues en eso estaba ahora, meter el xell en esos 2 megas e intentar todo lo demas por gentoo, pero es que tengo un lio de conceptos considerable.


no se puede escribir las nands de 512, es necesario el nandumper, lo que yo voy a hacer es extraer un dump de 512 por si acaso, pero flasheare el de 66 megas.
Pero escribir 512 sin fallos por lpt es una locura, no?
A que te refieres con 66? No hace falta flashear los 512?
central98 escribió:Pero escribir 512 sin fallos por lpt es una locura, no?
A que te refieres con 66? No hace falta flashear los 512?


SUpongo que escribir los 512 por lpt sin fallos es morirse, y segun he leido a bastante gente le ha funcionado con solo los primeros 64mb, creo que don pelayo de este foro lo hizo asi tambien o otro usuario que no recuerdo. Por eso quiero sacar ni que sea un dump de 512 por gento, pero llevo bastantes intentos y se cuelga. te adjunto el codigo que he usado para dumpear los 66mb.
      /* placed in public domain, written by Felix Domke <tmbinc@elitedvb.net> */
   /* USE ON YOUR OWN RISK. */
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <byteswap.h>
#include <string.h>

int nandsize;
int bsec;

extern void *mmap64 (void *__addr, size_t __len, int __prot, int __flags, int __fd, __off64_t __offset) __THROW;

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);
}

#define STATUS  1
#define COMMAND 2
#define ADDRESS 3
#define DATA    4
#define LOGICAL 5
#define PHYSICAL 6

volatile unsigned int *flash;

void sfcx_writereg(int reg, int value)
{
   flash[reg] = bswap_32(value);
}

unsigned int sfcx_readreg(int reg)
{
   return bswap_32(flash[reg]);
}

void readsector(unsigned char *data, int sector, int raw)
{
   int status;
   sfcx_writereg(STATUS, sfcx_readreg(STATUS));
   sfcx_writereg(ADDRESS, sector);   
   sfcx_writereg(COMMAND, raw ? 3 : 2);

   while ((status = sfcx_readreg(STATUS))&1);

   if (status != 0x200)
   {
      if (status & 0x40)
         printf(" * Bad block found at %08x\n", sector);
      else if (status & 0x1c)
         printf(" * (corrected) ECC error %08x: %08x\n", sector, status);
      else if (!raw)
         printf(" * illegal logical block %08x\n", sector);
      else
         printf(" * Unknown error at %08x: %08x. Please worry.\n", sector, status);
   }

   sfcx_writereg(ADDRESS, 0);

   int i;
   for (i = 0; i < 0x210; i+=4)
   {
      sfcx_writereg(COMMAND, 0);
      *(int*)(data + i) = bswap_32(sfcx_readreg(DATA));
   }
}

void flash_erase(int address)
{
   sfcx_writereg(0, sfcx_readreg(0) | 8);
   sfcx_writereg(STATUS, 0xFF);
   sfcx_writereg(ADDRESS, address);
   while (sfcx_readreg(STATUS) & 1);
   sfcx_writereg(COMMAND, 0xAA);
   sfcx_writereg(COMMAND, 0x55);
   while (sfcx_readreg(STATUS) & 1);
   sfcx_writereg(COMMAND, 0x5);
   while (sfcx_readreg(STATUS) & 1);
   int status = sfcx_readreg(STATUS);
   if (status != 0x200)
      printf("[%08x]", status);
   sfcx_writereg(STATUS, 0xFF);
   sfcx_writereg(0, sfcx_readreg(0) & ~8);
}

void write_page(int address, unsigned char *data)
{
   sfcx_writereg(STATUS, 0xFF);
   sfcx_writereg(0, sfcx_readreg(0) | 8);

   sfcx_writereg(ADDRESS, 0);

   int i;

   for (i = 0; i < 0x210; i+=4)
   {
      sfcx_writereg(DATA, bswap_32(*(int*)(data + i)));
      sfcx_writereg(COMMAND, 1);
   }

   sfcx_writereg(ADDRESS, address);
   sfcx_writereg(COMMAND, 0x55);
   while (sfcx_readreg(STATUS) & 1);
   sfcx_writereg(COMMAND, 0xAA);
   while (sfcx_readreg(STATUS) & 1);
   sfcx_writereg(COMMAND, 0x4);
   while (sfcx_readreg(STATUS) & 1);
   int status = sfcx_readreg(STATUS);
   if (status != 0x200)
      printf("[%08x]", status);
   sfcx_writereg(0, sfcx_readreg(0) & ~8);
}



extern volatile void * ioremap(unsigned long long physaddr, unsigned size, int sync);
extern int iounmap(volatile void *start, size_t length);

int dump_flash_to_file(const char *filename)
{
   printf(" * Dumping to %s...\n", filename);
   
   FILE *f = fopen(filename, "wb");
   
   int i;
   for (i = 0; i < nandsize; i += 0x200)
   {
      unsigned char sector[0x210];
      readsector(sector, i, 1);
      if (!(i&0x3fff))
      {
         printf("%08x\r", i);
         fflush(stdout);
      }
      if (fwrite(sector, 1, 0x210, f) != 0x210)
         return -1;
   }
   printf("done!   \n");
   fclose(f);
   return 0;
}

int verify_flash_with_file(const char *filename, int raw)
{
   FILE *f = fopen(filename, "rb");
   if (!f)
      return -1;

   if (raw == -1) /* auto */
   {
      fseek(f, 0, SEEK_END);
   
      if (ftell(f) == nandsize / 0x200 * 0x210)
      {
         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);
   }
   
   printf(" * Verifying flash with %s...\n", filename);
   
   int i;
   for (i = 0; i < nandsize; i += 0x200)
   {
      unsigned char sector[0x210], sector_flash[0x210];
      if (!(i&0x3fff))
      {
         printf("%08x\r", i);
         fflush(stdout);
      }
      if (fread(sector, 1, 0x210, f) != 0x210)
         return i;
      readsector(sector_flash, i, raw);
      if (sector_flash[bsec] != 0xFF) /* bad sector */
      {
         printf(" * ignoring bad sector at %08x\n", i);
         continue;
      }
      if (memcmp(sector, sector_flash, 0x210))
      {
         printf(" * VERIFY error at %08x\n", i);
         return -2;
      }
   }
   printf("done!   \n");
   fclose(f);
   return i;
}

int flash_from_file(const char *filename, int raw)
{
   printf(" * Flashing from %s...\n", filename);

   FILE *f = fopen(filename, "rb");
   if (!f)
      return -1;

   if (raw == -1) /* auto */
   {
      fseek(f, 0, SEEK_END);
   
      if (ftell(f) == nandsize / 0x200 * 0x210)
      {
         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);
   }
   
   int i;
   for (i = 0; i < nandsize; i += 0x4000)
   {
      unsigned char sector[0x210*32], sector_flash[0x210*32];
      memset(sector, 0xFF, sizeof(sector));
      if (!fread(sector, 1, 0x210*32, f))
         return i;

      printf("%08x\r", i);
      fflush(stdout);
      
      int phys_pos;
      
      if (!raw)
      {
         readsector(sector_flash, i, 0);

         phys_pos = sfcx_readreg(PHYSICAL);
      
         if (!(phys_pos & 0x04000000)) /* shouldn't happen, unless the existing image is broken. just assume the sector is okay. */
         {
            printf(" * Uh, oh, don't know. Reading at %08x failed.\n", i);
            phys_pos = i;
         }
         phys_pos &= 0x3fffe00;
      
         if (phys_pos != i)
            printf(" * relocating sector %08x to %08x...\n", i, phys_pos);
      } else
         phys_pos = i;

      flash_erase(phys_pos);
      int j;
      for (j = 0; j < 32; ++j)
         write_page(phys_pos + j * 0x200, sector + j * 0x210);
   }
   return 0;
}

int main(int argc, char **argv)
{
   flash = ioremap(0xea00c000, 0x1000, 1);
   
   printf(" * flash config: %08x\n", sfcx_readreg(0));
   
   sfcx_writereg(0, sfcx_readreg(0) &~ (4|8|0x3c0));
   
   int reg = sfcx_readreg(0);

   switch(reg)
   {
// 512MB/256MB NAND
   case 0x00AA3020:
   case 0x008A3020:
      nandsize = 64 * 1024 * 1024;
      bsec = 0x200;
      break;
// 16 MB NAND
   case 0x00023010:
   case 0x01198010:
      nandsize = 16 * 1024 * 1024;
      bsec = 0x205;
      break;
   default:
      printf(" * unknown flash config %08x\n", reg);
      return 1;
   }

   
   if (argc != 2 && argc != 3)
   {
      printf("usage: %s <current> [<new>]\n", *argv);
      return 2;
   }

   const char *orig = argv[1];
   int res = verify_flash_with_file(orig, 1);
   if (res == -1)
   {
      dump_flash_to_file(orig);
      res = verify_flash_with_file(orig, 1);
   }

   if (res != nandsize)
   {
      if (res == -2)
         printf(" * verify failed!\n");
      else if (res > 0)
         printf(" * verified correctly, but only %d bytes.\n", res);
      else
         printf(" * original image invalid\n");
      printf(" * I won't flash if you don't have a full, working backup, sorry.\n");
      return 1;
   }
   printf(" * verify ok.\n");
   
   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(" * verify failed! (%d)\n", res);
   }
   return 0;
}


Veo que estas como yo, que estoy saturada de leer tanto y tanto post jajaaja.
Ay ya veo, es otro lflash para sacar solo 66, seria lo mismo que sacarlos con el nandpro lpt: -r66, no? Eso es una cantidad/tiempo aceptable. Lo que tampoco tengo claro que hacer luego con el.

De todas formas yo le acabo de enchufar un -r512, ya vere mañana a las 4 de la tarde como ha quedado, y si me voy enterando de algo mientras. Si alguien me puede confirmar que el "nandpro lpt: -r512" es el comando adecuado mejor, que he leido algo por ahi de que sacaba mas megas por noseque.
central98 escribió:Ay ya veo, es otro lflash para sacar solo 66, seria lo mismo que sacarlos con el nandpro lpt: -r66, no? Eso es una cantidad/tiempo aceptable. Lo que tampoco tengo claro que hacer luego con el.

De todas formas yo le acabo de enchufar un -r512, ya vere mañana a las 4 de la tarde como ha quedado, y si me voy enterando de algo mientras. Si alguien me puede confirmar que el "nandpro lpt: -r512" es el comando adecuado mejor, que he leido algo por ahi de que sacaba mas megas por noseque.


yo paso de dumpear 512mb por lpt, sabiendo que sacando solo 2 mb me tiraba tantos dumps diferentes. Con gento son 1 o 2 minutos sacar 66mb, por lpt cuenta 30 min imagino. Cuando tengas el dump de 66 mb supongo que sera seguir el tuto para inyectar los archivos de tus 2mb originales, pero ya vere cuando llegue a esa parte.
Las 5 que hice de 2 megas salieron clavadas todas y me anime, ahora tras 4 h y algo ha dado algunos errores 250 y 210. Me pregunto si con el nandpro se podra leer bloques concretos y reparar esos errores de lectura, porque sino estoy por pararlo.
central98 escribió:Las 5 que hice de 2 megas salieron clavadas todas y me anime, ahora tras 4 h y algo ha dado algunos errores 250 y 210. Me pregunto si con el nandpro se podra leer bloques concretos y reparar esos errores de lectura, porque sino estoy por pararlo.


Disculpad que no haya seguido toda vuestra conversación dado que sólo voy a responder a esto último, pero ando algo pillado ahora mismo. Luego con calma leo y trato de ayudaros si no os ha ayudado nadie todavía.

A mí también me salieron errores 250, que al parecer son inofensivos, y errores 210. Como sólo hay que escribir los primeros 1000 bloques, la imagen del XBR sólo me pillaba uno de los bloques 250, y sin embargo me funcionó sin problemas. Es mi experiencia, lo cual no quiere decir que vaya a misa. Conozco a quien no le ha funcionado el XBR, dándole error de escritura en un bloque con error de lectura 250.

Por último, parece que ya hay una versión estable de lflash para escribir en la nand. Un testimonio:

"I understand now. Previous bad flashes were due to lflash freezing, because of gentoos usb driver but now that the nand file to be flashed is stored in ram, xbrflash does not freeze during flash so even if you flash a bad KV or Config block for XBR, you can still boot to Xell since the freezing due to usb would cause Xell to not be written to nand at all or only partially written requiring a flash via USB SPI or LPT."

Por lo visto ya no se cuelga dado que "el archivo nand que se flashea se almacena en la ram, y no en el usb" que al parecer era lo que causaba los cuelgues. Creo que voy a ir desoldando el nandumper. :)

Un saludo.
Este es el nuevo iflash.

/*
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;
}




Quien lo pruebe que comente que tal le va.

Por cierto Don Pelayo el usb que formato atenemos que darle,fat o fat 32?
Quien lo pruebe que comente que tal le va.

Por cierto Don Pelayo el usb que formato atenemos que darle,fat o fat 32?

Pues a mi con el nuevo iflash se me ha colgado al escribir, en 0xb ... que suerte la mia, y ahora intentando repetirlo me dice no se que de error en 0xa200 y que sin copia no puede seguir, uffff. En fin, ya no veo nada ...

En principio tengo el xbr.bin (de 66mb) con el "kv" y el "config" correctos. Quiero ver funcionando esto, aunque sea inyectando este xbr.bin desde lpt.

¿Algun alma caritativa me puede decir, a ciencia cierta, si con el siguiente comando podria cargar el xbr? En principio tengo guardadas una imagen de 66mb original y la key, asi que mucho no podria liarla, ¿no?
nandpro lpt: -w66 xbr.bin


O seria con -w16 ... no entiendo porque en algunos sitios se utilizan esos "16" en las consolas que son de 256 o 512 mb
nandpro lpt: -w16 xbr.bin


Dios, que dolor de cabeza ...a ver si alguien me saca de la oscuridad.
Maikelele escribió:
Quien lo pruebe que comente que tal le va.

Por cierto Don Pelayo el usb que formato atenemos que darle,fat o fat 32?

Pues a mi con el nuevo iflash se me ha colgado al escribir, en 0xb ... que suerte la mia, y ahora intentando repetirlo me dice no se que de error en 0xa200 y que sin copia no puede seguir, uffff. En fin, ya no veo nada ...

En principio tengo el xbr.bin (de 66mb) con el "kv" y el "config" correctos. Quiero ver funcionando esto, aunque sea inyectando este xbr.bin desde lpt.

¿Algun alma caritativa me puede decir, a ciencia cierta, si con el siguiente comando podria cargar el xbr? En principio tengo guardadas una imagen de 66mb original y la key, asi que mucho no podria liarla, ¿no?
nandpro lpt: -w66 xbr.bin



O seria con -w16 ... no entiendo porque en algunos sitios se utilizan esos "16" en las consolas que son de 256 o 512 mb
nandpro lpt: -w16 xbr.bin


Dios, que dolor de cabeza ...a ver si alguien me saca de la oscuridad.


Si tu nand es 16 megas el comando es -w16

A veces la gente pone comandos a modo de ejemplo y los demás nos hacemos la picha un lío pensando que el comando es el que te dan al pie de la letra sin tener en cuanta la nand que tenemos, el nombre de nuestros archivos, etc. Yo creo que los tiros van por ahí, aunque puedo equivocarme.
central98 escribió:Es de 512.

A ver aver, entonces primero saco una con "nandpro.ese lpt: -r512 nand512.bin" tal cual la tengo.

A ver montado el xell, se puede leer y escribir la nand por linux, no? Entonces ya no necesitaria mas el lpt, es lo que tenia entendido. Entonces segun te entiendo, el gentoo sirve para leer pero no para escribir.

Que es lo que nos afecta no poder usar el degraded exactamente? Solo no saber si el cb es valido aun?

Respecto a lo de Analisa, pues en eso estaba ahora, meter el xell en esos 2 megas e intentar todo lo demas por gentoo, pero es que tengo un lio de conceptos considerable.


El comando es "nandpro.exe" o "nandpro", según te funcione o no.

Con el gentoo, parece que se puede escribir a día de hoy, pero justo aquí tenemos un testimonio de alguien a quien no le ha ido bien. Mi pregunta para Maikelele es qué lflash entiendes que es el nuevo. El de rastaman o el que acaban de pasar en el hilo de "flashea Xbr sin usar nandumper".

El degraded afecta en la cuestión del CB, y creo que también en que te dice qué bloques están corruptos (que no tiene por qué corresponderse con bloques que dieron error de lectura por nandumper).

Yo creo que para flashear por gentoo, la cosa tiene que madurar todavía, aunque ahora mismo me voy a leer un foro gringo con testimonios sobre su funcionamiento.

Un saludo.
A ver si alguien me ayuda, despues de flashear el xbr por nandumper, no me arrancaba la consola y se quedaba la luz roja de abajo a la derecha encendida. Pense que era problema de flasheo asi que volvi a inyectar el kv en el xbr.bin pero esta vez sin el config.Volvi a flashear la nand y el caso que ahora la consola me arranca pero se queda bloqueada en el logo del principio de xbox360. Si arranco desde el eject me lanza el xell sin problemas.

ALguien tiene una idea de que puedo hacer? alguien que me pueda pasar un rawconfig.bin de una jasper 512?

gracias.
Pues ya nos contaras don pelayo.
Bueno, ya tengo varios backup de mi nand por LPT y ahora que hay un nuevo Lflash para big nands lo voy a hacer por Gentoo.

Se lo que tengo que hacer, pero no encuentro "jasper_6723_hack_for_256mb_512mb.bin" (yo creria que tenia que poner los 2 primeros megas del XBR 3...;)).

¿Alguien me pase un enlace por MP?. Llevo 1 hora buscandolo por xbins y no lo encuentro.

Un saludo y gracias.

P.D: Creo que he caido un poco en la obsesion detener una copia perfecta de la nand, en otros foros en ingles, solo leen los primeros 70 Mb de la nand, que es lo que ocupa el XBR (teniendo toda su logica). Y despues dicen que despues de esos 70 Mb solo estan las partidas guardas y cosas del perfil (yo en eso creia que estaba en otra memoria pero bueno), y que si te da un error en esa parte puede haber sido por apagar la consola estando escribiendo alguna partida grabada....en fin..
Estan en xbins en development creo.



A mi en el otro hilo me dicen ahora que tengo que leer con "-r16" la de 512, pero entiendo que con eso solo me va a sacar los 16 primeros megas, con los que se supone que no puedo hacer mucho, no entiendo.
ekanemore escribió:Bueno, ya tengo varios backup de mi nand por LPT y ahora que hay un nuevo Lflash para big nands lo voy a hacer por Gentoo.

Se lo que tengo que hacer, pero no encuentro "jasper_6723_hack_for_256mb_512mb.bin" (yo creria que tenia que poner los 2 primeros megas del XBR 3...;)).

¿Alguien me pase un enlace por MP?. Llevo 1 hora buscandolo por xbins y no lo encuentro.

Un saludo y gracias.

P.D: Creo que he caido un poco en la obsesion detener una copia perfecta de la nand, en otros foros en ingles, solo leen los primeros 70 Mb de la nand, que es lo que ocupa el XBR (teniendo toda su logica). Y despues dicen que despues de esos 70 Mb solo estan las partidas guardas y cosas del perfil (yo en eso creia que estaba en otra memoria pero bueno), y que si te da un error en esa parte puede haber sido por apagar la consola estando escribiendo alguna partida grabada....en fin..


Edito: Hablas para actualizar el XBR o para extraer la nand???.

De ese nuevo Iflash del que hablas es diferente al de este tuto???.

De ser uno nuevo podrías pasarlo o notificarlo al creador del hilo para que actualizase el tuto. :D
central98 escribió:Estan en xbins en development creo.



A mi en el otro hilo me dicen ahora que tengo que leer con "-r16" la de 512, pero entiendo que con eso solo me va a sacar los 16 primeros megas, con los que se supone que no puedo hacer mucho, no entiendo.


Yo doy fe de que sólo te saca los 16 primeros megas. A lo mejor quien te ha respondido piensa que tienes una nand de 16.
Como he comentado anteriormente en el hilo "[Tutorial] Actualiza el XBRebooter sin usar el nanddumper" tengo todo el proceso del xploit bastante claro después de leer los hilos relativos a este tema, pero el único tema que me echa para atrás a la hora de comenzar el proceso es que no tengo claro lo del backup de la nand. Mi nand, aunque la caja pone 256 Mb, creo que es de 512, porque la Xbox360 en memoria me dice que me quedan 365 mb libres.

Entonces para hacer una copia de la nand, ¿qué proceso es mejor?:

1. Sacar los primeros 2 megas por lpt y el resto por gentoo (proceso que todavía no tengo muy claro por el tema de qué lflash utilizar)
2. Sacar los primeros 66 megas por lpt, que calculando deben ser unas dos horas y media.
3. Sacar los primeros 16 megas por lpt, que es lo que ocupa el xbr

Gracias por vuestra colaboración.
marceono escribió:Como he comentado anteriormente en el hilo "[Tutorial] Actualiza el XBRebooter sin usar el nanddumper" tengo todo el proceso del xploit bastante claro después de leer los hilos relativos a este tema, pero el único tema que me echa para atrás a la hora de comenzar el proceso es que no tengo claro lo del backup de la nand. Mi nand, aunque la caja pone 256 Mb, creo que es de 512, porque la Xbox360 en memoria me dice que me quedan 365 mb libres.

Entonces para hacer una copia de la nand, ¿qué proceso es mejor?:

1. Sacar los primeros 2 megas por lpt y el resto por gentoo (proceso que todavía no tengo muy claro por el tema de qué lflash utilizar)
2. Sacar los primeros 66 megas por lpt, que calculando deben ser unas dos horas y media.
3. Sacar los primeros 16 megas por lpt, que es lo que ocupa el xbr

Gracias por vuestra colaboración.


No, el Xbr ocupa más o menos los primeros 1000 bloques, en las big nand. De modo que sacar en todo caso los primeros 66 (yo sacaría 70 directamente, pero si la gente habla de 66 es que así es y no tendrás problema). Para abreviar, como no te veo dispuesto a sacar una copia completa por Lpt, sacas los 2 megas varias veces, comparas, y si son idénticos, flasheas el xell. Y lo demás lo haces todo con gentoo y está.
el XBR de la jasper 256/512 son los primeros 64 megas cuidado con esto que no es como las de 16.
don pelayo escribió:No, el Xbr ocupa más o menos los primeros 1000 bloques, en las big nand. De modo que sacar en todo caso los primeros 66 (yo sacaría 70 directamente, pero si la gente habla de 66 es que así es y no tendrás problema). Para abreviar, como no te veo dispuesto a sacar una copia completa por Lpt, sacas los 2 megas varias veces, comparas, y si son idénticos, flasheas el xell. Y lo demás lo haces todo con gentoo y está.


Gracias don Pelayo, no te creas, creo que lo voy hacer por lpt porque 70 megas no lo veo un tiempo desproporcionado, eso si, si no me salen rápido un par de copias nand iguales, me iría al otro método.
El gentoo te saca los 512 no 66, para sacar 66 esta claro que usas lpt, solo son 2 horas.


A mi los 512 (350 libres antes) me los ha dejado en 200 libres, aun no se porque, mira a ver si te pasa cuando acabes.
Buenas a todos.
Despues de varios cuelgues he conseguido dumpear mi nand de 512 mediante el gentoo pero el archivo resultante ocupa 528 mb sin inyectarle el de dos megas que tengo guardado, es normal esto? a alguien mas le ha pasado??.
Por otro lado no puedo abrir la nand con dregaded demasiado grande, existe algun otro programa para comparar mis nands extraidas y comprobar que son correctas?

Muchas gracias.
kruen escribió:Buenas a todos.
Despues de varios cuelgues he conseguido dumpear mi nand mediante el gentoo pero el archivo resultante ocupa 528 mb sin inyectarle el de dos megas que tengo guardado, es normal esto? a alguien mas le ha pasado??.
Por otro lado no puedo abrir la nand con dregaded demasiado grande, existe algun otro programa para comparar mis nands extraidas y comprobar que son correctas?

Muchas gracias.

Usa el nand compare y saca varias nands. A mi me saco nands diferentes aun por gentoo. Las unicas iguales que me sacaba ocupaban siempre 540.672 kb.
central98 escribió:A mi los 512 (350 libres antes) me los ha dejado en 200 libres, aun no se porque, mira a ver si te pasa cuando acabes.

A mi tambien me ha pasado justamente eso.

Aunque mi imagen con el Gentoo era de 66mb ...
Usa el nand compare y saca varias nands. A mi me saco nands diferentes aun por gentoo. Las unicas iguales que me sacaba ocupaban siempre 540.672 kb.


Te refieres a 540mb con 672kb o a 540.672 kb o sea medio mega?

Y gracias por la rapida respuesta. [oki]
kruen escribió:
Usa el nand compare y saca varias nands. A mi me saco nands diferentes aun por gentoo. Las unicas iguales que me sacaba ocupaban siempre 540.672 kb.


Te refieres a 540mb con 672kb o a 540.672 kb o sea medio mega?

Y gracias por la rapida respuesta. [oki]


1 mb = 1024 kb
540572 kb = 528 mb

Me parece que se te ha pasado el prefijo.
Muy buenas, he extraido los 2 megas de la nand, y he instalado el hell, tal y como dice el manual, pero al encender la consola me saltan las 3lr, pero si vuelvo a escribir la copia de mi nand, arranca sin problemas.No sé que puedo hacer mal, quizás sea el jtag...., que puntos tengo que usar en la placa jasper los alternativos o los normales?
radical26 escribió:Muy buenas, he extraido los 2 megas de la nand, y he instalado el hell, tal y como dice el manual, pero al encender la consola me saltan las 3lr, pero si vuelvo a escribir la copia de mi nand, arranca sin problemas.No sé que puedo hacer mal, quizás sea el jtag...., que puntos tengo que usar en la placa jasper los alternativos o los normales?

Quizás sea el JTAG, porque tu consola es vulnerable, ¿¿verdad? Revisa esas soldaduras. :)
don pelayo escribió:
radical26 escribió:Muy buenas, he extraido los 2 megas de la nand, y he instalado el hell, tal y como dice el manual, pero al encender la consola me saltan las 3lr, pero si vuelvo a escribir la copia de mi nand, arranca sin problemas.No sé que puedo hacer mal, quizás sea el jtag...., que puntos tengo que usar en la placa jasper los alternativos o los normales?

Quizás sea el JTAG, porque tu consola es vulnerable, ¿¿verdad? Revisa esas soldaduras. :)


Si lo es, lo que pasa es que no se que puntos del JTAG usar, si los alternativos o normales, cual me aconsejas??
radical26 escribió:
don pelayo escribió:
radical26 escribió:Muy buenas, he extraido los 2 megas de la nand, y he instalado el hell, tal y como dice el manual, pero al encender la consola me saltan las 3lr, pero si vuelvo a escribir la copia de mi nand, arranca sin problemas.No sé que puedo hacer mal, quizás sea el jtag...., que puntos tengo que usar en la placa jasper los alternativos o los normales?

Quizás sea el JTAG, porque tu consola es vulnerable, ¿¿verdad? Revisa esas soldaduras. :)


Si lo es, lo que pasa es que no se que puntos del JTAG usar, si los alternativos o normales, cual me aconsejas??


Los normales, pero no por nada. Son los que yo hice y va perfecto.
don pelayo escribió:
Los normales, pero no por nada. Son los que yo hice y va perfecto.


OK, entonces según este esquema tengo varias preguntas:

Imagen

El diodo de la linea roja va directamente soldado a la placa?
El cable de la linea azul tiene que ser corto como el esquema o vale cualquier longitud?
No encuentro al punto de la linea amarilla que va a la parte trasera de la placa jasper, será porque esa imagen no es de la placa jasper o porque no son los mismos puntos?

Perdón por las molestias, soy nuevo en esto, y muchas gracias por todo
radical26 escribió:
don pelayo escribió:
Los normales, pero no por nada. Son los que yo hice y va perfecto.


OK, entonces según este esquema tengo varias preguntas:

Imagen

El diodo de la linea roja va directamente soldado a la placa?
El cable de la linea azul tiene que ser corto como el esquema o vale cualquier longitud?
No encuentro al punto de la linea amarilla que va a la parte trasera de la placa jasper, será porque esa imagen no es de la placa jasper o porque no son los mismos puntos?

Perdón por las molestias, soy nuevo en esto, y muchas gracias por todo


Me recuerdas tanto a mí hace tres semanas...

1- Preferiblemente, es más, sí.
2- No, desde luego que no.
3-Yo tampoco lo encontraba. Está por debajo de la placa, y es uno de los puntos a los que está soldado el conector de la plaquita de encendido de la consola.
don pelayo escribió:
Me recuerdas tanto a mí hace tres semanas...

1- Preferiblemente, es más, sí.
2- No, desde luego que no.
3-Yo tampoco lo encontraba. Está por debajo de la placa, y es uno de los puntos a los que está soldado el conector de la plaquita de encendido de la consola.


Mil gracias por todo supongo que todos hemos empezado....., que malos son los comienzo.

Espero no aburrirte con tanta pregunta pero es que tengo miles y todos esto para recuperar el dvd key del lector que le tengo estropeado.

Aquí van unas cuantas dudas más;

Para el JTAG tengo diodos de 1lN4153, serán compatibles?, es que no tenían de 1N4148 .

Si no consigo extraer todo la NAND por usb con el gento, puedo utilizar éstos comandos para ahorrar tiempo a la hora de leer la NAND y copiar el XBR?:
COMANDOS:

"nandpro lpt: -r70 1.bin" para leerla


1) Extraer el KV y el Config de de tu nand original orig.bin ( ponle asi si no lo nonbrastes de esta manaera)

nandpro.exe orig.bin: -r256/512 rawkv.bin 1 1
nandpro.exe orig.bin: -r256/512 rawconfig.bin EF7 2


2) injectalos al XBR.bin
nandpro.exe XBR.bin: -w256/512 rawkv.bin 1 1
nandpro.exe XBR.bin: -w256/512 rawconfig.bin EF7 2

3) Resultado de tu Flash
nandpro.exe lpt: -w256/512 XBR.bin 0

Por ciento qué XBRebooter tengo que usar con la jasper de 512? ó cual es el último compatible con ésta? es que hay unos cuantos fichero llamados:

XBR_JasperBB_8955_3.rar
XBR_Jasper16a_8955_3.rar
XBR_Jasper16_8955_3.rar

Se supone que en los ficheros que pone 16, será para las jasper de 16mb, pero estonces, como se llama el fichero válido para las jasper 512?
radical26 escribió:
don pelayo escribió:
Me recuerdas tanto a mí hace tres semanas...

1- Preferiblemente, es más, sí.
2- No, desde luego que no.
3-Yo tampoco lo encontraba. Está por debajo de la placa, y es uno de los puntos a los que está soldado el conector de la plaquita de encendido de la consola.


Mil gracias por todo supongo que todos hemos empezado....., que malos son los comienzo.

Espero no aburrirte con tanta pregunta pero es que tengo miles y todos esto para recuperar el dvd key del lector que le tengo estropeado.

Aquí van unas cuantas dudas más;

Para el JTAG tengo diodos de 1lN4153, serán compatibles?, es que no tenían de 1N4148 .


Si en la tienda te han dicho que son comatibles, no le des más vueltas. No sé decirte de esos en concreto, pero mucha gente utiliza diodos compatibles y no les han dado problemas.

Si no consigo extraer todo la NAND por usb con el gento, puedo utilizar éstos comandos para ahorrar tiempo a la hora de leer la NAND y copiar el XBR?:
COMANDOS:

"nandpro lpt: -r70 1.bin" para leerla


1) Extraer el KV y el Config de de tu nand original orig.bin ( ponle asi si no lo nonbrastes de esta manaera)

nandpro.exe orig.bin: -r256/512 rawkv.bin 1 1
nandpro.exe orig.bin: -r256/512 rawconfig.bin EF7 2


2) injectalos al XBR.bin
nandpro.exe XBR.bin: -w256/512 rawkv.bin 1 1
nandpro.exe XBR.bin: -w256/512 rawconfig.bin EF7 2

3) Resultado de tu Flash
nandpro.exe lpt: -w256/512 XBR.bin 0


No entiendo muy bien la pregunta, pero los comandos de lectura y escritura que pones son sólo para lectura/escritura mediante nandumper lpt. Los de extracción e inyección se hacen con el nandpro también, pero trabajando sobre archivos ya extraídos. En ningún caso puedes hacer esto por gentoo con estos comandos. Supongo que aunque no te haya entendido del todo, con esta respuesta puedas sacar tus propias conclusiones.

Por ciento qué XBRebooter tengo que usar con la jasper de 512? ó cual es el último compatible con ésta? es que hay unos cuantos fichero llamados:

XBR_JasperBB_8955_3.rar
XBR_Jasper16a_8955_3.rar
XBR_Jasper16_8955_3.rar

Se supone que en los ficheros que pone 16, será para las jasper de 16mb, pero estonces, como se llama el fichero válido para las jasper 512?


El primero, el Big Block (BB).

EDIT: Y sí, por puerto lpt, puedes utilizar esos comandos para ahorrar tiempo.
don pelayo escribió:
EDIT: Y sí, por puerto lpt, puedes utilizar esos comandos para ahorrar tiempo.


jejeje ya veo, lo que me refería es que si no puedo utilizar gento porque se me cuelga, lo podría hacer mediante lpt con ésos comandos para ahorrar tiempo y no tirarme 20 horas.

Entonces con el comando
nandpro lpt: -r70 1.bin
, serán unas 2 horas más o menos no?
radical26 escribió:
don pelayo escribió:
EDIT: Y sí, por puerto lpt, puedes utilizar esos comandos para ahorrar tiempo.


jejeje ya veo, lo que me refería es que si no puedo utilizar gento porque se me cuelga, lo podría hacer mediante lpt con ésos comandos para ahorrar tiempo y no tirarme 20 horas.

Entonces con el comando
nandpro lpt: -r70 1.bin
, serán unas 2 horas más o menos no?


2 horas y media, pero depende de tu pc el que tarde más o menos. De todas formas paciencia con el gentoo, lo mismo sale a la primera que se cuelga 6 veces seguidas.
ya esta comprobado que este metodo de copiar dos megas o 66 es seguro totalmente?
tvillaje1 escribió:ya esta comprobado que este metodo de copiar dos megas o 66 es seguro totalmente?


Sí la nand está bien extraida y el xbr no funciona, basta con escribir esos 66 megas originales en la nand para que vuelva a funcionar. Y hay gente que ha hecho esto con éxito.
don pelayo escribió:
radical26 escribió:
don pelayo escribió:
EDIT: Y sí, por puerto lpt, puedes utilizar esos comandos para ahorrar tiempo.


jejeje ya veo, lo que me refería es que si no puedo utilizar gento porque se me cuelga, lo podría hacer mediante lpt con ésos comandos para ahorrar tiempo y no tirarme 20 horas.

Entonces con el comando
nandpro lpt: -r70 1.bin
, serán unas 2 horas más o menos no?


2 horas y media, pero depende de tu pc el que tarde más o menos. De todas formas paciencia con el gentoo, lo mismo sale a la primera que se cuelga 6 veces seguidas.


Gracias de nuevo, esta tarde me pongo a ello.Entonces cuando acabe de todo el tinglado, como hago para recuperar el dvd key o como le puedo ver ? y otra dato la consola que se conecta por componente o por rgb? me refiero para ver el Xell en pantalla.
163 respuestas
1, 2, 3, 4