Rabu, 03 April 2013

Port BlankOn ke ARM

Sebenarnya kalau bilang mau port suatu sistem operasi ke ARM, itu artinya bisa luas sekali. Seperti kita ketahui. ARM itu bukan nama sebuah prosesor, tapi adalah arsitektur prosesor. Arsitektur ini sendiri memiliki banyak versi gugus instruksi, ada ARMv1, ARMv2, dan seterusnya sampai ARMv8. Dan tiap-tiap versi memiliki keluarga implementasi yang berupa-rupa. Misalnya ARMv3 diimplementasikan pada keluarga ARM6 dan ARM7 (perhatikan tidak ada huruf v sekarang), ARMv11 diimplementasikan pada keluarga ARM Cortex-A8, ARM Cortex-A9 dan sebagainya. (Mudah-mudahan tidak pusing :D)

Keluarga ARM tadi juga diimplementasikan oleh beragam pabrik yang memegang hak lisensi ARM. Misalnya untuk ARM Cortex-A9 ada cukup banyak pabrik yang menyediakan sistem dalam chip (System-On-Chip alias SoC), misalnya Amlogic, NVIDIA Tegra 2, ST-Ericsson, dan sebagainya.

Tiap-tiap SoC punya konfigurasi sendiri-sendiri dengan menggunakan sistem jaringan, audio, grafik dan kawan-kawan yang berbeda-beda pula.

Dari keragaman tadi, tentunya berimplikasi bahwa walaupun kita punya satu sistem operasi yang jalan baik di sebuah sistem ARM, belum tentu akan jalan sempurna di sistem ARM yang lain. Tidak seperti di keluarga i386, sebuah sistem Linux dapat dipasang dengan mudah dalam beragam komputer dengan keluarga prosesor yang sama.


Saat melakukan porting, kita akan menentukan lingkup pekerjaan:

  • Seberapa banyak keluarga ARM yang mesti didukung?
  • Seberapa banyak SoC yang mesti didukung?


Lalu kalau kita bilang BlankOn ingin di-port ke ARM, maksudnya apa?

Di sini, kita cukup pilih salah satu keluarga ARM yang ada di tangan para pengembang, dan dari situ sudah cukup klaim bahwa BlankOn di-port ke ARM. Paling tidak saya ada Raspberry Pi (ARM11) dan tablet dengan prosesor Amlogic AML8726-M (ARM Cortex-A9). Jadi kita mulai saja dari kedua sistem tersebut. Ini artinya kita harus mengembangkan dua jenis ARM yang berbeda (ARMv7 untuk ARM Cortex-A9 dan ARMv6 untuk Raspberry Pi).

Lalu bagaimana prosesnya secara umum?
Pertama kali adalah menyiapkan toolchain, yaitu seperangkat alat untuk melakukan kompilasi program. Toolchain harus dikonfigurasikan sesuai dengan jenis prosesor, gugus instruksi, dan varian kompilasi. Sebagai contoh, BlankOn hendak menggunakan konfigurasi hard-float untuk ARMv7 dan ARMv6. Maka, kita perlu dua buah konfigurasi yang berbeda.

Lalu, apa yang mesti dibangun ulang? Mari kita lihat bagan di bawah ini.

Itu adalah bagan sederhana sebuah sistem komputer yang umum. Untuk memastikan port kita berhasil atau tidak, maka kita perlu menyelesaikan port pada semua bagian pada bagan.

Boot loader
Ini adalah sebuah program kecil yang ditanam pada sistem komputer. Program ini dijalankan saat pertama kali komputer dinyalakan, sebelum kernel dimuat. Bootloader ini bertugas memuat sistem operasi atau bahkan memuat bootloader lain. Pada beberapa sistem, bootloader dikunci sehingga tidak dapat memuat sistem operasi lain selain sistem operasi yang disediakan pabrik. Untuk memudahkan pekerjaan kita, lebih baik gunakan perangkat yang bootloadernya tidak terkunci.

Kernel
Kernel adalah jantung sistem operasi. Dia yang mengatur bagaimana sebuah berkas ditulis, bagaimana sebuat paket data dikirim, bagaimana tombol pada papan tik dapat bereaksi, dan seterusnya. Jika perangkat yang kita targetkan memiliki perangkat keras tertentu, maka kita memerlukan penggerak (driver) untuk perangkat keras tersebut agar dapat diatur oleh kernel. Banyak SoC yang memerlukan penggerak dengan lisensi tidak bebas sehingga menyulitkan proses porting.

Userspace
Userspace adalah program-program yang dijalankan sistem dan pengguna akhir. Jika kita sudah memiliki program-program yang dibangun dengan gugus instruksi prosesor yang serupa dengan perangkat target kita, maka kita tinggal menyalin saja program-program tersebut. Namun bila tidak ada, kita harus membangun ulang semua program di userspace dengan gugus instruksi prosesor yang kita gunakan di perangkat target kita. Contohnya, paket-paket yang dikompilasi untuk Raspberry Pi harus dibangun ulang untuk perangkat tablet dengan ARM Cortex-A9.

Dari bagan di atas, bagian-bagian yang diarsir adalah bagian yang spesifik ada di perangkat target kita. Untuk setiap target yang kita inginkan, bagian yang diarsir tersebut harus kita sediakan. Jika kita ingin mendukung 5 buah tablet dengan konfigurasi berbeda, maka kita perlu 5 salinan bagian yang diarsir tadi khusus untuk masing-masing perangkat.

Lalu, setelah semua beres dan sistem dapat melakukan boot ke terminal, apakah kita stop di sini? Tentu saja tidak. Hal-hal yang didiskusikan di atas adalah baru pondasi dari keseluruhan port. Langkah selanjutnya adalah:

  • Memastikan performa perangkat berjalan baik: jaringan berjalan dengan benar dengan kapasitas yang sesuai spesifikasi, memori dan sistem pemberkasan tidak ada yang rusak/korup, tidak ada program yang beku, dan sebagainya
  • Optimasi penggunaan daya
  • Penyesuaian aplikasi. Jika kita menargetkan sebuah tablet, tentu aplikasi-aplikasi kita harus jalan di tablet dengan baik. Jika perangkat kita ada perangkat keras khusus misalnya sensor, maka sensor harus dapat dibaca dari aplikasi dengan baik


Jadi, begitulah kira-kira perjuangan yang harus dilakukan demi mengatakan klaim: Saya melakukan port <masukkan nama distro Anda di sini> ke ARM.

Senin, 01 April 2013

Referensi obyek di JavaScript

Mari jalankan nodejs di terminal lalu ketik:
> a = 12

(tanda > adalah prompt nodejs, tidak perlu diketik).

di layar akan tampil bahwa nilai a adalah 12.

Kemudian kita ketik:
> b = a

Tentu kita harapkan bahwa nilai b adalah sama dengan nilai a, yaitu 12.
Kita bisa pastikan dengan cara mengetik:
> b

Mestinya tampil angka 12.

Lalu bagaimana kalau kita ganti nilai a?
Ketikkan:
> a = 42

Berapa nilai b sekarang? 42 atau tetap 12?
Ketikkan lagi di layar:

> b

Maka akan tampil angka 12. Artinya, nilai b tetap walaupun nilai a diubah.

Mari kita coba lagi dengan jenis lain, yaitu string.
Mari kita ketik:
> a = "saya"

Kemudian kita buat variabel b dan isi dengan nilai a.
> b = a

Kemudian lihat isi nilai b dengan cara mengetik:

> b

Tentu nilai b adalah "saya".
Lalu bagaimana jika kita ubah nilai a?

> a = "sayur"

Periksa isi nilai b:

> b

Maka akan tampil tulisan "saya". Artinya, nilai b juga tidak berubah walaupun nilai a kita ganti.

OK. Sekarang mari kita bikin sebuah obyek.

> a = { nama: "cecep" }

Kemudian kita set variabel b dengan nilai a

> b = a

Kita periksa isi b:

> b
{ nama: 'cecep' }

Kemudian mari kita ubah nilai a menjadi:
> a.nama = "sodikin"

Periksa isi nilai a:

> a
{ nama: 'sodikin' }

Periksa isi b:
> b
{ nama: 'sodikin'}

Oh, ternyata sekarang isi b mengikuti isi a. Apa pun yang kita ubah di a, maka di b turut berubah, tidak seperti sebelumnya. Ini terjadi karena untuk jenis obyek, JavaScript akan menggunakan referensi. Ini mirip dengan pointer di bahasa C/C++. Ibaratnya, variabel b diikat dengan tali ke variabel a. Jika a diubah, maka saat membuka b, JavaScript akan mengikuti tali yang ada hingga ke ujungnya di variabel a, dan isinya dibaca. Jika bukan jenis obyek, isi nilai akan disalin mentah-mentah. Ibaratnya, setiap variabel memiliki kaleng. Setiap diset nilainya, nilai tersebut dimasukkan ke dalam kaleng. Jika nilai variabel yang ada di kaleng a diubah, maka nilai di kaleng di variabel b tidak terpengaruh.

Jika sekarang kita ubah jenis a ke jenis lain, maka jenis b akan tetap sebagai obyek dengan nilai yang tadinya dipegang oleh a.

> a = 12
> b
{ nama: 'sodikin' }

Sekarang bagaimana caranya kalau kita tidak ingin JavaScript mengikatkan tali ke obyek, namun benar-benar berlaku seperti kaleng? Silakan dijadikan PR. (Petunjuk, bisa gunakan Object.keys(b) untuk dapatkan semua kunci di obyek b, kemudian salin isi nilai yang ditunjuk oleh kunci-kunci tersebut ke obyek baru. Jangan lupa ini harus rekursif).