[Proyecto] Carga de backups con ficheros >4GBs en FAT32(USB)

Hola, soy nuevo en el foro y la verdad es que me he registrado para poder postear ;P no suelo andarme mucho por foros etc.

El caso es que no tengo mucha base en scenes de ninguna consola etc. ( he hecho "parches" ;) para apps de android ( en .so nativos, ni idea ni interes en bytecodes etc., algunas de iphone, etc. pero vengo mas bien de hacer cosas en x86 y sobre todo NT ).

En fin, la cosa es que tengo bastante pensado el como soportar de una forma facil/limpia ( de cara al usuario, el desarrollo no es demasiado complicado, pero bueno... ) la carga de backups en discos externos ( con fat32; personalmente no se si se conseguira soportar otras cosas como UDF etc., pero tampoco me parece una idea practica... quiza quitando NTFS, pero dar soporte a eso creo que es mucho mas curro ).

La idea seria que, tal como lo hace el comgenie´s file manager, los ficheros que tengan mas de 4GB, se partan en <nombre_de_fichero_original>.000 ( de 4GB -1byte ), <nombre_de_fichero_original>.001 ( de 4GB -1byte ), <nombre_de_fichero_original>.002 ... y asi hasta el ultimo ( maximo 4GB -1byte ) .

He mandado algun twit a comgenie pero no ha contestado ( no se, estara liado con el file manager, que por cierto agradezco mucho ) y lo que me gustaria, basicamente, es que alguno de los gurus que hay por aqui comentara como lo ve y no se, quiza poder preguntarle por alguna duda etc.

Bueno, basta de chapa, aqui va la idea:

- El soporte seria "independiente al backup manager", un programa que lo instalas y cada vez que quieras jugar a backups salvando la limitacion de 4GB, pues nada, ejecutas el programa y termina casi inmediatamente. Dejando el kernel preparado para que soporte backups con ficheros de mas de 4GB ( mete un pequeño parche + hooks en el kernel de lv2 ).

- El programa utiliza la funcionalidad de peek/poke de los ultimos psgroove/etc. para inyectar un trocito de codigo que son basicamente replacements de las funciones de cellfsXxx que se proveen a los programas.

- Tambien con peek/poke, se parchean los comienzos de las funciones de operaciones de ficheros ( o quiza un puntero a funcion, esta es otra duda que tengo... ).

- Cuando un programa ( el juego ) pida abrir un fichero, pasaria por nuestra funcion de replacement de cellFsOpen que haria lo siguiente:

1 - llamar a la funcion cellFsOpen original
1.1 - si el fichero se puede abrir ( no hay error ), devolver el handle y salir, no hacer nada mas
1.2 - si la apertura falla diciendo que no se encuentra el fichero ( con otros errores > salir directamente ), concatenar al nombre de fichero la extension ".000" y llamar otra vez a la funcion cellFsOpen original
1.2.1 - si esto falla, devolver el error que nos dio la primera llamada ( no esta llamada, si no la anterior, aunque al final va a ser lo mismo, probablemente )
1.2.2 - si esto funciona, quiere decir que ese fichero es un fichero "splitted" o partido y que en lugar del fichero <nombre_de_fichero_original> tenemos N ficheros con nombres <nombre_de_fichero_original>.000, <nombre_de_fichero_original>.001, etc.
En este caso, guardamos el handle obtenido y hacemos lo mismo para concatenaciones con ".001", ".002" etc. hasta que uno de ellos falle o hasta un maximo ( .015 o asi deberia valer, ya que de 000 a 015 son 16 "partes" de fichero, y 16x4GB son 64GB, que supera cualquier blu-ray que hay hoy dia para juegos... pero es facilmente adaptable/configurable en el futuro ).
Guardamos los N handles ( desde un minimo de 2 -se supone que al menos habra dos- a 16 -o el maximo que usemos )

En vez de devolver el handle real ( que de hecho hay varios ), devolvemos algo tal que asi: 0xF0F0xxxx donde esas "xxxx" son un indice o ID nuestro que apunta a una tabla donde tendremos estructuras que tengan toda la informacion necesaria para virtualizar ese fichero de mas de 4GBs a partir de N ficheros de 4GB.


SUBFILE SLOT 0 ( handle para el fichero .000 ) + ...
SUBFILE SLOT 1 ( handle para el fichero .001 ) + ...
SUBFILE SLOT 2 ( handle para el fichero .002 ) + ...
SUBFILE SLOT 3 ( handle para el fichero .003 ) + ...
SUBFILE SLOT 4 ( handle para el fichero .004 ) + ...
SUBFILE SLOT 5 ( handle para el fichero .005 ) + ...
SUBFILE SLOT 6 ( handle para el fichero .006 ) + ...
SUBFILE SLOT 7 ( handle para el fichero .007 ) + ...
SUBFILE SLOT 8 ( handle para el fichero .008 ) + ...
SUBFILE SLOT 9 ( handle para el fichero .009 ) + ...
SUBFILE SLOT 10 ( handle para el fichero .010 ) + ...
SUBFILE SLOT 11 ( handle para el fichero .011 ) + ...
SUBFILE SLOT 12 ( handle para el fichero .012 ) + ...
SUBFILE SLOT 13 ( handle para el fichero .013 ) + ...
SUBFILE SLOT 14 ( handle para el fichero .014 ) + ...
SUBFILE SLOT 15 ( handle para el fichero .015 ) + ...
+
CURRENT FILEPOS ( SLOT+OFFSET )
+
...

- Cuando un programa utiliza funciones de lectura como cellFsRead o de seek como cellFsFSeek, tambien pasa por nuestras funciones hookeadas ( redireccionadas ) y estas funciones hacen:

1 - detectan si el handle pasado como parametro es de tipo "hack" ( tienen el formato 0xF0F0xxxx )
1.1 - si no es asi, simplemente llaman a la funcion original
1.2 - si es asi, utilizan esos "xxxx" para indexar en nuestra tabla de estructuras de virtualizacion y simulan la lectura leyendo del slot correspondiente ( leyendo del fichero que corresponda al offset actual y si "cruza" la frontera de un fichero a otro, haciendo las dos lecturas y concatenando los datos en el mismo buffer etc. )

* Problemas posibles:

- hay una API de funciones para Streams que utiliza buffers circulares etc. que no creo que sea demasiado problema pero bueno, si que puede complicar la cosa o simplemente requerir mas desarrollo... aunque no se, """intuyo""" que quiza no se use tanto para leer, y menos para ficheros grandes ( por mucho que la palabra "Stream" pueda sugerir que se use para grandes volumenes y tal... lo veo mas propio para archivos de intercambio/cache/etc. pero puede que este equivocado, por supuesto. )

- hay tambien una API de IO asincrona que bueno, ya estoy pensando en las implicaciones y si, requiere su cosa tambien ( plegado de multiples peticiones asincronas con sus correspondientes callbacks de "completion" a una callback gestionada por nosotros etc... tiene su miga ). Esta API probablemente se use bastante mas... para pedir datos "de antemano" ( "mientras yo te saco el video, tu vas cargando el nivel siguiente..." ).

* En ambas APIs, quiza lo improbable es que se usen para ficheros de mas de 4GBs... "wishful thinking" ;D pero se puede ir implementando poco a poco y ver quetal va la cosa, nada que no se puede implementar poco a poco de todas formas.

* Dudas para los "gurus" ( en general para cualquiera que ya haya desarrollado/metido-mano a la ps3... ;P )

- Me conviene hacer esto en ensamblador de PPC64 por temas de espacio/codigo reubicable/etc. ? que opinais ?
- Hacerlo como aplicacion de modo usuario y tirando de peek/poke... le veis algun problema ? pensaba en este orden:
a) leer/detectar las posiciones en memoria de las rutinas que debamos hookear
b) preparar codigo "trampoline" para "llamar a las funciones originales" y meterlas como "stubs" en algun punto del kernel ( aqui tengo la duda de: como encuentro un hueco adecuado ? tengo lv2 kernel volcado y si, hay muuuchos huecos pero... alguna idea/ayuda en elegir "un buen sitio" ? )
c) meter todo lo que son las rutinas de reemplazo en algun hueco ( otra vez, donde... )
d) hookear las funciones, siendo la cellFsOpen la ultima ( de cara a la atomicidad, todo estriba de la apertura, asique es seguro hookear las demas, por que no van a encontrarse con handles de tipo 0xF0F0xxxx hasta que se hookee cellFsOpen y empiece a haber handles "virtuales"... pero bueno, tampoco es problema en realidad... seria muy raro que se abra un fichero mayor a 4GBs justo en medio del proceso de parcheo... )

f) si esto no ocupara mucho se podria meter como payload del propio psgroove/etc. y no requerir lanzar una aplicacion, aunque creo que de primeras... mejor hacerlo como app, sin mas, no ?

*) cualquier cosa que podais aportar, lo movais por gente que sepais que podria ayudar o tal...

He empezado a escribir las rutinas en C ( de momento no tiro del toolchain opensource, ya sabeis a que me refiero, asi que... pero no me importaria rular codigo -hoy noche o mañana o asi, cuando lo tenga un poco mas maduro... ) y no tengo mucho problema en pasarlo a ensamblador ( no tengo callo con asm de ppc64 pero bueno, podria portarlo con algo de tiempo ) si se necesita ( por lo que pregunto de si el codigo C compilado queda bien para ser realojable o funciona en cualquier direccion base... )


Bueno, por ultimo, decir que no quiero ningun protagonismo ( si, ya se que por psicologia inversa puede parecer que si... tendre mi "protagonismo" en un ambito cerrado entre colegas, pero nada mas ;) tampoco creo que esto sea gran cosa, y mas comparado con todo lo que se esta cociendo... pero precisamente, por que lo veo facil y que puede llegar a ser muy comodo de usar y demas lo quiero mover ).

A ver si entre todos conseguimos esta feature "enseguida" :P
mucha suerte con el proyecto
Gracias... acabo de terminar mi jornada de curro, en 10 mins a casa y al lio... a ver si tengo algo... quiza me haga el tema el formato .self ( menos lio... ) para probar y cargarlo con el launcher que acaba de salir...
La idea no está mal pensada, pero parchear al vuelo sistemas de ficheros no es trivial y además puede acarrear problemas de rendimiento y otros adicionales (tipo superar el número máximo de ficheros abiertos, compatibilidad, portabilidad a otras versiones de FW, etc).

Teniendo en cuenta que existen implementaciones de NTFS (y de otros sistemas de ficheros con soporte de archivos de más de 4 GB como EXT2/3/4), lo que no se es si no sería mejor tratar de implementar un controlador que maneje este tipo de archivos.

¿Se sabe cómo funcionan los controladores del sistema de archivos de PS3? ¿Se pueden cargar varios simultáneamente y asignar uno a cada partición independientemente? ¿Qué limitaciones de memoria y otros recursos hay para su implementación?

En cualquier caso, no se si alguien suficientemente capacitado está currando en el tema del NTFS, así que te animo con tu proyecto. Por desgracia no podré ayudarte :(.
si lo consigues seria muy util! ;)
no és exactamente lo que se trata,pero se podrian poner los archivos con 4GB en el HDD interno, y pedirlos allí,para no gastar tanto el HDD interno.
Seria mas sencillo transformar de NTFS a a FAT32 al vuelo
Tu proyecto es interesante. Pero creo que aunque vaya a funcionar, puedes realizarlo de manera más sencilla.
En vez de liarte con los ficheros. Es más optimo volver al tema de isos.

Crear un hook que monte una iso (o isos de 4GB .000 .001 ,etc) en un sistema de ficheros.
Abría que realizar la conversión entre la ISO y el sistema de ficheros.

Pero sería la forma más óptima de tratar el problema. Según mi punto de vista.
De todas formas, si quieres continuar con tu idea, adelante, si necesitas algo puedes mandarme PM.

Saludos!
Yo te deseo suerte.No es mejor esperar a que actualicen los Jailbreaks?
ssssO escribió:Seria mas sencillo transformar de NTFS a a FAT32 al vuelo


¿? Para eso primero habría que implementar NTFS, y si se implementa NTFS ya no hay necesidad de transformar a FAT.
Doragasu:

*** La idea no está mal pensada, pero parchear al vuelo sistemas de ficheros no es trivial y además puede acarrear problemas de rendimiento y otros adicionales (tipo superar el número máximo de ficheros abiertos, compatibilidad, portabilidad a otras versiones de FW, etc).

> En realidad no parcheas el sistema de ficheros; parcheas las syscalls para que pasen por tus funciones primero; de hecho pienso parchear los punteros a funcion y trabajar a nivel de syscall...

Simplificando ( ya que en realidad hay una tabla de punteros a descriptores que tienen el puntero a funcion y otras cosas mas, pero bueno... )

[puntero a funcion syscall 0000]
[puntero a funcion syscall 0001]
[puntero a funcion syscall 0002]
[puntero a funcion syscall 0003]
...

Suponed que queremos hookear/suplantar la syscall 0002, lo que hacemos es:

a) nos guardamos el valor "puntero a funcion syscall 0002" y la guardamos en un lugar de memoria al que despues podamos acceder

b) machacamos ese puntero con uno que sea la direccion que apunte a nuestro "funcion de reemplazo de syscall 0002":

[puntero a funcion syscall 0000]
[puntero a funcion syscall 0001] _______________
[puntero a nuestra syscall 0002-------> | |
[puntero a funcion syscall 0003] | codigo que hace |
... | lo que explique |
| en el primer |
| post que puse. |
| |
| |
| En uno o varios |
| puntos de esta |
| funcion puede |
| haber llamadas |
| a la funcion de |
| syscall 0002 |
| original: |
| |
| ... |
| codigo |
| ... |
| bl syscall0002 |
| ... |
| codigo |
| ... |
| bl syscall0002 |
|______________|

Esto es en plan cutre, sorry... pero bueno, esta forma de hookeo es muy robusta en general... y eso, no cambia el sistema de ficheros; solo hace de proxy de aperturas y luego las read y seeks... partiendo un fichero logico en varios reales.

*** Teniendo en cuenta que existen implementaciones de NTFS (y de otros sistemas de ficheros con soporte de archivos de más de 4 GB como EXT2/3/4), lo que no se es si no sería mejor tratar de implementar un controlador que maneje este tipo de archivos.

> Esto es mas ambicioso y ya si requeriria pinchar mas en las profundidades del kernel ( lo bueno de lo que ando yo es que es un "wrapper" en la superficie del kernel, las syscalls, y eso lo hace simple y poco intrusivo ).

El tema ademas es que una implementacion mediodecente de NTFS ocupa mucho y no se hasta que punto seria "facil"; de todas formas veo mas practico/ventajoso seguir usando fat32 y partir los ficheros grandes en multiples ficheros de 4GB:

- todo cristo soporta fat32 ( macosx, linux, windows nuevos y viejos... aparatos reproductores, la ps3,... ) sin problemas

- con este sistema no influimos en la operativa de acceso a ficheros, solo dejando estas virtualizaciones para ficheros grandes cuando la open real haya fallado.

- el codigo requerido no deberia ser mucho mas que unos 4KBs o asi y el requisito de memoria y tal... poquito, creo que con un total de 32KBs o asi vamos sobrados. En cuanto a uso de handles apenas crecemos el numero, solo añadimos los handles que haga falta para ficheros grandes y es en plan +1 handle por cada bloque de 4GBs que se pase de los primeros 4GBs; el rendimiento... sinceramente, no creo que se aprecie apenas; al abrir se abren todos los handles y luego ya al
leer... pues aaalgo si, por que al final el brazo del disco se movera de fichero a fichero... pero nada que no ocurra potencialmente ya, tal y como estamos ahora, ya que la fragmentacion, sobre todo en ficheros grandes, tendra situaciones semejantes

DZeros:

*** Tu proyecto es interesante. Pero creo que aunque vaya a funcionar, puedes realizarlo de manera más sencilla. En vez de liarte con los ficheros. Es más optimo volver al tema de isos.

> Jo, pues la verdad es que esta es la forma mas sencilla que se me ocurre, y lo jodido es que es bastante minimalista... al menos en vez de andar metiendo soporte para otros filesystems...

*** Crear un hook que monte una iso (o isos de 4GB .000 .001 ,etc) en un sistema de ficheros.
Abría que realizar la conversión entre la ISO y el sistema de ficheros.

> Aqui si te doy la razon, aunque puede haber pegas... pero tengo algunas ideas aqui... lo bueno es que seria, probablemente un hack de un solo punto de hook y serviria para hacer el volcado/guardado de "ISOs" asi como para la emulacion de los mismos... todo en el mismo punto, en
plan "replay attack" ;) y no haria falta implementar nada, ni el sistema de ficheros, ni conversiones, ni nada... basicamente haces que los sectores que se piden leer al BDVD se lean de ficheros ;D

La cosa es que he visto que hay unas llamadas al hypervisor/lv1 que se usan para acceder a nivel de sector a todo tipo ( esto se usaba en linux de la ps3 pero estoy casi convencido de que sigue aplicando en GameOS y es logico que asi sea... pero hay que investigar un poco ) de storage de la ps3; se podria pinchar en las llamadas a esa hvcall ( en este caso en vez de cambiar la entrada de la syscall table de lv1, como eso no es posible a dia de hoy, seria cambiar la instruccion de hvcall a un "b <nuestra_funcion>" y alli virtualizar la lectura de sectores que van dirigidas a BDVD a base de leer N ficheros de 4GBs con la imagen RAW ( llamalo ISO si quieres... ) guardada desde el Blu-ray original al disco ( sea interno o usb externo en fat32, da igual ).

*** Pero sería la forma más óptima de tratar el problema. Según mi punto de vista. De todas formas, si quieres continuar con tu idea, adelante, si necesitas algo puedes mandarme PM.

Pues la verdad es que se agradece ( igual te mando algun privado, si... tu andas con cosas de estas tambien ? ), algo desamparado si que me he encontrado :D pero bueno, ya me muevo con relativa soltura por el desensamblado del volcado del kernel lv2 que tengo, he sacado los puntos que hookear y he estado mirando como solucionar cosillas que salen y tal; lo malo va a ser la dificultad para depurar segun vayamos probandolo y tal.

Para esto, lo primero primero, que espero hacer mañana ( ya tengo todo lo que es "el compilador" O;P montado y puedo compilar mis elf/self y hacer PKGs... ) es un pequeño programa que usa peeks+pokes y mete hooks en esas syscalls que necesitamos hookear pero que de momento se van a limitar a loguear los valores que pasan como parametros a la syscall etc. De momento ese "logueo" sera escribir a un buffer en memoria y luego leere con peeks los valores guardados...

Tendreis mas noticias, a ver si el domingo o sino entre semana...

Gracias a todos por los animos y las ideas :)
11 respuestas