Ich habe Zweifel, dass der JTAG-Emulator von Texas Instruments zum Debuggen von Prozessoren ein so weit verbreitetes Gerät ist, dass es für jemanden interessant wäre, ihn wiederzubeleben. Der Artikel kann jedoch für diejenigen nützlich sein, die versuchen, etwas basierend auf einem Linux-System mit einer Karte mit begrenzten Ressourcen und Informationen wiederzubeleben. Sie können dies als praktische Arbeit mit U-Boot betrachten.

Anstelle des Vorworts
Jeder, der Programme für eingebettete Systeme debuggt, weiß, dass Sie spezielle Geräte verwenden müssen, um eine Verbindung zu Prozessoren herzustellen. Für die Prozessorfamilie Texas Instruments werden Adapter verwendet, die als JTAG-Emulatoren bezeichnet werden.
Es gibt viele und von verschiedenen Herstellern. In meinem Park erscheint unter anderem Blackhawk USB560v2 . Ich muss zugeben, nicht das billigste Stück Eisen. Und dann hörte sie eines Tages ohne ersichtlichen Grund auf zu arbeiten.
Symptome
Eines Tages passierte alles, das Gerät wurde einfach nicht mehr geladen und über USB erkannt. Die LED blinkte, ging jedoch nicht in den Status "Gebrauchsfertig" über.
Dieses Gerät verfügt über einen unterhaltsamen dokumentierten Modus: Nach 10 bis 15 erfolglosen Downloads sollte es in einen speziellen Modus (abgesicherter Modus) gewechselt sein, der ein erneutes Flashen ermöglicht. Mein Gerät weigerte sich jedoch, in diesen Modus zu wechseln, es erreichte nicht die USB-Nummerierungsstufe und daher gab es keine Möglichkeit, mit dem Standarddienstprogramm erneut zu flashen. Die Korrespondenz mit dem Support-Service führte zu nichts: Sie weigerten sich, mir mit technischen Geräten zu helfen, und boten ihnen nur an, (auf eigene Kosten) ein Gerät zur Diagnose und Reparatur an sie in den USA zu senden.
Es blieb keine andere Wahl, als eine unabhängige Reparatur zu starten.
Ubuntu ist auf dem Host installiert, einige verwendete Dienstprogramme sind in der Distribution enthalten, andere werden über apt installiert.
Externe Inspektion

Wir zerlegen, schauen auf die Tafel. Auf dem Brett befinden sich:
Ich war besonders zufrieden mit dem sorgfältig abgenutzten UART-Stecker, der außerdem für einen Standardkamm von 2,54 mm gezüchtet wurde, sodass die Kontakte signiert waren. Ich habe das schon lange nicht mehr gesehen, maximal fünf Stellen auf der Tafel und sogar mit unbedeutenden Markierungen wie TP1 usw.
Fangen wir an
Wir schließen USB-UART an (vergessen Sie nicht den Pegel, er beträgt hier 3,3 V). Wir starten minicom, wir erhalten:
TI UBL Version: 1.13, Flash type: NAND Booting PSP Boot Loader PSPBootMode = NAND Starting NAND Copy... Initializing NAND flash... Manufacturer ID = 0x0000002C Device ID = 0x000000A1 Pages Per Block = 0x00000040 Number of Blocks = 0x00000400 Bytes Per Page = 0x00000800 Valid MagicNum found at block 0x00000001, page 0x00000008 NAND Boot success. DONE U-Boot 2010.12 (May 09 2012 - 13:10:23) Cores: ARM 257 MHz, DSP 513 MHz DDR: 162 MHz I2C: ready DRAM: 256 MiB NAND: 128 MiB MMC: Bad block table found at page 65472, version 0x01 Bad block table found at page 65408, version 0x01 In: serial Out: serial Err: serial Read USBID pin : DEVICE Read boot progress legacy : 0 Read boot progress : 0 Write boot progress legacy : 0 Write boot progress : 0 Hit any key to stop autoboot: 0 Loading from NAND 128MiB 1,8V 8-bit, offset 0x60000 Image Name: Linux-2.6.10_mvl401-xds560 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1236292 Bytes = 1.2 MiB Load Address: 80008000 Entry Point: 80008000 NAND read from offset 60000 failed -74 ** Read error
Wie Sie sehen können, ist die Reihenfolge ziemlich normal: Zuerst wird der Bootloader (TI UBL) geladen, dann der U-Boot, der wiederum den Linux-Kernel lädt.
Laut Protokoll ist es offensichtlich, dass im internen NAND-Flash etwas geflogen ist. Wenn der Linux-Kernel gestartet wird, konvergiert die Prüfsumme nicht. Sie können den Download jedoch unterbrechen und die U-Boot-Konsole aufrufen.
Schauen Sie sich die verfügbaren Befehle an:
Es gibt viele von ihnen U-Boot > help ? - alias for 'help' askenv - get environment variables from stdin base - print or set address offset boot - boot default, ie, run 'bootcmd' bootd - boot default, ie, run 'bootcmd' bootm - boot application image from memory cmp - memory compare coninfo - print console devices and information cp - memory copy crc32 - checksum calculation echo - echo args to console editenv - edit environment variable eeprom - EEPROM sub-system env - environment handling commands exit - exit script false - do nothing, unsuccessfully fatinfo - print information about filesystem fatload - load binary file from a dos filesystem fatls - list files in a directory (default /) go - start application at address 'addr' help - print command description/usage i2c - I2C sub-system iminfo - print header information for application image imxtract- extract a part of a multi-image itest - return true/false on integer compare loadb - load binary file over serial line (kermit mode) loads - load S-Record file over serial line loady - load binary file over serial line (ymodem mode) loop - infinite loop on address range md - memory display mdc - memory display cyclic mii - MII utility commands mm - memory modify (auto-incrementing address) mmc - MMC sub system mmcinfo - display MMC info mtest - simple RAM read/write test mw - memory write (fill) mwc - memory write cyclic nand - NAND sub-system nboot - boot from NAND device nm - memory modify (constant address) printenv- print environment variables reset - Perform RESET of the CPU run - run commands in an environment variable saveenv - save environment variables to persistent storage saves - save S-Record file over serial line setenv - set environment variables showvar - print local hushshell variables sleep - delay execution for some time source - run script from memory test - minimal test like /bin/sh true - do nothing, successfully usb - USB sub-system usbboot - boot from USB device version - print monitor version
Sehen wir uns die Umgebungsvariablen an:
U-Boot > printenv autokern=0x60000 autoroot=/dev/mtdblock3 baudrate=115200 bootcmd=nboot 80700000 0 ${autokern}; run setbootargsnand; bootm setbootargsnand=setenv bootargs mem=64M console=ttyS0,${baudrate}n8 root=${autoroot} rw rootfstype=jffs2 ip=off stderr=serial stdin=serial stdout=serial ver=U-Boot 2010.12 (May 09 2012 - 13:10:23) Environment size: 338/16380 bytes
Das erste, was ich versuchte, war, die Prüfung auszuschalten und mit den U-Boot-Befehlen zu booten.
U-Boot > setenv verify n U-Boot > boot
Etwas weiter gegangen, aber nicht viel:
Weiterhin hängt das Gerät.
Aus den Umgebungsvariablen ist ersichtlich, dass das Kernel-Image in NAND Flash mit einem Offset von 0x60000 liegt. Beim Laden wird es in die Adresse 0x80700000 kopiert (gemäß der Speicherzuordnung des Prozessors ist dies der Adressraum des externen DRAM) und geladen. Die Größe des Kernel-Images beträgt, wie aus dem Protokoll ersichtlich, 1236292 Byte. Ich habe versucht, dies manuell zu tun. Wir gehen davon aus, dass das Bild im uImage-Format gespeichert ist. Wenn wir also 64 Bytes in den Header werfen, erhalten wir 1236356 Bytes = 0x12DD84:
U-Boot > nand read 80700000 60000 12dd84 U-Boot > iminfo
Als nächstes wollte ich den Image-Dump auf den Computer pumpen, um damit zu spielen. Ich habe mir nichts Besseres ausgedacht, als ein Konsolenprotokoll mit der Speicherausgabe auf dem Bildschirm zu schreiben und es dann in eine Binärdatei zu konvertieren.
Führen Sie minicom mit Protokollierung aus:
minicom -C orig-uImage.txt
Wir zeigen den Inhalt des Speichers auf dem Bildschirm an:
U-Boot > md.b 80700000 12dd84
Wir beenden minicom, bearbeiten das Protokoll, entfernen die zusätzlichen Zeilen und konvertieren es in die Binärdatei:
xxd -r -seek -0x80700000 orig-uImage.txt orig-uImage
Ich wollte das Bild neu packen, damit es keine Prüfsummenfehler erzeugt. Löschen Sie die ersten 64 Bytes und erstellen Sie ein neues uImage:
mkimage -A arm -T kernel -C none -a 80008000 -e 80008000 -n "Linux-2.6.10_mvl401-xds560" -d orig-uImage patched-uImage
Füllen Sie die resultierende Datei mit dem YModem-Protokoll wieder aus:
U-Boot > loady
Wir versuchen zu booten, hängen aber auch beim Entpacken des Kernels:
U-Boot > bootm
Es war zu erwarten, worauf man hier hoffen konnte. Aber zumindest haben sie den Workflow für die gemeinsame Nutzung von Dateien hochgeladen, nicht schlecht.
Wir haben USB560v2_firmware_5.0.573.0.bin
eine Firmware-Datei von der Website des Herstellers , USB560v2_firmware_5.0.573.0.bin
. Ich nahm an, dass diese Datei ein Kernel-Image enthält, aber es ist zu erwarten, dass die Datei mit mindestens einem einfachen Schlüssel verschlüsselt ist. Ich gebe daher zu, dass ich zusammengebrochen bin und dem Hersteller eine Anfrage geschrieben habe, mir ein ununterbrochenes uImage
zur Verfügung zu stellen, damit ich es auf das Gerät hochladen und von dort booten kann. Dann konnte ich das Gerät bereits mit dem Standarddienstprogramm über USB neu starten. Er verwies sogar auf die Bedingungen der GPL (unter der Linux vertrieben wird), wonach es nicht schaden würde, die Kernel-Quellcodes zusätzlich bereitzustellen.
Unmittelbar nach dem Senden der Anfrage habe ich mich dennoch entschlossen, die Firmware-Datei als einfaches Archiv zu entpacken. Und siehe da, es stellte sich heraus!
tar -xf USB560v2_firmware_5.0.573.0.bin
Nach dem Entpacken wurden zwei Dateien uImage
: uImage
und rootfs.tar.gz
. Was der Arzt verschrieben hat, ist ein Kernel-Image und ein Root-Dateisystem.
Es bleibt, uImage
mit uImage
in den Speicher des Geräts zu füllen und zu starten, was ich getan habe. Das Gerät wurde erfolgreich in den gleichen abgesicherten Modus gebootet, ich habe diese aufgelegt. Herstellerunterstützung und da ich dachte, dass ich das Gerät das nächste Mal bekommen werde, ging ich ruhig ins Bett.
Zweite Serie
Am nächsten Tag erwartete mich jedoch eine unangenehme Überraschung. Das Gerät wurde erfolgreich nicht mehr geladen. Was ich gerade nicht ausprobiert habe, habe ich einen Fehler bekommen:
INIT: PANIC: segmentation violation! sleeping for 30 seconds.
Langes Kernel-Boot-Protokoll Starting kernel ... Uncompressing Linux................................................................................. done, booting thelLinux version 2.6.10_mvl2 CPU: ARM926EJ-Sid(wb) [41069265] revision 5 (ARMv5TEJ) CPU0: D VIVT write-back cache CPU0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets CPU0: D cache: 8192 bytes, associativity 4, 32 byte lines, 64 sets Machine: DaVinci EVM Memory policy: ECC disabled, Data cache writeback Built 1 zonelists Kernel command line: mem=64M console=ttyS0,115200n8 root=/dev/mtdblock3 rw rootfstype=jffs2 ip=off PID hash table entries: 512 (order: 9, 8192 bytes) Console: colour dummy device 80x30 Dentry cache hash table entries: 16384 (order: 4, 65536 bytes) Inode-cache hash table entries: 8192 (order: 3, 32768 bytes) Memory: 64MB = 64MB total Memory: 62080KB available (2118K code, 448K data, 136K init) Mount-cache hash table entries: 512 (order: 0, 4096 bytes) CPU: Testing write buffer coherency: ok spawn_desched_task(00000000) desched cpu_callback 3/00000000 ksoftirqd started up. desched cpu_callback 2/00000000 desched thread 0 started up. NET: Registered protocol family 16 Registering platform device 'nor_davinci.0'. Parent at platform Registering platform device 'nand_davinci.0'. Parent at platform DaVinci I2C DEBUG: 12:46:30 Mar 29 2012 Registering platform device 'i2c'. Parent at platform musb_hdrc: version 2.2a/db-0.4.8 [cppi-dma] [peripheral] [debug=0] Registering platform device 'musb_hdrc'. Parent at platform musb_hdrc: USB Peripheral mode controller at c4800000 using DMA, IRQ 12 JFFS2 version 2.2. (NAND) (C) 2001-2003 Red Hat, Inc. yaffs Mar 29 2012 12:46:15 Installing. Registering platform device 'davincifb.0'. Parent at platform Console: switching to colour frame buffer device 90x30 Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing disabled Registering platform device 'serial8250'. Parent at platform ttyS0 at MMIO 0x1c20000 (irq = 40) is a 16550A io scheduler noop registered io scheduler anticipatory registered RAMDISK driver initialized: 1 RAM disks of 32768K size 1024 blocksize Registering platform device 'ti_davinci_emac'. Parent at platform TI DaVinci EMAC: MAC address is 00:00:00:04:12:64 TI DaVinci EMAC Linux version updated 4.0 TI DaVinci EMAC: Installed 1 instances. netconsole: not configured, aborting i2c /dev entries driver elevator: using anticipatory as default io scheduler NAND device: Manufacturer ID: 0x2c, Chip ID: 0xa1 (Unknown NAND 128MiB 1,8V 8-bit) Scanning device for bad blocks Creating 8 MTD partitions on "nand_davinci.0": 0x00000000-0x00020000 : "params" 0x00020000-0x00060000 : "bootloader" 0x00060000-0x00260000 : "safekernel" 0x00260000-0x01260000 : "saferootfs" 0x01260000-0x01460000 : "kernel" 0x01460000-0x02860000 : "rootfs" 0x02860000-0x03860000 : "application" 0x03860000-0x03c60000 : "logging" nand_davinci: hardware revision: 2.1 mice: PS/2 mouse device common for all mice NET: Registered protocol family 2 IP: routing cache hash table of 512 buckets, 4Kbytes TCP: Hash tables configured (established 4096 bind 8192) NET: Registered protocol family 1 NET: Registered protocol family 17 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x0000016c: 0xffef instead Empty flash at 0x00a237fc ends at 0x00a23800 Empty flash at 0x00c3b7d8 ends at 0x00c3b800 mtd->read(0x1f320 bytes from 0xec0ce0) returned ECC error mtd->read(0x1fb8c bytes from 0xf20474) returned ECC error VFS: Mounted root (jffs2 filesystem). Freeing init memory: 136K mtd->read(0x44 bytes from 0xf39da8) returned ECC error mtd->read(0x988 bytes from 0xf39420) returned ECC error mtd->read(0x44 bytes from 0xed8d20) returned ECC error jffs2_get_inode_nodes(): Data CRC failed on node at 0x00ed8d20: Read 0xa8462b94, calculated 0xa03c90e8 mtd->read(0xa7e bytes from 0xed82a0) returned ECC error jffs2_get_inode_nodes(): Data CRC failed on node at 0x00c3ad78: Read 0x31ac7e30, calculated 0xa52ecb11 jffs2_get_inode_nodes(): Data CRC failed on node at 0x00a22d9c: Read 0x31ac7e30, calculated 0xe9f89c4c mtd->read(0x988 bytes from 0xf39420) returned ECC error mtd->read(0xa7e bytes from 0xed82a0) returned ECC error INIT: version 2.85 booting INIT: PANIC: segmentation violation! sleeping for 30 seconds. jffs2_get_inode_nodes(): Data CRC failed on node at 0x00a2ad10: Read 0x5fa921cc, calculated 0x5282f1d9 INIT: PANIC: segmentation violation! sleeping for 30 seconds.
Ich kam zu dem Schluss, dass das Root-Dateisystem ebenfalls beschädigt war. Nun, dann müssen Sie es auch flashen.
Schreiben Sie zunächst uImage
in NAND, um es nicht jedes Mal über UART zu laden (ich muss zugeben, dass bei einer Geschwindigkeit von 115200 selbst bei einer Größe von einem Megabyte eine spürbare Zeit geladen wird). Bei der Arbeit mit NAND richten wir für alle Fälle die Bildgröße an der NAND-Seitengröße aus (ich habe irgendwo eine solche Empfehlung getroffen), und die Seitengröße beträgt hier 1024 Byte = 0x800 (siehe das allererste Protokoll).
U-Boot > loady ... U-Boot > nand erase 60000 12DC00 U-Boot > nand write 80700000 60000 12DC00
Wählen Sie im Kernel-Boot-Protokoll die nützlichen Informationen aus:
Creating 8 MTD partitions on "nand_davinci.0": 0x00000000-0x00020000 : "params" 0x00020000-0x00060000 : "bootloader" 0x00060000-0x00260000 : "safekernel" 0x00260000-0x01260000 : "saferootfs" 0x01260000-0x01460000 : "kernel" 0x01460000-0x02860000 : "rootfs" 0x02860000-0x03860000 : "application" 0x03860000-0x03c60000 : "logging"
Das Root-Dateisystem muss also mit einem Offset von 0x260000 in NAND geschrieben werden. Es bleibt nur zu verstehen, in welchem Format. Wir erinnern uns an die U-Boot-Umgebungsvariablen, insbesondere an diese Zeile:
setbootargsnand=setenv bootargs mem=64M console=ttyS0,${baudrate}n8 root=${autoroot} rw rootfstype=jffs2 ip=off
Wir müssen also unsere rootfs.tar.gz
, die aus der Firmware-Datei gefischt wurde, in das JFFS2-Format konvertieren. Bei der Eingabeaufforderung mit dem Wiki von Texas Instruments tun wir dies ( sudo
für tar
benötigt, sodass beim Ausführen des mknod
Fehler mknod
):
mkdir rootfs sudo tar -xf rootfs.tar.gz -C rootfs mkfs.jffs2 -n -r rootfs -e 16 -o rootfs.jffs2
Wir laden die resultierende Datei in den Speicher des Geräts und kopieren sie dann in den gewünschten NAND-Bereich (die Größe wird ebenfalls auf die Seite gerundet):
U-Boot > loady ... U-Boot > nand erase 260000 39f000 U-Boot > nand write 80700000 260000 39f000
Wir drücken die Daumen, starten neu, nun ist definitiv alles in Ordnung.
Sehr langes vollständiges Protokoll des erfolgreichen Downloads TI UBL Version: 1.13, Flash type: NAND Booting PSP Boot Loader PSPBootMode = NAND Starting NAND Copy... Initializing NAND flash... Manufacturer ID = 0x0000002C Device ID = 0x000000A1 Pages Per Block = 0x00000040 Number of Blocks = 0x00000400 Bytes Per Page = 0x00000800 Valid MagicNum found at block 0x00000001, page 0x00000008 NAND Boot success. DONE U-Boot 2010.12 (May 09 2012 - 13:10:23) Cores: ARM 257 MHz, DSP 513 MHz DDR: 162 MHz I2C: ready DRAM: 256 MiB NAND: 128 MiB MMC: Bad block table found at page 65472, version 0x01 Bad block table found at page 65408, version 0x01 In: serial Out: serial Err: serial Read USBID pin : DEVICE Read boot progress legacy : 3 Read boot progress : 10 Write boot progress legacy : 2 Write boot progress : 9 Hit any key to stop autoboot: 0 Loading from NAND 128MiB 1,8V 8-bit, offset 0x1260000 Image Name: Linux-2.6.10_mvl401-xds560 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 1235632 Bytes = 1.2 MiB Load Address: 80008000 Entry Point: 80008000
Nachwort
Ja, das endgültige Verfahren erwies sich als nicht sehr kompliziert, tatsächlich gibt es hier nicht viel echtes Reverse Engineering. Aber ich persönlich habe während des Startvorgangs von Embedded Linux viele neue Dinge über Low-Level-Dinge gelernt und gelernt, wie man mit der U-Boot-Konsole arbeitet.
Für Besitzer von Blackhawk USB560v2Es ist zu sehen, dass sich die Jungs nicht um den Schutz gekümmert haben. Nach dem Booten von Linux wird in der Konsole eine Aufforderung zum Anmelden angezeigt. Mit der root
Anmeldung ohne Kennwort können Sie sich mit Administratorzugriff anmelden und alles mit dem Gerät tun. Am interessantesten ist das /usr/local/bin
.
Aber das ist eine ganz andere Geschichte.
Ich hoffe es war interessant.