← laboratuvar · bellek eğitimi · ders
Önce evrensel kısım: bellek neden eğitilir, eğitim neyi arar, neden her seferinde biraz farklı sonuç verir. Sonra vaka: bir dizüstünün firmware'i "ne zaman baştan eğiteyim" sorusuna ne cevap veriyor, ve bu cevap kasa açmadan, yalnız saati oynatarak nasıl bulundu.
1 · Bir bit ne kadar yaşar
Vakadaki makinenin belleği saniyede 5200 milyon kez veri aktarıyor. Tek bir bitin telde kalma süresi bunun tersi: 1 / 5 200 000 000 saniye, yani yaklaşık 192 pikosaniye.
Bunu bir mesafeye çevirelim. Işık 192 pikosaniyede 6 santimetre kadar gider. Bir devre kartının üstündeki sinyal ışıktan kabaca iki kat yavaştır, yani bir bit kartta 3 santimetre kadar yol alırken ömrünü doldurur.
Bellek modülüyle işlemci arasında onlarca paralel hat var. Hepsi aynı anda yola çıkan bitleri taşıyor, ama hiçbiri tam aynı uzunlukta değil. Birkaç milimetrelik fark, pencerenin azımsanmayacak bir kısmını yer. Üstüne her çip biraz farklı hızda, her transistör sıcaklıkla biraz yavaşlıyor.
Soru şu: alıcı, her hat için biti tam ne zaman okumalı?
2 · Göz
Tek bir hattan geçen binlerce biti üst üste çizersen şöyle bir resim çıkar: bitler 0'dan 1'e, 1'den 0'a geçerken çizgiler iki kenarda çaprazlanır, ortada ise boş bir alan kalır. O boşluk, bitin "kesin" olduğu bölge. Şekli bir göze benzediği için adı göz diyagramı (İngilizce eye diagram).
Alıcının iki ayarı var. Biri ne zaman okuduğu: saat kenarına eklenen küçük gecikme adımları, adı tap. Öbürü hangi eşikle okuduğu: "bu gerilimin üstü 1" dediği çizgi, adı Vref (İngilizce reference voltage — "karşılaştırma gerilimi"). Doğru ayar gözün tam ortası: iki kenara da, üste de alta da en uzak nokta.
Eğitim bu ortayı bulmaktır. Aşağıdaki tezgâhta dene: tara ve eğite bas. Her (tap, Vref) noktası kısa bir denemeden geçer, hatasız okunanlar boyanır, göz ortaya çıkar ve eğitim ortasına bir işaret koyar. Sonra yeniden eğite birkaç kez bas ve işaretin nereye düştüğüne bak.
Bu bir model, ölçüm değil: bir veri hattının basitleştirilmiş taklidi. Gürültü ve sıcaklık katsayıları temsilî. Yön ve biçim gerçek davranışla aynı.
İşaret her seferinde bir iki adım oynuyor. Hat aynı, koşul aynı, ama sonuç farklı. Çünkü tarama bir ölçüm, ve her ölçüm gibi gürültülü: kenardaki bir nokta bir taramada şans eseri geçer, öbüründe kalır. Merkez de ona göre kayar.
Bu, vakada gerçek eğitimlerde de görüldü. Aynı bellek yedi kez eğitildiğinde ayarların ezici çoğunluğu her seferinde aynı çıktı, oynayanlar ise bir iki adım oynadı. Rakamlar 8. bölümde.
3 · Kim ölçüyor
İşin tuhaf yanı: bu ölçüm yapılırken bildiğin işlemci, yani programları çalıştıran x86 çekirdekleri, daha uyanmamış oluyor. Belleği eğitilmemiş bir işlemci program çalıştıramaz; programı koyacak güvenilir bir yeri yok.
AMD işlemcilerde eğitimi, yonganın içindeki ayrı ve küçük bir çekirdek yönetiyor. Adı PSP (İngilizce Platform Security Processor). x86 değil, bir ARM çekirdeği. Güç gelince ilk o uyanır, BIOS çipinden kendi yazılımını okur, imzasını denetler, belleği eğitir ve ancak ondan sonra x86 çekirdeklerini serbest bırakır.
Bellek hatlarını fiilen tarayan şey ise bellek denetleyicisinin fiziksel katmanındaki bir başka küçük işlemci. Yani tek bir yongada, sen hiç görmeden, birkaç ayrı işlemci sırayla çalışıyor.
Kabaca sıra şöyle (AMD platformları için açık kaynak belgelerle uyumlu, ayrıntı nesilden nesile değişir):
Yani kara ekranın sürdüğü o bir dakikada ekranı çizecek olan x86 henüz hiç çalışmamış oluyor. Ekran bu yüzden kara.
4 · Kayıt ve güven
Tam bir eğitim onlarca saniye sürüyor, çünkü her hat için yüzlerce (tap, Vref) noktası denenmeli. Her açılışta bunu yapmak kimsenin istemeyeceği bir şey. Bu yüzden eğitimin sonucu, hat başına seçilmiş ayarlardan oluşan bir tablo, BIOS çipine kaydedilir. Sonraki açılışlar ölçmez, tabloyu yükler. Vakadaki makinede fark: tam eğitimle yaklaşık 57 saniye, kayıttan yaklaşık 7 saniye firmware süresi.
Ama kayıt bir fotoğraf: çekildiği anın koşullarını gösterir. RAM değiştirilmişse, işlemci başkasıysa, sıcaklık çok farklıysa, yazılım güncellendiyse, o fotoğraf artık bugünü göstermeyebilir. Bayat bir ayarla açılmak rastgele bellek hataları demek.
Firmware her açılışta bir karar veriyor: kayda güveneyim mi, baştan mı ölçeyim? Hızla güvenlik arasında bir denge. Bu kararın kuralı ise genellikle hiçbir yerde yazmıyor.
Bu kararı kendin vermeyi denemek istersen: tezgâhtaki politika oyunu. Sekiz olay kartı, her birinde "güven mi, eğit mi".
5 · Vaka: kaydın içi
Vakadaki makinede bir gün açılış iki kez üst üste bir dakika sürdü, sonra normale döndü. Sebebini bulmak için kaydın kendisine bakıldı. Makinenin firmware'i, kendi üzerinde ve salt okunarak incelendi; hiçbir şey yazılmadı, değiştirilmedi. (Bu sayfa inceleme yöntemini anlatmıyor, yalnız bulunanları.)
AMD bu kayda APOB diyor (İngilizce AGESA PSP Output Buffer — "PSP'nin çıktı tamponu"). Eğitimden sonra PSP bu tamponu belleğe yazar, bir kopyasını da BIOS çipinde saklar. Açılışta geri yüklenen şey o kopya.
Tamponun yapısı AMD'nin açık kaynak başlatma projesi openSIL'in başlık dosyalarında tanımlı. Vakadaki kopya bu tanımlara birebir oturdu: APOB imzası, 62 KB, 25 giriş. Her giriş bir grup ve tür numarası taşıyor: bellek, çekirdekler, genel ayarlar, olay günlüğü…
openSIL tanımına göre her girişin başlığında 32 baytlık bir HMAC var: yalnız anahtarı bilenin üretebileceği bir özet. PSP, bir sonraki açılışta kaydın kendi yazdığı kayıt olduğunu buradan denetleyebilir. Vakada da içeriği değişen her girişin HMAC'i değişti, içeriği aynı kalanların aynı kaldı.
Yani kayıt okunabiliyor, ama anahtarı bilmeyen birinin yazdığı sahte bir kaydın kabul edilmemesi amaçlanıyor: imza okumayı değil, sahteciliği engellemek için.
Bellek modülünün üstünde, kimliğini ve hız değerlerini taşıyan küçük bir bilgi çipi var: SPD (İngilizce Serial Presence Detect). Linux bu çipi spd5118 sürücüsüyle okuyabiliyor: DDR5'te 1024 bayt.
Kayıttaki "DIMM SPD verisi" girişi ile modülün kendi çipinden okunan 1024 bayt karşılaştırıldı: 1024 baytın 1024'ü aynı. x86 daha uyanmadan PSP modülün kimliğini okumuş ve kaydına koymuş. Tanımların doğru okunduğunun da ilk kanıtı bu oldu.
Bir ayrıntı: modül 5600 MT/s için yapılmış, ama makine onu 5200'de çalıştırıyor. Hızı modül değil, eğitimi yapan platform belirliyor.
"Açılış bilgisi" girişinde AMD'nin tanımında adı LastPmuTrainTime olan bir alan var: son eğitimin zamanı. Değeri 0x00260924. Onaltılık okuyunca anlamsız bir sayı, ama iki haneli gruplar halinde okununca: 26 · 09 · 24, yani 24 Eylül 2026. Kayıt alındığı gün.
Firmware son eğitimin tarihini tutuyor. Saatini değil, yalnız gününü.
Bu kodlamanın adı BCD (İngilizce binary-coded decimal — "ikilikle kodlanmış onluk"): her 4 bit tek bir onluk rakam tutar. 0x26 onaltılıkta 38 eder, ama BCD'de "2 ve 6" demek. Bilgisayarların gerçek zaman saati tarihleri tarihsel olarak böyle tutar; kayıt da saatten okuduğunu aynen yazmış.
6 · Hipotez
Makinenin açılış süreleri sistem günlüğünde duruyordu. O günkü iki uzun açılışın öncesinde bilgisayarın saati bozulmuştu: bir tanı aracı, çalışırken saatin içine veri yazan bir yöntem kullanmış ve tarihi 2024'e atmıştı. Günlük şunu gösteriyordu:
Hipotez: tarih son eğitimden geriye giderse ya da çok ileri sıçrarsa firmware kayda güvenmiyor. Ama her gün yeni bir tarih ve açılışlar her gün 7 saniye, yani "tarih değişti" tek başına sebep değil. "Çok ileri" ne kadar?
7 · Deney: saati oynatmak
Deney basit: bilgisayarın donanım saatini (RTC) belli bir tarihe al, yeniden başlat, iki şeye bak. Biri firmware süresi (57 s mi, 7 s mi). Öbürü kaydın içindeki tarih: eğitim olduysa yeni tarih yazılmış olmalı. İki bağımsız kanıt, aynı soru.
Saat oynatılırken ağ saati geçici olarak kapatıldı ve her deneyin sonunda geri açıldı. Saatin ileri atladığı açılışlarda zamanlanmış görevlerin bir şey silmediği ayrıca denetlendi. Her adım bir öncekinin sonucuna göre seçildi:
| deney | saat, son eğitime göre | firmware | eğitim |
|---|---|---|---|
| E1 | 1 gün geri | 57,6 s | var |
| E2 | 1 gün ileri, aynı ay | 7,0 s | yok · kayda dokunulmadı bile |
| E3 | 9 gün ileri, ay değişti | 57,6 s | var |
| E3 dönüşü | 8 gün geri | 57,6 s | var |
| E4 | 6 gün ileri, aynı ay | 7,0 s | yok |
| E4 dönüşü | önceki açılışa göre geri, ama son eğitimle aynı gün | 7,0 s | yok |
| E5a | 37 gün ileri (ayın son günü) | 57,6 s | var |
| E5b | 1 gün ileri, ama ay değişti | 57,6 s | var |
| E5 dönüşü | geri | 57,6 s | var |
İki sonuç kilit. E4 dönüşü: saat bir önceki açılışa göre geri gitti ama eğitim olmadı, çünkü son eğitimin tarihiyle aynı gündü. Yani firmware bir önceki açılışla değil, kayıttaki tarihle karşılaştırıyor.
E5b: yalnız bir gün ileri gidildi, ama ay değişti ve eğitim oldu. E2'de de bir gün ileri gidilmişti, ay aynıydı, eğitim olmamıştı. İkisi arasındaki tek fark ay.
Saat, son eğitimin tarihinden gerideyse ya da ay (veya yıl) farklıysa: baştan eğit. Aynı ay içinde ileriyse: kayda güven.
Pratik anlamı: bu makinede her ayın ilk açılışı yaklaşık bir dakika sürüyor. O günkü gizemin cevabı da buydu: saat önce geriye, sonra yirmi iki ay ileriye gitmişti.
Yalnız yılın değişip ayın aynı kaldığı durum (örneğin bir Eylül'den ertesi Eylül'e) denenmedi; kural "ay ya da yıl" diye yazıldı ama o parça çıkarım.
8 · Gürültü: aynı bellek, yedi eğitim
Deney bir yan ürün bıraktı: aynı belleğin yedi ayrı eğitim kaydı. Eğitim sonuçlarının durduğu 16 384 baytlık giriş yedi kayıtta karşılaştırıldı:
En ilginç olanı iki durumlu bir alan: yedi eğitimde ya 0x55 ya 0x44 çıktı, arası hiç çıkmadı; biri dört, öbürü üç kez. Sürekli bir değer olsaydı arada bir yerler de görülürdü. Görülmedi. Eğitim burada iki aday arasında kalıyor ve ikisi neredeyse eşit iyi olduğu için bazen birini, bazen öbürünü seçiyor. En iyi nokta sivri bir tepe değil, bir düzlük.
Hangi baytın hangi hatta, hangi ayara karşılık geldiği bulunamadı: o yerleşim fiziksel katmanın üreticisine ait ve açık bir kaynakta bulunamadı. Buradaki sayılar yalnız "ne kadar oynuyor" sorusunu cevaplıyor.
9 · Neyi bilmiyoruz
Neden hazır betik yok
Bu sayfa ne yapıldığını ve ne bulunduğunu anlatıyor, kopyalanıp çalıştırılacak komutlar vermiyor. Bilerek. Saati geri almak dosya zamanlarını, yedekleme araçlarını ve zamanlanmış görevleri şaşırtabilir; firmware'le ilgili her işlem makineden makineye değişir. Merak edip kendi makinende bakmak istersen, önce ne yaptığını anlaman gerekiyor. Anlayan biri için bu sayfadaki anlatım yeterli.
Repoda nereye bağlanıyor
Kaynaklar
xUSL/Include/ApobCmn.h içinde.