La Switch era de un amigo y yo no tenía demasiado claro qué se había tocado antes. Podía entrar en Hekate, pero al intentar arrancar la consola se quedaba en negro. Me pasaba tanto con CFW como con stock. En uno de los intentos apareció CAL0 is corrupt or wrong keys.
Lo primero que pregunté fue si podía reinstalar el firmware completo. Al principio solo había sacado algunos dumps desde Hekate; todavía no tenía una copia de la NAND. Estuve con ella entre el 2 y el 3 de noviembre, pasando la microSD del PC a la consola y de vuelta al PC.
Lo hice con ayuda de Codex. Yo iba probando en la Switch y pasándole los resultados, mientras el asistente preparaba scripts y revisaba el código. Hubo cosas que resolvió bien y otras que tuvimos que corregir sobre la marcha.
He dejado los offsets, los diagramas y las comparaciones de bytes en la versión técnica: dentro de la NAND.
Guardé la NAND antes de seguir
Una de las primeras cosas que pedí fue hacer backup del backup. No quería ir modificando la única copia mientras intentaba entender por qué no arrancaba.
Guardé la RAWNAND completa, sus quince partes, BOOT0, BOOT1 y las claves extraídas de esta Switch. La imagen ocupaba 31.268.536.320 bytes; los BOOT eran de 4 MiB cada uno. Después hice una segunda copia de los materiales de recuperación. Las copias se volvieron a leer y sus hashes SHA-256 coincidían.
El primer script para mirar la emuMMC se paró con Unaligned physical read. Tocó corregir la alineación de las lecturas físicas antes de poder fiarme de lo que devolvía. Una vez arreglado, el resultado seguía siendo malo: ni CAL0 ni los comienzos FAT de las particiones examinadas se validaban con las claves disponibles.
Los fusibles no cuadraban con el firmware
Antes de cambiar de versión pedí revisar los eFuses. La consola tenía 24 fusibles anti-downgrade quemados, pero el package1 de su BOOT0 llevaba la fecha 20240207110330: correspondía a 18.0.0–18.1.0.
En la tabla de Switchbrew, esa familia espera 19 fusibles. Los 24 encajaban con 23.0.0–23.0.1. También contrasté la fecha con el histórico de package1. Había un desfase, así que tenía sentido preparar 23.0.1.
Pero CFW tampoco arrancaba, y ese recorrido podía saltarse la comprobación de fusibles. Todavía quedaba por explicar por qué no conseguía descifrar las particiones.
Saqué las claves otra vez
Repetí la extracción entrando por RCM directo para compararla con la que había hecho pasando por el chip. Las claves obtenidas eran coherentes con las derivadas para el hardware actual. Aun así, con ellas no aparecían las estructuras esperadas en PRODINFO, SAFE, SYSTEM ni USER de la NAND original.
La imagen tampoco parecía un bloque de datos completamente roto: la GPT tenía sus CRC correctos y las imágenes de package2 revisadas pasaban sus comprobaciones.
Miré la emuMMC antigua por si conservaba algo aprovechable. BOOT0 y BOOT1 eran iguales a los de la memoria interna, y los primeros fragmentos cifrados que comparé también coincidían. No comparé toda la emuMMC, pero en esos fragmentos no había una copia distinta a la que recurrir.
Busqué además entre backups que tenía guardados de otras reparaciones. Algunas copias se descifraban con sus propias claves, lo que sirvió para comprobar que el procedimiento de lectura funcionaba. Ninguna me devolvió los datos originales de esta Switch. Sí encontré un PRODINFO donante válido.
La causa exacta de lo que había pasado antes sigue sin estar clara. No pude demostrar si la NAND era de otra consola o si sus datos estaban dañados.
Preparé otra emuMMC
Revisé con Codex NANDFixPro, HATS-Tools y el instalador de HATS. Me interesaba saber qué escribía cada uno antes de darle una NAND.
De NANDFixPro aproveché las plantillas de particiones limpias. La reconstrucción se hizo en el PC, sin usar su interfaz para escribir directamente en la eMMC. Para generar los componentes de firmware utilicé EmmcHaccGen 3.2.1.
El paquete 23.0.1 tenía 238 NCA. Comprobé sus hashes contra los identificadores de contenido, las cabeceras y el contenido de versión. No hice una validación de las firmas de Nintendo.
Preparé PRODINFOF, SAFE, SYSTEM y USER limpios y monté la nueva imagen con las claves BIS de esta consola. Los BOOT que generaba EmmcHaccGen eran parciales: hubo que integrarlos en imágenes completas de 4 MiB, conservando las zonas necesarias de los volcados originales. Las herramientas de cifrado respetaban las unidades XTS de 16 KiB; después se volvieron a descifrar las particiones para comparar su contenido con lo preparado en el PC.
Como no había recuperado el CAL0 original, partí del donante. Ahí llegó el primer error del planteamiento: no bastaba con que aquel PRODINFO fuera válido en su consola. Faltaba adaptarlo al hardware en el que quería arrancarlo.
Llamé REC1 a la nueva emuMMC, basada en archivos. Dejé la antigua RAW1 donde estaba. Para las pruebas usé Hekate 6.5.4 y Atmosphère 1.12.1. La memoria interna seguiría sin tocarse hasta que tuviera algo que funcionara desde la SD.
Tres errores antes de llegar al menú
Con la imagen nueva empezaron a salir errores concretos en lugar de quedarse todo en negro. Esta fue la secuencia:
| Error | Proceso | Lo que hubo que revisar |
|---|---|---|
2026-0002 | es | Identificadores internos en los paquetes RSA del donante |
2162-0002 | account | El contexto de idgen, que no se había creado |
2105-0584 | am / Settings | El identificador del certificado de eTicket |
Primero, los paquetes RSA
El fallo de es acababa en un argumento rechazado por el monitor seguro. Los paquetes extendidos de eTicket y SSL tenían material criptográfico válido, pero llevaban dentro el identificador del dispositivo donante.
Se adaptaron esos identificadores al hardware actual, manteniendo el material RSA y rehaciendo la autenticación y los controles de integridad afectados. Antes se guardaron los rangos originales; después se volvió a leer PRODINFO completo.
Al probar de nuevo, es ya no era lo que paraba el arranque. Ahora fallaba account.
Después, un archivo de 48 bytes
El registro llevó hasta idgen:/context.bin, dentro del save de sistema 8000000000000011. Era un archivo de 48 bytes que todavía no existía. Su formato está descrito en Nintendo File Formats.
Al intentar crearlo, la rutina pedía información de las interfaces de red. En ese arranque la enumeración no devolvía una interfaz utilizable y el proceso abortaba. Llegué a plantear una prueba por Ethernet, pero mi dock no tenía puerto y aquella prueba se quedó sin hacer.
Para salir de ese punto se estudió la rutina del binario de esa misma versión y se emuló con Unicorn. Sin el contexto, la emulación reproducía el aborto. Con el contexto inicializado, evitaba esa llamada y generaba identificadores distintos en llamadas sucesivas. También se comprobó qué ocurría al cambiar el origen del reloj.
El cambio se hizo en una copia del save vacío que había creado la consola, mediante un programa pequeño basado en LibHac. Se comprobaron su integridad y sus MAC antes de aplicar los bloques cifrados modificados en SYSTEM. El ejecutable de account quedó igual.
Más tarde pude conectar la Switch por Wi-Fi. Aquella enumeración fallida no había sido suficiente para dar por averiado el chip.
Por último, el certificado de tickets
El siguiente intento terminó en 2105-0584. Esta vez el fallo venía de una llamada a Settings: estaba leyendo el identificador del certificado RSA de eTicket y comparándolo con el del hardware.
Había una cadena de 16 caracteres hexadecimales que seguía apuntando al donante. La emulación de esa rutina devolvía el mismo error; al adaptar el campo, devolvía éxito. Se corrigieron el campo, el CRC del registro y el hash de CAL0, guardando antes los bytes que se iban a sustituir.
Encontré después un precedente que habría venido bien leer antes. prodinfo_gen 1.1.0 ya explicaba en 2022 que Horizon había pasado a comparar el identificador de Rsa2048ETicketCertificate. La incidencia 24 recoge las pruebas de aquella corrección. Había perdido tiempo con una adaptación incompleta que ese proyecto ya contemplaba.
Cambiar ese campo servía para superar la comparación local. La firma del emisor quedaba invalidada al modificar el certificado; recalcular su CRC no arreglaba eso. La identidad original de mi consola seguía sin recuperarse.
«Ha arrancado entero»
Eso fue lo que escribí cuando por fin llegó a HOME. Después configuré el Wi-Fi e hice la prueba de conexión. Volvió a caerse.
El nuevo error era 2123-0011, en nim. El registro señalaba un error de E/S SSL. La entrada de recuperación llevaba cal0blank=1, así que había que revisar ese recorrido sin asumir que el fallo era físico.
Se añadió un archivo de DNS.mitm específico para REC1, con los dominios de Nintendo redirigidos a 127.0.0.1. El registro confirmó que Atmosphère estaba leyendo ese archivo. Cuando volví a probar, ya no crasheaba. La selección de estos archivos y el log están explicados en la documentación de Atmosphère.
Más adelante añadí sys-patch. Entre sus ajustes hay uno para el cierre de nim relacionado con certificados SSL no intactos, según su documentación. El log confirmó que se aplicaba en 23.0.1. El bloqueo DNS ya había evitado el cierre antes de instalar ese módulo; son dos momentos distintos de la reparación.
Probé un juego y volví a apagarla
De HATS añadí DBI, Goldleaf, JKSV y sys-patch. También pedí meter CyberFoil. Se comprobó el hash publicado del paquete y se comparó el módulo de sys-patch con su distribución de origen.
No sustituí la configuración por la del pack: el instalador permite borrar o reemplazar carpetas completas y yo ya tenía una entrada de recuperación y un bloqueo que quería conservar.
Instalé Pokémon Verde Hoja, que ocupaba unos 33 MB. Se instaló y funcionó sin problemas. Luego hice un apagado completo y volví a encender la consola. También arrancó.
Con eso ya me planteé pasar la reconstrucción a la memoria interna.
Antes de restaurar tuve que actualizar el backup
La imagen que tenía en el PC se había quedado atrás. No incluía todo lo que Horizon había creado durante los arranques ni el estado posterior a instalar el juego.
Tampoco me cabía otra imagen completa de 31 GB en el PC. Guardé la base y un archivo con los bloques que habían cambiado: 127 bloques de 1 MiB, unos 133 MB contando las cabeceras. Para comprobar que aquello era un backup utilizable, se reconstruyó por lectura toda la RAWNAND a partir de las dos piezas. Su SHA-256 coincidía con el de REC1. Guardé además BOOT0, BOOT1, las configuraciones y los datos del juego en Nintendo.
Ese respaldo depende de conservar la base y las diferencias juntas. Dejé ambas cosas protegidas contra escritura.
Al comparar los BOOT apareció una diferencia de 33 bytes. Estaba en la zona de NAND Patrol, a partir de 0x184000: habían cambiado su HMAC y el campo de posición; el contador seguía en 3. Las BCT, el firmware y los keyblobs seguían iguales; BOOT1 también. Lo contrasté con la descripción de BOOT0 antes de continuar.
Preparar los archivos de restauración en la SD también dio trabajo. El lector devolvió un error de escritura de Windows; hubo que reabrir el archivo, comprobar el reintento y reanudar cotejando lo ya copiado. Al terminar se leyeron completas las quince partes y se compararon sus hashes. No quedó marcada como lista hasta pasar esa comprobación.
Dejé una entrada nueva, CFW SYS RECUPERADA, con emuMMC desactivada. Preparé el bloqueo en hosts/sysmmc.txt, habilité sys-patch para sysMMC y la verificación completa de Hekate. También copié el juego al directorio Nintendo de la raíz de la SD, conservando los atributos de los directorios NCA.
Finalmente restauré BOOT0, BOOT1 y RAW GPP desde Hekate, con este procedimiento. REC1 se quedó en la tarjeta por si necesitaba volver a ella.
También arrancó en stock
El plan de Codex daba por hecho que seguiría necesitando Atmosphère. Probé la entrada CFW SYS RECUPERADA y funcionó, pero también quise probar Stock (sysMMC). Arrancó. Incluso terminó la prueba de conexión.
Confirmé en el chat que había probado las dos entradas. El log de sys-patch mostraba is_emummc=0, y el de DNS.mitm cargaba hosts/sysmmc.txt en CFW. En eso Codex se había adelantado: cuando me dijo que seguiría necesitando Atmosphère, yo aún no había probado stock con la NAND nueva.
Hasta ahí he comprobado el juego y el apagado completo en REC1, y el arranque stock y CFW sobre la sysNAND restaurada. El arranque stock lo hice mediante Hekate; no he probado a prescindir de la SD o del chip.
En stock tampoco actúa el bloqueo DNS de Atmosphère. La prueba de conexión terminó bien, pero no he probado cuentas Nintendo ni eShop y sigo sin haber recuperado la identidad original. prodinfo_gen también separa el arranque de las capacidades online.
Después de esas pruebas retiré las copias temporales de restauración y recuperé unos 31 GB de espacio en la tarjeta. Me quedé con la emuMMC que había probado, la reconstrucción respaldada en el PC y los dumps originales. La Switch vuelve a arrancar. Sigo sin saber qué le había pasado a la NAND original.