1 puan yazan GN⁺ 2025-01-10 | 1 yorum | WhatsApp'ta paylaş
  • SerenityOS çoğunlukla QEMU üzerinde iyi çalışıyordu, ancak gerçek bir dizüstü bilgisayarda önyükleme, hata ayıklama ve depolama erişiminden başlayarak tek tek takılınca donanım desteğindeki boşluklar ortaya çıktı
  • Deney hedefi Intel Celeron N4020, 4GB DDR4, 32GB eMMC ve 1366×768 TN ekrana sahip Dell 3100 Chromebook idi; beklenen Cr50 tabanlı kapalı kasa hata ayıklama bu kartta başarısız oldu
  • Cr50 yolu kapanınca RP2040 tabanlı Pi Pico cihazın içine yerleştirildi ve UART ile SPI flash’a doğrudan bağlanarak CircuitPython ve serprog ile PicoCCD adlı geçici bir hata ayıklama ve flashlama aygıtı oluşturuldu
  • İlk önyükleme günlükleri, PCI arkasındaki MMIO 16550 UART’ı doğrudan kullanmak zor olduğundan, ChromeOS EC’nin kaydettiği IO port 0x80 yavaş bir geçici çıktı kanalı olarak kullanılarak alındı
  • eMMC desteği SD/MMC başlatma farkları, eksik SDHCI güç denetimi ve yalnızca SD’ye özgü komutların devre dışı bırakılması sorunlarını aşarak kısmi bir grafik oturumuna kadar ulaştı; ancak performans, kararlılık ve yamaların düzenlenmesi hâlâ bekliyor

Gerçek donanım hedefi olarak seçilen Dell 3100 Chromebook

  • SerenityOS’a daha derin katılma sürecinde ilk göze çarpan zayıflık, QEMU’da çalışıyor ama gerçek donanım desteği yetersiz olmasıydı
  • UEFI desteği zaten spholz tarafından yürütüldüğü için buna dokunulmadı; bu çalışmada master dalındaki çekirdeğin TianoCore UEFI runtime’ı altında GRUB ile önyüklenmesi yeterliydi
  • Ana geliştirme makinesiyle aynı cihazda işletim sistemi hata ayıklamaktan kaçınmak istendi ve gerçekten günlük kullanıma yetecek kadar görece yeni bir donanım hedeflendi
  • Allegro’da ucuz bir Chromebook ararken Dell 3100 95 PLN’ye, yaklaşık 25 EUR’ya satın alındı
    • Intel Celeron N4020, 2 çekirdek, Hyper-Threading yok
    • 4GB DDR4
    • 32GB yerleşik eMMC
    • UHD600 IGP tarafından sürülen 1366×768 TN ekran
    • 2 USB-A, 2 USB-C, 3.5mm jak
    • Dell’in üst seviye iş dizüstülerinden daha iyi hissettiren klavye
  • Bu cihaz daha sonra octopus ana makine adıyla anıldı

Cr50 tabanlı hata ayıklama beklentisi ve başarısızlık

  • Chromebook seçmenin büyük nedenlerinden biri, Cr50 güvenlik çipi ve embedded controller’ın kapalı kasa hata ayıklama için yararlı özellikler sunmasıydı
  • 2018 sonrası neredeyse tüm Chromebook’larda SuzyQ kablosuyla USB-C portlarından biri hata ayıklama için kullanılabiliyor ve Cr50 genellikle üç ttyUSB aygıtı gösteriyor
    • Dahili Cr50 konsolu
    • AP konsolu, yani Chromebook’un seri portu
    • cros_ec konsolu, yani embedded controller
  • Amaç, dizüstünü açık bırakıp kablolar sarkıtmadan seri konsola erişmekti; cros_ec’nin tuş girişi emülasyonu ve güç durumu kontrolü de düşünülünce basit bir KVM biçimi bile mümkün görünüyordu
  • Gerçek octopus üzerinde Cr50 CCD çalışmadı
    • Yeni bir SuzyQ kablosu yapıldı ve lehim durumu başka bir Chromebook ile doğrulandı, ama başarısız oldu
    • octopus, Dell’in kart üzerindeki bazı dirençleri koymaması nedeniyle CCD’nin çalışmadığı az sayıdaki dizüstülerden biriydi
    • Bazıları belirli port yönü ve şarj cihazı bağlantı koşullarında sınırlı başarı bildirdi, ancak bu cihazda hiç çalışmadı
  • Daha sonra edinilen bilgilere göre eksik direncin USB köprüsünü değil yalnızca SPI flashlamayı etkilemesi gerektiği de söylendi; bu yüzden Cr50 debug’ın hiç çalışmamasının kesin nedeni hâlâ belirsiz

Pi Pico ile yapılan PicoCCD

  • Cr50 yolu kapanınca, cihaz içindeki boş alana sıradan bir Pi Pico kartının sığıp sığmayacağı kontrol edildi ve yeterince sığabileceği görüldü
  • Benzer dizüstü bilgisayarların şemalarına bakıldı, ancak octopus ile tam eşleşen bir şema yoktu
    • Karttaki büyük debug portlarından biri Intel ile ilgili JTAG ve test noktalarıydı, amaca uygun değildi
    • Diğeri Google Servo’ydu; ancak Google, Servo adı altında birçok debug probe çıkarmıştı ve belgeler de sınırlı olduğundan bulmak zordu
    • İlgili belge olarak Servo belgeleri incelendi
  • Glasgow’un UART applet’i ve frekans algılama etkinleştirilip, Linux /dev/ttyS1 üzerinden tekrar tekrar çıktı verirken şüpheli UART TX pad’leri doğrudan problandı
    • TX pad’i birkaç dakika içinde bulundu
    • RX, aktif gönderim gerektirdiği ve yanlış hatta dokunmak kartı resetleyebileceği için daha zordu; gerçekten de iki kez reset oldu
    • Daha sonra EC için RX/TX pinleri de yaklaşık 10 dakika içinde bulundu
  • Lehimlenen kablolar UV kürlenen epoksiyle sabitlendi ve 6 ay boyunca bağlantı sorunu yaşanmadı
  • RP2040’ın SPI çevre birimi de kullanılarak flash çipine 6 kablo lehimlendi; write-protect pinine giden iz kesilip GND’ye bağlanarak Cr50 izni olmadan yazma erişimi elde edildi
  • Yazılım olarak CircuitPython seçildi
    • Çünkü USB mass storage üzerinden script ve veri yüklenebiliyordu
    • UART’ı cdc_acm USB aygıtı olarak köprülemek kolaydı
    • SPI flash da bağlandığı için flashlama işlevi de gerekiyordu
  • Genel açık kaynak EEPROM ve SPI flashlama aracı olarak flashrom kullanıldı; SPI’yi UART üzerinden proxy eden serprog amaca uygundu
    • stacksmashing’in pico-serprog C uygulaması vardı, ancak BIOS her flashlandığında Pico’yu yeniden flashlamak gerekmesi uygun değildi
    • Bunun yerine serprog CircuitPython ile uygulandı ve Glasgow serprog applet’i büyük ölçüde referans alındı
  • Ortaya çıkan kod, hızlıca yapılmış kapalı kasa hata ayıklama çözümü PicoCCD olarak düzenlendi; depo Forgejo’daki PicoCCD üzerinde
  • WeirdTreeThing de benzer amaçlı RP2040 C kodu yazdı; onun PicoCCD sürümü de mevcut

SerenityOS önyükleme günlüklerini almak

  • Hata ayıklama için Alpine Linux kuruldu ve dışarıda derlenen SerenityOS çekirdeğini getiren temel yardımcı araçlar yapılandırıldı
  • Daha sonra bu yapı, build makinesinden artifact’leri otomatik indiren, çekirdeği açıp üzerine yazan ve kullanıcı alanı .tar dosyasını çıkaran GRUB girdilerine kadar büyüdü
  • Değişiklikten teste kadar olan yineleme süresi yazı anında yaklaşık 20 saniyeydi; bare metal hacking için oldukça iyi bir düzeydi
  • İlk GRUB önyükleme girdisi fiilen multiboot /Kernel serial_debug idi, ancak hem ekranda hem seri portta hiçbir çıktı yoktu
  • Ekran çıktısı sorunu için GRUB önyükleme girdisine insmod all_video ekleme yolu bulundu; bu tek başına çözmedi ama doğru yöndü
  • Seri çıktı eksikliği daha büyük bir sorundu
    • coreboot günlükleri birkaç saniye öncesine kadar geliyordu
    • Bu cihazın UART’ı geleneksel port-mapped 16550 değil, MMIO tabanlı 16550A idi
    • Linux günlüklerinde ttyS0 ve ttyS1, MMIO adreslerinde bulunan 16550A olarak görünüyordu
    • lspci içinde Intel Celeron/Pentium Silver Processor Serial IO UART Host Controller bir PCI aygıtı olarak görünüyordu

16550 UART ve port 0x80 kestirmesi

  • Geleneksel olarak IBM PC’nin harici aygıtları x86 CPU’nun port I/O alanına eşlenir ve outb ile inb gibi komutlarla erişilirdi
  • Birçok aygıt sonradan MMIO’ya taşındı, ancak seri portlarda yüksek hız rekabeti kritik olmadığından eski yöntem kaldı ve debug portu olarak kullanışlı oldu
  • Tipik bir ortamda outb 0x3f8, 0x41 gibi yazıldığında karşı tarafta A alınabilir; başlatması da kısa olduğundan küçük projelerde uygulaması kolaydır
  • octopus’un UART’ı PCI arkasındaki bir MMIO aygıtıydı ve SerenityOS önyüklemesinin erken aşamasında PCI başlatmanın tamamlanmasını beklemek zordu
    • SerenityOS’ta PCI bus uygulaması var, ancak önyükleme aşaması bunun için çok erkendi
    • Mevcut PCISerialDevice de MMIO bağlamında kullanılmamıştı
    • Debug çıktısı olmadan bu sürücüyü yazmak ideal değildi
  • ChromeOS cihazlarının embedded controller’ı IO port 0x80 üzerine yapılan tüm yazmaları günlükler
    • Bu port geleneksel olarak POST durum raporlamasında kullanılır
    • Anakartlardaki 7 segment önyükleme kodu göstergeleri port 80’i decode ederek çalışır
  • Linux’ta /dev/port’a byte yazan bir script ile varsayım test edildi ve cros_ec konsolunda ilgili byte okunabildi
  • SerenityOS’un başlangıç noktası olan Kernel/Arch/init.cpp civarına IO::out8(0x80, 1); gibi kodlar eklenerek ilerleme konumu izlendi ve Memory::MemoryManager::initialize(0); içinde çakıldığı noktaya kadar daraltıldı
  • Daha sonra seri yazma rutinindeki adresi 0x3f8 yerine 0x80 olarak değiştirme yolu denendi
    • Başta çok sayıda byte geliyordu, ancak cros_ec bunları güvenilir biçimde iletemediğinden overflow oluşuyordu
    • Daha ileride cros_ec günlük çıktısının kendisi de bozuluyordu
    • Gerçek seri çipten farklı olarak büyük bir buffer’ı olmadığı için
  • Her yazma arasına çok sayıda nop tabanlı wait state eklenerek sorun aşıldı
    • Tüm önyükleme mesajları yazdırıldığında birkaç saniyelik önyükleme birkaç dakikaya uzuyordu
    • Yine de bare metal debug için kabul edilebilir bir maliyet olarak görüldü
  • cros_ec günlük satırlarını otomatik parse edip ASCII’ye decode etmek için picocom, watch, grep, sed, cut, xxd birleşiminden oluşan tek satırlık bir Bash komutu kullanıldı

Framebuffer ve ilk grafik çıktı

  • Önyükleme günlükleri alındıktan sonra birkaç gün kod tabanını doğrudan okuyarak sorunu anlamaya çalışıldı, ancak sonunda topluluktan yardım istendi
  • spholz o sırada açık olan SerenityOS PR #24435’i gösterdi; ilgili branch ile build edilince generic framebuffer çalıştı
  • Ekranda, işlem başarısız olmuş ama başarılıymış gibi görünen bir durumun sonucu belirdi; ardından depolama sorunu asıl olarak ortaya çıktı

eMMC ve SD/MMC başlatma sorunu

  • Mevcut StorageManagement çökmesi, SD Host Controller başlatma hatasının ardından controller listesinin boş olması assertion’ına gidiyordu
    • Günlüklerde PCI: Failed to initialize SD Host Controller ve ASSERTION FAILED: !m_controllers.is_empty() görünüyordu
    • Sonuçta StorageManagement::enumerate_storage_devices() içinde kernel panic oluşuyordu
  • octopus’ta 32GB eMMC çipi vardı ve SerenityOS’ta zaten kısmi bir SD sürücüsü olduğundan MMC desteği eklemek yeterli olacak gibi görünüyordu
  • SD/MMC kart kullanmak için genel olarak üç unsur gerekir
    • Host Controller: Modern cihazlarda genellikle SD Association tarafından tanımlanan SDHCI
    • Host Controller’a bağlanan bus: Bu durumda PCI
    • Host ile kartın iletişim kurduğu protokol uygulaması
  • Çökme günlüklerine göre SerenityOS’ta ilk iki unsur vardı; kalan sorun protokol tarafındaydı
  • SD protokolünün açık spesifikasyonu var, ancak MMC 2007’de JEDEC standardı olduktan sonra resmi erişim ücretli hale geldi
  • SD ve MMC’nin başlatma dizileri farklıdır
    • SerenityOS, CMD0 gönderip yanıt bekleyerek başlıyordu; bunun hem SD hem MMC için geçmesi gerekir
    • Ardından voltaj ayarı için CMD8 gönderilir, ancak MMC bunu desteklemediğinden hata vermelidir
    • Bazı kaynaklar sonrasında kartı resetleyip MMC varsaymayı önerir
    • Diğer kaynaklar CMD8 ve CMD58 sonuçlarının kombinasyonuyla SD sürümü ve kapasite türünü de ayıran daha kapsamlı bir akış sunar
  • Gelişmiş uyumluluk kontrollerinin tamamı yerine yalnızca temel kontroller uygulandı

Eksik güç denetimi register’ı ve çözüm

  • MMC başlatma akışı özetle şu adımlardan oluşuyordu
    • Reset sonrasında clock’u 400KHz’e ayarla
    • 1ms bekle, ardından 74 clock daha bekle
    • CMD0 gönder ve yanıt bekle
    • Yanıttaki 31. bit 1 olana kadar CMD1’i tekrarla
    • Döngü bitince değeri Operating Conditions register’ı olarak kaydet
    • SD’ye özgü register sorgularını hariç tutup SD başlatma algoritmasına devam et
    • İsteğe bağlı olarak High-Speed uyumluluğunu algıla ve HS modlarından birini etkinleştir
  • Kod 4. adım civarına kadar gidiyordu, ancak sonrasında eMMC hiçbir isteğe yanıt vermiyordu
  • Birkaç gün boyunca neden bulunamadı; controller reset kodu kaldırılınca eMMC yanıt vermeye başladı ve sorun reset_host_controller() fonksiyonuna daraltıldı
  • Bu fonksiyondaki tuhaf nokta, standartta host_configuration register’ının bulunamamasıydı
    • Önceki kod, birkaç register’ı keyfi iki host_configuration grubunda toplamıştı
    • Başlatma da tamamen bitmemişti ve ilk grup basitçe 0’a ayarlanıyordu
  • İlk grupta kart güç düzenleyicisini kontrol eden Power Control register’ı yer alıyordu
    • eMMC kullanan tüm uygulamalar dahil bazı donanımlarda bu register, kartın kendisini açmak için gereklidir
    • Güç hattını doğrudan slota bağlayan başka tasarımlarda bu ayar yok sayılabilir
  • Geçici çözüm olarak host_configuration_0 içinde başlangıçta bulunan değer alınıp kullanıldı
  • Temel sorun, kartın gücü açılmadan iletişim kurulmaya çalışılmasıydı
  • Sonrasında yalnızca SD kartlar için geçerli bazı komutların bulunup devre dışı bırakılması birkaç saat daha sürdü; controller’dan daha anlamlı debug çıktısı gelmeye başlayınca kalan işler görece sıradan ilerledi

Güncel durum ve kalan işler

  • Sonunda SerenityOS çok yavaş şekilde, kısmen bozuk bir grafik oturumu açmayı başardı, ancak kısa süre sonra kilitlendi
  • Bu grafik oturumu sorunu ve framebuffer’ın yeniden normale döndürülmesi süreci sonraki yazıda ele alınacak
  • Tüm çalışma yaklaşık 6 ay süren bir öğrenme süreciydi; bu arada başka işler de yürütüldü
  • Sıradaki hedef yamaları düzenleyip yıl içinde upstream’e göndermek

1 yorum

 
GN⁺ 2025-01-10
Hacker News yorumları
  • NetBSD’nin sürücülerini özel bir çekirdeğe uyarlamanın nispeten kolay olduğunu okumuştum; Serenity de böyle bir yola gidebilir mi diye düşünüyorum.
    Yeni bir işletim sistemi için aygıt sürücüleri büyük bir engel.

    • Serenity’nin felsefelerinden biri, mümkün olduğunca her şeyi sıfırdan kendi yapmak olduğu için, NetBSD sürücüleri kolay uyarlanabilir ve lisansları uyumlu olsa bile muhtemelen o yolu seçmek yerine sürücüleri kendileri yazmayı tercih ederler.
    • Yeni ya da hobi amaçlı bir işletim sistemi için baştan Raspberry Pi gibi popüler bir tek kart bilgisayarı hedeflemek daha iyi olmaz mı diye merak etmiştim.
      Donanım yapılandırması neredeyse sabit olduğundan sürücü yazmak ya da almak ve sistemi test etmek daha kolay olur.
    • rump kernel/anykernel tam da böyle bir kavram.
      Sürücüleri yalnızca asgari temel destekle kullanıcı alanında çalıştırabiliyor.
      https://en.wikipedia.org/wiki/Rump_kernel
    • NetBSD tarafı güvenilir. libc’si çok temiz; birkaç projede birkaç kez kullanmıştım.
      Ama sürücü tarafını pek bilmiyorum.
    • Çözüm, iyi bir donanım seti seçmek ve mümkünse yazılımı yazan kişinin doğrudan sattığı bir cihaz belirleyip yalnızca o donanım için sürücü geliştirmek.
      Apple’ın başından beri genel olarak yaptığı yöntem bu gibi görünüyor ve tüketiciye yönelik Unix benzeri sistemler içinde büyük ölçekte başarılı olmuş tek örnek.
      System76 da neredeyse böyle bir örnek; Frame.work de benzer, ama işletim sisteminin kendisine daha az odaklanıyor.
  • Her şeyin aleyhte olduğu bir makinede çalışır hâle getirmek gerçekten muazzam bir hack işi ve yetenekli insanların çok büyük emek harcadığının sonucu gibi görünüyor.

  • Böyle yazıları okuyunca sürücüler ve işletim sistemi dünyasına nasıl girileceğini merak ediyorum.
    Çok karmaşık görünüyor; nereden başlayacağımı pek bilmiyorum.

    • Modern donanımla iletişim kurmak aslında oldukça basit sayılır; temel mesele donanım belleğini okumak ve yazmaktır.
      Buna bellek eşlemeli giriş/çıkış (MMIO) denir. Normal uygulamalarda çekirdek donanım belleğine doğrudan erişimi engellediği için bunu yapamazsınız.
      Başlamak için hedef CPU’ya makine kodu üretebilen Rust/C++/C/Zig gibi bir dil gerekir; çalışma zamanı ya da GC olmayan bir dil daha iyidir. Düşük seviyeli dillere yeniyseniz, çok örnek olduğu için C’yi öneririm.
      Hedef CPU’nun temel assembly’sini de öğrenmeniz gerekir; bazı komutlar üst seviye dillerin yerleşik fonksiyonları olarak sunulmayabilir.
      Sonra bir hello world çekirdeği yazarak CPU’nun çekirdeği nasıl başlattığını, çalışma modlarının ve yetki seviyelerinin nasıl ayrıldığını öğrenirsiniz.
      Ardından x86’da 64 bit komutları kullanmak için long mode’a geçmek gibi, CPU’yu istediğiniz biçimde yapılandırırsınız; genellikle bu aşamada sanal bellek de ayarlanır.
      Buraya kadar geldiğinizde CPU’nun işletim sistemiyle nasıl iç içe geçtiğine, kullanılabilir aygıtları nasıl listeleyeceğinize ve bellek konumlarını nasıl bulacağınıza dair fikir edinirsiniz; sonrasında dosya sistemi ve zamanlayıcı gibi yapılacak çok iş kalır.
      İşletim sistemi üzerinde çalışan yazılım ile işletim sistemi çekirdeği arasındaki fark, nihayetinde o kodu o anda çalıştıran CPU modudur; en yüksek yetkide normal uygulamaların kullanamadığı komutlar kullanılabilir.
    • Ben LDD ile başlamıştım. Yaklaşık 10 yıllık bir kitap ama hâlâ geçerliliğini koruyor.
      Daha sonra FreeBSD belgelerinin içinde gizli hazine gibi kaynaklar buldum; bunlardan FreeBSD Architecture Handbook ve FreeBSD Developers' Handbook özellikle faydalı olabilir.
      https://lwn.net/Kernel/LDD3/
      https://docs.freebsd.org/en/books/
    • Yaklaşık 15 yıl önce üniversitede işletim sistemi geliştirme dersi almıştım ve Minix kullanmıştık.
      Minix çok temiz yazılmıştır; çekirdeği de yaklaşık 5 bin satırdır ve birçok ders kitabında ele alınır.
      Basit bir sunucu uyguladım ve çekirdekle de uğraştım; Minix bir mikroçekirdek olduğu için çoğu sürücü bu şekilde çalışır.
      Ders materyallerini önceden okuyup derslere neredeyse hiç girmediğim hâlde 10 üzerinden 8 almıştım.
      NetBSD ve SerenityOS hakkında da çok iyi şeyler duydum; Andreas da geliştirmelerin büyük kısmını canlı yayınlarla yaptı.
      Nereden başlayacağınızı bilirseniz aslında kolaylaşıyor.
    • Açıkçası ilk adım, işletim sistemi, sürücü, aygıt gibi her bileşenin amacını anlamak.
      Örneğin bir aygıt sürücüsünün görevi, bilgisayarda çalışan başka programların belirli bir aygıta erişip onu denetleyebilmesi için bir arayüz sunmaktır.
      https://m.youtube.com/watch?v=juGNPLdjLH4 fena olmayan bir hızlandırılmış ders.
      Arduino gibi bir şeyle PC ile bilgi alışverişi yapan basit bir USB aygıtı da yapabilirsiniz. Örnek: https://m.youtube.com/watch?v=yTc2GLXfCOY
      Sonra ilgilendiğiniz alt sistemin ne yaptığını ve nasıl çalıştırılacağını anlayıp kod yazmanız yeterli. Depolama aygıtları, grafik aygıtları vb. buna girer.
      Raspberry Pi de bu tür deneyler için iyi bir başlangıç noktası olabilir. Örnek: Raspberry Pi için bare metal işletim sistemi yazmak https://github.com/babbleberry/rpi4-osdev
    • Bu öğretici gerçekten çok iyiydi.
      https://wiki.osdev.org/Bare_Bones
  • SerenityOS konseptini ve Ladybird tarayıcısını sevdiğim için bu ilerlemeyi görmek sevindirici.

    • Ne yazık ki artık ikisi ayrıldı.
      Ladybird yalnızca bağımsız bir proje hâline gelmekle kalmadı, artık SerenityOS’i hedef platform olarak da görmüyor.
      Ladybird kendi Serenity katmanını giderek azaltıp daha ana akım alternatiflerle değiştiriyor.
      Çoğunlukla Linux kullanan biri olarak Ladybird’ün Linux’ta gerçek bir alternatife dönüşmesini heyecanla bekliyorum.
      Ama bir SerenityOS hayranı olarak Ladybird’e giden enerji ve yeniliğin SerenityOS’ten uzaklaşması üzücü.
  • Chromebook hackleme konusunda yardıma ihtiyaç varsa chromium-os-dev posta listesine sorabilirsiniz.
    Birileri CCD’nin çalışmasını sağlamaya yardımcı olabilir gibi görünüyor.
    https://groups.google.com/a/chromium.org/g/chromium-os-dev?p...

  • Depthcharge önyükleyicisi de TFTP üzerinden ağdan boot etmeyi destekliyor.
    Kendiniz derleyip SPI’ye flashlamanız gerekiyor, ama çekirdeği yinelemeli geliştirmek için çok iyi bir özellik.
    https://chromium.googlesource.com/chromiumos/platform/depthc...

  • SerenityOS’in zaten gerçek donanımda çalıştığını sanıyordum; hâlâ tamamen QEMU içinde mi çalışıyor?

    • Geçmişte gerçek donanımda çalıştırıldığı doğru.
      Ancak bahsetmeye değer neredeyse hiç sürücü olmadığı için yalnızca en temel anlamda çalışıyordu, sadece belirli donanımlarda mümkündü ve muhtemelen pek de iyi çalışmıyordu.
      Bu girişim, en azından bir gerçek donanım platformunda güvenilir biçimde çalışmasını sağlamaya yönelik.
  • Serenity, uygulama biçimine katılmadığım zamanlar olsa da etkileyici olmaya devam ediyor.

  • Görmeye geldiğim ürkütücü şey tam da buydu.
    doas dd seek=$((0x$1)) bs=1 count=1 of=/dev/port < <(xxd -p -r <<< "$2")

    • Sıradan biri için o kodun ne anlama geldiğini gerçekten merak ediyorum.