1 poin oleh GN⁺ 2024-04-07 | 1 komentar | Bagikan ke WhatsApp
  • UEFIRC adalah klien IRC grafis yang berjalan di lingkungan pra-boot UEFI pada firmware motherboard sebelum sistem operasi menyala, dan menunjukkan bahwa bahkan di lingkungan untuk bootloader pun UI serta kemampuan jaringan yang mendekati aplikasi biasa bisa diwujudkan
  • Implementasinya memanfaatkan driver NIC dan stack TCP yang disediakan UEFI untuk boot lewat jaringan, sementara backend jaringan vmnet untuk QEMU memungkinkan proses pengembangan
  • Bagian yang paling sulit adalah menangani protokol TCP UEFI di Rust, dengan status global, callback reentrant, buffer scatter-gather, serta event, token, handle, dan protokol yang saling terkait secara kompleks
  • GUI-nya merupakan adaptasi toolkit GUI Rust dan renderer TrueType milik axle ke UEFI, dan peningkatan libgui juga dilakukan untuk input mouse, scrollbar, serta rendering teks pada scroll view
  • Hasil akhirnya lebih mirip proyek lelucon yang sangat serius daripada klien IRC yang benar-benar praktis, tetapi tetap menjadi alat untuk mengeluhkan stack TCP/IP UEFI dari dalam UEFI melalui IRC

Apa yang dilakukan UEFIRC

  • UEFIRC adalah klien IRC grafis yang berjalan di UEFI
  • Ditulis dalam Rust dan memanfaatkan toolkit GUI serta renderer TrueType yang dibuat untuk axle user space
  • Dapat terhubung ke server IRC untuk mengobrol dan membaca pesan
  • Pengembangannya menggunakan backend jaringan vmnet untuk QEMU

UEFI sebagai panggung eksekusi

  • Bootloader sistem operasi dimuat dengan bantuan firmware yang disimpan di ROM motherboard
  • BIOS lama memiliki berbagai keterbatasan, dan standar UEFI dibuat untuk menggantikannya
    • BIOS mengharuskan bootloader dimulai dalam mode 16-bit
    • Ada juga syarat agar loader tahap pertama muat dalam 512 byte
  • UEFI menempatkan bootloader langsung di lingkungan 64-bit sejak awal, dan menyediakan API seperti pergantian resolusi layar VESA, alokasi memori, serta akses ke filesystem EFI
  • Ini adalah kemajuan besar dibanding BIOS, meski juga sering dinilai terlalu rumit dalam perancangannya

Memakai ulang fitur boot jaringan untuk IRC

  • Beberapa bootloader dapat memuat sistem operasi lewat jaringan alih-alih dari block device lokal
  • Untuk mendukung kasus penggunaan ini, firmware UEFI harus menyertakan stack jaringan
    • driver NIC
    • implementasi TCP
    • API agar aplikasi yang berjalan di lingkungan pra-boot dapat mengakses stack tersebut
  • Karena bootloader tidak harus selalu memuat sistem operasi, klien IRC juga bisa dijalankan di lingkungan yang sama

Sulitnya menangani TCP UEFI di Rust

  • Bagian paling rumit dalam proyek ini adalah mengimplementasikan klien protokol TCP UEFI dalam Rust
  • Protokol TCP UEFI menuntut masa hidup data dan interaksi yang sulit dijelaskan ke Rust
    • status global
    • callback reentrant
    • buffer scatter-gather
    • event, token, handle, dan protokol
  • Kode Rust diuji selama beberapa hari untuk menghilangkan kebocoran memori dan use-after-free pada buffer penerimaan TCP

Kebingungan NOTIFY_SIGNAL dan NOTIFY_WAIT

  • API event UEFI sulit ditebak perilakunya hanya dari nama
  • Jika NOTIFY_SIGNAL ditetapkan, callback dipanggil saat event terjadi, dan penggunaan wait() menjadi error
  • Jika NOTIFY_WAIT ditetapkan dan wait() dipanggil, UEFI dapat memanggil callback berkali-kali sebelum event terjadi, lalu wait() akan terlepas ketika event benar-benar terjadi
  • Kedua mode ini memberi makna yang sepenuhnya berbeda bahkan pada callback yang sama
    • NOTIFY_SIGNAL: event sudah terjadi, saatnya melakukan pekerjaan berikutnya
    • NOTIFY_WAIT: event belum terjadi, saatnya mendorong proses agar terus berjalan
  • Untuk melakukan buffering data paket yang diterima secara asinkron, akhirnya digunakan loop NOTIFY_WAIT bersama timer timeout singkat

Dukungan mouse dan kursor

  • Mouse tidak wajib untuk klien IRC, tetapi membuat aplikasi terasa lebih interaktif
  • Dengan Simple Pointer Protocol milik UEFI, pergerakan mouse dan input tombol dapat dibaca, lalu umpan balik posisi kursor dimasukkan ke GUI
  • Simple Pointer Protocol tidak mendukung scroll wheel
    • Di UEFIRC, pengguna harus memakai tombol panah atau menyeret scrollbar dengan kursor
  • Pada firmware UEFI OVMF standar, event mouse tidak bisa diperoleh, sehingga dibangun firmware UEFI kustom yang menyertakan driver dan protokol yang diperlukan seperti UsbMouseDxe
  • Agar UEFIRC bisa diuji di QEMU, firmware UEFI tersebut juga diunggah ke rilisan

Penskalaan gerakan mouse

  • Driver mouse melaporkan perubahan posisi, bukan posisi absolut
  • Jika delta_x dan delta_y langsung dijumlahkan begitu saja dengan penskalaan linear, hasilnya terasa lamban
  • Sistem operasi biasanya memakai penskalaan yang memungkinkan gerakan cepat sekaligus penyesuaian yang halus
  • Pada implementasi contoh, besar gerakan kursor ditingkatkan dengan mengalikan nilai log2() dari jumlah nilai absolut perpindahan
  • Kursor dengan gerakan linear mudah membuat seluruh lingkungan terasa lambat dan kurang responsif

Pemodelan pesan IRC

  • Pemodelan pesan IRC tergolong cukup sederhana dan menyenangkan
  • IRC menggunakan format baris berbasis teks sehingga mudah diparse
  • Namun, akibat ekstensi selama puluhan tahun, ada juga beban karena hanya sebagian yang benar-benar distandardisasi

Menggunakan libgui di UEFI

  • Toolkit GUI Rust milik axle sudah cukup banyak dikerjakan agar bisa dipakai juga di luar konteks axle, jadi menjalankannya di UEFI bukan hal yang terlalu sulit
  • Pekerjaan utamanya adalah menyediakan implementasi AwmWindow yang bisa digunakan di dalam UEFI
  • Setelah itu, berbagai fitur libgui bisa dimanfaatkan apa adanya
    • manajemen event
    • rendering font
    • komposisi layer
    • dekorasi view
    • komponen kompleks seperti scroll view

Scrollbar dan rendering teks pada scroll view

  • libgui berbasis C milik axle sudah memiliki fitur scrollbar, tetapi versi Rust-nya masih kekurangan sebagian kemampuan
  • Karena interaksi utama UEFIRC terjadi di scroll view berisi teks, fitur scrollbar diimplementasikan kembali di Rust libgui
  • Scroll view memiliki biaya rendering piksel yang lebih besar dibanding view berukuran tetap
    • Untuk view ukuran tetap, cukup bayangkan buffer RGB berukuran width * height
    • Scroll view harus menangani kanvas yang bisa meluas tanpa batas
  • Toolkit GUI Rust axle menangani scroll view secara berbasis tile
    • Setiap tile adalah buffer piksel persegi dengan lebar ratusan piksel
    • Hanya tile yang diperlukan untuk area tempat konten benar-benar dirender yang dialokasikan
    • Tile yang terlihat dihitung lalu disusun menjadi gambar akhir
  • Jika renderer TrueType memanggil putpixel() untuk setiap piksel glif, scroll view tidak bisa mengetahui seluruh area render sebelumnya sehingga menjadi tidak efisien
  • Untuk mengatasinya, polygon stack ditambahkan ke unit gambar dasar seperti garis, lingkaran, dan persegi panjang
    • Scroll view bisa mengetahui bahwa poligon besar akan digambar dan mengalokasikan tile yang diperlukan lebih dulu
    • Menjadikan pengisian poligon arbitrer sebagai primitif dasar memang terasa kurang ideal, tetapi secara praktis bekerja dengan baik

libgui yang membaik selama pembuatan UEFIRC

Hasil yang sepenuhnya tidak perlu

  • Klien IRC itu sendiri adalah proyek lelucon yang sangat serius, sehingga kegunaan praktisnya tidak tinggi
  • Saat kesal pada stack TCP/IP UEFI, ini bisa dipakai sebagai alat untuk menyampaikan keluhan itu
  • Sebagai penutup, penulis masuk ke kanal IRC pengembangan UEFI #edk2 dari dalam UEFI dan meninggalkan sapaan

1 komentar

 
GN⁺ 2024-04-07
Pendapat Hacker News
  • Sekadar iseng, saya membuat klien IRC grafis yang hanya berjalan di lingkungan sebelum boot UEFI, lengkap dengan fitur berlebihan seperti font TrueType, kursor, dan dekorasi GUI.
    Awalnya ini proyek untuk mencoba sesuatu yang cepat dan ringan karena lelah membuat penerima GPS dari nol, tetapi seperti biasa, ternyata memakan waktu jauh lebih lama dari perkiraan.
    Saya juga menghabiskan cukup banyak waktu untuk visualisasi di artikel yang menunjukkan cara memodelkan scroll view dan merendernya ke viewport statis; semoga kalian menikmatinya.
    Awalnya, dengan ide “mari memaksakan sesuatu yang tidak semestinya masuk ke UEFI”, saya terpikir membuat klien Twitter, tetapi karena sudah ada orang yang membuatnya dengan baik memakai protokol HTTP UEFI, saya memutuskan menghindari HTTP.
    Jadi saya memilih IRC, yang berjalan di atas TCP dan juga punya nuansa media sosial yang sama sekali tidak cocok dengan lingkungan sebelum boot.

    • Katanya “rasanya tidak boleh berada bahkan di dekat lingkungan sebelum boot”, tetapi kalau ingin meminta bantuan untuk masalah boot, ini justru tampak seperti tempat yang tepat.
    • Saya ingin membuang sistem operasi yang kelewat besar dan segala fitur acak, lalu beralih ke UEFI yang lebih kecil dan sederhana. Startup juga akan lebih cepat dan pengembangan “embedded” jadi lebih mudah.
      Tentu saja bercanda. Setidaknya sebagian.
      Saya minimalis, jadi tidak butuh GUI atau mouse; UEFI pun rasanya sudah lebih banyak dari yang saya perlukan.
      Klien Twitter yang disebutkan ada di sini: https://github.com/arata-nvm/mitnal
    • Kalau sebuah software terlalu besar untuk dijejalkan ke UEFI, berarti sejak awal semuanya adalah software bloat yang tidak perlu. Dulu dua floppy 360KB saja sudah cukup.
    • Benar-benar keren. Sejak dulu saya penasaran apakah kredensial VPN bisa disimpan di UEFI, lalu sistem terhubung ke server untuk melakukan boot jaringan PXE.
      Ini tampak seperti cara yang cukup bagus, dan mungkin aman untuk diizinkan, agar sistem jarak jauh yang instalasinya benar-benar rusak dan tidak bisa boot normal dapat dipulihkan otomatis.
    • Saya lebih penasaran dengan cerita soal penerima GPS yang dibuat dari nol.
  • Sangat bagus. Ini juga memperlihatkan dengan baik bahwa di bawah sistem yang dibayangkan kebanyakan orang, ada software yang lebih rumit dan kuat daripada yang diduga.
    Orang sering keliru menganggap sistem operasi sebagai “lapisan terbawah” dari stack software, padahal sebenarnya ada kode sejenis firmware yang benar-benar memiliki sistem.
    Kadang kode itu selesai bekerja lalu menghilang, kadang tetap berada di sana sepanjang sistem menyala dalam keadaan yang bahkan terasa transparan bagi sistem operasi.
    Ada sikap “itu cuma kode low-level untuk menjalankan perangkat, tidak ada hal serius yang akan terjadi di sana”, tetapi kalau bahkan klien IRC bisa dimasukkan ke bawah sana, berbagai hal jahat lain pun cukup mudah dibayangkan.

  • “Kenapa?” Maksudnya, “kenapa” itu pertanyaan macam apa? Saya datang ke HN untuk melihat semangat seperti ini.
    “Kesadaran paling menakutkan datang menghampiri. Tidak ada alasan apa pun untuk hal yang kulakukan. Aku tahu kenapa aku melakukannya. Aku melakukannya hanya karena kupikir itu akan menyenangkan. Tapi mereka akan bertanya ‘kenapa kau melakukan hal seperti ini’, dan kalau aku tidak punya alasan yang cukup masuk akal, mereka mungkin akan memasukkanku ke rumah sakit jiwa.” — Boyd Rice

  • Tidak perlu merendahkan diri sendiri. Di sini ada proyek klien command-and-control botnet.
    UI-nya memang agak lucu.

  • Benar-benar keren. Saya tidak tahu UEFI API semudah ini diakses dan terdokumentasi sebaik ini.
    Saya penasaran seperti apa siklus pengembangannya. Sepertinya dijalankan di VM, tetapi apakah setiap kali menjalankan klien harus “boot” ulang?

    • Biasanya loop kerjanya adalah mem-boot instance QEMU yang memuat aplikasi UEFI.
      Skrip eksekusi utama membuat ulang filesystem EFI berisi build baru UEFIRC, lalu memberikannya ke QEMU.
      Namun saat membuat GUI, overhead ini jadi cukup merepotkan, jadi saya mengatur agar aplikasi bisa dibuild untuk dua target: UEFI murni dan lingkungan host yang berjalan di Mac.
      Dengan mengubah build flag, toolkit GUI bisa menggambar langsung ke framebuffer yang disediakan UEFI, atau terhubung ke window system Mac untuk mengirim dan menerima event.
      Overhead pendekatan dual target ini juga terlihat di entry point: https://github.com/codyd51/uefirc/blob/main/src/main.rs
      Parsing pesan IRC tidak membutuhkan dekorasi khusus, jadi saya mengembangkannya sebagai kumpulan unit test yang langsung berjalan di Mac; sebagian ada di sini: https://github.com/codyd51/uefirc/blob/main/src/irc/response...
    • QEMU bisa menjalankan aplikasi UEFI.
  • Suatu hari saya ingin menyelesaikan pembuatan sistem operasi untuk bot IRC saya yang masih berjalan.
    Mungkin ini hal paling tidak berguna untuk dikatakan, tetapi gerakan mouse non-linear, alias akselerasi, adalah pengaturan pertama yang saya matikan saat mem-boot sistem operasi baru. Anehnya, itu benar-benar membuat tangan saya sakit.
    Misalnya di Mac ada linearmouse yang gratis, dan di Windows cukup matikan akselerasi. Di Linux tentu saja mudah.
    Kalau memakai akselerasi mouse, sulit membangun rasa pemetaan antara jarak gerak mouse dan jarak perpindahan di layar; dalam jangka panjang, menurut saya lebih efisien memakai tanpa akselerasi.
    Saya mempelajarinya dari para gamer, dan saya rasa para gamer masih punya alasan bagus untuk melakukannya.

    • Saya tidak mengubah pengaturan mouse, jadi tidak tahu nilai default-nya apa, tetapi saya masih bisa mengklik area layar yang tersembunyi dengan tepat.
      Rasanya kepekaan akan terbiasa ke arah mana pun. Seperti pedal gas mobil yang biasanya tidak langsung dipetakan ke kecepatan.
  • Kalau bertanya “kenapa?”, itu karena saat UEFI pertama diperkenalkan, aplikasi low-level seperti ini memang dijanjikan.
    Pihak yang membuat UEFI juga bermimpi menggantikan mini OS khusus internet berbasis Linux yang disediakan sebagian vendor dan bisa diakses dengan menekan tombol tertentu saat boot. Saya tidak ingat namanya.

    • Itu adalah fitur Quick View / Quick Boot yang dulu ada di tempat seperti Dell. Biasanya langsung boot ke beberapa aplikasi produktivitas.
      Saya pernah melihat video YouTube yang membahasnya secara mendalam; seingat saya awalnya berupa Linux yang diperkecil atau OS kustom lain, lalu belakangan dipindahkan menjadi aplikasi UEFI, dan akhirnya trennya mereda.
  • Artikelnya bagus. Saya jadi teringat lelucon April Mop bootloader barebox dua tahun lalu: jika semua target boot lain gagal, fiturnya akan menghubungkan ke #barebox[1].
    Fokus mereka adalah menambahkan dukungan TCP ke barebox, dan tidak ada elemen GUI keren seperti di sini.
    Antarmukanya hanya command line, dan jika barebox dibuild sebagai payload EFI, ia bisa menggambar di atas EFI GOP.
    [1]: https://lore.barebox.org/barebox/20220401145902.GF4351@telli...

  • Saya langsung teringat video terbaru Cathode Ray Dude. Video itu membahas “klien email” HP, QuickLook, yang sebenarnya adalah plugin Outlook, dan produk itu juga diimplementasikan serta dirilis dengan cara seperti ini: https://www.youtube.com/watch?v=ssob-7sGVWs
    Video tersebut juga menunjukkan hal-hal lebih aneh yang dilakukan HP. Namun proyek ini bahkan menyelesaikan bagian sulit yang dihindari QuickLook, yaitu networking.

  • Visualisasi di artikelnya luar biasa bagus dan mengesankan.