TUTORIAL El rincón del Updater-script

JDesing

Cuando arrivo a casa...
Diamante
Cocinero
Corazón DualSIM
Mensajes
6.145
Puntos
16.976
Móvil
Lenovo K3 Note, Xiaomi Redmi Note 4
edify.jpg

El rincón del Updater-script

Desde el primer updater-script que ví, sentí curiosidad por saber que lenguaje era usado y que posibilidades ofrecía este Script. Llevo unas cuantas horas hechadas al tema de manera paralela junto con los demás trabajos y he ido haciendo pruebas para tratar de comprender algo más sobre este lenguaje.

Aún me quedan varios aspectos por tratar de comprender completamente, pero estoy seguro que entre todos seremos capaces de terminar de hacerlo.


Updater-script:

Archivo que gobierna el proceso de flashear un archivo *.zip, principalmente sobre el formato y la sintaxis utilizada en el updater-script.

En cristiano: Es un Script escrito en el Lenguaje Edify con el cual se pueden dar órdenes para realizar cualquier proceso de instalación, actualización, reparación, borrado, etc...

Edify: Es el lenguaje de Script para actualizaciones que se interpreta por update-binary. Es el sucesor del lenguaje de escritura Amend.

1. updater-script: Es sólo un archivo de texto que contiene todos los comandos que le dice al Recovery qué hacer con el archivo *.zip. El Script de actualización se escribe en formato UNIX y con el lenguaje de escritura Edify.

2. update-binary: Es un binario que requiere el Recovery para traducir el formato legible por el usuario del updater-script a formato legible por el sistema para la ejecución del Script de actualización en nuestro dispositivo.

Comenzamos:

*Resaltar que el updater-script debe acabar con una línea en blanco al final del documento.

Síntaxis:
  • Se debe usar Lenguaje Edify y formato UNIX.
  • Puede utilizarse libremente el espacio en blanco (Tab, LF 0x0a, pero no CR 0x0d).
  • Los comentarios se pueden usar en cualquier línea con #.
  • Todos los comandos se terminan con un punto y coma. Las cláusulas (en ifelse) pueden contener cualquier número de comandos, cada uno terminado con un punto y coma.
  • Las cadenas suelen ser delimitadas con comillas dobles.
  • Los caracteres /n, /t, /” y // se entienden, al igual que escapes hexadecimales como \x4a.
  • Los números son realmente sólo cadenas y generalmente no están delimitados.
  • Los valores lógicos son 't' para verdadero o ''f” para falso.
  • Los operadores de comparación son == (string igual), =! (string no igual).
  • Los operadores lógicos son || (Lógico o), && (lógico y), ! (No lógico).
  • El operador de concatenación es +. (Precaución: 2+2==22).
  • Las palabras clave condicionales: if, then, else y endif funcionan si no están citados. La macro ifelse se puede utilizar en su lugar.

Operaciones de Disco:
  • format(fs_type, partition_type, device, fs_size, mountpoint) - se puede usar "0" para fs_size (toma la partición entera).
  • mount(fs_type, partition_type, device, mountpoint)
  • unmount(mountpoint)
  • is_mounted(mountpoint)
  • wipe_cache()

Operaciones de Imagen:
  • write_raw_image(filename, device)
  • write_firmware_image

Operaciones de Archivo:
  • package_extract_file(source, destination) - devuelve "t" si es correcto y "" si falla (e.j. si el archivo no existe).
  • package_extract_dir(source, destination).
  • delete(file) – Elimina un archivo.
  • delete_recursive(directory) – Borra completamente un directorio.
  • symlink(target, link0, ...) – Crear cualquier número de enlaces a un destino.
  • set_perm(user, group, mode, file) – Realiza un chown, chmod en un archivo.
  • set_perm_recursive(user, group, mode, directory) – Realiza un chown, chmod en todos los contenidos de un directorio.
  • getprop(key) – Devuelve un valor de cadena de la clave asociada de las propiedades del sistema.
  • file_getprop(file, key) – Devuelve un valor de cadena de la clave asociada de un archivo específico.
  • sha1_check(file) - Devuelve el hash de archivo sha1.
  • sha1_check(file, sha1_hex, [sha1_hex2, ...]) - Devuelve el hash que coincida, si no hay coincidencias devuelve "".

Operaciones de Parcheo:
  • apply_patch(srcfile, tgtfile, tgtsha1, tgtsize, sha1_1, patch_1, ...)
  • apply_patch_check(file, [sha1_1, ...])
  • apply_patch_space(bytes)
  • run_program(program, arg0, ...) - Devuelve el código de salida del programa.

Control:
  • assert(condition0, ...) – Aborta e imprime en cualquier condición falsa.
  • abort(message)
  • ifelse(condition, trueclause, falseclause) – condicional, falseclause es opcional.

Predicados:
  • is_substring(substring, string) – Comprueba si la cadena contiene subcadena en cualquier lugar.
  • less_than_int(x, y) – Comprueba si x<y cuando se considera como enteros.
  • greater_than_int(x, y) – Comprueba si x<y cuando se considera como enteros.

Información para Usuarios:
  • show_progress(fraction, seconds) – Avanzar la barra de progreso una cantidad fraccionada durante un período de segundos.
  • set_progress(fraction) – Anaza la barra de progresos la fracción indicada.
  • ui_print(message0, ...) – Mostrar cualquier información en pantalla.
  • sleep(seconds) – Pausar un determinado número de segundos indicados.

...
 
Última edición:
Explicaciones en "Modo Cristiano" del updater-script:
  • Abre el updater-script con Notepad++ o crea un documento en blanco con formato UNIX.
  • Ahora intentaré explicar los comandos generalmente usados en el updater-script.

Agregar comentarios: (Para colaboración, información y/u orientación)
Los comentarios deben ser agregados en una sola línea que empiece por #. Se pueden agregar tantos comentarios como se deseen, pero siempre respetando el Número de línea en el que está creado.
Código:
1 #Hola esto es un comentario de ejemplo bien estructurado.
2
3 #Esto es un comentario
4 mal estructurado

Verificación del Modelo del Terminal antes de instalar:
Código:
Assert(getprop("ro.product.device") == "K50t5" || getprop ("ro.build.product") == "K50t3s" ||
getprop("ro.product.device") == "K50a40" || getprop("ro.build.product") == "A7000" ||
getprop("ro.product.device") == "aio_otfp_m" || getprop("ro.build.product") == "aio_otfp");

El grupo de líneas anterior comprueba el modelo de dispositivo para confirmar que el archivo *.zip es compatible con el dispositivo para el cual está específicamente creado. Este conjunto de líneas es muy importante porque impide el Flasheo del archivo *,zip a los dispositivos que no están destinados, por lo tanto evita cualquier problema debido al Flashear el *,zip equivocado. Por ejemplo, las líneas anteriores comprueban el valor de "ro.product.device" y "ro.build.product" en el archivo build.prop de la ROM ya existente en el dispositivo, si alguno de los valores definidos K50T5, K50T3S, K50a40. aio_otfp_m o aio_otfp es encontrada, continuará con la siguiente línea del updater-script. Por el contrario si no es encontrado el dispositivo, se aborta la instalación con error de getprop.


Formateo de Particiones:
El siguiente comando se utiliza para formatear la partición especificada.
Código:
format("ext4", "EMMC", "system", "0", "/system");
Otro ejemplo:
Código:
format(“ext4”, “EMMC”, “/dev/block/mmcblk0p19”, "/system");
Código:
format("ext4", "emmc", "/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/cache", "0", "/cache");
Explicación de la sintaxis:
format: Comando principal para dirigir el Recovery a dar formato utilizando los siguientes parámetros;
"ext4" - Tipo de sistema de archivos utilizado en el dispositivo.
"EMMC" - Tipo de partición utilizada en el sistema de archivos.
"system" - Nombre de la partición a formatear.
0” - Se utiliza para tomar toda la partición.
"/system" - Ubicación de la partición a formatear.
"/dev/block/mmcblk0p19" - Ruta del system (varía según teléfono).
  • Debemos mirar en el Recovery.fstab de la Rom para verificar los datos anteriores y ponerlos acorde.

Montar una partición:
El comando mount ordena al Recovery que monte el siguiente sistema de archivos y la siguiente partición. La sintaxis es exactamente como se explica en el comando format excepto que este comando monta, mientras que el comando format formatea la partición definida.
Código:
mount("ext4", "EMMC", "system", "0", "/system");
Otro ejemplo:
Código:
mount(“ext4”, “EMMC”, “/dev/block/mmcblk0p19”, "/system");

Vamos a revisar lo que hemos hecho hasta ahora,
  1. Hemos comprobado el dispositivo para confirmar que el *,zip séa compatible.
  2. Hemos formateado la partición del sistema del dispositivo (esto solo se hace cuandose flashea una nueva ROM completa, para los mods flasheables nunca debes formatear la partición del sistema!).
  3. Hemos montado una partición del sistema del dispositivo.

Instalar una Imagen o Archivo:

Instalando sistema de archivos:

Código:
package_extract_dir("system", "/system");
Este comando busca el directorio (carpeta) denominado "system" en la raíz del archivo *.zip y
Copia todo el contenido de la carpeta "system" del archivo *.zip en la partición "/system" que ya está montado por el comando de montaje anterior.

Recuerda que la estructura del sistema de archivos en el archivo *.zip y la partición "/system" del dispositivo debe ser siempre idénticas. Por ejemplo, has creado un mod modificando el Settings.apk y quieres Flasherlo al sistema, el Settings.apk reside en "/system /priv-app/Settings/", por lo que la estructura del sistema de archivos en el *.zip de actualización debe ser "/system/priv-app/Settings/Settings.apk". Es decir, el *.zip de actualización debe contener la carpeta denominada "system" en la raíz del mismo y la carpeta denominada "priv-app" dentro de la carpeta "system" y la carpeta de la Apk "Settings.apk" debe colocarse dentro de la carpeta "priv-app".

Instalar img y bin:

Código:
Package_extract_file( "system.img", "/system");
Código:
Package_extract_file( "recovery.img", "/recovery");
Código:
Package_extract_file( "boot.img", "/boot");
Código:
Package_extract_file( "logo.bin", "/logo");

Instalar ZIP:
Código:
package_extract_dir("META-INF/SuperSu", "/tmp/SuperSu");
run_program("/sbin/busybox", "unzip", "/tmp/SuperSu/SuperSu-v2.78.zip", "META-INF/com/google/android/*", "-d", "/tmp/SuperSu");
run_program("/sbin/busybox", "sh", "/tmp/SuperSu/META-INF/com/google/android/update-binary", "dummy", "1", "/tmp/SuperSu/SuperSu-v2.78.zip");

Instalar sh desde el ZIP:
Código:
Package_extract_file( "autoroot.sh", "/tmp/autoroot.sh");
Este comando busca el archivo llamado "autoroot.sh" en la raíz del archivo *.zip y copia el archivo a la carpeta "/tmp" y lo nombra como "autoroot.sh" (aquí no cambia el nombre). De igual manera se puede establecer cualquier archivo a instalar en la ruta de destino especificada.

Instalar sh desde la memoria interna:
Código:
run_program("/tmp/autorrot.sh")
run_program("/tmp/autorrot.sh", "argumento1", "argumento2",...)
Recuerdas el archivo autoroot.sh del comando package_extract_file?
Ese archivo se supone que es un script de shell, el comando anterior ordena al Recovery que ejecute el script de shell "autoroot.sh" presente en la carpeta "/tmp".


Establecer Permisos:
Los permisos pueden ser aplicados de 2 maneras, tanto de manera individual a cada Archivo, tanto como a carpetas completas con sus subdirectorios y archivos.

Establecer permisos a un Archivo:
Código:
set_perm(uid, gid, perm, “file_path”);
Síntaxis:
uid - ID de Usuario, normalmente es 0.
gid - ID de Grupo, normalmente es 0.
per - Permisos a establecer. (ej: 644 rw r r)
file_path - Archivo o ruta a establecer permisos. (Debe estra entre comillas "xxxx")

Ejemplo:
Código:
set_perm(0, 0, 0644, “/system/priv-app/Settings.apk”);
asignará permisos 644 (rw- r-- r--) a Settings.apk

Establecer permisos a Carpeta(s):
Código:
set_perm_recursive(0, 0, 0755, 0755, “/system/priv-app/”);

Explicación de Permisos:
r - representa permiso de lectura.
w - representa permiso de escritura.
x - representa permiso de ejecución.

Valores numéricos:

1 : –x
2 : -w-
3 : -wx
4 : r–
5 : r-x
6 : rw-
7 : rwx

Puedes usar un Explorador Root como MiXplorer para ver los permisos de cualquier archivo o directorio.


Borrado de Archivos y/o Carpetas:

Existen dos tipos de comandos para borrar, el que borra un archivo específico y el que borra un directirio completo. Pasémos a ver como:

Borrado de Archivos:
Código:
delete("/system/priv-app/LenovoSettings/Settings.apk");

Borrado de un directorio completo:
Código:
delete_recursive("/system/priv-app/LenovoGallery");


Estos son los comandos más usados por el momento, según vallamos avanzando en el tiempo, iré añadiendo más explicaciones sobre los comandos necesarios.

Continuará...
 
Última edición:
Ejemplo de Updater-script:
Código:
Pendiente...


Errores del Updater-script:
  • Error 6: Este error es común cuando el Recovery no es capaz de montar alguna de las particiones indicadas.
  • Error 7: Este error es común cuando existe algun error de síntaxis dentro del updater-script o algún condicional devuelve ifelse sin valor.
Continuará...
 
Última edición:
Muy guapo,a ver si conseguimos entenderlo.
 
¡Muchas gracias por el tutorial! Nos permitirá entender de una vez el updater script (y por qué a veces parece que instala bien pero luego no arranca :tearsofjoy::tearsofjoy:).
 
¡Muchas gracias por el tutorial! Nos permitirá entender de una vez el updater script (y por qué a veces parece que instala bien pero luego no arranca :tearsofjoy::tearsofjoy:).
Creo que tu también tienes algo que enseñar sobre esto, sin menospreciar el trabajo de J por su puesto
 
Creo que tu también tienes algo que enseñar sobre esto, sin menospreciar el trabajo de J por su puesto

Es posible, pero siendo sincero, de todo eso que JDesing ha puesto en el primer mensaje, yo no tenía ni idea.

@JDesing No sé si aceptas sugerencias, pero ¿podrías explicar como "fabricar" las líneas que llevan algunos updater-script que están destinadas a comprobar ciertas firmas? El único remedio que encontré a esos scripts fue el de eliminar toda comprobación de firmas para evitar los típicos errores de instalación al ver el script que la partición sistema/boot o lo que fuese no era la que él esperaba. Gracias
 

Del blog

Es tendencia

¿Ha terminado la locura de añadir tantas cámaras a los móviles?

  • Si

  • No

  • No lo se

  • Ya me gustaría...

  • Ya te gustaría...


Los resultados solo son visibles tras votar.
Atrás
Arriba