-[ 0x08 ]-------------------------------------------------------------------- -[ SX1-Segunda parte ]------------------------------------------------------- -[ by FCA00000 ]-----------------------------------------------------SET-32-- 28/09 *********** Miércoles *********** El parche de aumentar el tiempo de infrarrojos no ha tenido tanto éxito. Al parecer la gente usa BlueTooth para transferir sus ficheros hacia el móvil, o los mete en la tarjeta MMC usando un PC. En fin, no me extraña, pero yo no tengo ninguna de esas posibilidades. Bastante contento estoy con que mi ordenador tenga infrarrojos... Hoy voy a un cursillo de cata de vinos. Carpe Diem ! 29/09 *********** Jueves *********** Un usuario de www.siemens-mobile.org ha pedido que alguien publique un parche especial: El SX1 es Series60v1.2 (Symbian 6.1), mientras que algunos de los juegos necesitan Series60v2.0 (Symbian 7.0), el cual se encuentra, por ejemplo, en el Nokia 7310 . El parche debería engañar al instalador para que, al menos, se puedan instalar, aunque posteriormente no funcionen porque haga falta algún dispositivo especial. Dentro del sistema de archivos existen 4 llamados Series*.sis : Series60v0.9.sis Series60v1.0.sis Series60v1.1.sis Series60v1.2.sis La razón es que para instalar un programa, necesitas tener exactamente esa versión, que puede que no sea compatible con las anteriores. Por ejemplo, si no tienes Series60v1.1.sis , puedes instalar una aplicación para 1.2 , o para 1.0 , pero no para 1.1 El truco para permitir instalar aplicaciones para Series60v2.0 es tomar Series60v2.0.sis desde un Nokia 7310 y usarlo en vez de, por ejemplo, Series60v1.0.sis. Esto hace que no se puedan instalar las aplicaciones específicas para v1.0 pero creo que hay pocas que necesiten exactamente esta versión. Cuando compilas tu propia aplicación, necesitas un fichero *.pkg en el que indicas la versión mínima que necesitas de sistema operativo. Por ejemplo (0x101F6F88), 0, 0, 0, {"Series60ProductID"} dice que necesitas que previamente esté instalado el fichero con UID 0x101F6F88 Este UID son los primeros 4 bytes presentes en el fichero Series60v0.9.sis Si los cambio, la aplicación anterior no se podrá instalar. Por ejemplo, una aplicación puede necesitar que una DLL en particular esté instalada, o que sólo funcione en un modelo de móvil. El fichero SiemensSX1.SIS comienza con los bytes 0x101F9071 Así, si quisiera hacer una aplicación que sólo funcione en el SX1, debería incluir en el *.pkg esta línea: (0x101F9071), 0, 0, 0, {"Series60ProductID"} Pero para hacer que el SX1 parezca como Series60v2.0 no sólo hay que cambiar el nombre del fichero Series60v1.0.sis por Series60v2.0.sis ; sino que también hay que cambiar el contenido. Por tanto, busco en toda la flash la cadena "Series60v1.0.sis" y la cambio por "Series60v2.0.sis" y también 0x101F6F88 (UID del Series60v1.0.sis) por 0x101F7960 (UID del Series60v2.0.sis) Tras aplicar los cambios en mi móvil pruebo a instalar una aplicación específica para Nokia 7310 , y veo con deleite que se deja instalar. Si funciona o no, eso es otro asunto. Lo meto en un fichero, le pongo una explicación indicando su peligrosidad, y ya está listo para publicar. Mañana será otro día. 30/09 *********** Viernes *********** En vista de que puedo hacer parches, recibo unas cuantas sugerencias para desarrollarlas. Lamentablemente no tengo todos los conocimientos que necesitaría, además de la falta de tiempo. Por eso, ni siquiera investigo las peticiones que sólo vienen de 1 persona. También rechazo algunas que sé que son imposibles. Por ejemplo, hay gente empeñada en instalar Symbian 8.0 en el SX1. Eso es totalmente imposible. El hardware necesario no está dentro del SX1, por no mencionar que necesitaría mas potencia, y más memoria. Esto me recuerda cuando la gente del Commodore querían crear un emulador del Amstrad. Tambien recibo un par de ofrecimientos para ayudarme a hacer parches. Les indico las herramientas y conocimientos que necesitan, y se ponen en marcha. Espero que sea fructífero. Algunas de las peticiones son para eliminar más mensajes inútiles. Además de los de la instalación, y los de cambiar la tarjeta MMC, quieren que elimine el que aparece cuando bloqueas el teclado. Estoy de acuerdo; es bastante molesto. Hay otro que me gustaría eliminar: cuando la batería se llena de nuevo, el teléfono se enciende y emite un pitido breve. Como ésto suele suceder de noche, me despierta, lo cual me irrita mucho. Pero este segundo parche es mas difícil de probar, ya que cuando la batería está rellena, hay que descargarla un poco antes de que se recargue de nuevo. Como ya he dicho, la solución sería encontrar dónde está el texto que aparece dentro del mensaje, y eliminar la llamada a la rutina que muestra el mensaje. Pero hasta ahora no he encontrado estos textos. Así que voy con el primero, para eliminar el mensaje cuando bloqueas el teclado pulsando la tecla "#" durante más de 1 segundo. Lo primero que encuentro es que hay un fichero llamado AknNotify.Std.h que incluye una enumeración TKeyLockNotifierReason con los valores: ELockEnabled ELockDisabled EAllowNotifications EStopNotifications EInquire EOfferKeylock ECancelAllNotifications éstos son los valores 0-6 Despues están struct SAknSoftNoteNotifierParams { TInt iNoteResource; TInt iNoteCbaResource; TInt iResponse; }; struct SAknKeyLockNotifierParams { TKeyLockNotifierReason iReason; TBool iEnabled; }; Lo cual me lleva a hurgar en los ficheros AknNotify.dll y AknNotifyPlugin.dll Un poco de investigación me lleva a la conclusión de que AknNotifyPlugin.dll acaba llamando a CAknNoteDialog Elimino la llamada, pero entonces pierdo todas las notificaciones. Demasiado. Pero no me cuesta mucho encontrar una subrutina que hace uso de una estructura de 3 int , lo cual podría ser SAknSoftNoteNotifierParams. En realidad es más fácil: el mensaje de que el teclado está bloqueado aparece, y al cabo de 1 segundo y medio desaparece automáticamente. Como 1 segundo y medio son 1.500.000 microsegundos, es decir, 0x0016E360 , busco este dato, el cual aparece 6 veces. Lo cambio cada ocurrencia por un valor distinto, desde 3 segundos hasta 9. Meto el firmware modificado, bloqueo el teclado, y veo que tarda 4 segundos en desaparecer. Ya sé cual es la rutina involucrada. Así que en la rutina original LDR R1, =0x16E360 MOV R2, #0 BL CAknSleepingNote::ShowNote_CAknNoteDialog(TTimeout CAknNoteDialog,TTone) elimino la llamada al diálogo. También podría reducir el tiempo a 0.001 segundos, pero ésto no me parece tanelegante. Como veis, siempre hay más de una manera de atacar al problema. Estoy asombrado de mí mismo: he hecho 4 parches en 4 días. 31/09 *********** Sábado *********** Septiembre solo tiene 30 días, hombre ! 01/10 *********** Sábado *********** Otro de los parches más solicitados es el de borrar la línea horizontal. En el SX1, si no estás en ninguna aplicación, vuelve a la aplicación llamada Phone.app que muestra la pantalla en 4 trozos: 1) el superior, con el indicador de potencia de red, carga de batería, mensajes pendientes, infrarrojos activado, ... ocupa 14 pixels. 2) el segundo, donde muestra un reloj, el proveedor de red, y la fecha. Se puede poner un dibujo de fondo. Ocupa 54 pixels. 3) el tercero, con un dibujo de fondo a elección del usuario. Ocupa 120 pixels de altura, más o menos. 4) el de abajo, con el texto de OK y el de NO. ES posible cambiarlos para que arranquen cualquier aplicación. Ocupa 16 pixels. Así que es posible hacer un dibujo de fondo de 54+120 dividido en 2 trozos. Lo malo es que entre ambos se dibuja una línea horizontal de 1 pixel de grosor, que destroza el efecto visual e impide poner bonitos dibujos de fondo. Lo que han conseguido otros antes que yo es cambiarle el color. La pantalla ocupa 172 pixels de ancho. En Symbian estan soportados varios modelos de pantalla: monocromo, 4-bits por pixel, 8-bits, 12-bits, o 24-bits. La mayoría de los dispositivos Symbian tienen como mínimo 12-bits, lo cual permite 4096 colores. El SX1 soporta 65536. Es posible definir tu propio color, o usar una paleta de 256 colores. Esto permite tener distintos "esquemas" para el escritorio. Por defecto existen 4 esquemas, pero hay un parche para usar 6. Esta paleta define colores para el borde de las ventanas, el texto, el texto de un control, el texto de una advertencia, el texto de un error, el título de la aplicación, el título de un diálogo, el menú, ... y así hasta 60 colores distintos. El resto, hasta 256, están libres. Todo ésto definido en gulcolor.h Uno de estos colores es el que se usa para dibujar la línea horizontal, en concreto la entrada 0xF4 de la paleta. Así que empiezo a buscar ese dato en la aplicación desensamblada Phone.app Aparece muchas veces, así que tengo que refinar la búsqueda para que esté cerca de algo que dibuje una línea. Imagino que la rutina será algo parecido a: SetColor(0xF4); DrwaLine(0,54,172,54); Así que refino más todavia la búsqueda para que una de las coordenadas sea 54, o bien 54+14 Encuentro la rutina adecuada, veo que tiene sentido, y decido que no llame a la rutina de dibujar la linea. Efectivamente no dibuja la línea, sino que en la coordenada y=54+14 deja el dibujo que estuviera anteriormente. Ahora tengo que conseguir que la imagen 2) ocupe 54+1 pixel, o bien que la imagen 3) se dibuje un pixel más arriba. Lamentablemente no encuentro dónde se hace, y tras aproximadamente 15 pruebas, decido dejarlo para otro momento. Esto es frustrante. Pierdo un montón de tiempo, y no obtengo nada. Pero por otra parte es normal. ?Dónde encuentras las llaves que has perdido? En el último sitio en el que buscas. Claro; porque una vez encontradas, dejas de buscar. Si hubiera encontado pronto la solución no habría perdido tanto tiempo. A pesar de todo decido publicar un parche, por si alguien quiere seguir mis investigaciones. También sería posible hacer una aplicación que cada 5 segundos mire si Phone.app está en primer plano, y en ese caso tomar el control, dibujar la línea horizontal que quiera el usuario, y devuelva el control, sabiendo que Phone.app no la sobre-escribirá. Pero sería un programa extra, que usaría la batería inútilmente. 02/10 *********** Domingo *********** Hoy toca cambiar los muebles. Me niego a poner cosas de IKEA. Aunque compres un único mueble, ya toda la casa parece hecha en IKEA. Es como un virus. Pero ésto es lo único en que yo no transijo. Lo demás, me suele parecer bien lo que mi chica disponga. Eso sí, el cuadro de Modigliani no hay que ponerlo cerca del de Munch. Acabamos cansados, pero la casa parece otra. Lista para el invierno. Un consejo: si cubres el techo con telas, parece más bajo y mas acogedor. Pero también más oscuro. 03/10 *********** Lunes *********** Los parches siguen creando expectación. Lo que me sorprende es que no haya más gente que los haya hecho. Para otros modelos de Siemens hay un montón de desarrolladores. Claro que el sistema de estos otros es distinto, y no es muy difícil adaptar un parche de un modelo inferior hacia otro superior. Pero el SX1 pertenece a otra familia conceptualmente distinta. Cada vez me voy dando más cuenta de que necesito una herramienta que me permita saber por dónde se va ejecutando un programa. Para el modelo S45 hice un emulador que me resultó realmente útil (e interesante) así que pienso en hacer lo mismo para el SX1. Busco por la red algún debugger para Symbian o para ARM, pero no encuentro nada que se adapte a mis necesidades. Un emulador de las instrucciones de ARM es sencillo, ya que apenas hay 20 instrucciones y son fáciles de codificar. El sistema de memoria tampoco es complicado, excepto cuando accede a los puertos, la pantalla, el SIM o la MMC. Pero no necesito tanto: simplemente hacer un volcado de la memoria del programa en ejecución, incluyendo la pila, y luego emular el programa en el PC. En Symbian cada programa se ejecuta en un entorno protegido, y siempre parece que está en la dirección 0x00400000. Puede llamar a otras rutinas a través de referencias (stubs), pero no puede leer memoria que no le pertenece. La excepción a ésto es el kernel, ubicado en ekern.exe , que puede leer y escribir cualquier dirección, ya que se ejecuta en modo supervisor. Para que una aplicación pueda saltar más alla' de sus límites, debe pasar por las funciones de la librería User, que llamarán al kernel. Otra posibilidad es usar un PDD (Physical Device Driver) o un LDD (Logical Device Driver), que tienen acceso a cualquier dirección de memoria. Un tercer modo es llamar directamente a una interrupción, que llamará al kernel directamente. Voy a explicar la tercera opción: La instrucción SWI interrupt_number hace que el kernel salte a 0x5000B0D8 ArmVectorSwi que salta a la dirección 0x5000AD24 + 4*interrupt_number Por ejemplo, SWI 0xCD mirará el dato de 0x5000AD24 + 4*0xCD=0x5000B058 que vale 0x5001B8D4 y el código código ubicado en esta dirección hace algo muy simple: MVN R0, #4 RET lo que indica que no ha sido procesado satisfactoriamente, con lo que la aplicación que ha invocado esta interrupción posiblemente será terminada. Pero puedo cambiar ese trozo de código para que haga mas cosas, por ejemplo: org 0x5001B8D4: MOV R12, [R12] MVN R0, #0 ; todo ha ido satisfactorio RET Posiblemente no entiendas el sentido de la primera instrucción, así que te diré cómo voy a llamarlo: ---- prueba.c -- .... int valor=0x50000000; asm volatile ("MOV r12, %0" : : "r"(valor) : "r12" ); asm volatile ("SWI 0xCD" : : : ); asm volatile ("STR r12, %0" : "=m"(valor) ); paso a paso: -la primera línea indica la dirección de memoria que quiero leer, por ejemplo 0x50000000 -la segunda pone ese valor en R12 -la tercera llama a la interrupción, que acabará llamando a 0x5001B8D4 -en 5001B8D4, r12 tomará el valor de la dirección 0x50000000, por ejemplo 0xEA000086 -al retornar, la tercera línea lo pondrá de nuevo en la variable "valor" , con lo que la puedo mostrar en la pantalla de mi aplicación Esto parece una manera complicada de leer la dirección 0x50000000, pero es que se necesita pasar a modo supervisor. He usado el registro R12 por una razón: los registros R0, R1, R2, R3 son comúnmente usados en las rutinas, y si alguna otra interrupción sucede mientras la mía se esta procesando, casi seguro que machacarán estos registros. En cambio R12 apenas se usa a lo largo del código. Parece ser que los desarrolladores andaban sobrados de registros, y no lo necesitaban. Con esto aprovecho para hacer volcados de varios trozos de memoria. Hay un grave inconveniente: si leo una dirección que no está definida, el móvil se resetea. Por ejemplo, la dirección en 0x60000000 no existe físicamente, por lo que al intentar leerla, peta el móvil. No me queda mucho tiempo para probarlo, pero es un gran paso. 04/10 *********** Martes *********** Hoy he hecho volcados de: 0x50000000-16Mg = código de los programas 0x50F00000-512 Kb = tabla de rutinas exportadas 0x58000000-32 Kb = pantalla? 0x5800A000-4 Kb = tabla de interrupciones hardware? 0x80000000-32 Kb = programa en ejecución? 0x80400000-32 Kb = stack de otros programas en ejecución? 0x81500000-32 Kb = pila de otros programas en ejecución? 0x80400000-32 Kb = otros programas en ejecución? 0xFF800000-4 Kb = memoria DMA de dispositivos? Pero tendré que analizar con más detalle todos estos volcados, porque no estoy seguro de su significado. Lo que estoy convencido es que acabaré encontrando un modo de volcarlos todos, y hacer una copia exacta de la memoria. Mientras tanto, tengo que seguir buscando un emulador de ARM, con su código fuente. A ser posible, que sea sencillo de entender. 05/10 *********** Miércoles *********** Parcheando uno de los programas del móvil (Calculator, con UID=0x10005902) con el truco de llamar a SWI, he conseguido una imagen, tal como se estaba ejecutando. Lo he seguido a mano, con la ayuda del código desensamblado (no tengo un debugger) y creo que la copia es bastante buena. De paso he encontrado otros bloques de memoria que a los que accede el programa, y que también he tenido que volcar. El tema del debugger se podría solucionar con un JTAG, que es un protocolo usado para debuggear dispositivos ARM. Se conecta el dispositivo con el PC, se arranca el programa, se pone el móvil en modo "debug", y a partir de ese momento se puede tracear exactamente lo que está pasando paso a paso. Se pueden poner breakpoints, condiciones complejas, mirar la memoria, modificarla. Pero necesito un cacharro de hardware para eso, y los que hay son un poco caros. Hay un proyecto en sourceforge para hacerlo, pero como yo no tengo ni idea de electrónica, tendré que pedirle a alguien que lo construya para mí. 06/10 *********** Jueves *********** Hoy hemos sacado unos billetes para irnos a Croacia, a ver si nos da un poco el sol. Salimos por la tarde y no volveremos hasta el Lunes. Creo que no me las merezco, pero sin duda me sentarán bien. Me da el tiempo justo para publicar el parche que elimina el mensaje de bloqueo de teclado, pues me doy cuenta de que se me había olvidado anunciarlo. 07/10 *********** Viernes *********** 08/10 *********** Sábado *********** 09/10 *********** Domingo *********** 10/10 *********** Lunes *********** 11/10 *********** Martes *********** La gente está bastante entusiasmada con los parches. En la web SMO apenas llevo 10 mensajes, y ya tengo 20 puntos de karma. Es para estar orgulloso, ?no crees? Incluso gente que manda 3/4 mensajes por día no tienen más de 15 puntos de karma, y los más antiguos tienen 30 , excepto los administradores y el mega-jefe, que tienen 70 . O todos los que quieran darse, claro. Y en la web de CS se habla de hacerme Maestro, título para el que normalmente se necesitan más de 100 mensajes y mínimo 6 meses de antiguedad. Esto demuestra varias cosas: -cada esfuerzo tiene su recompensa -la gente es agradecida -las reglas están para saltárselas -la suma de los ángulos de un triángulo suman PI Tengo un poco de tiempo para revisar las peticiones de parches. Uno de los mas útiles parece ser uno para reducir la intensidad de la luz. 12/10 *********** Miércoles *********** El Sx1 tiene 2 zonas de iluminación: la pantalla y el teclado. Estas luces se encienden cuando pulsas cualquier tecla o cuando el móvil muestra un mensaje, y se apagan al cabo de 20 segundos de inactividad. Lamentablemente no existe un programa para apagarlas antes, ni siquiera para reducir la intensidad de la luz. Esto está incluido en los otros modelos de Siemens, así que supongo que la pantalla del SX1 es distinta y no permite graduar la luminosidad, o bien Symbian no tiene rutinas para hacer esto. Pensando un poco veo que no puede ser lo primero, ya que cuando la pantalla se va a apagar, no lo hace de golpe, sino gradualmente. Esto quiere decir que la pantalla sí que soporta distintos niveles de intensidad. Y también Symbian lo permite, ya que es posible hacerlo en los Nokia. Entonces, la única razón es que los ingenieros del SX1 decidieron no incluir el programa. Es una pena, porque si se consiguiera bajar la intensidad, seguro que la batería duraría más. Investigando el código desensamblado del kernel veo que hay unas rutinas que ponen datos en 0x5800E000. Esta dirección la he visto en U-boot, que es un intento de instalar Linux en dispositivos ARM, el cual espero investigar con detalle. En particular, 0x58000000 contiene un montón de punteros a datos DMA compartidos entre la pantalla y la memoria, según dice el manual del DMA. En el kernel symbian, la zona a partir de esta dirección se usa en una rutina que obtiene el dato de algo llamado Sofia. Buscando por la red he descubierto que Sofia es un chip que se encarga de proporcionar acceso a dispositivos externos, para procesadores de bajo consumo, por ejemplo ARM. Parece que voy por el buen camino. Al menos tiene sentido lo que estoy averiguando. El funcionamiento es sencillo: se pone un dato en una cierta dirección de memoria, y Sofia se lo manda al dispositivo. O sea, que 0x58000000 es una zona de memoria de intercambio, y 0x5800E000 es la parte referente a la pantalla. Ahora bien, ?cual es el dato? ?y cual es la dirección de memoria que almacena la intensidad? Hago un volcado de 4Kb a partir de 5800E000 cuando la pantalla está apagada. Hago otra copia cuando la pantalla está encendida, y anoto las diferencias. Repito la prueba varias veces. La diferencia es que hay 2 datos seguidos con valor #0x2B, en la dirección [5800E000+#0x2A] y [5800E000+#0x2B]. Notar que el valor #0x2B no tiene nada que ver con que sea la dirección [5800E000+#0x2B]. Es pura coincidencia. El código que lo inicia hace algo así: .... LDR R4, =0x5800E000 .... MOV R3, #0x2B STRB R3, [R4,#0x2A] STRB R3, [R4,#0x2B] .... BL TSofiaSX1::WriteReq .... El equivalente en lenguage C sería algo así: int *p=0x5800E000, i=0x2B; p[0x2A]=i; p[0x2B]=i; TSofiaSX1::WriteReq(p); Ya sé que es muy peligroso cambiar un valor sin estar seguro de lo que hace, pero tras mucho estudio me arriesgo y cambio MOV R3, #0x2B por MOV R3, #0x10 Inicio el móvil, y veo que ahora la pantalla apenas se ilumina. Y tampoco el teclado. Deduzco que [0x5800E000+#0x2A] guarda la intensidad de la pantalla, y [0x5800E000+#0x2B] la del teclado. Así que para poner la pantalla al 70% uso el valor 0x2B * 0.7 = 0x1E Y para dejar el teclado al 20% de intensidad uso 0x2B * 0.2 = 0x8 La rutina queda MOV R3, #0x1E STRB R3, [R4,#0x2A] MOV R3, #0x08 STRB R3, [R4,#0x2B] Otro parche listo para ser publicado. Me gustaría ver si de verdad se nota el ahorro de batería, pero esto necesitaría varios dias de pruebas, y prefiero compartirlo, para que otros usuarios también opinen. Lo que me sería perfecto es hacer un parche para poder cambiarlo dinámicamente, pero por ahora me vale que se pueda meter en la flash permanentemente. 13/10 *********** Jueves *********** He encontrado que hay un driver llamado edosyin.ldd que incluye una llamada a la rutina anterior, por lo que quizás podría cargarlo y llamar a una de sus rutinas para que haga todo el trabajo por mí. Recordar que no puedo llamar directamente a la rutina de poner la intensidad debido a que hay que inicializar unas variables privadas, y necesitaría hacerlo desde modo supervisor. En cambio un driver de tipo ldd (Logical Device Driver) funciona de la siguiente manera: -se define el nombre del driver, sin extensión #define LDD_NAME_WRITE _L("edosyin") -se carga TInt r = User::LoadLogicalDevice (LDD_NAME_WRITE); puede devolver un error, pero si tiene éxito devuelve valor 0 -declarar un objeto RDevice dev_write; -averiguar el nombre lógico del driver En mi caso es "DosPlugInLdd" . Lo he averiguado mirando el fichero edosyin.ldd -abrir el RDevice r=dev_write.Open(_L("DosPlugInLdd"),EOwnerProcess); -instanciar un canal lógico chan_write=dev_write.GetLogicalChannel(); -llamar a la función DoRequest chan_write.DoRequest( numero_servicio, datos_entrada, datos_salida) Todo esto está explicado en http://www.symbian.com/developer/techlib/v70docs/SDL_v7.0/doc_source/ en el apartado "Base Porting Guide and Reference->Device drivers->model" pero es la típica explicación que sirve sólo después de que has resuelto el problema. Ahora la gracia está en encontrar los valores de estos parámetros Desensamblando edosyin.ldd he visto que cuando numero_servicio=2 entonces llama a la rutina de cambiar la intensidad. El valor de datos_entrada es un descriptor con un entero que contiene el valor de la intensidad de la luminosidad. Esto merece una explicación: en symbian, como en casi cualquier otro sistema operativo, existe una zona de datos privada a cada programa. Para que este dato pueda ser leído por otro programa (en particular, el kernel) hay que ponerlo en una zona compartida. Esto se hace reservando memoria en la pila, y obteniendo un puntero a la dirección del dato. Pero hay más: lo que reservamos es un objeto. Un objeto se compone de 2 partes: -un dato que indica el tipo: String, TInt, Class, Exception, RFile, RDevice, ... -otra parte con los datos en sí HBufC* data=HBufC::New(40); // reserva un objeto, consistente en 40 bytes TPtr ptr=data->Des(); // puntero a los datos strcpy(ptr, "+++++" ); Ahora ya puedo llamar a chan_write.DoRequest( 2, data, data); He usado el mismo puntero para los datos de entrada y de salida porque sé que no se modifican. Como he dicho, el valor de data depende del servicio. En particular el servicio 2 incrementa la luz en 1 unidad por cada vez que aparece el signo "+" en datos_entrada. Si escribo "+++++" entonces la intensidad sube en 5 unidades. Lo que más difícil me está resultando de Symbian es la verificación de tipos. Si defino una variable como char data[]="+++++"; el compilador no me deja usarla en chan_write.DoRequest() porque necesita exactamente un puntero a un descriptor. Yo sé que es lo mismo, pero como los tipos no coinciden, el compilador se queja. A decir verdad, pierdo más tiempo buscando los tipos correctas, que probando mi programa. Pero al final consigo que funcione. El documento clarificador es "Descriptors" escrito por Tim Band, Technical Architect for Text and Internationalization, de Symbian. Lamentablemente compruebo que aunque los datos se ponen correctamente, al cabo de 5 segundos se resetean al valor por defecto, así que esto no me vale para establecer dinámicamente el valor de la intensidad. Tendré que buscar otro método. Hoy hay otra vez cursillo sobre vinos. Iremos a una enoteca. A ver si somos capaces de volver por nuestro propio pie. 14/10 *********** Viernes *********** Existe otro driver etestserver_ldd.ldd que es mucho más atractivo, pues invoca a funciones tales como leer/escribir los puertos serie/infrarrojos/USB/Giga/ Pantalla/Flash/SIM Pero nada más cargar el driver, el teléfono se resetea. !Ni siquiera he podido cargar el canal lógico ! Encuentro otro programa TestSvr.exe que promete bastante, pues también llama a funciones interesantes para verificar la cámara, Bluetooth, Radio, teclado, IPC y Pantalla. Pero cuando lo ejecuto no presenta un interface gráfico. En symbian existen 2 tipos de programa: -exe, sin interface gráfico. Se suelen arrancar cuando se enciende el teléfono, y nunca se cierran. Sirven como servidores. Por ejemplo: wimcertsrv.exe , LogServ.exe, EDbsrv.exe -app, con elementos gráficos. Suelen ser iniciados manualmente por el usuario. Usan los servicios ofrecidos por el servidor. Por ejemplo: ClockApp.app, SmsEditor.app, Calendar.app En ambos casos un programa sólo puede estar ejecutándose una vez. Cuando lo inicias de nuevo, en lugar de iniciarlo, muestra la otra instancia que se está ejecutando. Esto tiene sentido para un exe, porque sólo hay un servidor que crea una cola para atender las peticiones, y no puede procesar una hasta que no ha acabado con la anterior. Pero para un app, esto impide que puedas tener la misma aplicación abierta 2 veces. Estoy de acuerdo que la pantalla es pequeña, pero me gustaría tener 2 veces la agenda por si quiero saber lo que tengo que hacer hoy y también mañana. La manera de evitar 2 instancias del mismo programa es a través del UID. Cada fichero (de tipo app y exe) tiene una cabecera, uno de cuyos datos es un identificador único. Cuando se pretende iniciar una aplicación, el kernel mira en su lista de procesos para ver si ya está ejecutándose uno con el mismo UID. Si no es así, continua la carga. El UID también sirve para reinstalar una aplicación, en vez de instalarla 2 veces. Cuando se pretende instalar una aplicacion, el kernel mira en su lista de "aplicaciones instaladas" para ver si ya está instalada una con el mismo UID. Si no es así, continua la instalación. Otro sitio donde se usa es en el menú. Esto es una aplicación con los iconos de todas las aplicaciones instaladas en c:\system\apps\ y e:\system\apps\ También incluye algunas aplicaciones que están en Z:\system\apps\ Cuando programas una nueva aplicación hay que darle un UID único. Si hay otra aplicación con el mismo UID, el menú (y el instalador) puede confundirlas. No se puede instalar en C: una aplicación con el mismo UID de otra de Z: 15/10 *********** Sábado *********** Sigo intentando cargar drivers, pues creo que me abrirán la puerta al kernel. Hay uno llamado PowerMeasLdd que llama a funciones tales como: THelen::ReadReg - para leer un registro del coprocesador (usado, entre otros, para la red GSM) ImpHal::GetIbootChunk - para leer la memoria usada durante la inicialización del móvil THelen::SetCLKMReg - para definir el reloj interno THelen::ModifyMmcReg - para acceder a la tarjeta MMC El driver se carga correctamente, pero el significado de los datos es un misterio para mí. Las pruebas con GetIbootChunk funcionan, pero lo único que consigo leer son datos que ya conocía porque anteriormente he volcado toda la memoria Flash. Al usar ReadReg leo algunos valores, pero desconozco su significado. En este sentido la documentación de ARM no me sirve, y necesitaría la del fabricante de los dispositivos. Intentaré encontrar algo en Internet. Algunas de las pruebas resetean el móvil, y me entra un poco de miedo de romper el móvil. Al principio he dicho que tengo 7 móviles iguales, así que no me importa romper 1 ó 2. Pero prefiero andar sobre seguro antes de hacer pruebas a lo loco. Este interés por el kernel obedece al hecho de que quiero entender el modelo de memoria para hacer una copia exacta de la memoria en tiempo de ejecución. Recordaréis que en un artículo anterior hice un emulador para el móvil S45 que me permitía ejecutar exactamente los mismos programas que el móvil real, y debugearlo desde el PC. Pretendo hacer lo mismo para el SX1. El objetivo no es sólo éste móvil Siemens, sino que he leído que Symbian está instalado en el 40% de los móviles Nokia, y Nokia tiene el 25% de cuota de mercado. Por consiguiente cualquier averiguación se aplicará sobre los Nokia, incluida la N-Gage. Otros modelos incluyen el P800 de Ericsson y Sendo. Al parecer el mercado de sistemas operativos para móviles se reparte entre Symbian (25%), Microsoft (20%) y el resto son sistemas propietarios de cada fabricante. Algunos incluyen Linux, pero sólo la parte gráfica. El módulo de comunicaciones GSM y control de dispositivos es privado y secreto. 16/10 *********** Domingo *********** Hoy he tenido que ir a trabajar. Tengo que actualizar una aplicación en todos los ordenadores de la empresa, y no quiero que nadie me moleste. La instalación es automatizada, pero debo encender todos los ordenadores. Y apagarlos al final del día. Podría pasarme el día navegando porque nadie me vigila, pero lo único que hago es publicar el parche de reducir la luminosidad. Al cabo de 5 horas el trabajo está terminado, así que me queda tiempo para ver lo que la gente opina del parche para reducir la luminosidad que publiqué hace un rato . Al parecer ha sido un éxito. En todos los foros ha tenido gran aceptación. En CS van a juntar todos los parches y sacar una versión especial de la flash. Tambien incluirá nuevos iconos hechos por gente del foro. Esto tardará al menos un mes, así que espero que me dé tiempo para hacer otros parches. Por lo pronto, hoy invitamos a unos amigos y les sometemos a una sesión de visionado de fotos de vacaciones. Como contraprestación les damos los regalos que les hemos comprado. 17/10 *********** Lunes *********** He recibido una petición para hacer un parche concreto. En el móvil viene incluida una aplicación para grabar sonido. Es bastante útil para grabar notas de voz. Otro uso que tiene es grabar la conversación mientras hablas por telefono. Así se pueden evitar esas discusiones de tipo "pero tú me dijiste que..." Lo malo es que sólo permite 2 minutos, y cuando grabas una conversación emite un pitido inicial que se oye al otro lado, con lo que tu interlocutor sabe que le estas grabando. Aprovecho para decir que en España esta prohibido grabar conversaciones sin permiso. Incluso las tuyas propias. Aunque no tenga que ver, me gustaría comentar algo que vi en un capítulo antiguo de la serie de televisión CSI. Encuentran un móvil de la víctima, con la batería gastada. Lo llevan al laboratorio y reproducen la última conversación. No sólo éso, sino que eliminan la conversación y se quedan con el ruido de fondo. Aplican un filtro y averiguan que es el sonido del motor de un coche. Deducen el modelo de coche. Cuando lo ví, me partía de risa. Primero: la conversación transmitida por GSM se realiza a unos 22Kbits/segundo. Una conversación de 1 minuto ocuparía aproximadamente 100 Kb. Pocos móviles en 2001 tienen una memoria capaz de almacenar tanto. Segundo: en GSM la voz se codifica y se divide en paquetes, los cuales se mandan por la red. Una vez que un paquete se ha recibido al otro lado, no tiene sentido guardarlo. En todo caso, sería la red quien lo podría almacenar (por orden judicial previa a la conversación). Tercero: los datos van cifrados. Este cifrado cambia con el tiempo, y es de clave simétrica. Para descifrarlos hay que tener la clave de ambos móviles y de la red, los cuales son desconocidos para un móvil en solitario. Cuarto: cuando al móvil se le acaba la batería, se apaga. La única manera de guardar los datos es en una memoria estática. Pero recordar que la batería se ha acabado, así que no hay manera de hacer nada más que el procedimiento de emergencia: un pitido, y poco más. Quinto: un móvil tiene un filtro por hardware para oir sólo sonidos pronunciables por un humano. Los sonidos demasiado graves o muy agudos no los capta. Y el ruido de un motor es bastante grave. Sexto: el micrófono de un móvil esta diseñado para oir sonidos cercanos, a unos 10 centímetros del auricular. El ruido de fondo ni siquiera es detectado. Séptimo: la voz se digitaliza, eliminando los picos de sonido. Esto produce una muestra homogénea. Luego se digitaliza incluyendo los parámetros usados para el filtrado. La reproducción efectuada al otro extremo tiene una calidad entre el 70% y el 90%. Si tuviera más, indicaría que el filtro no es eficaz, pues no ha sido capaz de comprimir los datos. En resumen, que los móviles nunca graban las conversaciones, y es imposible escuchar un motor como ruido de fondo. A menos, por supuesto, que cuentes con la magia de la televisión. 18/10 *********** Martes *********** El parche de la luminosidad tiene un lugar destacado en el foro de oslik. Ya hay quien está intentando modificarlo para que se pueda hacer dinámicamente. Yo ya no lo voy a intentar hasta que entienda un poco más. En cambio trabajo en el parche de aumentar la duración de la grabación de voz. El tiempo es de 2 minutos, así que son 2*60=120 segundos, es decir, 120.000.000 microsegundos. Pasado a hexadecimal, es 0x7270E00 Convertido a little-indian, resulta 000E2707 Busco este dato y lo encuentro en Z:/System/Libs/bt.prt Z:/System/Libs/satcli.dll Z:/System/Libs/sdp.exe Z:/System/Libs/VOICERECORDERRECVIEW.DLL Z:/System/Programs/SplashScreen.exe A ver, ?cuál eligirías tu? Claro, VOICERECORDERRECVIEW.DLL El nuevo valor será 000E2747 que significa 0x47270E00, o sea, 1.193.741.824 , unos 20 minutos. Parcheo la flash, reemplazando 000E2707 por 000E2747, pruebo a grabar, y me deja 20 minutos, más que suficiente. Analizando esta misma aplicación veo que hay algo llamado PlaySoundIfCallActive que invoca a otra rutina externa de nombre PlaySound. El parámetro R1 es 0x45 . Lo cambio y compruebo que efectivamente cambia el tono del pitido inicial. Verifico que sólo se llama desde este punto, y con mucho cuidado anulo ésta llamada. Meto el parche, grabo una conversación, y ya no se oye el pitido. Otro parche para la colección. 19/10 *********** Miércoles *********** Hoy he recibido la grata noticia de que los chicos de oslik estan intentando meter Linux en el SX1. Me han pedido colaborar con ellos. Yo no sé mucho del hardware físico del móvil ni los dispositivos, pero supongo que podría espiar el código de Symbian, y traducirlo a Linux. Lo primero que me han informado es que van a usar algo llamado U-boot. Esto es un cargador de Linux para procesadores ARM. Inicialmente basado en el proyecto PPCboot, la parte específica para ARM se ha pasado a llamar ARMboot. Simplemente es un cargador que inicializa el sistema de memoria, los puertos y las interrupciones. Lo que pase después de esto es independiente del SX1, y sólo tiene que ver con el kernel de Linux, que en este caso sabe bastante poco de modelos de memoria y de puertos. Y para otros dispositivos hay que crear módulos. Como ellos ya tienen algo funcionando, lo instalo en el móvil para ver si funciona. Pero como quiero estar seguro de lo que hago, me tengo que leer unos cuantos manuales antes de empezar a trastear. 20/10 *********** Jueves *********** Antes de instalar Linux en el SX1 tengo que meterlo en mi ordenador. La última vez que me actualicé Linux tenía el kernel 2.4 pero necesito el 2.6 Así que decido instalarlo desde cero. Esto llevará tiempo. 21/10 *********** Viernes *********** Sigo instalando. 22/10 *********** Sabado *********** Ya he instalado todo. Una de las cosas que necesito es el compilador cruzado para ARM. Básicamente, permite compilar en el PC aplicaciones que se ejecutarán en otro procesador. Pero hay que definir muy exactamente cuál es el otro procesador. Se empeña en usar PPC, no ARM. se ve que PPC es la configuración por defecto. No es fácil de hacerlo funcionar, pero más o menos lo he conseguido. Ha sido imprescindible la ayuda del documento "Embedded Linux on OMAP1710 SDP (H3 board)" hecha por Magnus Aman, de Texas Instruments. Ahora hay que construir un kernel 2.6.13 para OMAP0310, con procesador ARM925Tid (ARMv4T) 23/10 *********** Domingo *********** Construir el kernel para otro procesador cuesta un rato. Además da un montón de fallos que no sé si son importantes o no. El documento básico es: U-Boot for the OMAP16xx GSM/GPRS Software Development Platform Luego, el proceso típico de comprimir el kernel, mkimage, y por último transferirlo. Para esto hay que entrar en el SX1 en modo "meter nueva flash", que espera a que se le manden los datos por USB. Yo uso kermit para transferirlo. Una vez terminada la carga, hay que iniciarlo con bootm. Tras unos cuantos intentos, por fin arranca ! Casi me caigo de la silla cuando lo veo! Cuando inicia, se ve algo así: Linux version 2.6.13.4-omap1 (root@linux) (gcc version 3.4.2) #70 Sun Oct 23 21:04:26 MSK 2005 <4>CPU: ARM925Tid(wb) [54029252] revision 2 (ARMv4T) <4>Machine: OMAP310 based Siemens SX1 <4>Memory policy: ECC disabled, Data cache writeback <4>OMAP0310 revision 2 handled as 15xx id: 65858c1d22451c1c <6>SRAM size: 0x30000 <4>Clocks: ARM_SYSST: 0x1000 DPLL_CTL: 0x3a33 ARM_CKCTL: 0x010d <6>Clocking rate (xtal/DPLL1/MPU): 12.0/120.0/120.0 MHz <7>On node 0 totalpages: 4096 <7> DMA zone: 4096 pages, LIFO batch:1 <7> Normal zone: 0 pages, LIFO batch:1 <7> HighMem zone: 0 pages, LIFO batch:1 <4>CPU0: D VIVT write-back cache <4>CPU0: I cache: 16384 bytes, associativity 2, 16 byte lines, 512 sets <4>CPU0: D cache: 8192 bytes, associativity 2, 16 byte lines, 256 sets <4>Built 1 zonelists <5>Kernel command line: mem=16M console=ttyS0,115200n8 root=/dev/mtdblock3 rw <4>Total of 64 interrupts in 2 interrupt banks <6>OMAP1510 GPIO hardware <4>PID hash table entries: 128 (order: 7, 2048 bytes) <4>Console: colour dummy device 80x30 <4>Dentry cache hash table entries: 4096 (order: 2, 16384 bytes) <4>Inode-cache hash table entries: 2048 (order: 1, 8192 bytes) <6>Memory: 16MB = 16MB total <5>Memory: 14672KB available (1111K code, 301K data, 72K init) <7>Calibrating delay loop... 59.80 BogoMIPS (lpj=299008) <4>Mount-cache hash table entries: 512 <6>CPU: Testing write buffer coherency: ok <6>Linux NoNET1.0 for Linux 2.6 <6>DMA support for OMAP15xx initialized <4>Initializing OMAP McBSP system <4>MUX: initialized W4_USB_PUEN <3>no usb0 alt pin config on 15xx <4>USB: hmc 0, usb0 3 wires (dev) <6>i2c_omap: rev1.0 at 100 KHz <7>i2c_adapter i2c-0: registered as adapter #0 <6>omapfb: configured for panel SX1 <6>OMAP LCD controller initialized. <4>Sofia write: 7 10 <7>i2c_adapter i2c-0: master_xfer[0] W, addr=0x32, len=2 <4>Console: switching to colour frame buffer device 44x36 <6>OMAP framebuffer initialized vram=131072 <6>omap_rtc: RTC power up reset detected. <6>omap_rtc: Enabling RTC. <6>io scheduler noop registered <6>io scheduler cfq registered <6>i2c /dev entries driver <7>i2c-core: driver dev_driver registered. <7>i2c_adapter i2c-0: Registered as minor 0 <6>udc: OMAP UDC driver, version: 4 October 2004 (iso) (dma) <6>udc: OMAP UDC rev 2.7 <6>udc: hmc mode 0, (unknown) transceiver <6>udc: fifo mode 3, 648 bytes not used <6>gs_bind: Gadget Serial v2.0 bound <6>gs_module_init: Gadget Serial v2.0 loaded <6>mice: PS/2 mouse device common for all mice <6>OMAP Keypad Driver <4>VFS: No root yet, retrying to mount root on mtdblock3 (unknown-block(0,0)) <4>omap-keypad: Spurious key event 0-3 <4>omap-keypad: Spurious key event 1-3 <4>omap-keypad: Spurious key event 2-3 <4>omap-keypad: Spurious key event 3-3 <4>omap-keypad: Spurious key event 4-3 <4>omap-keypad: Spurious key event 5-3 <4>omap-keypad: Spurious key event 6-3 <4>omap-keypad: Spurious key event 7-3 <4>omap-keypad: Spurious key event 0-3 <4>omap-keypad: Spurious key event 1-3 <4>omap-keypad: Spurious key event 2-3 <4>omap-keypad: Spurious key event 3-3 <4>omap-keypad: Spurious key event 4-3 <4>omap-keypad: Spurious key event 5-3 <4>omap-keypad: Spurious key event 6-3 <4>omap-keypad: Spurious key event 7-3 <4>VFS: No root yet, retrying to mount root on mtdblock3 (unknown-block(0,0)) Y esto es todo. Luego da un fallo y se queda colgado. Recordar que U-boot es un proyecto en estado alpha, y las adaptaciones para el SX1 todavía estan en pañales. Bueno, hay muchos detalles que se pueden extraer de este listado, pero serán objetivo de otro artículo. Debo decir que yo apenas he desarrollado nada para Linux-SX1, y mi tarea es analizar las rutinas y registros que se ponen en el sistema operativo Symbian, y traducirlas al ARMboot. En particular, tengo que sacar tramas del protocolo usado con la pantalla LCD, la tarjeta de memoria MMC, el teclado, y el chip de sonido. Esto lo hago sniffeando lo que pasa a través de la aplicación "Sofia", en particular la función TSofiaSX1::WriteReq A mí me interesa más la parte de GSM, pero ésto me dicen que llegará más tarde. Primero tenemos que conseguir un shell en el SX1. Notar que una vez que el kernel ha arrancado satisfactoriamente será posible ejecutar cualquier programa de Linux. Incluidas aplicaciones gráficas. Y también podremos empezar a cargar módulos para atacar a otros dispositivos, tales como infrarrojos, Bluetooth, DSP, o el E-Gold, responsable del interface GSM. El tema es apasionante, pero requiere más tiempo y esfuerzo del que tengo. He mirado otros móviles que funcionan con Linux, pero me ha sido imposible localizar el código fuente que usan. Me parece entender que el kernel es el estándar 2.6.13 pero el bootloader es específico para cada arquitectura de teléfono. Como entorno gráfico usan las librerías QT de Trolltech. 24/10 *********** Lunes *********** Entre unas cosas y otras he aprendido cómo funcionan las interrupciones de usuario en ARM. Lo explico porque es el corazón del sistema operativo. Existen varios modos de ejecución. El mas común es el modo de usuario. Las aplicaciones no pueden acceder a la memoria de otras, ni a recursos hardware. Si necesitan rebasar los límites tienen que llamar a las librerías User. Esta librería prepara los datos y llama al kernel haciendo uso de la instrución SWI. Existen 3 niveles de SWIs: -bajo, con un número entre 0x0 y 0xFE, por ejemplo SWI 0x4D -alto, con un número entre 0x800000 y 0x8000FE, por ejemplo SWI 0x80004E -ultra-alto, con un número entre 0xC00000 y 0xC000FE, por ejemplo SWI 0xC0006E Cuando se encuentra una de estas instrucciones, el procesador toma el dato de la memoria en la dirección 0x00000008 y salta a donde indique. En mi firmware ésto es 0x5000B0D8 Aquí hay una rutina llamada ArmVectorSwi que averigua cuál es la interrupción solicitada. A partir de la dirección 0x5000AD24 hay una tabla de direcciones de rutinas. Toma el valor, y salta a la rutina correspondiente. Vamos con un ejemplo: Creamos un objeto de tipo TChar TChar michar; lo convertimos a minúsculas: michar=User::LowerCase('B'); Observar que hemos llamado a una rutina de la librería User, por lo que generará una interrupcion. TChar User::LowerCase(uint) { asm("SWI 0x51"); } Ahora saltará al gestor de interrupciones en 0x5000B0D8, donde calcula: 0x5000AD24+4*0x51 vale 0x5000AE68 y en la dirección 0x5000AE68 está el valor 0x5001A340, equivalente a ExecHandler::LowerCase(uint) Así que salta a 0x5001A340, que simplemente usa una tabla para convertir 'B' en 'b'. Recordar que ahora estamos procesando una interrupción, por lo que estamos en modo supervisor, con control total sobre la memoria. Aquí me surge una duda: ?por qué Symbian hace e'sto con interrupciones, cuando lo podía hacer más simple sin ellas? Pues no lo sé. Quizás sea porque sea mas fácil que usar las librerías típicas stdio y string. Lo importante es que puedo parchear esta rutina para hacer lo que yo quiera, en modo supervisor. Por ejemplo, suponer que quiero leer la memoria 0x40000000 (que está protegida). Modifico la rutina org 0x5001A340: ExecHandler::LowerCase(uint) { if(R9==0x69) R9=*(0x40000000); Call ExecHandler::LowerCase_original(uint) } Y la invocacion sería: asm("Mov R9, 0x69"); michar=User::LowerCase('B'); asm volatile ("STR r9, %0" : "=m"(valor) ); Notar que confío en el hecho que R9 no se modifique entre medias. Si otra rutina intermedia (por ejemplo, el gestor de interrupciones ArmVectorSwi ) modifica R9, esto no funcionaría. En mis pruebas he visto que efectivamente nadie lo modifica, y sirve perfectamente para mis propósitos. Una modificacion similar en la rutina ExecHandler::UpperCase(uint) me permite escribir cualquier dirección de memoria. 25/10 *********** Martes *********** Más util es parchear la rutina ArmVectorSwi. Si recordáis los detalles de mi debugger para el S45, ponía una variable en una zona fija de memoria. Cada rutina tenía una cabecera que miraba esta variable. Si estaba puesta a un valor determinado, empezaba a debugear la información relevante: registros, pila, y flags. Ahora pretendo hacer lo mismo: org 0x5000B0D8: void ArmVectorSwi() { #define dir_hay_que_debugear 0x40000000 int dir_datos_debugeados 0x40000000+0x10 R9=*(dir_hay_que_debugear); if(R9==0x69) { *(dir_datos_debugeados+4*0)=R0; *(dir_datos_debugeados+4*1)=R1; ... *(dir_datos_debugeados+4*14)=R14; *(dir_datos_debugeados+4*15)=R15; *(dir_datos_debugeados+4*16)=*(SP); *(dir_datos_debugeados+4*17)=*(SP+4); dir_datos_debugeados+= 4*(16+2); } call ArmVectorSwi_original(); } Espero que esté claro. -Mantengo un dato que me dice dónde he guardado el último dato. -Guardo los 16 registros, y las 2 últimas entradas en la pila. -Luego incremento el contador de datos guardados. Recordar que en ARM cada dato ocupa 4 bytes. 26/10 *********** Miércoles *********** Ahora se abren muchas más posibilidades. Puedo poner un breakpoint en cualquier rutina, volcar su memoria, modificarla, y seguir el proceso. Esto me permite averiguar exactamente lo que hace un programa, por lo que espero hacer muchos más parches. 27/10 *********** Jueves *********** Después de 2 meses de trabajo creo que le he sacado bastante partido a mis móviles. He conseguido cerrar algunas puertas, pero muchas más se me han abierto por el camino. Entre los proyectos que me gustaría explorar están: -Linux en el SX1 -Analizador de protocolos GSM en el propio móvil -Instalar Symbian7 o superior -Rutinas de procesado de MMS. Estoy convencido de que hay un buffer-overflow usable. ?Captas las implicaciones? -Bluetooth. Virus y antivirus -Análisis de modelos Nokia -Crakeo de programas Shareware protegidos En fin, ha sido largo pero satisfactorio. Espero que te haya picado el gusanillo y ahora seas tú el que investigue sobre este tema tan apasionante. Yo ahora vuelvo a mis quehaceres familiares. *EOF*