Zapraszam na kolejną analizę starszego odbiornika telewizji naziemnej. W tym temacie pokażę jego wnętrze, obejrzę jego płytkę kamerą termowizyjną, zgram zawartość jego pamięci Flash oraz spróbuję samodzielnie zdekodować znajdujące się tam partycje we własnym programie napisanym w języku C++. Na koniec przedstawię znalezione SDK, które może pasować pod ten tuner.
Temat nie jest ukończony i wszelka pomoc jest mile widziana.
Wnętrze TE 1050 HD
Standardowo - na początek rzut oka z zewnątrz, sprzęt jest malutki, już bez pilota. Do TV i tak się nie przyda, nie odbierze DVB-T2, ale może przyda się elektronikowi? W środku co najmniej musi być jakiś zasilacz, a i obudowa może do czegoś się nada.
W środku jest jedno PCB, nie ma nawet podziału na osobny zasilacz. Nie ma też wyświetlacza, więc nie można użyć części do budowy zegara.
Płytka składa się z dwóch sekcji - "gorącej", strona pierwotna zasilacza, oraz "zimnej", niskonapięciowej. Większość elementów jest montowana powierzchniowo.
Zasilacz jest zbudowany dość nieźle, jest nawet filtr przeciwko emisji zakłóceń, bezpiecznik, odpowiedni kondensator łączący stronę pierwotną z wtórną.
Zasilacz oparty jest o TNY176DG w wersji montowanej powierzchniowo. Na płytce jest też miejsce na jego przewlekany odpowiednik.
Transoptor do sprzężenia strony pierwotnej z wtórną przy zachowaniu separacji galwanicznej:
Po stronie wtórnej widać klasyka - "programowalną diodę Zenera" TL431, podaje on napięcie odniesienia i bierze udział w pętli sprzężenia zwrotnego zasilacza. Zmiana jego rezystorów może w pewnym stopniu zmienić napięcie wyjściowe.
Teraz można obejrzeć sekcje CPU. Płytka jest podpisana jako MC6379-M3801-VER1.0:
Zasilacz daje typowo 5 V, więc niższe napięcie dla RAM i CPU generują dodatkowe przetwornice:
Program trzyma pamięć Flash - 25Q32BSIG (4 MB):
EM6GC16EWXD-12H to pamięć DDR3 DRAM , 64M x 16 bit.
Sam CPU wygląda na M3801 ALI. Zgadza się to z kartą katalogową urządzenia.
Tuner włącza się, daje obraz, pokazuje brak sygnału.
Co grzeje się w takim tunerze?
Krótka zabawa z InfiRay P2 PRO. Sprzęt pochodził 5 minut bez sygnału, ciągle wyświetlając obraz.
Najmocniej grzeje się CPU oraz przetwornica - osobno jej strona pierwotna i wtórna. Po stronie pierwotnej grzeje się TNY i rezystor od pomiaru prądu:
Po stronie wtórnej, dioda Schottkiego:
Troszkę grzeje się też transformator:
Znacznie mniej grzeją się przetwornice od napięć dla CPU i RAM:
Port UART
Urządzenie ma wyprowadzone pady od UART. Dostępne są cztery pady, 5 V (te samo co na USB idzie, główna linia zasilania), masa, RX i TX.
RX i TX sięga tutaj - nie mam pod ręką precyzyjniejszej sondy:
Boot log UART
Przy baudzie 115200 można odebrać szczątkowe komunikaty przy starcie. Tuner nie reaguje na żadne komendy, ani na specjalne znaki przy bootowaniu. Narzędzie Upgrade też go nie widzi.
APP init!
bl_flash_init!
bl_verify_sw
check_program!
success!
MC: APP init ok
<< SDK4.0ba.4.0_20101217 >>
Libcore version 8.1c.0@SDK4.0bd.8.7_20121127(gcc version 3.4.4 mipssde-6.06.01-20070420)(vic.wang@ Fri Nov 30 11:35:29 2012)
Application version 1.0.0@SDK4.0bd.8.7_20121127byUSER
Zgrywanie pamięci Flash
Wystarczy wylutować kość i użyć CH341. Po stronie komputera korzystam z NeoProgrammer.
Testy z istniejącymi narzędziami
Ali MainCode-BY-ARB Tech V 9 - BABAR coś tam dekoduje, ale potem wysypuje się z błędem. Nie da się wypakować ani wpakować kodu.
Ali Background Viewer potrafi znaleźć jeden obraz:
Analiza zrzutu pamięci Flash
Zacząłem klasycznie od binwalk, ale nie dał on zbyt wielu rezultatów, a z kolei nie chciałem sprawdzać znów każdego wyniku pokazanego z przełącznikiem -I.
tester@DESKTOP-6SD9MUK:/mnt/w/WaitingRoom/tuner202512$ binwalk dump.bin
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
2321543 0x236C87 Copyright string: "copyright laws as"
2636264 0x2839E8 Cisco IOS experimental microcode, for "']"
Szybko uznałem, że pobawię się ręcznie. Już na samym początku widzimy coś, co przypomina struktury nagłówka - widać napisy NCRCbootloader, 1.0.0 oraz jakąś datę.
Podkreśliłem ją na obrazku na czerwono. Łatwo zatem się domyśleć, że wartości wcześniej (podkreślone na niebiesko) to pewnie jakieś offsety bądź rozmiary partycji.
Teraz starczy każdy z nich sprawdzić - może któryś jest długością partycji?
Sprawdzałem po cztery bajty, w dwóch kolejnościach: big-endian i little-endian. Albo pierwszy jest najstarszy bajt, albo namłodszy. Potem wykonywałem skok o daną wartość w moim edytorze hex xvi32 i patrzyłem gdzie wyląduję:
Wartość tuż przed nazwą NCRC prowadzi do następnej partycji! Można nakreślić strukturę:
Kod: C / C++
Potrzeba jeszcze pomocniczej funkcji zamieniającej kolejność bajtów:
Kod: C / C++
I można całość przeanalizować w programie.
Kod: C / C++
Jest dobrze, ale nie jest idealnie:
Partition 0 @ offset=0 (0x0) id=268435747 unk=0 len=130560 name=NCRCbootloader ver=1.0.0 dat=2009-06-18
Partition 1 @ offset=130560 (0x1fe00) id=128521 unk=1879048192 len=512 name=NCRCHDCPKey ver=Demo M3801 dat=2009-11-10
Partition 2 @ offset=131072 (0x20000) id=16907777 unk=2091331328 len=3145728 name=yÝĘ~maincode ver=M3801 DVBT dat=2013-2-1
Partition 3 @ offset=3276800 (0x320000) id=130306 unk=1651900416 len=65536 name=ułż°Radioback ver=1.0.0 dat=2009-05-08
Partition 4 @ offset=3342336 (0x330000) id=130051 unk=1611005952 len=130944 name= ver=1.1.0 dat=2013-2-1
Partition 5 @ offset=3473280 (0x34ff80) id=129796 unk=1879051008 len=0 name=NCRCuserdb ver=1.0.0 dat=2013-2-1
Stopping: invalid length at offset 3473280
Unused bytes at end: 721024 (0xb0080)
Te dziwne znaczki na początku nazw partycji sprawiają sugerują, że NCRC to nie jest część nazwy (łańcucha znaków), tylko specjalna wartość pola, pewnie z CRC...
Kod: C / C++
O wiele lepiej:
Partition 0 @ offset=0 (0x0) id=268435747 unk=0 len=130560 name=bootloader ver=1.0.0 dat=2009-06-18
Partition 1 @ offset=130560 (0x1fe00) id=128521 unk=1879048192 len=512 name=HDCPKey ver=Demo M3801 dat=2009-11-10
Partition 2 @ offset=131072 (0x20000) id=16907777 unk=2091331328 len=3145728 name=maincode ver=M3801 DVBT dat=2013-2-1
Partition 3 @ offset=3276800 (0x320000) id=130306 unk=1651900416 len=65536 name=Radioback ver=1.0.0 dat=2009-05-08
Partition 4 @ offset=3342336 (0x330000) id=130051 unk=1611005952 len=130944 name=defaultdb ver=1.1.0 dat=2013-2-1
Partition 5 @ offset=3473280 (0x34ff80) id=129796 unk=1879051008 len=0 name=userdb ver=1.0.0 dat=2013-2-1
Stopping: invalid length at offset 3473280
Unused bytes at end: 721024 (0xb0080)
Następnie zacząłem szukać informacji o stałej, która wygląda mi na identyfikator nagłówka. Bingo - na GitHubie są wyniki:
https://github.com/search?q=0x01FE0101&type=code&p=1
Odpowiada on stałej - CHUNKID_MAINCODE.
Można znaleźć kod pokazujący jak startuje aplikacja:
https://github.com/qttest1/PDK_GoBian/blob/master/uboot/board/ali-stb/norflash/flash.c#L109
Kod: C / C++
W ten sposób udało się znaleźć też resztę struktury nagłówka:
Kod: C / C++
Wygląda na to, że moja pierwsza ocena była prawie w pełni poprawna - jedynie zmienna, którą określiłem jako długość jest w rzeczywistości offsetem do kolejnej partycji, a długość partycji może być mniejsza.
Kod: C / C++
To się potwierdza - drugi int32 wygląda na rzeczywisty rozmiar partycji (nie maksymalny):
Tu mamy jeszcze wzmiankę o NOCRC:
Kod: C / C++
To by wyjaśniało wszystko, przecież w ASCII 0x4E435243 to jest "NCRC". To jest specjalna wartość, którą oznacza się partycje bez CRC.
Poprawne sprawdzenie CRC
Na tym etapie udało mi się znaleźć już kod gdzie weryfikowane jest CRC:
Kod: C / C++
Funkcja mg_table_driven_crc też jest dostępna, co więcej, nie ma zależności od innych bibliotek. Można ją łatwo przeportować.
https://github.com/erwinbsbqq/PDK_GoDroid/blo...63f95/uboot/board/ALi/ali_3503/fastCRC.c#L171
Dodałem ją do mojego programu i od teraz mogę weryfikować CRC partycji.
Wszystkie CRC są poprawne:
Poszukiwania kompilatora
Na GitHubie jest interesująca paczka ACS_release_combo.rar. Jeden z tropów prowadzi do architektury mips i kompilatora sde-6.06:
https://github.com/levi028/loader/blob/master.../app/demo/combo/sabbat_dual/platform/Makefile
Poniżej zamieszczam komendę dla GCC:
../bin/sde-gcc -membedded-data -ffunction-sections -g -EL -mips2 -O1 -msoft-float -fsigned-char -fno-builtin-printf -D_DEBUG_VERSION_ -D_M3711C_ -D_ALI_TDS_ -D_BOARD_DB_M3711C_01V01_ -D_RD_DEBUG_ -D_MPEG4_SUPPORT -D_GEN_CA_ENABLE_ -D_C1200A_ENABLE_ -D_DVBC_ENABLE_ -D_SUPPORT_TUNER_M3031_ -D_VFB_SUPPORT_ -D_COPY_OPTIMIZATION -D_OUC_LOADER_IN_FLASH_ -D_STRIP_PLUGIN_OUTPUT -DDUAL_ENABLE -DMAIN_CPU -D_BUILD_OTA_E_ -D_BUILD_USB_LOADER_ -D_BUILD_USB_LOADER_GEN -D_BUILD_OUC_LOADER_ -I/cygdrive/d/svn/3711C_NBC_PA_HIGH/GA15_NBC1.01.61_Dominican_COMCAST/ALi_UPG_128M_export/inc -I/cygdrive/d/svn/3711C_NBC_PA_HIGH/GA15_NBC1.01.61_Dominican_COMCAST/ALi_UPG_128M_export/inc/freetype2/freetype2 -I/cygdrive/d/svn/3711C_NBC_PA_HIGH/GA15_NBC1.01.61_Dominican_COMCAST/ALi_UPG_128M_export/inc/freetype2 -Wextra -Wall -Wall -Wno-unused-parameter -Wno-unused-function -Wformat=2 -D_FORTIFY_SOURCE=2 -I../lib/gcc/sde/3.4.4/include -I../sde/include -Wall -Wno-unused-parameter -Wno-unused-function -Wformat=2 -D_FORTIFY_SOURCE=2 -I../lib/gcc/sde/3.4.4/include -I../sde/include -c -o ali_i2c_common.o ali_i2c_common.c
make[6]: ../bin/sde-gcc: No such file or directory
make[6]: *** [<builtin>: ali_i2c_common.o] Error 127
make[6]: Leaving directory '/cygdrive/w/GIT/loader/ali_upg_128m/src/bus/i2c/scb'
make[5]: *** [Makefile:45: all] Error 2
make[5]: Leaving directory '/cygdrive/w/GIT/loader/ali_upg_128m/src/bus/i2c/scb'
make[4]: *** [makefile:863: BUS_I2C_SCB] Error 2
make[4]: Leaving directory '/cygdrive/w/GIT/loader/ali_upg_128m/src'
make[3]: *** [Makefile3711c.cmd:1753: release] Error 2
make[3]: Leaving directory '/cygdrive/w/GIT/loader/ali_upg_128m/prj/app/demo/combo/sabbat_dual'
make[2]: *** [Makefile3711c:724: release] Error 2
make[2]: Leaving directory '/cygdrive/w/GIT/loader/ali_upg_128m/prj/app/demo/combo/sabbat_dual'
make[1]: *** [MakefileCommon:124: all] Error 2
make[1]: Leaving directory '/cygdrive/w/GIT/loader/ali_upg_128m/prj/app/demo/combo/sabbat_dual'
make: *** [Makefile:22: all] Error 2
Teraz pytanie skąd wziąć sde-gcc...
https://github.com/search?q=sde-gcc&type=code
#CC=/usr/groups/ecad/mips/sde-6.06/bin/sde-gcc
Na razie jednak tu się zatrzymam, i będę kontynuować prezentację w kolejnym temacie.
Inne powiązane materiały:
https://github.com/levi028/loader
https://github.com/jinfeng-geeya/3202C
https://github.com/erwinbsbqq/PDK_GoDroid
https://github.com/qttest1/PDK_GoBian
https://course.khoury.northeastern.edu/cs3650...XT-CD/Content/Software/SDElite/clickthru.html
Podsumowanie
Udało się poznać format partycji w zrzucie flash, mój program też poprawnie sprawdza CRC, więc w razie czego mogę wygenerować nową sumę kontrolną. Kod źródłowy umieściłem na GitHub:
https://github.com/openshwprojects/AliUnpacker
Do mojej kolekcji zrzutów pamięci dodałem kopię 4 MB z tego urządzenia:
https://github.com/openshwprojects/FlashDumps/commit/c601366e6d63c2d1f65597aa96c4dfa477191aaf
Na ten moment mam kolejne duże postępy - w osobnym temacie być może uda się coś prostego uruchomić na Ali M3801.
Czy próbował ktoś nadać drugie życie tego typu starym tunerom?
Fajne? Ranking DIY Pomogłem? Kup mi kawę.