Saya ragu bahwa emulator Texas Instruments JTAG untuk prosesor debugging adalah perangkat yang tersebar luas sehingga siapa pun akan tertarik untuk menyadarkannya. Namun, artikel ini mungkin berguna bagi mereka yang mencoba menghidupkan kembali sesuatu berdasarkan sistem Linux dengan satu kartu, dengan sumber daya dan informasi yang terbatas. Anda dapat menganggap ini sebagai pekerjaan praktis dengan U-Boot.

Alih-alih kata pengantar
Siapa pun yang mendebug program untuk sistem tertanam tahu bahwa Anda perlu menggunakan perangkat khusus untuk terhubung ke prosesor. Adaptor yang disebut emulator JTAG digunakan untuk keluarga prosesor Texas Instruments.
Ada banyak, dan dari berbagai produsen. Di taman saya, antara lain, Blackhawk USB560v2 muncul . Saya harus mengakui, bukan sepotong besi termurah. Dan kemudian suatu hari dia berhenti bekerja tanpa alasan yang jelas.
Gejala
Semuanya terjadi suatu hari, perangkat hanya berhenti memuat dan terdeteksi melalui USB. LED berkedip, tetapi tidak masuk ke status "siap pakai".
Perangkat ini memiliki mode mendokumentasikan yang menghibur: setelah 10-15 unduhan yang gagal, seharusnya beralih ke mode khusus (safe mode) yang akan memungkinkannya untuk di-reflash. Namun, perangkat saya menolak untuk beralih ke mode ini, itu tidak mencapai tahap penomoran USB, dan karena itu tidak ada kemungkinan untuk reflash dengan utilitas standar. Korespondensi dengan layanan dukungan tidak mengarah pada apa pun: mereka menolak untuk membantu saya dengan peralatan teknis, hanya menawarkan untuk mengirim (dengan biaya mereka sendiri) sebuah perangkat kepada mereka di AS untuk diagnosa dan perbaikan.
Tidak ada pilihan selain memulai perbaikan independen.
Ubuntu diinstal pada host, beberapa utilitas yang digunakan termasuk dalam distribusi, beberapa diinstal melalui apt.
Inspeksi eksternal

Kami membongkar, lihat papan tulis. Di papan tulis terletak:
Saya terutama senang dengan konektor UART yang sudah usang, yang, apalagi, dibiakkan untuk sisir standar 2,54 mm, sehingga kontak ditandatangani. Saya belum pernah melihat ini untuk waktu yang lama, maksimal lima tempat di papan tulis, dan bahkan dengan tanda yang tidak signifikan seperti TP1, dll.
Mari kita mulai
Kami menghubungkan USB-UART (jangan lupa tentang level, itu adalah 3,3 V di sini). Kami memulai minicom, kami menerima:
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
Seperti yang Anda lihat, urutannya cukup standar: bootloader pertama (TI UBL) dimuat, lalu U-Boot, yang pada gilirannya memuat kernel Linux.
Menurut log, jelas bahwa sesuatu telah terbang di internal NAND Flash, ketika kernel Linux di-boot, checksum tidak menyatu. Namun, Anda dapat menghentikan unduhan dan masuk ke konsol U-Boot.
Lihatlah perintah yang tersedia:
Ada banyak dari mereka 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
Mari kita lihat variabel lingkungan:
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
Hal pertama yang saya coba adalah mematikan cek dan boot menggunakan perintah U-Boot.
U-Boot > setenv verify n U-Boot > boot
Pindah sedikit lebih jauh, tetapi tidak banyak:
Selanjutnya perangkat hang.
Dapat dilihat dari variabel lingkungan bahwa gambar kernel terletak pada NAND Flash dengan offset 0x60000, ketika dimuat, itu disalin ke alamat 0x80700000 (sesuai dengan peta memori prosesor, ini adalah ruang alamat DRAM eksternal) dan dimuat. Ukuran gambar kernel, seperti dapat dilihat dari log, adalah 1236292 byte. Saya mencoba melakukan ini secara manual. Kami berasumsi bahwa gambar disimpan dalam format uImage, jadi kami membuang 64 byte pada header, kami mendapatkan 1236356 byte = 0x12DD84:
U-Boot > nand read 80700000 60000 12dd84 U-Boot > iminfo
Selanjutnya, saya ingin memompa dump gambar ke komputer untuk bermain dengannya. Saya tidak menemukan sesuatu yang lebih baik daripada menulis log konsol dengan output memori pada layar, dan kemudian mengubahnya menjadi file biner.
Jalankan minicom dengan logging:
minicom -C orig-uImage.txt
Kami menampilkan konten memori di layar:
U-Boot > md.b 80700000 12dd84
Kami keluar dari minicom, mengedit log, menghapus baris tambahan, dan mengonversinya menjadi biner:
xxd -r -seek -0x80700000 orig-uImage.txt orig-uImage
Saya ingin mengemas ulang gambar sehingga tidak akan menghasilkan kesalahan checksum. Hapus 64 byte pertama, lalu buat uImage baru:
mkimage -A arm -T kernel -C none -a 80008000 -e 80008000 -n "Linux-2.6.10_mvl401-xds560" -d orig-uImage patched-uImage
Isi kembali file yang dihasilkan menggunakan protokol YModem:
U-Boot > loady
Kami mencoba untuk boot, tetapi juga menggantung pada tahap membongkar kernel:
U-Boot > bootm
Diharapkan apa yang bisa diharapkan di sini. Tapi setidaknya mereka mengunggah alur kerja berbagi file, tidak buruk.
Yang kami miliki hanyalah file firmware dari situs web USB560v2_firmware_5.0.573.0.bin
, USB560v2_firmware_5.0.573.0.bin
. Saya berasumsi bahwa file ini berisi gambar kernel, tetapi akan masuk akal untuk berharap bahwa file tersebut dienkripsi dengan setidaknya kunci sederhana. Oleh karena itu, saya akui, saya mogok dan menulis kepada pabrikan permintaan untuk memberi saya uImage
tidak terputus sehingga saya akan mengunggahnya ke perangkat dan mem-boot darinya, dan kemudian saya dapat merombak perangkat dengan utilitas USB standar. Dia bahkan merujuk pada ketentuan GPL (di mana Linux didistribusikan), yang menurutnya tidak ada salahnya untuk memberikan kode sumber kernel sebagai tambahan.
Segera setelah mengirim permintaan, saya memutuskan untuk mencoba meng-unzip file firmware, sebagai arsip sederhana. Dan, lihatlah, ternyata!
tar -xf USB560v2_firmware_5.0.573.0.bin
Setelah membongkar, dua file muncul: uImage
dan rootfs.tar.gz
. Apa yang diresepkan dokter adalah gambar kernel dan sistem file root.
Masih mengisi uImage
ke dalam memori perangkat menggunakan YModem dan mulai, yang saya lakukan. Perangkat berhasil boot ke mode aman yang sama, saya menutupnya. dukungan pabrikan dan, berpikir bahwa saya akan mendapatkan perangkat lain kali, saya dengan tenang pergi tidur.
Seri kedua
Namun, keesokan harinya kejutan yang tidak menyenangkan menunggu saya. Perangkat berhasil berhenti memuat. Apa yang saya tidak coba, saya mendapat kesalahan:
INIT: PANIC: segmentation violation! sleeping for 30 seconds.
Log boot kernel yang panjang 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.
Saya menyimpulkan bahwa sistem file root juga rusak. Nah, maka Anda perlu menginstalnya juga.
Pertama, tulis uImage
ke NAND, agar tidak memuatnya melalui UART setiap kali (harus saya akui, pada kecepatan 115200, waktu yang nyata dimuat bahkan pada ukuran satu megabyte). Ketika bekerja dengan NAND, untuk berjaga-jaga, kami menyelaraskan ukuran gambar dengan ukuran halaman NAND ke atas (saya bertemu dengan rekomendasi semacam itu di suatu tempat), dan ukuran halaman kami adalah 1024 byte = 0x800 (lihat log pertama).
U-Boot > loady ... U-Boot > nand erase 60000 12DC00 U-Boot > nand write 80700000 60000 12DC00
Dari log boot kernel, pilih informasi yang berguna:
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"
Jadi sistem file root harus ditulis ke NAND dengan offset 0x260000. Tetap hanya untuk memahami dalam format apa. Kami mengingat variabel lingkungan U-Boot, khususnya, baris ini:
setbootargsnand=setenv bootargs mem=64M console=ttyS0,${baudrate}n8 root=${autoroot} rw rootfstype=jffs2 ip=off
Jadi, kita perlu mengkonversi rootfs.tar.gz
kita, yang rootfs.tar.gz
dari file firmware, ke format JFFS2. Pada prompt dengan Wiki dari Texas Instruments, kami melakukan ini ( sudo
diperlukan untuk tar
, sehingga menghasilkan kesalahan saat menjalankan perintah mknod
):
mkdir rootfs sudo tar -xf rootfs.tar.gz -C rootfs mkfs.jffs2 -n -r rootfs -e 16 -o rootfs.jffs2
Kami memuat file yang dihasilkan ke dalam memori perangkat, dan kemudian menyalinnya ke bagian NAND yang diinginkan (ukurannya juga dibulatkan ke halaman):
U-Boot > loady ... U-Boot > nand erase 260000 39f000 U-Boot > nand write 80700000 260000 39f000
Kami menyilangkan jari kami, reboot, well, sekarang semuanya baik-baik saja.
Log lengkap yang sangat panjang untuk unduhan yang berhasil 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
Kata penutup
Ya, prosedur terakhir ternyata tidak terlalu rumit, pada kenyataannya, tidak ada banyak rekayasa balik yang nyata di sini. Tetapi saya secara pribadi belajar banyak hal baru tentang hal-hal tingkat rendah selama proses boot embedded Linux, belajar cara bekerja dengan konsol U-Boot.
Untuk pemilik Blackhawk USB560v2Dapat dilihat bahwa orang-orang tidak peduli dengan perlindungan. Setelah mem-boot Linux, sebuah prompt muncul di konsol untuk login. Login root
tanpa kata sandi memungkinkan Anda untuk masuk dengan akses administratif dan melakukan apa saja dengan perangkat. Yang paling menarik adalah di /usr/local/bin
.
Tetapi ini adalah kisah yang sangat berbeda.
Saya harap itu menarik.