2013-08-22 15 views
6

Ich versuche, (ist CPU-Kern ARM Cortex A9) mit i.MX6 auf einem kundenspezifischen Board Linux via U-Boot zu bootenWie finde ich den ARM Linux-Einstiegspunkt, wenn die Dekomprimierung fehlschlägt?

Wir Das U-Boot portiert zu haben scheinen (2009.08) erfolgreich. Aber Linux Booten versagt bei der letzten U-Boot-Nachricht: "Starten Kernel ..."

Hier ist meine relevante Umgebung:

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,[email protected],if=RGB24 calibration tsdev=tsc2004 fbmem=10M,28M 
bootcmd=ext2load mmc 0:1 10800000 /boot/uImage ; bootm 10800000 

Der Boot-Ausgang ist

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 ... 

Als ich objdump der Kernel, bei Adresse 80008000, sehe ich den Einstiegspunkt bei arch/arm/kernel/head.S, und nicht arch/arm/boot/komprimiert/head.S

Was ich sehe, ist der Kernel nicht einmal dekomprimieren. Ich habe versucht, etwas Registermanipulationscode hinzuzufügen, um GPIOs in komprimiertem/head.S ohne Antwort zu signalisieren.

Meine Frage ist, wie kann ich sicherstellen, dass U-Boot den richtigen Einstiegspunkt aufruft?

Die exakt gleiche Kernel-Binärdatei bootet erfolgreich auf der Freescale-Referenzplatine, wobei dieselben U-Boot-Befehle verwendet werden.

EDIT: Ich habe einige Spuren zu U-Boot hinzugefügt. Kurz bevor der Kernel aufgerufen wird, ist der Zeiger theKernel 10008000 und nicht 10800000. Bedeutet das, dass U-Boot an der falschen Stelle springt?

+0

Haben Sie JTAG haben? Wenn ja, debugge es einfach. –

+0

Ich denke, Kernel wird erst nach der Dekomprimierung starten, nach dem Start des Kernel-Drucks springt der Kernel zur Kernel-Eingabefunktion, die u-boot vom Kernel-Image-Header bekommt. Sie haben den komprimierten Kernel vom Boot-Medium auf 10800000 kopiert, der Bootm-Befehl wird dekomprimiert und der Kernel wird auf die korrekte Ladeadresse gesetzt, die 10008000, 32K Grenze von der RAM-Startadresse ist. Wenn es nicht bootet, dann ist der Grund wahrscheinlich die Maschinen-ID. Ich würde gerne wissen, was der richtige Grund war? – JagsVG

Antwort

7

Wir scheinen das U-Boot erfolgreich portiert zu haben.

Es gibt Beweise, dass das eine fehlerhafte Annahme ist.

Kurz vor dem Kernel-Aufruf wird der Zeiger theKernel 10.008.000 und nicht 10800000.

Welche Version von U-Boot verwenden Sie?
In den Versionen 2012.10 und 2013.04 von U-Boot wird die Variable theKernel nur von Code für Bögen wie AVR32 und MIPS deklariert und verwendet.
Es gibt keinen ARM-Code, der theKernel verwenden sollte.

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$ 


Bitte erläutern Sie, wie Sie in der Lage sind, eine Variable zu verfolgen, die nicht auf einem ARM-Prozessor definiert werden soll oder zugewiesen.

Die nächste Ausgabe nach U-Boot druckt "Starting kernel ..." sollte "Uncompression Linux ..." sein.
Für den Freescale-Bogen ist diese Textausgabe abhängig von der ordnungsgemäßen Weitergabe der machine type number (aka arch_id) von U-Boot an den Kernel.
Sie müssen überprüfen, dass diese machine type number in U-Boot ordnungsgemäß definiert ist.

Wie sieht Ihre Konfigurationsdatei für U-Boot aus?

Ich habe versucht, einige Register Manipulation Code GPIOs in komprimierten/head.S ohne Antwort zu signalisieren.

Haben Sie diesen Code überprüft, um sicherzustellen, dass er wie erwartet funktioniert?
Haben Sie die GPIO-Operationen von der U-Boot-Befehlszeile aus getestet?

Meine Frage ist, wie kann ich sicherstellen, dass U-Boot den richtigen Einstiegspunkt aufruft?

für den ARM-Bogen, ist es ein Sprung zu der Adresse in dem Befehlbootm angegeben.
Da die uImage-Ladeadresse und der bootm die gleiche 0x10800000-Adresse angeben, sollte das gut sein (vorausgesetzt, dass U-Boot korrekt konfiguriert und für ARM erstellt wurde).

Kurz bevor der Kernel aufgerufen wird, lautet der Zeiger theKernel 10008000 und nicht 10800000. Bedeutet dies, dass U-Boot an der falschen Stelle springt?

JA.
Wenn Sie den Quellcode (für AVR32 oder MIPS) überprüfen, werden Sie feststellen, dass theKernel aus der Bildkopfzeile zugewiesen wird, insbesondere der Einstiegspunktwert. U-Boot würde dann zu diesem Ort springen.
Aber das eigentliche Problem ist, dass Ihr ARM Cortex A9 diesen Code oder diese Variable nicht verwenden sollte.

Es scheint, als ob dieser U-Boot nicht für den richtigen Arch konfiguriert ist und/oder der Maschinentyp möglicherweise nicht korrekt definiert ist.

KORREKTUR:

Wie die OP wies darauf hin, ältere Versionen von U-Boot haben die Variable theKernel auch für den ARM-Bogen.

Die Linie der U-Boot-Ausgang:

Loading Kernel Image ... OK 

zeigt an, dass U-Boot hat (erfolgreich), kopiert das Kernel-Image (ohne die Bildinformationen-Header) von der bootm Adresse 0x10800000 (plus Versatz 0x40 für die Kopfzeilenlänge) an die Ladeadresse von 0x10008000. Dieser Speicherverschiebevorgang wird von der Prozedur bootm_load_os() in common/cmd_bootm.c durchgeführt.

Der von Ihnen gemeldete Wert von 0x10008000 ist also korrekt für theKernel.
Es gibt keine Anzeichen dafür, dass U-Boot zum falschen Ort springt.

Wie bereits erwähnt, sollten Sie überprüfen, ob der Maschinentyp korrekt definiert ist. Der Wert würde in __arch_decomp_setup() in arch/arm/plat-mxc/include/mach/uncompress.h verwendet, so dass Text während der Dekomprimierung vor dem Systemstart des Kernels ausgegeben werden konnte.

+0

Tehn Sie für die ausführliche Erklärung. Ich werde meine Frage auch bearbeiten, weil wir U-Boot 2009.08 verwenden, was die offiziell unterstützte Version von Freescale ist. Dort wird ** theKernel ** in einem Unterbaum namens lib \ _arm verwendet. Außerdem verwenden wir den Cortex A8-Bogen, um A9 zu booten, was für andere mx6-basierte Boards perfekt zu sein scheint. –

+0

Ich stehe korrigiert. "Antwort" wurde geändert. – sawdust

+0

Ihr Änderungsantrag löste das Problem! Ich wusste nicht, dass ich meine benutzerdefinierten Boarddefinitionen zu mach/uncompress.h hinzufügen musste. –

4

Sie scheinen die vmlinux-Kernel-Datei nicht zu booten, damit Sie sich keine Sorgen um Einstiegspunkte machen müssen. Der Dekomprimierungscode am Anfang des Bildes verschiebt den Kernel nach Bedarf und springt zum richtigen Einstiegspunkt, wenn er fertig ist. Sie müssen nur den Anfang des Bildes springen, das uBoot anscheinend korrekt macht.

Ich würde Kernel-Debugging aktivieren, insbesondere die Debugging-Optionen earlyprintk und lowlevel und versuchen, erneut zu booten. Zumindest bekommst du zu sehen, wo es stopft.

Edit: Wie bereits erwähnt, gilt meine Antwort nur dann, wenn uBoot es in erster Linie richtig macht. In diesem Fall besteht die Möglichkeit, dass dies nicht der Fall ist. Vielleicht könnten Sie einen Dummy-Kernel erstellen und versuchen, ihn zu booten, der einfach einige LEDs einschaltet oder einige Registerwerte auf seriell ausgibt (insbesondere r0, r1 und r2). Dann können Sie uBoot als Täter zumindest überprüfen und/oder ausschließen.

+0

* "uBoot scheint es richtig zu machen." * - Es gibt keine Beweise, die diese Schlussfolgerung stützen. * "Ich würde das Kernel-Debugging einschalten" * - das OP gibt eindeutig an, dass es keinen Hinweis darauf gibt, dass der Kernel unkomprimiert ist. Da der Kernel nicht gestartet wurde, können Sie nicht erwarten, dass Sie etwas von den "Kernel-Debugging" -Funktionen erhalten. Sie bieten nur allgemeine Ratschläge an, die für diese spezielle Situation nicht hilfreich sind. – sawdust