Tuesday, September 1, 2026

SGI O2: PROM'dan bootp ile IRIX Kurtarmaya

SGI O2'yi component video capture denemek için yeniden kurduğumda bir dizi sorunla karşılaştım. Bunları çözdükten sonra makineyi ağa bağladım; IRIX ortamını düzenleyip Nekoware ve wget kurulumuna kadar ilerledim. Fakat ertesi gün sistemi açtığımda öncekilerden farklı boot hatalarıyla karşılaştım. Böylece tek bir arıza hikâyesi değil, peş peşe yaşanan iki ayrı kurtarma süreci ortaya çıktı: önce SGI'yi yeniden kullanılabilir hâle getirmek, ardından yeni önyükleme hatalarını ağ üzerinden IRIX kurulum ortamına girerek çözmek.

Yıllar Sonra İlk Açılış

PROM monitöründe önce hinv ile donanım envanterine baktım. Sistem IP32 olarak kendisini, 256 MB belleği ve SCSI aygıtlarını görüyordu. Gerçek sistem diski SCSI ID 2 üzerindeydi. Buna karşılık önyükleme denemelerinde media not loaded, no recognizable filesystem, Unable to execute ... /unix ve SASH ile ilgili hatalar geliyordu.

PROM donanım envanteri: IP32 sistem, 256 MB RAM ve SCSI aygıtları.
PROM donanım envanteri: IP32 sistem, 256 MB RAM ve SCSI aygıtları.
İlk açılışta karşılaşılan disk ve önyükleme hataları.
İlk açılışta karşılaşılan disk ve önyükleme hataları.
SASH ve /unix yolları denenirken alınan media/file hataları.
SASH ve /unix yolları denenirken alınan media/file hataları.
printenv çıktısı: bazı önyükleme değişkenleri yanlış diski gösteriyor.
printenv çıktısı: bazı önyükleme değişkenleri yanlış diski gösteriyor.
Değişkenler disk(2)'ye çevrildikten sonra görülen SASH relocation/bootfile hatası.
Değişkenler disk(2)'ye çevrildikten sonra görülen SASH relocation/bootfile hatası.
IRIX 6.5 IP32 PROM ekranında CD-ROM ve SASH denemeleri.
IRIX 6.5 IP32 PROM ekranında CD-ROM ve SASH denemeleri.

PROM'da Kaybolan HDD Ayarları

printenv çıktısı sorunun ilk kısmını gösterdi: SystemPartition ve OSLoadPartition değişkenleri disk(1) tarafına kaymışken gerçek IRIX diski disk(2) idi. kernname ise disk(2)'yi gösteriyordu; yani PROM ortamındaki yollar kendi aralarında da tutarlı değildi.

Önyükleme değişkenlerini gerçek diske göre yeniden girdim:

setenv SystemPartition pci(0)scsi(0)disk(2)rdisk(0)partition(8)
setenv OSLoadPartition pci(0)scsi(0)disk(2)rdisk(0)partition(0)
setenv OSLoader sash
setenv OSLoadFilename /unix
setenv OSLoadOptions auto
setenv AutoLoad Yes
setenv kernname pci(0)scsi(0)disk(2)rdisk(0)partition(0)/unix

SystemPartition volume header içindeki standalone araçları, OSLoadPartition kök bölümü, kernname ise yüklenecek IRIX çekirdeğini gösteriyor. Bunlardan biri yanlış SCSI ID'ye baktığında disk fiziksel olarak görülse bile sistem açılmıyor.

Sorun Yalnızca PROM Değişkenleri Değilmiş

Disk yollarını düzeltmek tek başına yeterli olmadı. Bu kez SASH tarafında relocation error, invalid argument ve invalid bootfile mesajları gördüm. Bir noktadan sonra güç kablosunu takar takmaz sistem kendiliğinden çalışıyor, ön panel LED'i kırmızı yanıp sönüyor ve normal açılışa geçemiyordu. Bu aşamada yalnızca yazılım ayarıyla uğraşmayı bırakıp donanım tarafını kontrol ettim.

RTC/NVRAM, PROM Reset ve RAM'ler

İlk şüphelerden biri Dallas DS1687 RTC/NVRAM entegresiydi. Dahili pil hattını ölçtüğümde yaklaşık 3,05 V gördüm. Bu değer tamamen bitmiş bir pil göstermiyordu; dolayısıyla arızayı yalnızca “RTC pili ölmüş” diye açıklamak mümkün değildi.

Anakartı çıkarıp RTC/NVRAM bölgesini inceledim. Kartı kaldırmaya yarayan mandallardan birinin kırılması nedeniyle bunun elektriksel bir kilit olup olmadığından da şüphelendim; fakat mandalı kesin arıza nedeni yapacak bir bulgu yoktu.

Anakart kızağı ve arka bağlantı bölgesi.
CDRW konfigürasyon jumperları.
Sistemin kimlik etiketi.
Yamaha CDRW.
PROM donanım envanterinin yeniden kontrolü.
PROM donanım envanterinin yeniden kontrolü.
İşlemci, bellek ve SCSI aygıtlarının kontrolü.
İşlemci, bellek ve SCSI aygıtlarının kontrolü.
Donanım envanteri: disk ve CD-ROM aygıtları.
Donanım envanteri: disk ve CD-ROM aygıtları.
Anakart üzerindeki Dallas RTC/NVRAM entegresi.
Anakart üzerindeki Dallas RTC/NVRAM entegresi.
DS1687'nin söküldükten sonraki pinleri.
DS1687'nin söküldükten sonraki pinleri.
Dallas DS1687-5 RTC/NVRAM.
Dallas DS1687-5 RTC/NVRAM.
DS1687 pinlerinin yan görünümü.
DS1687 pinlerinin yan görünümü.
RTC/NVRAM entegresinin diğer yüzü.
RTC/NVRAM entegresinin diğer yüzü.
DS1687 üzerinde yapılan fiziksel inceleme.
DS1687 üzerinde yapılan fiziksel inceleme.
Entegre çevresinden çıkarılan dolgu parçaları.
Dallas alt yüz.
RTC/NVRAM entegresinin sabitlenerek kontrol edilmesi.
RTC/NVRAM entegresinin sabitlenerek kontrol edilmesi.
DS1687 üzerindeki çalışma.
DS1687 voltaj ölçümü için yontma.

Sonra PROM ayarlarını sıfırladım ve RAM modüllerini tamamen söküp yeniden oturttum. İşlemleri peş peşe yaptığım için sistemi tek başına PROM resetinin mi yoksa RAM temasının mı düzelttiğini kesin olarak ayıramıyorum. Bildiğim şey, RAM'ler yeniden takıldıktan ve PROM tarafı temizlendikten sonra makinenin yeniden normal açılış sürecine döndüğü.

  1. PROM'daki hatalı HDD yollarını tespit edip disk(2)'ye göre düzelttim.
  2. DS1687 RTC/NVRAM pil hattını ölçtüm: yaklaşık 3,05 V.
  3. PROM ayarlarını sıfırladım.
  4. RAM modüllerini söküp yeniden oturttum.
  5. Disk yollarını tekrar doğrulayıp sistemi açtım.

IRIX Yeniden Açıldı

RAM/PROM işlemleri öncesindeki başarısız açılış ekranı.
RAM/PROM işlemleri öncesindeki başarısız açılış ekranı.
RAM'ler yeniden oturtulduktan sonraki donanım kontrolü.
RAM'ler yeniden oturtulduktan sonraki donanım kontrolü.
PROM komutları ve disk yollarının tekrar sınanması.
PROM komutları ve disk yollarının tekrar sınanması.
Önyükleme değişkenlerinin doğrulanması.
Önyükleme değişkenlerinin doğrulanması.
Disk ve /unix önyükleme denemesi.
Disk ve /unix önyükleme denemesi.
Sistemin yeniden PROM menüsüne ulaşması.
Sistemin yeniden PROM menüsüne ulaşması.

Sistem açıldıktan sonra PROM/HDD değişkenlerini IRIX içinden de tekrar kontrol ettim. Aşağıdaki görüntüde SystemPartition, OSLoadPartition, OSLoader, OSLoadFilename ve kernname değerlerinin disk(2) üzerinde tutarlı hâle geldiği görülüyor.

Düzeltilen SGI PROM HDD ve IRIX önyükleme değişkenleri.
Sistem açıldıktan sonra doğrulanan PROM/HDD değişkenleri. IRIX diski scsi(0)disk(2) yolunda.

Makine ayağa kalkınca asıl ikinci aşamaya geçtim. IRIX tarafındaki ağ ayarları yarım yamalak durumdaydı: sistem yönlendiriciye ve doğrudan IP adreslerine ulaşabiliyor, buna rağmen alan adlarını çözemiyordu. Üstelik normal kullanıcı hesabında ping bile “Command not found” diyordu. Buradan devam edip ağ, DNS, kabuk ayarları ve Nekoware paket kurulumunu tek seferde toparladım.

Bu yazı IRIX'in eski UNIX alışkanlıklarıyla modern ağın birbirine sürttüğü yerleri, yaptığım yanlış denemeleri ve çalışan son düzeni içeriyor. Ekran fotoğraflarını özellikle sırayla bıraktım; komutların gerçek sistemdeki karşılığını takip etmek isteyen için küçük bir kurulum günlüğü oldu.

Ağ Arayüzü ve /etc/hosts

Önce root oldum ve ağ servisini, makine adını, arayüzü ve yönlendirme tablosunu kontrol ettim. Makineye 192.168.1.50 adresini verdim; varsayılan ağ geçidi 192.168.1.1. /etc/hosts içinde hem localhost hem de SGI'ın kendi adı doğru IP ile bulunmalı. Ben makine adını sgi-irix olarak kullandım.

su root
hostname
ifconfig -a
netstat -rn
cat /etc/hosts
/usr/etc/ping 192.168.1.1

IRIX'te bazı yönetim komutları /usr/etc altında. Root ortamında bulunan bir komut normal kullanıcıda PATH'e girmemiş olabiliyor. Bu yüzden “ping yok” sonucu ağ aracının kurulu olmadığı anlamına gelmiyor; önce /usr/etc/ping ile denemek gerekiyor.

İlk durum: ağ servisi ve DNS çözümleme hatası.
İlk durum: ağ servisi ve DNS çözümleme hatası.
/etc/hosts ve makine adı kontrolü.
/etc/hosts ve makine adı kontrolü.
/etc/hosts dosyasının düzenlenmesi.
/etc/hosts dosyasının düzenlenmesi.
ec0 arayüzü ve 192.168.1.50 adresi.
ec0 arayüzü ve 192.168.1.50 adresi.
192.168.1.1 ağ geçidine ping testi.
192.168.1.1 ağ geçidine ping testi.
/etc/nsswitch.conf içindeki çözümleme sırası.
/etc/nsswitch.conf içindeki çözümleme sırası.
DNS sunucuları ve doğrudan IP erişimi.
DNS sunucuları ve doğrudan IP erişimi.
IP çalışırken alan adı çözümlemesinin başarısız olması.
IP çalışırken alan adı çözümlemesinin başarısız olması.
nslookup çalışıyor; nsd önbelleği yeniden yükleniyor.
nslookup çalışıyor; nsd önbelleği yeniden yükleniyor.
nsd süreci ve yapılandırma dosyalarının kontrolü.
nsd süreci ve yapılandırma dosyalarının kontrolü.
nsd günlüğündeki domain/search path uyarısı.
nsd günlüğündeki domain/search path uyarısı.

IP Çalışıyor, DNS Çalışmıyor

Ağ geçidine ve 8.8.8.8 adresine ping başarılıydı. Yani Ethernet, IP adresi ve route tarafı çalışıyordu. Buna karşılık ping google.com hâlâ “Cannot resolve” hatası veriyordu. /etc/resolv.conf içine DNS sunucularını ekledim:

nameserver 8.8.8.8
nameserver 1.1.1.1

İlginç tarafı, nslookup google.com cevap veriyor ama normal uygulamalar alan adını çözemiyordu. IRIX isim çözümlemeyi doğrudan yalnızca resolv.conf üzerinden değil, nsd ve /etc/nsswitch.conf üzerinden yürütüyor. nsd günlüklerinde “no domain or search path in resolv.conf” uyarısını görünce dosyaya yerel ağ için bir arama alanı ekledim ve servisi yeniden yükledim.

search local
killall -HUP nsd
/etc/init.d/network stop
/etc/init.d/network start
/usr/etc/ping google.com

Buradaki local yalnızca ev ağı için kullandığım arama alanı. Kendi DNS alanınız varsa onu yazmanız gerekir. Bu düzeltmeden sonra hem IP hem alan adı çözümlemesi çalıştı.

PATH, Komut Geçmişi ve tcsh

Normal kullanıcı hesabında ping komutunun bulunmamasının nedeni PATH'ti. /usr/etc dizinini kullanıcı ortamına ekledim. Ardından her oturumda yukarı/aşağı oklarla komut geçmişini kullanabilmek için tcsh ayarlarını kalıcılaştırdım.

which tcsh
echo $SHELL
set path = ( /usr/etc $path )
set history = 100

Bu satırları kullanıcı hesabındaki ~/.cshrc dosyasına ekledim ve yeni oturum açmadan denemek için source ~/.cshrc çalıştırdım. Sonuçta ping doğrudan çağrılabildi, komut geçmişi çalıştı ve istemde makine adı görünür hâle geldi.

Kullanıcı kabuğunda ping komutunun PATH içinde bulunmaması.
Kullanıcı kabuğunda ping komutunun PATH içinde bulunmaması.
/usr/etc/ping komutunun doğrudan çalıştırılması.
/usr/etc/ping komutunun doğrudan çalıştırılması.
Ağ geçidine kullanıcı hesabından başarılı ping.
Ağ geçidine kullanıcı hesabından başarılı ping.
Ağ bağlantısının kararlı hâle gelmesi.
Ağ bağlantısının kararlı hâle gelmesi. (olmalı :P)
PATH değişkenine /usr/etc eklenmesi.
PATH değişkenine /usr/etc eklenmesi.
Kullanıcı .cshrc dosyasının incelenmesi.
Kullanıcı .cshrc dosyasının incelenmesi.
Komut geçmişi ve istem ayarlarının eklenmesi.
Komut geçmişi ve istem ayarlarının eklenmesi.
Yeni .cshrc ayarlarının source ile yüklenmesi.
Yeni .cshrc ayarlarının source ile yüklenmesi.
tcsh testi, tarih ve internet bağlantısının doğrulanması.
tcsh testi, tarih ve internet bağlantısının doğrulanması.

Türkçe Klavye Denemesi

Ağ işi bitince Türkçe klavye düzenine de baktım. IRIX'teki find, GNU find ile aynı seçeneklere sahip değil; örneğin -iname yok. X11 tuş eşlemelerini xmodmap -pke ile çıkardım, Türkçe karakter keysymlerini ve ISO-8859-9 fontlarını aradım.

xmodmap -pke
xlsfonts | grep iso8859-9
locale
locale -a
setenv LC_CTYPE tr

xmodmap ile tek tek keycode eşlemek mümkün görünse de sistemde xev bulunmadığı için fiziksel tuşları rahatça teşhis edemedim. Ayrıca locale ile klavye eşlemesi aynı şey değil: LC_CTYPE=tr Türkçe karakter sınıflandırmasını sağlıyor, tuşların hangi karakteri ürettiğini tek başına değiştirmiyor. Bu yüzden bu aşamada çalışan ağı bozacak kadar dosya kurcalamak yerine Türkçe klavyeyi ayrı bir işe bıraktım.

IRIX find ve chsh farklılıklarının görülmesi.
IRIX find ve chsh farklılıklarının görülmesi.
Varsayılan kabuğun /usr/bin/tcsh olarak doğrulanması.
Varsayılan kabuğun /usr/bin/tcsh olarak doğrulanması.
xmodmap ile mevcut tuş eşlemelerinin dökülmesi.
xmodmap ile mevcut tuş eşlemelerinin dökülmesi.
Harf tuşlarının keycode değerleri.
Harf tuşlarının keycode değerleri.
Noktalama ve işlev tuşlarının keycode değerleri.
Noktalama ve işlev tuşlarının keycode değerleri.
Yön ve sayısal tuş takımının eşlemeleri.
Yön ve sayısal tuş takımının eşlemeleri.
Üst keycode bölgesinin kontrolü.
Üst keycode bölgesinin kontrolü.
Türkçe karakter keysymlerinin aranması.
Türkçe karakter keysymlerinin aranması.
xmodmap ile geçici Türkçe karakter eşlemesi denemesi.
xmodmap ile geçici Türkçe karakter eşlemesi denemesi.
Eşleme denemesinin tekrar kontrolü.
Eşleme denemesinin tekrar kontrolü.
İlgili keycode satırının bulunması.
İlgili keycode satırının bulunması.
ISO-8859-9 destekli fontların listelenmesi.
ISO-8859-9 destekli fontların listelenmesi.
Geçerli LANG ve LC_* değerleri.
Geçerli LANG ve LC_* değerleri.
Sistemdeki Türkçe locale seçeneklerinin aranması.
Sistemdeki Türkçe locale seçeneklerinin aranması.
locale komutu ve kabuk sözdizimi denemeleri.
locale komutu ve kabuk sözdizimi denemeleri.
LC_CTYPE=tr denemesi.
LC_CTYPE=tr denemesi.
xev bulunmadığı için klavye teşhisinin burada bırakılması.
xev bulunmadığı için klavye teşhisinin burada bırakılması.

Nekoware ve wget Kurulumu

IRIX üzerinde wget ve curl kurulu değildi; fakat klasik FTP istemcisi vardı. IRIX Network'ün FTP sunucusuna anonymous olarak bağlanıp nekoware/current dizinine geçtim. Nekoware paketleri tardist biçiminde ve IRIX'in kendi inst aracıyla kuruluyor.

ftp ftp.irixnet.org
Name: anonymous
cd nekoware
cd current
binary
get neko_wget-1.11.3.tardist
quit

İlk denemede paketi yanlış dizinden açmaya çalıştığım için “No such file or directory”, salt okunur konuma yazmaya çalıştığım için de izin hataları aldım. inst içinde göreli dosya adıyla uğraşmak yerine tardist dosyalarının tam yolunu vermek en temiz çözüm oldu.

Donanım özeti ve wget/curl/ftp kontrolü.
Donanım özeti ve wget/curl/ftp kontrolü.
IRIX Network FTP sunucusuna bağlantı.
IRIX Network FTP sunucusuna bağlantı.
FTP dizinleri ve IRIX Network açıklaması.
FTP dizinleri ve IRIX Network açıklaması.
Nekoware paket arşivinin incelenmesi.
Nekoware paket arşivinin incelenmesi.
inst paket yöneticisinin ana menüsü.
inst paket yöneticisinin ana menüsü.
wget tardist paketinin ürün listesi.
wget tardist paketinin ürün listesi.
İlk kurulum denemesinde dağıtım kaydetme uyarısı.
İlk kurulum denemesinde dağıtım kaydetme uyarısı.
Salt okunur konum ve izin hatası.
Salt okunur konum ve izin hatası.
root posta bildirimi ve düzenlenen sistem dosyaları.
root posta bildirimi ve düzenlenen sistem dosyaları.
Ara kontrol ekranı.
Ara kontrol ekranı.
root .cshrc dosyasına kalıcı kabuk ayarları.
root .cshrc dosyasına kalıcı kabuk ayarları.
root oturumunda PATH ve kabuk kontrolü.
root oturumunda PATH ve kabuk kontrolü.
DISPLAY olmadığı için nedit'in açılamaması.
DISPLAY olmadığı için nedit'in açılamaması.
xmodmap denemesinin root oturumundaki sonucu.
xmodmap denemesinin root oturumundaki sonucu.

Bağımlılıklar ve inst

wget tek başına kurulmadı; kullandığım Nekoware paketinin gettext, libiconv ve OpenSSL bağımlılıkları vardı. Paketleri önce kullanıcı dizinine indirdim, ardından root olarak inst başlattım.

su root
cd /usr/people/kadir
inst

inst ana menüsünde her paketi tam yoluyla açtım:

open /usr/people/kadir/neko_libiconv-1.14.tardist
open /usr/people/kadir/neko_gettext-0.18.1.1.tardist
open /usr/people/kadir/neko_openssl-0.9.8x.tardist
open /usr/people/kadir/neko_wget-1.11.3.tardist
list
go

Paket adı veya sürümü FTP'deki dosyayla birebir aynı olmalı. Fotoğraflardaki bazı “file not found” ve tar hataları, adı ezberden yazdığım ya da eksik inmiş dosyayı açmaya çalıştığım denemelere ait. Son turda dosyaları ls -l ile doğrulayıp tam yolları kullanınca ürün açıklamaları düzgün okundu ve bağımlılıklar birlikte seçilebildi.

inst ile yerel tardist paketlerini açma.
inst ile yerel tardist paketlerini açma.
FTP'deki Nekoware current dizininde paket seçimi.
FTP'deki Nekoware current dizininde paket seçimi.
PASV önerisi ve gerekli bağımlılıkların indirilmesi.
PASV önerisi ve gerekli bağımlılıkların indirilmesi.
libiconv, OpenSSL ve wget paketlerinin hazırlanması.
libiconv, OpenSSL ve wget paketlerinin hazırlanması.
İndirilen tardist dosyalarının kullanıcı dizininde kontrolü.
İndirilen tardist dosyalarının kullanıcı dizininde kontrolü.
root oturumuna geçiş ve paket listesinin doğrulanması.
root oturumuna geçiş ve paket listesinin doğrulanması.
inst ana menüsüne dönüş.
inst ana menüsüne dönüş.
Kurulum ve kaldırma komutlarının özeti.
Kurulum ve kaldırma komutlarının özeti.
gettext paketi açılırken libiconv dosya adı hatası.
gettext paketi açılırken libiconv dosya adı hatası.
Dağıtımın /var/tmp altına açılması.
Dağıtımın /var/tmp altına açılması.
Paketlerin tam yol kullanılarak yeniden açılması.
Paketlerin tam yol kullanılarak yeniden açılması.
inst kurulum seçim ekranı.
inst kurulum seçim ekranı.
FTP sunucusunda nekoware/current dizinine geçiş.
FTP sunucusunda nekoware/current dizinine geçiş.
gettext paketinin binary modda indirilmesi.
gettext paketinin binary modda indirilmesi.
İndirilen paketlerle inst'in yeniden başlatılması.
İndirilen paketlerle inst'in yeniden başlatılması.
Bağımlılıkların hazırlanması.
Bağımlılıkların hazırlanması.
Eksik veya bozuk tardist denemesinin tespiti.
Eksik veya bozuk tardist denemesinin tespiti.
Yerel dizindeki paket dosyalarının kontrolü.
Yerel dizindeki paket dosyalarının kontrolü.
Paket adlarının ve sürümlerinin doğrulanması.
Paket adlarının ve sürümlerinin doğrulanması.
inst ile paketlerin tam yoldan açılması.
inst ile paketlerin tam yoldan açılması.
Kurulum seçimlerinin gözden geçirilmesi.
Kurulum seçimlerinin gözden geçirilmesi.
Paket açma ve bağımlılık çözümleme adımı.
Paket açma ve bağımlılık çözümleme adımı.
Eksik OpenSSL paketiyle ilgili hata.
Eksik OpenSSL paketiyle ilgili hata.
Nekoware paketlerinin masaüstünde kontrolü.
Nekoware paketlerinin masaüstünde kontrolü.
Kurulumun tam yollarla son kez tekrarlanması.
Kurulumun tam yollarla son kez tekrarlanması.
Netscape üzerinden yerel HTTP erişim testi.
Netscape üzerinden yerel HTTP erişim testi.
Nekoware current dizininin Netscape'te açılması.
Nekoware current dizininin Netscape'te açılması.
Paket listesinin tarayıcıdan görüntülenmesi.
Paket listesinin tarayıcıdan görüntülenmesi.

İkinci Perde: Farklı Boot Hataları ve Ağdan IRIX Kurtarma

İlk sorunları giderip ağı çalıştırmış, Nekoware paketleri ve wget aşamasına kadar gelmiştim. Bugün karşıma çıkan boot hataları ise önceki arızaların devamı değil, ayrı bir olaydı. Bu kez SGI O2'yi CD-ROM'a bağımlı kalmadan modern bir Windows bilgisayar üzerinden kurtarma ortamına alabilmek için bir ağ kurulum sunucusu hazırladım. Amaç mevcut diski hemen silmek değildi; önce kurulum medyasını görünür hâle getirmek, fx ve inst yollarını doğrulamak ve diskteki mevcut IRIX kurulumunu onarmaktı.

Modern Windows araçlarından SGI O2 üzerindeki IRIX kurulum ortamına uzanan ağdan kurtarma zinciri.
Modern araçlardan eski silikona: Windows, WSL, Vagrant, VirtualBox ve ağ servisleri üzerinden SGI O2'ye uzanan kurtarma zinciri.

Windows tarafındaki arşivde IRIX 6.5 taban diskleriyle 6.5.3, 6.5.9 ve 6.5.30 overlay setleri zaten duruyordu. Bunları E:\Program\SGI\irixboot\irix\6.5 altında aracın beklediği foundation ve overlay30 dizinlerine yerleştirdim. Ardından Vagrantfile içindeki istemci adı, O2'nin Ethernet adresi, SGI'nin sabit IP'si, sunucu IP'si ve köprü kurulacak Windows adaptörünü kendi ağıma göre düzenledim.

clientname   = 'o2'
clientip     = '192.168.1.50'
clientether  = '08:00:69:0c:09:68'
hostip       = '192.168.1.109'
bridgenic    = 'Ethernet 2'
Vagrant ve VirtualBox köprü ağında Windows bilgisayar, irixboot sanal makinesi ve SGI O2 arasındaki adresler.
Vagrant ve VirtualBox ağ düzeni: köprü adaptörü, irixboot sunucusu ve SGI O2'nin aynı yerel ağdaki rolleri.
IRIX 6.5.3 kurulum ve overlay ISO dosyaları.
IRIX 6.5.3 kurulum ve overlay ISO dosyaları.
Arşivdeki 6.5, 6.5.3, 6.5.9 ve 6.5.30 setleri.
Arşivdeki IRIX sürüm dizinleri.
Vagrantfile içinde O2 ağ bilgilerinin düzenlenmesi.
Vagrantfile'ın O2 ve yerel ağ için düzenlenmesi.
WSL içinden Windows Vagrant ve VirtualBox araçlarının aranması.
WSL, Windows yolu ve Vagrant kurulumu arasında ilk temas.
irixboot dizinindeki Vagrant ve IRIX dosyalarının kontrolü.
Windows tarafında irixboot dizininin kontrolü.

İlk Vagrant Çalıştırması ve Jessie Duvarı

vagrant up sanal makineyi oluşturdu, ikinci adaptörü köprü modunda açtı ve paylaşımlı klasörü bağladı. Fakat irixboot projesi artık arşivlik sayılabilecek Debian Jessie tabanını kullanıyordu. Normal paket depoları taşındığı için provision aşamasında apt 404 hataları verdi; bunun zincirleme sonucu olarak parted, mkfs.xfs, rsync, dnsmasq, DHCP, TFTP ve inetd eksik kaldı. Ekranda “Ready to network boot” yazması bu yüzden gerçeği tam anlatmıyordu: servisleri olmayan bir sunucu hazır sayılmazdı.

parted: command not found
mkfs.xfs: command not found
rsync: command not found
Failed to start dnsmasq.service
Failed to start isc-dhcp-server.service
Failed to start tftpd-hpa.service
Vagrant sanal makinesinin oluşturulması ve ağ adaptörlerinin hazırlanması.
Debian Jessie sanal makinesi oluşturuluyor.
irixboot sanal makinesine SSH bağlantısı ve eski apt kaynakları.
Sanal makineye girip Jessie kaynaklarını inceleme.
IP bağlantısı çalışırken archive.debian.org adının çözülememesi.
IP erişimi var, DNS yok: ikinci küçük zaman kapsülü.
archive.debian.org üzerinden apt paket listelerinin alınması.
Jessie depoları archive.debian.org'a taşındıktan sonra apt yeniden çalışıyor.
Gerekli DHCP TFTP RSH ve disk araçlarının kurulması.
Eksik ağ ve disk araçlarının kurulması.

Dağıtım Diskinin Yeniden Hazırlanması

Paketler kurulunca paylaşımlı dizindeki Foundation ve 6.5.30 overlay görüntülerini doğruladım. İlk başarısız deneme geride yarım hazırlanmış bir /irix dizini ve .irixboot işaret dosyası bırakmıştı. Betik bu dosyayı görünce dağıtımın hazır olduğunu sanıyordu. İşaret dosyasını kaldırıp dist.sh 6.5 komutunu yeniden çalıştırınca ikinci sanal disk XFS olarak biçimlendirildi ve disk görüntülerinin içeriği gerçek dağıtım ağacına kopyalandı.

ls -lh /vagrant/irix/6.5/foundation/ /vagrant/irix/6.5/overlay30/
sudo rm /irix/.irixboot
sudo /vagrant/scripts/dist.sh 6.5
Yarım kalmış IRIX dağıtım dizininin ve işaret dosyasının görülmesi.
Yarım kurulumun bıraktığı yanıltıcı .irixboot işareti.
dist.sh betiğindeki mevcut dağıtım kontrolünün incelenmesi.
Betiğin dağıtımı hangi koşulla hazır saydığının bulunması.
boot.sh ile BOOTP DHCP TFTP ve RSH servislerinin başlatılması.
O2 için BOOTP/TFTP/RSH zincirinin başlatılması.
Foundation ve overlay30 disk görüntülerinin sanal makinede doğrulanması.
Foundation ve overlay30 görüntüleri doğru yerde.

O2 Üzerinde inst ile Onarım

Sunucu tarafı ayağa kalktıktan sonra O2'yi PROM menüsünden Install System yoluyla ağ kaynağına yönlendirdim. inst açıldığında önce dağıtım kaynağını, ardından sistem diskini denetledim. Bu noktada kritik ayrıntı, IRIX'in kök dosya sistemini geçici olarak /root altına bağlamasıydı. Dolayısıyla normal açılmış sistemdeki /bin yerine kurtarma ortamında /root/usr/bin ve benzeri yolları görmek doğaldı.

Dosya sistemi erişilebiliyordu; /root/unix okunuyor, dizin yapısı duruyordu. Kurulum/onarım işlemi tamamlandıktan sonra restart seçildi. Asıl hüküm yeniden açılışta verildi: makine PROM'a geri düşmedi, IRIX masaüstüne sorunsuz ulaştı.

SGI O2 üzerinde ağ kurulum ortamına geçiş.
O2, ağdaki IRIX kurulum ortamına bağlanıyor.
inst içinde dağıtım ve disk denetimi.
inst içinde dağıtım kaynağı ve sistem diski.
Kurtarma kabuğunda kök dosya sisteminin kontrolü.
Kök dosya sistemi kurtarma ortamında /root altında.
IRIX dosyalarının ve unix çekirdeğinin doğrulanması.
Dizinler ve /root/unix yerinde.
inst işlemi sonrasında yeniden başlatma aşaması.
Onarımın ardından restart aşaması.




Sonuç

Son durumda SGI yerel ağda 192.168.1.50 adresiyle çalışıyor; ağ geçidine, internetteki IP adreslerine ve alan adlarına ulaşabiliyor. Normal kullanıcı ortamında /usr/etc PATH içinde, varsayılan kabuk tcsh ve komut geçmişi kalıcı. Daha önemlisi, Windows üzerindeki modern araçlardan başlayıp Vagrant içindeki tarihî Debian'a, oradan BOOTP/TFTP/RSH zincirine ve nihayet O2'nin inst ortamına uzanan ağdan kurtarma yolu da sınanmış oldu.

Bu işte en yanıltıcı nokta tek bir arızanın olmamasıydı. IRIX tarafında nsd, nsswitch.conf ve resolv.conf; Windows tarafında köprü adaptörü; sanal makinede ömrünü tamamlamış Jessie depoları; dağıtım betiğinde ise yarım kalmış .irixboot işareti aynı hikâyenin ayrı katmanlarıydı. Sistem bozuk değildi; yalnızca 1990'ların UNIX mantığıyla, 2010'ların Linux betikleriyle ve 2020'lerin sanallaştırma araçlarıyla aynı anda konuşmak gerekiyordu :)


SGI O2, IRIX 6.5, PROM, SASH, inst, Vagrant, VirtualBox, BOOTP, TFTP, RSH, Debian Jessie, nsd, DNS, tcsh, Nekoware, tardist, wget, IRIX Network.

Sunday, May 10, 2026

5V yerine 12V verilmiş Raspberry Pi 3B tamiri.

Besleme için 2.5A kaynak önerilmesine rağmen genelde 2A akım verebilen cep telefonu şarj aletleriyle kullandığım Pi sürekli low voltage uyarısı verdiğinden sorunsuz besleme için PC ATX güç kaynağından DIY dişi USB adaptör yaptım. Yapmaz olaydım :) ATX PSU'da sarı kablo 12V, kırmızı 5V. Ama montaj sırasında dalgaınlıkla 5V yerine 12V hattını dişi USB'ye, oradan da Pi'ın güç girişine bağladım. (Tamir sonrası 3A Macbook adaptörüne geçtim.)

Pi bozuldu ama tamamen ölmemişti. Açılışta rainbow splash ve boot splash ekranı geliyordu ama desktop'a ulaşamadan yeniden başlıyordu. Her boot denemesinde besleme bölgesi de aşırı ısınıyordu. Elle kontrol etmeye çalıştığımda parmak ucumu havyaya değmiş gibi kabarttı, o derece sıcaktı.

Multimetreyle 5V GPIO pini ile GND arasını ölçtüm: yaklaşık 10 ohm, neredeyse kısa devre. Sağlıklı bir Pi'de bu değer çok daha yüksek olmalı.

Raspberry Pi 3B'nin devre şemasına baktım. 5V girişinde koruma elemanı olarak D5 konumunda bir TVS diyot var: SMBJ5.0A. 600W peak güç absorbe edebilen, 5V hat için tasarlanmış bir transient suppressor. 12V'u yutmaya çalışmış, kurban gitmiş. Sürekli ısınan ve Pi'ın boot loop'a düşmesine neden olan eleman buydu.

Pi 3 Model B power katı. Sağolsun Raspi foundation resmi bir şey yayınlanmadığından eldeki en iyi şema ve çözünürlüğü bu. Buna da şükür.

TVS Diyot Nedir

Şemadaki sembolü zenerle aynı olsa da TVS (Transient Voltage Suppressor) diyotlar anlık gerilim spiklerini absorbe etmek için tasarlanmış. Pikosaniye mertebesinde tepki süresi, yüksek peak güç kapasitesi. ESD koruması ve güç girişi koruması için ideal.

Zener referans gerilimi ve sürekli regülasyon için kullanılır, tepki süresi yavaş, güç kapasitesi düşük. Pi girişindeki gibi bir koruma uygulaması için Zener yetersiz kalır.

Multimetre diyot modunda TVS her iki yönde de açık devre gibi görünüyor. Eşik geriliminin multimetrenin test voltajından yüksek olması dolayısıyla bu normalmiş. Multimetreyle olmayınca polariteyi belirlemek için paketteki işarete bakarak montaj yaptım: SMB pakette beyaz şerit genellikle katot tarafını gösterir, TVS de zener gibi devreye ters bağlandığından bu taraf VCC'ye gelecek. 

Tamir

SMBJ5.0A SMB (DO-214AA) pakette geliyor. Orijinalle aynı değerde, farklı üreticiden yeni bir TVS temin ettim. Doğru polaritede lehimledim. Pi'yi çalıştırdım, sorunsuz boot etti. 5V-GND direnci normale döndü, besleme bölgesinde ısınma yok.

Pad polaritesi.
Doğru montaj sonrası.

Sonuç

Pi 3B'nin girişindeki TVS bu tür kazalarda ilk savunma hattı. 12V gibi ciddi bir aşımda kendini feda ederek geri kalan devreyi koruyor — en azından koruyabiliyor. Bu vakada şanslıydım, hasar TVS'de kaldı, PMIC ve SoC'yi vurmadı :) 

ATX adaptörü yaparken her kabloyu voltmetre ile doğrulamak, yük bağlamadan önce boşta ölçmek standart prosedür. Biliyordum, yapmadım. 


Raspberry Pi 3B, SMBJ5.0A, SMB paketi, TVS tamiri, ATX DIY adaptör.

Saturday, May 2, 2026

Vannevar Bush ve Memex

MIT'li bir mühendis, Temmuz 1945'te The Atlantic dergisinde Memex adlı bir masaüstü bilgisayarı anlatan 13 sayfalık bir makale yayınladı. Bu bilgisayar, bir kişinin sahip olduğu her kitabı, her fotoğrafı ve her mektubu saklayacak, belgeler arasındaki bağlantılara tıklayarak içeriğe göz atmalarına ve ilgili düşüncelerin izlerini kaydetmelerine olanak tanıyacaktı.

Kişisel bilgisayarı, hiper bağlantıları, Vikipedi'yi ve Dünya Çapında Ağı, bunların hiçbiri var olmadan 50 yıl önce tek bir dergi makalesinde icat etti.

Bir saatten kısa sürede kapağı okuyup, yaşadığımız dünyanın planını okuduğuna ikna olmuştu.

Adı Vannevar Bush'tu.


Makalenin adı "Düşündüğümüz Gibi"dir.

Yazdıklarının bağlamı önemlidir çünkü tek bir kişinin nasıl bu kadar ileriyi görebildiğini açıklar. Vannevar Bush bir fütürist değildi, bir bilim kurgu yazarı da değildi. II. Dünya Savaşı sırasında Amerika Birleşik Devletleri'nin en güçlü bilim insanıydı. Manhattan Projesi'ni, radarın geliştirilmesini, yakınlık füzesini, penisilinin seri üretimini ve savaşın neredeyse tüm önemli Amerikan bilimsel atılımlarını koordine eden Bilimsel Araştırma ve Geliştirme Ofisi'ni yönetti. 30.000 bilim insanının çalışmalarını bizzat yönetti. Doğrudan Başkan Roosevelt'e rapor veriyordu.

Savaş 1945 yazında sona ererken, yıllardır kafasında şekillenen bir şeyi yazmak için oturdu. Makale Temmuz 1945'te The Atlantic'te yayınlandı. 13 sayfa uzunluğunda. Üç hafta sonra Japonya'ya atom bombaları atıldı.

İşte gördükleri ve bir makalenin neden tesadüfen yaşadığım dünyanın bir taslağı haline geldiği.

Başlangıçtaki sorunu spesifikti: Bilim insanları, insanların okuyabileceğinden daha fazla araştırma üretiyordu. İnsan bilgisinin birikimi katlanarak artıyordu. Her bir araştırmacının, çalışmalarıyla ilgili olanların çok küçük bir bölümüne erişimi vardı. Keşiflerin çoğu, yanlış oldukları için değil, kimse onları bulamadığı için kayboluyordu. Bush bunu savaş sonrası dünyanın temel sorunu olarak adlandırdı. Bilgi boldu. Dikkat azdı. Darboğaz artık bilgi üretmek değil, onu geri almaktı.

Bir çözüm önerdi. Buna, hafıza genişletici anlamına gelen Memex adını verdi.

Memex, masa boyutunda bir makineydi. Kullanıcı önünde oturuyordu. Ekranları vardı. Klavyesi vardı. Transistör henüz icat edilmediği için mikrofilm kullanıyordu, ancak tanımladığı işlev, günümüzdeki bir sabit sürücünün yaptığıyla tamamen aynıydı. Kullanıcı, okuduğu her kitabı, aldığı her notu, sahip olduğu her fotoğrafı ve yazdığı her mektubu saklayabilirdi. Hepsine saniyeler içinde erişilebilirdi.

Bu bile tek başına çarpıcı bir tahmin olurdu. 1945'te kişisel bir bilgisayar tanımladı. Kişisel bilgisayar yoktu. Dünyanın ilk elektronik bilgisayarı ENIAC, bir yıl sonra tanıtılacaktı ve 30 ton ağırlığındaydı ve bir odayı dolduruyordu. Bush, tek bir kişinin bildiği her şeyi barındırabilecek, masa büyüklüğünde bir makineyi tarif ediyordu.

Ancak masaüstü bilgisayar küçük bir fikirdi.

Büyük fikir ise, makaleyi alıntılayan neredeyse hiç kimsenin gerçekten anlamadığı kısımdır.

Bush, insanların bilgiyi kitaplarda ve kütüphanelerde saklama biçiminin yanlış olduğunu savundu. Kitaplar kategoriye göre düzenlenir. Kütüphane rafları Dewey ondalık sistemine göre düzenlenir. Herhangi bir bilginin hiyerarşide bir konumu vardır. Onu bulmak için, içinde bulunduğu kategoriyi bilmeniz gerekir.

Bunun insan beyninin çalışma şekliyle hiç alakası olmadığını belirtti.

Beyin bilgiyi kategoriye göre saklamaz. Beyin bilgiyi çağrışım yoluyla saklar. Büyükannenizi düşünürsünüz ve hemen bir şarkıyı hatırlarsınız. Şarkı size bir tatili hatırlatır. Tatil size bir yemeği hatırlatır. Yemek size yıllardır düşünmediğiniz bir kişiyi hatırlatır. Her düşünce bir diğerini tetikler, çünkü aynı kategoriyi paylaştıkları için değil, bağlantılı oldukları için.

Bush, bilgi depolamanın beyni taklit etmesi gerektiğini öne sürdü. Belgeler doğrudan diğer belgelere bağlanmalıydı. Birine tıkladığınızda diğerine atlayın. Bir dipnota tıkladığınızda kaynağı görün. Bir isme tıkladığınızda kişinin diğer yazıları görün. Bu bağlantılara "ilişkisel izler" adını verdi.

Bu, hipermetindir. Bunu 1945'te kağıt üzerinde icat etti.

1989'da CERN'de Dünya Çapında Ağı (WWW) kuran Tim Berners-Lee, bu makaleyi doğrudan ilham kaynağı olarak gösterdi. HTTP protokolü, HTML standardı, günde binlerce kez kullandığınız bir belgeden diğerine tıklama sisteminin tamamı, Bush'un Japonya'ya bombalar düşmeden önce kağıt üzerinde çizdiği bir fikirden türemiştir.

Makalenin üçüncü kısmı beni en çok etkileyen kısım oldu.

Bush, Memex kullanıcısının sadece bilgi tüketmeyeceğini savundu. Bilgi üzerinden kendi izlerini oluşturacaklardı. Kendileri için önemli olan belge dizilerini kaydedeceklerdi. Bunları kendi notlarıyla açıklayacaklardı. İzlerini diğer insanlarla paylaşırlardı. Diğer araştırmacılar bu izleri devralır ve genişletirlerdi.

Kişisel not alma, sosyal yer imleme, bağlantı paylaşımı, kısacası tüm bu süreçleri anlatıyordu.

Orjinal makale linki.

Thursday, April 23, 2026

"Anlatıyor Olacağım": Türkçenin Gövdesine Saplanmış Bir Diken

Huzursuzluk

"Bu yazıda konuyu anlatıyor olacağım" cümlesini okuduğumda içimde bir huzursuzluk oluyor. Dilbilimsel bir refleks mi yoksa estetik bir tiksinme mi - tam olarak bilemiyorum. Ama bu yapının Türkçeye ne yaptığını biliyorum.

Meselenin Özü

Türkçe, zamanlama ve görünüş (aspect) kategorilerini çok zarif bir biçimde kodlayan bir dildir. Geniş zaman, gelecek zaman, süregelen eylem — bunların her biri ayrı ek sistemleriyle ifade edilir ve bu sistem yüzyıllardır tutarlı biçimde işlemektedir.

"Anlatacağım" bu sistemin ürünüdür. Gelecek zaman eki -acak/-ecek doğrudan eyleme bağlanır, kişi eki eklenir, cümle tamamdır. Yapı berraktır, ekonomiktir, işlevseldir.

"Anlatıyor olacağım" ise başka bir şeydir. Bu yapı, şu parçalardan oluşur:

  • anlat- (eylem kökü)
  • -ıyor (şimdiki zaman / süregelen görünüş eki)
  • ol- (yardımcı eylem)
  • -acak (gelecek zaman eki)
  • -ım (1. tekil kişi eki)

Ortada iki zaman eki var: -ıyor ve -acak. Bunları "süregelen gelecek" olarak yorumlamak mümkün mü? Teorik olarak evet — İngilizce future continuous yapısının (I will be explaining) bir kopyası gibi düşünülebilir. Ama Türkçenin bu ayrımı zaten başka araçlarla yaptığını, ve bu yapının büyük çoğunlukla o süregelen anlamı taşımadan kullanıldığını gözden kaçırmamak gerekir.

Anlambilimsel içeriği boş, sözdizimsel yükü ağır. Bu, kötü dil kullanımının tanımıdır.

Ne Zaman Ortaya Çıktı?

Bu yapının yükselişi yaklaşık 2010'ların ortasından itibaren hız kazandı. Başlangıcı belli: sunum dili, kurumsal konuşma, akademik jargon ve özellikle çeviri kaynaklı metinler. PowerPoint kültürünün Türkçeye hediyesidir büyük ölçüde.

Konuşmacı kürsüye çıkar ve şöyle der: "Bu sunumda size şirketin büyüme stratejisini aktarıyor olacağım, ardından rakip analizi yapıyor olacağız ve sonunda sorularınızı alıyor olacağız."

Tek bir cümlede üç kez. Kulağa ne kadar ciddi, ne kadar kurumsal, ne kadar profesyonel geliyor, değil mi?

Hayır. Kulağa şişirilmiş, boş, yılışık geliyor. Ama bunu söylemeye cesaret eden fazla kimse çıkmadı — çünkü bu dil bir statü işareti olarak benimsendi.

Toplumsal Dilbilim Boyutu

Burada dürüst olmak zorundayız: bu yapı dilbilgisel bir hata değildir. Türkçe bunu üretebilir. Mesele dilbilgisellik değil, tercihtir — ve bu tercihin arkasındaki toplumsal dinamikler ilginçtir.

Bu yapı bir prestij göstergesi işlevi görüyor. Kullananlar farkında olmadan şunu söylüyor: "Ben eğitimli biriyim, kurumsal ortamlarda bulunuyorum, İngilizce biliyorum, benim konuşmam sıradan değil."

Bu mekanizma yeni değil. Her dilde benzer süreçler yaşanmıştır — Latince kaynaklı kelimelerin İngilizce'de entelektüel prestij taşıması, Fransızcadan alınan sözcüklerin Osmanlı yazı dilinde statü göstergesi olması gibi. Ama fark şu: o örneklerde sözcük dağarcığı genişliyordu. Bu örnekte mevcut bir yapı gereksiz yere şişiriliyor.

Sonuç: dilin ekonomisi bozuluyor. Daha az anlamı daha çok sesle ifade etmek, dilbilimsel değer kaybıdır.

Peki Ya Gerçekten Fark Var mı?

"Yok mu hiç farkı?" diye sorabilirsiniz. Nadir durumlarda, evet.

Eğer biri şöyle diyorsa: "Siz burada oturuyorken, ben arka odada raporları inceliyor olacağım" — burada gerçek bir süregelen gelecek anlamı var. Eş zamanlılık söz konusu ve yapı o anlamı taşıyor.

Ama bu, istisnadır. Kuralı şöyle koyabiliriz: eğer "anlatacağım" yerinde kullanılabiliyorsa, "anlatıyor olacağım" demek dili şişirmektir. Kendinize dürüstçe sorun: gerçekten süregelen bir eş zamanlılık mı kastediyorum?

Sonuç

Türkçe, sesli-sessiz uyumu, eklemeli yapısı, özgür sözdizimi ve görünüş sistemiyle dünyanın biçimbilimsel açıdan en tutarlı dillerinden biridir. Gereksiz yapı şişirmesi bu tutarlılığa zarar verir.

"Anlatıyor olacağım" demek için özel bir neden yoksa, "anlatacağım" deyin.

Dil ekonomidir. Her kelime, her ek, her yapı bir şey ödemektedir — dikkat, zaman, anlam. Gereksiz ödeme yapmayın.


Bu yazıdaki görüşler dilbilimsel bir perspektiften kaleme alınmıştır. Kullanım normları toplumsal süreçlerle şekillenir; bu eleştiri dilin doğal evrimine karşı değil, bilinçsiz taklit ve statü kaygısıyla üretilen gereksiz karmaşıklığa karşıdır.

Thursday, April 9, 2026

DDC/CI ile monitör ayarlarının analog kontrolü bölüm 2.

Bir önceki yazıda Arduino Uno ve Python kullanarak DDC/CI protokolü üzerinden monitör parlaklık ve kontrast kontrolünü iki potansiyometreyle nasıl yapabileceğimizi anlatmıştım. O yazının sonunda birkaç yapılacak madde listelemiştim. Bu yazı o listedeki en kritik iki maddenin hayata geçirilmesini anlatıyor: Arduino'dan bağımsız bir MCU'ya geçiş ve uygulamanın Win32 ile yeniden yazılması.

Neden Arduino değil?

Arduino Uno güzel bir prototipleme platformu, ancak bu proje için fazla büyük ve gereksiz. Bizim ihtiyacımız olan tek şey iki ADC kanalı ve USB iletişimi. Bunun için 28 pinli bir AVR ve ayrı bir USB-Serial çevirici çipi kullanmak israf.

Daha da önemlisi, Arduino Uno USB üzerinden HID olarak görünmüyor — seri port (CDC) üzerinden haberleşiyor. Bu da Python tarafında pyserial kütüphanesi ve COM port yönetimi gerektiriyor. Farklı bilgisayarlarda farklı COM port numaraları atanıyor, kullanıcı bunu elle değiştirmek zorunda kalıyor.

Hedef: cihazı taktığında ek bir kurulum veya konfigürasyon gerektirmeden çalışan, native USB HID olarak görünen, mümkün olduğunca küçük bir devre.

CH552: USB HID yetenekli minimal MCU

WCH firmasının ürettiği CH552, bu iş için biçilmiş kaftan. Enhanced 8051 çekirdeği üzerine kurulu bu MCU'nun öne çıkan özellikleri:

  • Dahili USB full-speed transceiver — harici USB-Serial çeviriciye gerek yok
  • 4 kanallı 8-bit ADC (P1.1, P1.4, P1.5, P3.2)
  • 16KB program ROM, 1KB xRAM
  • DIP20 pakette mevcut — breadboard dostu
  • Adet fiyatı 0.5-1 dolar civarı
  • ch55xduino ile Arduino IDE desteği

Geliştirme için WeAct Studio'nun CH552 Core Board'unu kullandım. USB konektörü, boot ve reset butonu dahil, breadboard uyumlu, tüm pinler erişilebilir.


Bağlantı şeması

Devre son derece sade:

  • POT1 (Parlaklık): Orta bacak → P1.1, uçlar → GND / 3.3V
  • POT2 (Kontrast): Orta bacak → P1.4, uçlar → GND / 3.3V
  • Her iki pot için 10kΩ değer ideal
  • USB, hem güç hem veri için kullanılıyor

USB HID descriptor: Vendor HID

Önceki Arduino versiyonunda CDC (seri port) kullanıyorduk. Bu versiyonda cihaz native USB HID olarak görünüyor. Ancak burada önemli bir detay var: standart keyboard veya mouse descriptor kullanırsak Windows cihazı gerçek bir giriş aygıtı olarak tanımlıyor ve klavye girişlerini karıştırabiliyor.

Bunun yerine Vendor Defined HID (Usage Page 0xFF00) kullandım. Bu şekilde Windows cihazı tanıyor ama sistem giriş aygıtı olarak muamele etmiyor. Device Manager'da "HID-compliant device" olarak görünüyor, herhangi bir sürücü kurulumu gerekmiyor.

CH552 ADC: Dikkat edilmesi gereken detaylar

CH552'nin ADC'sini kullanırken birkaç önemli nokta var. Standart Arduino analogRead() fonksiyonu çalışıyor, ancak kanal seçimi biraz farklı. ch55xduino'da pin numaralandırması port.pin formatında: P1.1 için pin 11, P1.4 için pin 14.

Öte yandan ADC çıkışı 8-bit olmasına rağmen dahili referans voltajı nedeniyle değerler 0-255 aralığının tamamını kullanmıyor. Pratikte 4-174 arası bir aralık elde ettim. Python tarafında bu değerleri 0-100 aralığına map ediyorum:

ADC_MIN = 4
ADC_MAX = 174

def map_val(raw):
    val = (ADC_MAX - raw) * 100 // (ADC_MAX - ADC_MIN)
    return max(0, min(100, val))

Firmware: HID veri gönderimi

USB HID üzerinden veri göndermek için ch55xduino'nun HID keyboard örneğinin kaynak dosyalarını kullandım. Descriptor'ı Vendor HID olarak değiştirdim, veri gönderimi için mevcut USB_EP1_send() fonksiyonunu ve HIDKey[] buffer'ını kullandım.

Her HID paketi şu şekilde:

  • HIDKey[0] — Parlaklık (ADC P1.1)
  • HIDKey[1] — Kontrast (ADC P1.4)

Firmware ana döngüsü 50ms aralıklarla çalışıyor:

void loop() {
    uint8_t b = adc_read_ch(0);  // P1.1
    uint8_t c = adc_read_ch(1);  // P1.4

    HIDKey[0] = b;
    HIDKey[1] = c;
    USB_EP1_send();
    delay(50);
}

Cihazı flash'lamak için WCHISPTool kullandım. Boot moduna girmek için P3.6 butonuna basılı tutarken USB bağlamak yeterli.

Cold boot sonrası sorunu ve çözümü

Projeyi tamamladıktan sonra kritik bir bug fark ettim: devre Windows yeniden başlatıldıktan sonra resetlemeden çalışmıyordu. Sök-tak veya board reset sonrası her şey normal çalışıyordu, ancak bilgisayar kapatılmadan yeniden başlatıldığında potansiyometreler tepki vermiyordu.

Başlangıçta USB enumerate sorunu olduğunu düşündüm. Device Manager'da cihaz görünüyordu, hid.enumerate() ile descriptor bilgileri okunabiliyordu. Sorun farklı bir yerdeydi.

Kök neden UpPoint1_Busy flag'inin stuck kalmasıydı. Windows başlatma sırasında USB host controller enumerate sürecinde bir veya birden fazla USB bus reset sinyali gönderiyor. Eğer CH552 o anda EP1 üzerinden veri gönderiyorsa transfer yarıda kesiliyor; ancak USB_EP1_IN() callback'i tetiklenmediği için UpPoint1_Busy flag'i 1 olarak kalıyor. Bundan sonra USB_EP1_send() her çağrıda sessizce return 0 dönüyor — cihaz çalışır görünüyor ama hiç HID raporu göndermiyor. Kullanıcı CH552'yi fiziksel olarak resetleyince MCU yeniden başlar, flag sıfırlanır ve çalışır.

Çözüm USBhandler.c'deki UIF_BUS_RST interrupt handler'ına üç satır eklemekten ibaretti:

// USBhandler.c - UIF_BUS_RST handler
extern volatile __xdata uint8_t UpPoint1_Busy;

// ... handler içinde:
UsbConfig = 0;
UpPoint1_Busy = 0;  // Bus reset gelince stuck flag'i temizle

Bus reset geldiğinde UpPoint1_Busy sıfırlanıyor, bir sonraki USB_EP1_send() çağrısında transfer yeniden başlıyor. Windows'un başlatma sırasında gönderdiği bus reset sinyali artık sorunu çözmek için kullanılıyor. Soğuk açılışta artık resetlemeye gerek kalmadı.

Python daemon: Win32 ve dxva2

Önceki versiyonda Python GUI için tkinter, DDC/CI için monitorcontrol kütüphanesi kullanıyordum. Bu versiyonda her ikisini de değiştirdim.

OSD: tkinter yerine doğrudan Win32 GDI ile layered window. Transparan arka plan, her zaman üstte, tıklanamaz. Sağ alt köşede 2 saniye görünüp kayboluyor.

DDC/CI: monitorcontrol kütüphanesi yerine Windows'un native dxva2.dll API'si. SetMonitorBrightness ve SetMonitorContrast fonksiyonları doğrudan çağrılıyor. Bu yöntem hem daha hızlı hem de monitorcontrol kütüphanesinin yaşadığı "failed to get VCP feature" hatasını tamamen ortadan kaldırıyor.

dxva2 = ctypes.windll.dxva2

def _ddc_worker():
    while True:
        brightness, contrast = _ddc_queue.get()
        for h in _monitor_handles:
            if brightness is not None:
                dxva2.SetMonitorBrightness(h, brightness)
            if contrast is not None:
                time.sleep(0.05)
                dxva2.SetMonitorContrast(h, contrast)

DDC/CI komutları bir queue üzerinden tek bir worker thread'e gönderiliyor. Queue kapasitesi 1 — yeni komut geldiğinde işlenmemiş eski komut atılıyor. Bu sayede monitör hiçbir zaman komut yağmuruna tutulmuyor.

Sonuç

Arduino versiyonuyla karşılaştırıldığında bu versiyon birçok açıdan daha iyi:

  • COM port konfigürasyonu yok — USB tak çalıştır
  • Ayrı USB-Serial çevirici yok — tek çip, tek USB kablo
  • OSD daha responsive ve görsel olarak daha temiz
  • DDC/CI iletişimi daha stabil
  • Soğuk açılışta resetleme gerekmiyor
  • Devre boyutu ve maliyeti önemli ölçüde düştü

Yapılacaklar listesinde hala birkaç madde var: ADC gürültüsü için firmware tarafında smoothing buffer, Python daemon yerine standalone exe, ve nihai hedef olarak özel PCB tasarımı. Önümüzdeki yazılarda bunları ele alacağım.

Projenin kaynak kodlarına GitHub üzerinden ulaşabilirsiniz.

Wednesday, April 8, 2026

E=mc² ve Maddenin Gerçek Yüzü

Little Boy ve 0,7 Gram

1945'te Hiroşima'ya atılan Little Boy bombası yaklaşık 64 kg U-235 içeriyordu. Ama bunun sadece yaklaşık 1 kg'ı gerçekten fisyona girdi. Daha da çarpıcısı, bu reaksiyona giren kısmın da sadece yaklaşık 0,7 gramı saf enerjiye dönüştü.

Bunu sayıya dökersen:

\[ E = 0{,}0007 \times c^2 \approx 6 \times 10^{13} \text{ joule} \]

Bu da yaklaşık 15 kiloton TNT demek.

Yani koca 64 kg'lık sistemde:

  • %98'i reaksiyona bile girmiyor
  • Reaksiyona girenin de %99,9'u hâlâ "madde" olarak kalıyor

Ve yine de: bir şehir yok oluyor.

Bu tek başına şu cümleyi gerçek yapıyor: Madde inanılmaz yoğun bir enerji deposudur. Ama aynı zamanda şunu da gösteriyor: nükleer silahlar bile aslında çok verimsiz.

Kütle mi, Ağırlık mı?

Fiziği ilk öğrenirken dünya bize çok basit görünür. Cisimler vardır, ağırlıkları vardır, hareket ederler. Momentum da sanki "ağırlık çarpı hız" gibi bir şeydir. Ama işin içine girince ilk çatlak burada oluşur. Çünkü momentum aslında şöyle tanımlanır:

\[ p = mv \]

Burada \(m\) kütledir, ağırlık değil. Ağırlık ise tamamen farklı bir şeydir:

\[ W = mg \]

Biri cismin kendisiyle ilgili, diğeri bulunduğu ortamla. Dünya'da 80 kg olan biri Ay'da hâlâ 80 kg'dır ama ağırlığı ciddi şekilde düşer. Bu küçük ayrım aslında büyük bir kapıyı açar: ölçtüğümüz şey ile gerçek fiziksel büyüklük aynı şey olmayabilir.

Fiziğin Kalbi

Momentumun bu basit hali Newton dünyasında çalışır, ama biraz derine inince bunun sadece özel bir durum olduğunu fark ediyorsun. Daha genel çerçevede enerji ve momentum birlikte hareket eder:

\[ E^2 = (pc)^2 + (mc^2)^2 \]

Parçacık duruyorsa (\(p = 0\)), buradan direkt şu çıkar:

\[ E = mc^2 \]

Yani bir cismin sadece var olması bile enerji demektir. Ama daha da ilginci, kütle sıfırsa (\(m = 0\)) denklem şu hale gelir:

\[ E = pc \quad \Rightarrow \quad p = \frac{E}{c} \]

İşte ışığın sırrı burada. Kütlesi yoktur ama enerjisi vardır, dolayısıyla momentumu da vardır. "Momentumu taşıyan şey kütle değil, enerjidir" fikri ilk kez gerçekten anlam kazanır.

Einstein'ın Sıçraması

Bir cisim düşün, iki yana eşit ışık yayıyor. Kendi referansında hareket etmiyor, her şey dengede. Ama başka bir gözlemciye göre bu ışıkların enerjisi eşit değildir (Doppler etkisi). Momentum dengesi bozulur gibi görünür. Bu çelişkiyi çözmenin tek yolu şudur: cisim enerji kaybettiyse kütle de kaybetmelidir.

\[ \Delta m = \frac{E}{c^2} \]

Bu noktada "madde = enerji" artık slogan değil, zorunluluk haline gelir.

Parçacık Yok, Alan Var

"Madde enerjidir" dediğinde insan şunu sorar: peki bu somut şeyler nereden geliyor? Proton, nötron, elektron? Burada modern fizik sahneye çıkar ve der ki: evrende parçacık diye bir şey yoktur, aslında her şey alanların titreşimidir. Elektron bir elektron alanının, foton elektromanyetik alanın titreşimidir.

Proton ise daha karmaşık: quark ve gluon alanlarının birleşik bir enerji konfigürasyonu. Ve protonun kütlesinin büyük bölümü quarklardan gelmez. Asıl kaynak, onları bağlayan güçlü etkileşimin enerjisidir. Bu yüzden bir çekirdeğin toplam kütlesi, içindeki parçacıkların toplamından daha küçüktür. Aradaki fark:

\[ E_{\text{bağ}} = \Delta m \cdot c^2 \]

Fisyon ve füzyon tam olarak bu farktan enerji üretir. Little Boy'un "verimsizliği" de burada anlam kazanır: sistem çok daha büyük bir enerji rezervine sahipken onun sadece çok küçük bir kısmını kullanabilmiştir. Eğer teorik olarak 1 kg madde tamamen enerjiye dönüşseydi:

\[ E = 1 \times c^2 \approx 9 \times 10^{16} \text{ joule} \]

Bu, yaklaşık 21 megaton TNT ederdi. Hiroşima'daki patlamanın binlerce katı.

Işığı Tartabilir misin?

Bu noktada "katı madde" fikri tamamen çözülmeye başlar. Katılık, sadece atomlar arası elektromanyetik kuvvetlerin makroskopik etkisidir. Temel seviyede her şey enerji ve alan organizasyonudur. Bu yüzden ışık gibi tamamen kütlesiz bir şey bile mekanik etki yaratabilir — çünkü momentum taşıyordur.

Ama asıl zihin açan nokta şu: ışığı tek başına tartamazsın çünkü durduramazsın. Kütle dediğimiz şey aslında bir sistemin "durgun haldeki enerjisi" ile tanımlıdır. Foton için böyle bir durum yoktur, hep \(c\) ile gider. Ama ışığı bir kutunun içine hapsedersen, sistemin toplam momentumu sıfır olur ve artık bir "durgun sistem" elde edersin. O zaman sistemin kütlesi:

\[ m = \frac{E_{\text{toplam}}}{c^2} \]

kadar artar. Yani bir kutunun içine ışık koyarsan gerçekten daha ağır olur. Bir cismi ısıtırsan, içine enerji koyduğun için kütlesi artar. Fark çok küçüktür ama prensip kesindir.

Yerçekimi ve Eğri Uzay

Son adımda yerçekimine baktığında yine aynı hikâyeyi görürsün. Newton'a göre yerçekimi bir kuvvettir ve kütleleri çeker. Ama Einstein'a göre kütle ve enerji uzay-zamanı büker. Işık da bu eğri geometri içinde hareket eder. Bu yüzden bükülür — "çekildiği" için değil, bulunduğu uzay eğri olduğu için yolunu değiştirir.


Bütün bu hikâyeyi tek bir cümleyle özetlemek mümkün: evren, katı nesnelerden oluşan bir yer değil; enerji ve alanların belirli kurallara göre organize olmuş halidir. Kütle, momentum, bağ enerjisi ve yerçekimi, bu organizasyonun farklı yüzleridir.

Ve en güzel tarafı şu: bu hikâyeyi gerçekten anlamaya başladığın anlar hep aynı şekilde geliyor — "oha" 😄

Sunday, April 5, 2026

Steelseries Engine 3 ve Rival 100 not connected problemi.

Rival 100 mouse kullanıyorum. Bazen soldaki B4-B5 tuşlarına atadığım ses kontrolü çalışmıyor.

SteelSeries Engine 3'ü açıp bakınca Rival 100'ün yanında Not Connected yazıyor.

Mouse takılı ve çalışıyor, ama Steelseries Engine 3 yazılımı mouse'u görmüyor.

SteelSeries Engine 3, mouse'u tanıyamazsa tüm özel atamalar devre dışı kalıyor. Volume up, volume down, ben sadece bu tuşları kullandığım bunlar gidiyor, muhtemelen diğer atamalar da gidiyordur, denemedim. Çözüm için USB'yi çıkarıp takıyorum ya da bilgisayarı yeniden başlatıyorum, sorun geçici olarak düzeliyor. Ama bu her seferinde yapılacak bir şey değil. Zaten sonra rastgele bir restartta tekrar ediyor.

Rival 100, Windows'a USB Composite Device olarak bağlanıyor. Yani tek bir fiziksel cihaz, Windows'a birden fazla giriş olarak görünüyor. Bunların hepsinin düzgün başlatılması gerekiyor.

Bazen sistem açılışında bu başlatma süreci aksıyor. Mouse fiziksel olarak çalışıyor ama Engine 3 cihazı recognize edememiş oluyor.

Device Manager'da driver uninstall/reinstall yapmak işe yaramıyor.

Yazılımsal çözüm: USBDeview

Fiziksel olarak USB'yi çıkarıp takmanın tam yazılım karşılığı NirSoft'un ücretsiz aracı USBDeview.

İndirme linki: nirsoft.net/utils/usb_devices_view.html

Kurulum yok, portable .exe.

  1. USBDeview yönetici olarak çalıştırılır. (Sağ tık → Run as Administrator)
  2. Listede SteelSeries Rival 100 için üç satır var: USB Composite Device olanı resetlenecek.
  3. Üzerine sağ tıklayıp, Disable+Enable seçilir.
  4. Engine 3 kapatıp açılır.

Mouse connected görünüyor, atamalar geri geliyor.

Neden Composite Device? Çünkü diğer iki girişin (HID ve USB Input Device) ebeveyni o. Onu sıfırlayınca altındaki her şey yeniden başlatılıyor. Tek tek uğraşmaya gerek yok.

Kalıcı çözüm: USB güç tasarrufunu kapatmak

USBDeview sorunu çözüyor. Ama sorun tekrar yaşanıyor. 

Sebep büyük ihtimalle Windows'un USB güç tasarrufu özelliği. Bu seçenek belirli koşullarda USB cihazlarını uyutabiliyor. Mouse fiziksel olarak çalışmaya devam ediyor ama Engine 3 bağlantıyı kaybediyor.

Kapatmak için:

  1. Denetim Masası → Güç Seçenekleri
  2. Aktif planın yanındaki Plan ayarlarını değiştir
  3. Gelişmiş güç ayarlarını değiştir
  4. USB ayarları → USB seçici askıya alma ayarı → Devre dışı

Şimdilik bu kadar. Sorunun tekrarlanıp tekrarlamadığını birkaç gün izleyeceğim.


Friday, April 3, 2026

Açık Kaynağın Karanlık Yüzü: Dependency Hell ve Güvenlik Kabusu

"Sadece npm install yap"


Bir uygulama geliştirmeye karar verdiniz. Modern, açık kaynak araçlar kullanacaksınız. Ücretsiz, özgür, topluluk destekli. Harika.

İlk komutunuzu yazıyorsunuz:

npm install

Ve başlıyor. Ekran dolup taşıyor. Yüzlerce paket, onlarca uyarı, birkaç hata. Beş dakika sonra hâlâ kurulum yapıyor. On dakika sonra bir şeyler ters gidiyor.

Hoş geldiniz. Dependency hell'e düştünüz.

Bu nasıl bir yer?

Bir Node.js projesi açın, node_modules klasörüne bakın. Siz 5 paket istediniz. Ama orada 1.500, belki 2.000 paket vardır. Geri kalanı ne?

Onların bağımlılıkları. Onların bağımlılıklarının bağımlılıkları. Onların bağımlılıklarının bağımlılıklarının bağımlılıkları.

Bir paket "A" ister, A paketi "B v2.x" ister, başka bir paket "B v3.x" ister, ikisi uyuşmaz, Metro bundler çöker, ekran kırmızıya döner. Günün geri kalanı bu hatayla geçer.

npm ekosisteminde 2 milyondan fazla paket var. Bu sayı her gün büyüyor. Hiçbir merkezi denetim mekanizması yok. Herkes her şeyi yayınlayabiliyor.

left-pad: İnternetin 11 Satıra Bağlı Olduğu Gün

2016 yılında Azer Koçulu isminde bir geliştirici, npm'deki "left-pad" adlı paketini sildi. Bir hukuki anlaşmazlık yüzünden kızmıştı, paketi çekti.

left-pad ne yapıyordu? Bir string'in soluna boşluk ekliyordu. 11 satır kod.

Sonuç: React çöktü. Babel çöktü. Binlerce proje build edilemez hale geldi. Dünyanın dört bir yanında CI/CD pipeline'ları durdu. Şirketler saatler içinde milyonlarca dolar kaybetti.

İnternetin önemli bir kısmı, tek bir insanın sinirli bir öğleden sonrasına bağlıydı.

event-stream: Hacker'ın Hediyelik Paketi

2018'de daha da ürkütücü bir şey yaşandı.

"event-stream" popüler bir npm paketiydi. Geliştirici paketi artık aktif olarak sürdürmediğini, devretmek istediğini açıkladı. "right9ctrl" isimli biri gönüllü oldu ve paketi devraldı.

Haftalarca kimse fark etmedi. Ta ki bir araştırmacı, paketin içine gizlenmiş kod parçasını bulana kadar.

O kod ne yapıyordu? Kullanıcıların kripto para cüzdanlarını arıyor, özel anahtarları çalıyordu. Hedef spesifikti: Copay isimli bir Bitcoin cüzdan uygulaması.

Paket bu sürede milyonlarca kez indirilmişti.

Peki kim fark etti? Bir GitHub kullanıcısı. Gönüllü, ücretsiz çalışan biri.

Kim Denetliyor?

Kısa cevap: Kimse.

npm'in otomatik tarama sistemleri var. Bilinen zararlı yazılım imzalarını arıyor. Ama sıfırıncı gün saldırıları için, özellikle hazırlanmış hedefli kötü kod için bu taramalar kör.

Büyük şirketler kendi çözümlerini üretmiş durumda. Google, Meta, Microsoft kritik paketleri fork edip kendi güvenlik ekiplerinden geçiriyor. Ama bu lüks her şirkete nasip olmuyor.

Snyk, Dependabot, Socket gibi araçlar bilinen açıkları takip ediyor. CVE veritabanlarıyla karşılaştırıyor. Faydalılar, ama reaktifler: açık önce bulunuyor, sonra işaretleniyor, sonra siz güncelliyorsunuz. Bu arada ne kadar süre geçiyor?

Açık Kaynak'ın Trajedisi

Burada bir paradoks var.

Açık kaynak, yazılım dünyasını demokratikleştirdi. Bir öğrenci, dünyaca kullanılan bir kütüphane yazabiliyor. Küçük şirketler, enterprise araçları ücretsiz kullanabiliyor. Bilgi paylaşılıyor, ilerleme hızlanıyor.

Ama bu ekosistem, gönüllü emeği üzerine kurulu. Ve gönüllü emek tükeniyor.

"left-pad" geliştiricisi yoruldu, bıraktı. "event-stream" geliştiricisi yoruldu, devretti. Her gün onlarca kritik paket, hayatının farklı bir dönemine geçmiş, artık ilgilenemeyen biri tarafından "sürdürülüyor."

Siz o paketi kullanıyorsunuz. Onun bağımlılığının bağımlılığı olarak. Habersizce.

Microsoft'un Kapalı Dünyası Daha mı İyiydi?

Nostalji tehlikeli. Eski Microsoft dünyasının da bedelleri vardı.

Her şey Windows'a kilitliydi. Lisanslar pahalıydı. Topluluk katkısı neredeyse sıfırdı. "Linux bir kanser" diyen bir şirketten bahsediyoruz. Yenilik yavaştı, her şey Microsoft'un roadmap'ine bağlıydı.

O dünya güvenliydi çünkü dardı. Bugünkü dünya özgür ama kaotik.

İkisi arasında sağlıklı bir denge henüz bulunamadı.

Ne Yapmalı?

Bağımlılıklarınızı tanıyın. npm ls ile dependency tree'ye bakın. Her paketin ne yaptığını en azından kabaca bilin.

Sürümleri kilitleyin. package-lock.json'u commit edin. ^ ve ~ versiyonlarına dikkat edin, her npm install'da farklı bir şey kurulabilir.

Güvenlik taraması yapın. npm audit çalıştırın. Snyk veya Dependabot entegre edin. Mükemmel değil ama hiç yoktan iyi.

Az bağımlılık, daha az risk. Her şey için paket kurmak yerine zaman zaman kendiniz yazın. 11 satırlık bir şey için left-pad kurmayın.

Büyük, aktif topluluğa sahip paketleri tercih edin. Son commit tarihi 4 yıl önceyse, o paket için iki kez düşünün.

Son Söz

Bugün bir uygulama kurarken Node versiyonu uyumsuzluğu, Expo SDK çakışması, TurboModule hatası, babel-preset eksikliği derken saatler harcadım.

Şikâyet etmek kolay. Ama şunu da söylemek lazım: bu kaotik, güvensiz, yorucu ekosistemi gönüllüler inşa etti. Ücretsiz. Bazen gecenin üçünde. Karşılıksız.

Belki de asıl sorun, milyar dolarlık şirketlerin bu gönüllü emeğin üzerine ticari ürünler inşa etmesi ve o emekçilere yeterince geri vermemesi.

Ama bu başka bir yazının konusu.


Bu yazıyı bir React Native uygulaması kurulum hatasının 15. dakikasında yazmaya karar verdim. Uygulama 1.5 saatte çalıştı.