Diawali dari percobaan mengoprek router Bolt BL100 dengan tujuan untuk mengetahui isi dari router tersebut karena belum banyak post terkait pcb dan module yang ada di dalam router di internet, setelah itu dimulailah journey reverse engineering router bolt bl100, mulai dari mengakses port serial, rooting firmware, install openwrt, hingga aktivasi modem ltenya.

Sekarang firmware openwrt bolt bl100 sudah didukung official di repository openwrt dan telah masuk ke official download nya. Karena telah masuk ke repo official maka kedepannya firmware akan mendapatkan update kernel yang terus berlanjut serta akan banyak bugfix dan security fix yang dilakukan oleh komunitas open source OpenWRT nantinya.

Lalu firmware openwrt bl100 akan masuk release cycle build openwrt, dimana setiap versi merupakan versi yang stable yang sudah dikeluarkan, saya kurang paham sih berapa lama release cycle dari openwrt kita tunggu saja rilis kedepan.

Berikut ini adalah timeline pengerjaan yang sudah di merge ke official openwrt, saya akan coba deskripsikan hehe.

#1 Initial Pull Request

Initial pull request dimulai dengan deskripsi commit sesuai standar openwrt ramips: add support for BOLT BL100, ramips artinya arsitektur CPU yang digunakan oleh router yaitu Ralink MIPS, dan deskripsi commit nya adalah menambahkan support untuk router bolt bl100.

Kemudian untuk pesan commit dibawahnya adalah deskripsi router yang akan disupport secara singkat, dilengkapi dengan spesifikasi routernya. Contoh CPU, Memory,ROM, Hardware peripherals yang didukung.

Pada baris terakhir dilengkapi cara melakukan instalasi secara singkat juga. Instalasi dilakukan dengan menggunakan akses root router dan melakukan mtd_write langsung ke partisi Kernel.

#2 Issue Pertama (Bootloader)

Issue pertama dimulai dari feedback dari komunitas openwrt yang mengatakan bahwa tutorial instalasi menggunakan breed bootloader tidak diperbolehkan, dan firmware openwrt harus bisa booting menggunakan bootloader bawaan routernya. Karena sebelumnya memang instalasi dan tutorial yang ada di blog ini menggnakan bootloader breed karena beberapa kelebihan dan sebagai failsave ketika terjadi firmware corrupt dapat dilakukan flash dengan mudah, tapi okelah saya coba gali lebih dalam.

Kondisi sebelumnya jika mencoba booting menggunakan image openwrt yang sudah di build terdapat error Bad magic number dari pesan bootloader uBoot, hal ini terjadi karena bootloader uboot sudah di modifikasi source codenya dari pabrikan untuk menghindari modifikasi firmware oleh pihak luar. Sehingga diberikan checksum untuk mengecek magic number yang sesuai dengan firmware originalnya.

Gambar diatas adalah boot log yang diambil dengan menggunakan port serial dari Bolt BL100, terdapat error Bad Magic Number,27051956 setelah itu router stuck di pesan terakhir dan tidak bisa booting ke next step yaitu decompressing kernel. Lalu saya coba gali lebih dalam kenapa hal itu terjadi.

Lalu okelah, kalau ngga mau boot dalam posisi firmware yang sudah ada di dalam ROM / flash di uBoot terdapat opsi untuk meload firmware ke memory langsung, jadi kita bisa booting dan jump ke memory address tersebut tanpa harus write firmware ke flash memory. Saya coba cek.

Untuk menghentikan proses booting uBoot dan masuk ke menu boot dapat dilakukan dengan menahan tombol WPS sambil menghidupkan routernya, jika sukses maka proses booting akan terinterupsi. Disini terdapat opsi load system code to memory via TFTP, lalu selanjutnya saya coba setup TFTP server di komputer yang terhubung dan satu jaringan dengan router tersebut, dan saya coba namai filenya dengan nama openwrt.bin.

Setelah terbaca oleh TFTP server serta mendapatkan request ARP yang artinya router teserbut sukses menghubungi pc saya, Tetapi hasilnya sama juga ada validasi magic number juga pada saat booting via memory. Kesimpulannya yaitu bootloader ini sudah dimodifikasi oleh pabrik.

#3 Mencoba Reversing Firmware

Karena terdapat error magic number, saya coba cari apa itu magic number dan efek yang ditimbulkan ke bootloader.

https://en.wikipedia.org/wiki/Magic_number_(programming)

Magic numbers are common in programs across many operating systems. Magic numbers implement strongly typed data and are a form of in-band signaling to the controlling program that reads the data type(s) at program run-time. Many files have such constants that identify the contained data. Detecting such constants in files is a simple and effective way of distinguishing between many file formats and can yield further run-time information.

Ohh gitu, setelah browsing beberapa kali di referensi embedded firmware linux dan dari referensi wikipedia ternyata magic number adalah konstanta yang biasanya dimasukkan pada awalan file untuk mengidentifikasi jenis file itu, Jadi dalam konteks firmware ini bisa dibilang magic number adalah kostanta yang mengidentifikasi bahwa file ini adalah file firmware untuk router yang diawali dengan konstanta tertentu, jadi contoh dengan 0x27051956 ini merupakan magic number dari firmware openwrt yang saya pakai dan berbeda dengan yang di expect oleh bootloader uBoot dari pabrikan.

Kalau dipikir2 memang benar juga karena komputer hanya membaca bit dan biasanya dibaca menjadi stream atau buffer, dengan membuat magic number menjadi fixed size contoh 0x27051956 meriupakan bilangan hexadecimal. Maka sebagai programmer kita bisa dengan mudah mengidentifikasi suatu file dengan membaca 4 byte awal sebuah file, contoh peseudocode read(*file, 4) untuk mengetahui apakah file itu valid dengan konstanta yang kita definisikan.

Lanjut kita coba reversing dari dump.bin yang merupakan original firmware dari bolt bl100. Saya coba extract filenya menggunakan binwalk dan ketemu banyak binary dan shell script di dalam partisi linuxnya. Saya coba search apakah ada yang mengandung magic number. Dan ternyata ketemu salah satu file firmware upgrade seperti ini.

Nah akhirnya ketemu, disini ada variable dari bash script yang mendefinisikan magic number, Ada dua tipe yang satu MTK dan yang satu custom. Karena yang MTK magic number dikomen jadi kita bisa abaikan saya. Coba fokus ke magic number bawahnya yaitu 26 11 20 15 jadi hexadecimalnya 0x26112015 dan kebetulan dibawahnya ada komentar check by uBoot hehe.

Setelah diketahui nilai kernel magic numbernya, coba saya cari pada firmware dump original dari boltnya dan hasilnya ternyata.

Nah ternyata ketemu nilainya di baris 04ffd4 setelah ditelusuri ternyata magic number ini berada setelah section kosong yang dimulai dari blok ffffffff pada keterangan ascii pada bagian kanan terdapat text Linux Kernel Image yang menandakan bahwa blok tersebut adalah blok linux kernel.

#4 Mengubah Header uBoot

Setelah berhasil melakukan kompilasi firmware openwrt, hasilnya adalah file binary firmware sesuai dengan tipe router yang dipilih saat konfigurasi awal.

Contoh file binary hasil kompilasi:

openwrt-23.05.2-ramips-mt7620-bolt_bl100-201-squashfs-sysupgrade.bin

File firmware diatas memiliki header data 64 byte awal

27051956 27D8A9DB 65537843 00563E27 80000000 80000000 013F7B9D 05050203 4D495053 204F7065 6E577274 204C696E 75782D35 2E31352E 31333700 00000000
^^^^^^^^ ^^^^^^^^
Magic   | CRC32  | Rest of headers data
Number  |        |  
--------|--------|
4 byte  | 4 byte | 56 byte

Magic Number = 0x27051956

Checksum CRC32 = 0x27D8A9DB

Magic number yang ada tidak match dengan nilai yang di expect oleh uboot sehingga router tidak bisa booting. Untuk melakukan patching magic number dilakukan dengan mengubah magic numbernya, lalu menghitung checksum crc32 pada byte 4-7.

Modifikasi Header Dengan Magic Number 0x26112015

26112015 00000000 65537843 00563E27 80000000 80000000 013F7B9D 05050203 4D495053 204F7065 6E577274 204C696E 75782D35 2E31352E 31333700 00000000
^^^^^^^^ ^^^^^^^^
New     | Nulled | Rest of headers data
Magic   | CRC32  | 
Number  |        |
--------|--------|
4 byte  | 4 byte | 56 byte

Karena checksum CRC32 harus dihitung ulang maka pada byte 4-7 harus dinullkan terlebih dahulu. Setelah itu dapat dihitung checksum crc32 menggunakan crc32 calculator (https://danielwiese.com/crc-calculator/)

Checksum = CRC32 (26112015 00000000 65537843 00563E27 80000000 80000000 013F7B9D 05050203 4D495053 204F7065 6E577274 204C696E 75782D35 2E31352E 31333700 00000000)

Hasil Perhitungan CRC32

Karena arsitektur MIPS adalah big endian, maka didapatkan nilai CRC32 dengan nilai 0x06F6FC0D

Hasil akhirnya maka seperti ini

26112015 06F6FC0D 65537843 00563E27 80000000 80000000 013F7B9D 05050203 4D495053 204F7065 6E577274 204C696E 75782D35 2E31352E 31333700 00000000
^^^^^^^^ ^^^^^^^^
New     | New    | Rest of headers data
Magic   | CRC32  | 
Number  |        |
--------|--------|
4 byte  | 4 byte | 56 byte

Untuk mengubah file binary secara langsung dapat menggunakan hexeditor untuk windows, atau melalui terminal jika menggunakan linux. Disini saya menggunakan aplikasi HexFiend.

Saatnya dicoba untuk firmware barunya, saya coba metode booting menggunakan TFTPd pada uBoot dan hasilnya seperti berikut.

Yess, Akhirnya 😁 

Firmware openwrt berhasil booting menggunakan bootloader bawaan router (uBoot). Hasilnya ditandai dengan kernel yang berhasil di decompress oleh bootloader dan berhasil menampilkan versi kernelnya.

Setelah saya post komentar tersebut, ternyata ada kontributor dari openwrt yang menginformasikan bahwa ada fungsi yang dapat digunakan untuk melakukan set magic code secara otomatis, yang sebelumnya saya tidak ketahui hehe. Sehingga tidak perlu ubah manual lagi dan prosesnya akan diotomatisasi pada saat proses kompilasi.

Langsung saja cuss, saya implementasikan di Pull Requestnya untuk direview maintainer kedepannya.

#5 Wrapping Up

Setelah beberapa kali perbaikan dan penambahan request dari maintainer repository openwrt diantaranya adalah perbaikan commit message, penambahan fungsi led untuk patch openwrt terbaru, akhirnya pada tanggal 1 April pull request sudah dilakukan merge ke branch main openwrt.

Setelah dilakukan merge maka otomatis build firmware Bolt BL100 sudah masuk ke release snapshot openwrt, untuk linknya bisa dicek disini.

Versi Sysupgrade (bolt_bl100-squashfs-sysupgrade.bin)

https://downloads.openwrt.org/snapshots/targets/ramips/mt7620/openwrt-ramips-mt7620-bolt_bl100-initramfs-kernel.bin

Versi Initramfs (bolt_bl100-initramfs-kernel.bin)

https://downloads.openwrt.org/snapshots/targets/ramips/mt7620/openwrt-ramips-mt7620-bolt_bl100-initramfs-kernel.bin

Oh iya, untuk versi snapshot belum include web interfacenya (luci) dan loginnya masih melalui ssh atau port serialnya. Jadi setelah install dapat dilakukan instalasi luci terlebih dahulu. Untuk saat ini firmware bl100 belum masuk release cycle terbaru, untuk tepatnya belum tau tetapi untuk kedepan jika ada release versi terbaru openwrt maka akan otomatis include di dalamnya.

Dengan firmware ini, maka tidak usah melakukan instalasi breed bootloader, bisa menggunakan bootloader bawaannya (uboot). Untuk tutorial instalasinya sama seperti di artikel sebelumnya (Install OpenWRT Bolt BL-100/BL-201 Tanpa Alat Tambahan) jika anda mau coba instalasi sendiri. Kalau sebelumnya sudah melakukan install openwrt juga bisa melakukan upgrade versi openwrt melalui halaman upgrade firmware openwrt.

Sekian artikel kali ini, sebenarnya hanya ingin mendeskripsikan proses penambahan device ke support openwrt dan untuk case bolt bl100 ini terdapat beberapa kendala dan case yang unik yang dapat dieksplor lebih lanjut kedepannya hehe.

Referensi

https://github.com/openwrt/openwrt/pull/14836

https://forum.openwrt.org/t/how-do-i-calculate-the-crc32-of-u-boot-header/76611