¿Cómo encuentro el punto de entrada de ARM Linux cuando no se puede descomprimir?

Estoy tratando de arrancar Linux a través de U-boot en una placa personalizada con i.MX6 (el núcleo de la CPU es ARM Cortex A9)

Parece que hemos portado Das U-Boot (2009.08) con éxito. Pero el arranque de Linux falla en el último mensaje de U-Boot: “Starting kernel …”

Aquí está mi entorno relevante:

bootargs=console=ttymxc1,115200 vmalloc=400M root=/dev/mmcblk0p1 rootwait consoleblank=0 earlyprintk video=mxcfb0:dev=lcd,LCD-ORTUS,if=RGB24 video=mxcfb1:dev=hdmi,1280x720M@60,if=RGB24 calibration tsdev=tsc2004 fbmem=10M,28M bootcmd=ext2load mmc 0:1 10800000 /boot/uImage ; bootm 10800000 

La salida de arranque es

 Loading file "/boot/uImage" from mmc device 0:1 (xxa1) 4043552 bytes read ## Booting kernel from Legacy Image at 10800000 ... Image Name: Linux-3.0.35 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 4043488 Bytes = 3.9 MB Load Address: 10008000 Entry Point: 10008000 Verifying Checksum ... OK Loading Kernel Image ... OK OK Starting kernel ... 

Cuando objdump el kernel, en la dirección 80008000, veo el punto de entrada en arch / arm / kernel / head.S, y no arch / arm / boot / compressed / head.S

Lo que veo es que el núcleo ni siquiera se descomprime. Traté de agregar algún código de manipulación de registro para señalizar GPIOs en compressed / head.S sin respuesta.

Mi pregunta es, ¿cómo puedo asegurarme de que U-Boot llame al punto de entrada correcto?

El mismo binario del kernel exacto se inicia correctamente en la placa de referencia de Freescale, utilizando los mismos comandos de arranque en U.

EDITAR: Agregué algunos rastros a U-Boot. Justo antes de llamar al kernel, el puntero theKernel es 10008000 y no 10800000. ¿Significa esto que U-boot está saltando en la ubicación incorrecta?

    Parece que hemos portado Das U-Boot con éxito.

    Hay evidencia de que es una suposición errónea.

    Justo antes de llamar al kernel, el puntero theKernel es 10008000 y no 10800000.

    ¿Qué versión de U-Boot estás usando?
    En las versiones 2012-10 y 2013.04 de U-Boot, la variable theKernel solo se declara y usa por código para arcos como AVR32 y MIPS.
    No hay un código ARM que deba usar el theKernel .

     u-boot-2012.10$ find . -print | xargs grep theKernel ./arch/avr32/lib/bootm.c: void (*theKernel)(int magic, void *tagtable); ./arch/avr32/lib/bootm.c: theKernel = (void *)images->ep; ./arch/avr32/lib/bootm.c: theKernel, params_start); ./arch/avr32/lib/bootm.c: theKernel(ATAG_MAGIC, params_start); ./arch/microblaze/lib/bootm.c: void (*theKernel) (char *, ulong, ulong); ./arch/microblaze/lib/bootm.c: theKernel = (void (*)(char *, ulong, ulong))images->ep; ./arch/microblaze/lib/bootm.c: (ulong) theKernel, rd_data_start, (ulong) of_flat_tree); ./arch/microblaze/lib/bootm.c: theKernel (commandline, rd_data_start, (ulong) of_flat_tree); ./arch/mips/lib/bootm.c: void (*theKernel) (int, char **, char **, int *); ./arch/mips/lib/bootm.c: theKernel = (void (*)(int, char **, char **, int *))images->ep; ./arch/mips/lib/bootm.c: (ulong) theKernel); ./arch/mips/lib/bootm.c: theKernel(linux_argc, linux_argv, linux_env, 0); ./arch/mips/lib/bootm_qemu_mips.c: void (*theKernel) (int, char **, char **, int *); ./arch/mips/lib/bootm_qemu_mips.c: theKernel = (void (*)(int, char **, char **, int *))images->ep; ./arch/mips/lib/bootm_qemu_mips.c: (ulong) theKernel); ./arch/mips/lib/bootm_qemu_mips.c: theKernel(0, NULL, NULL, 0); ./arch/nds32/lib/bootm.c: void (*theKernel)(int zero, int arch, uint params); ./arch/nds32/lib/bootm.c: theKernel = (void (*)(int, int, uint))images->ep; ./arch/nds32/lib/bootm.c: (ulong)theKernel); ./arch/nds32/lib/bootm.c: theKernel(0, machid, bd->bi_boot_params); u-boot-2012.10$ 


    Explique cómo puede rastrear una variable que no debe definirse ni asignarse en un procesador ARM.

    La siguiente salida después de que U-Boot imprima “Starting kernel …” debería ser “Descomprimir Linux …”.
    Para el arco Freescale, esta salida de texto depende del paso correcto del machine type number (también arch_id como arch_id ) por U-Boot al kernel.
    Debe verificar que este machine type number esté definido correctamente en U-Boot.

    ¿Cómo es tu archivo de configuración para U-Boot?

    Traté de agregar algún código de manipulación de registro para señalizar GPIOs en compressed / head.S sin respuesta.

    ¿Revisó su cordura este código para asegurarse de que funciona como espera?
    ¿Probaste las operaciones de GPIO desde la línea de comando de U-Boot?

    Mi pregunta es, ¿cómo puedo asegurarme de que U-Boot llame al punto de entrada correcto?

    Para el arco ARM, es un salto a la dirección especificada en el comando bootm .
    Como la dirección de carga de uImage y el bootm especifican la misma dirección 0x10800000, eso debería ser bueno (suponiendo que U-Boot esté configurado y construido correctamente para ARM).

    Justo antes de llamar al kernel, el puntero theKernel es 10008000 y no 10800000. ¿Significa esto que U-boot está saltando en la ubicación incorrecta?

    SÍ.
    Si comprueba el código fuente (para AVR32 o MIPS), encontrará que el theKernel se asigna desde el encabezado de la imagen, específicamente el valor del punto de entrada. U-Boot saltaría a esta ubicación.
    Pero el verdadero problema es que su ARM Cortex A9 no debería usar este código o esta variable.
    Parece como si ese U-Boot no estuviera configurado para el arco apropiado y / o el tipo de máquina no se haya definido correctamente.

    CORRECCIONES :

    Como señaló el OP, las versiones anteriores de U-Boot usaban la variable theKernel incluso para el arco ARM.

    La línea de salida de U-Boot:

      Loading Kernel Image ... OK 

    indica que U-Boot ha copiado (con éxito) la imagen del núcleo (sin el encabezado de información de la imagen) desde la dirección bootm de 0x10800000 (más el offset 0x40 para la longitud del encabezado) a la dirección de carga de 0x10008000. Esta operación de movimiento de memoria se realiza mediante el procedimiento bootm_load_os() en common / cmd_bootm.c .

    Entonces, el valor de 0x10008000 que informó es correcto para el theKernel .
    No hay indicación de que U-Boot salte a la ubicación incorrecta.

    Como ya se mencionó, debe verificar que el tipo de máquina esté correctamente definido. El valor se usaría en __arch_decomp_setup() en arch / arm / plat-mxc / include / mach / uncompress.h para que el texto pueda salir durante la descompresión antes del arranque del kernel.

    Parece que no estás arrancando el archivo kernel de vmlinux, por lo que no tienes que preocuparte por los puntos de entrada. El código de descompresión al principio de la imagen reubicará el kernel según sea necesario y saltará al punto de entrada correcto cuando esté listo. Solo tiene que saltar al principio de la imagen que uBoot parece estar haciendo correctamente.

    Me gustaría activar la depuración del kernel, especialmente las opciones earlyprintk y de depuración de bajo nivel e intentar reiniciar de nuevo. Al menos puedes ver dónde se acumula.

    Editar: Como se señaló, mi respuesta solo se aplica si uBoot está haciendo lo correcto en primer lugar. En este caso, existe la posibilidad de que no lo sea. Tal vez podría crear e intentar arrancar un “kernel” ficticio que simplemente enciende algunos LED o genera algunos valores de registro en serie (r0, r1 y r2 en particular). Entonces al menos puedes verificar y / o descartar a UBoot como el culpable.

    ¿Podría ser que el archivo que U-Boot está cargando es en realidad la imagen binaria del archivo vmlinux lugar de la imagen autoextraíble zImage / bzImage ? Es solo una suposición, no soy un experto en esto.

    Esta pregunta que hice recientemente en Unix Stack Exchange podría ser de su interés: https://unix.stackexchange.com/questions/197225/is-vmlinuz-and-bzimage-really-the-same