21 Ağustos 2021 Cumartesi

VirtualBox'ta FreeDOS Invalid Opcode Problemi ve Makinaya Ağdan Dosya Aktarmak


Merhaba. Daha önceki yazılarda (özellikle disk ve dosya sistemi yazılarında) onlarca kere FreeDOS kurup üzerine konuştum. Bu kurulumlarda önceden hiç sorun yaşamadım.

Bu yılın başında, eski işletim sistemimi silip Fedora kurdum ve repoların da güncel olması sayesinde kullandığım programların son sürümlerini yükleme şansım oldu. Bunlardan biri de VirtualBox. Daha önceden 5.x sürümünü kullanırken şu anda v6.1.20 sürümü yüklü. Bu yazıyı hazırladığım sırada en güncel sürümü v6.1.22'ydi. Ancak bu yeni VBox'ta FreeDOS'u açarken komut satırına bile düşmeden sistem çöktü ve sorunun çözümünü araştırmam gerekti. İşte bu yazıda bunun çözümüne değineceğim.

FAT32 yazısı için yeni bir makina kurmak istiyordum. Makina olarak DOS seçtim. Zaten adında DOS geçen bir sanal makinada DOS otomatik seçiliyor. Diskin garanti FAT32 olması (>2GB) için de 4 GB'lik bir disk oluşturdum. FD12CD.iso'yu takıp boot eder etmez başlıkta sözünü ettiğim "Invalid Opcode" hatasını aldım:


Aslında hata HIMEMX.EXE dosyasında oluşuyor. İlkin boot ederken F8'le adım adım onaylama (trace) moduna girip, hatanın hangi adımda ortaya çıktığını buldum. Ardından makinayı tekrar resetleyip adım adım onaylama modunda bu dosyayı geçtim ancak kurulumdaki metin arayüz de .bat dosya komutlarıyla oluşturulduğundan kurulumda sorun oluyor.

Görünüşe göre bu bilinen bir hata ve ilk olarak 2018'de bildirilmiş. Ben önceki kurulumları eski sürüm VBox'ta yaptığımdan sorun olmamıştı. Bu arada önceden hangi sürümü kullandığımı hatırlamasam da muhtemelen 5.x'ti. Ve arada majör sürüm farkı olmasına rağmen sorun ilk önce VBox v5.2.10'da bildirilmiş.

Çözüm
Hata FreeDOS'ta mı yoksa VBox'ta mı anlayamadım, çünkü FreeDOS, Vmware'de sorunsuz boot ediyor ama diğer yandan hata kaydında FreeDOS v1.3'te* bu sorunun çözüleceği ifade ediliyor. Sorunun iki farklı çözümü var: (1) Makinayı FD12CD.iso yerine FD12LGCY.iso'yla açmak veya (2) çekirdek parametrelerine "raw" ifadesini eklemek. Ben legacy iso'yu kullanarak boot ettiğimde bir uyarı almama rağmen kurulumda sorun yaşamadım. Uyarı şöyleydi: "Unfortunately, this method of installation is not supported on this hardware platform. Please try a different installation method.". Ekran görüntüsü yukarıda (bu uyarıyı vmware'de almadım). Her ne kadar makina uyarı verse de komut satırına düştüğünde "fdisk"le önce diski bölümledim, makinayı yeniden başlattım ve "setup" komutuyla kuruluma başladım.

İkinci seçenekte, makinayı FD12CD.iso ile başlattım ve "Welcome to FreeDOS 1.2" ekranında Tab'a basıp, satır sonunda bir karakter boşluk bırakarak "raw" ekledim ve Enter'la devam ettim. Bu durumda kurulum sihirbazı otomatik başladı ama önce diski bölümlemem gerektiğinden ikinci adımda "Return to DOS"u seçip kurulumdan çıktım.

Disk bölümlemeyi kurulum sihirbazına bırakınca 4 GB'lik diski otomatik olarak 2x 2GB'lık FAT32 bölüme ayırıyor. Ben tek bir bölüm oluşturmak için bölümlemeyi elle yapacağım. Prompt'a düştükten sonra fdisk'i çalıştırıp FAT32 desteğiyle ilgili soruya Y dedim. 1, 1, Enter, Esc tuş kombinasyonuyla 4GB'lik bir disk bölümü oluşturup makinayı yeniden başlattım. Kurulum sihirbazında (Legacy CD'yle boot edildiği durumda önce setup komutunu girip) "Erase and format drive C:"yi ve sonra "Full installation"ı seçtim. Kurulum bittikten sonra CD'yi çıkarıp makinayı yeniden başlattım. Diski elle formatlamanın bir getirisi olmuyor çünkü bilinmeyen bir nedenden dolayı sihirbaz formatlanmış diski kendi tekrar formatlamak istiyor.

Invalid opcode hatasının çözümü bu kadar.

* Yazıyı hazırladığım sırada FreeDOS posta listesinde v1.3 RC4'ün yayınlanacağı duyuruldu. En son kontrol ettiğimde freedos.org da güncellenmişti.


FreeDOS Makinasına Dosya Kopyalamak
İkinci sorunu FreeDOS'a dosya kopyalamak isterken yaşadım. Normalde dışarıdan dosya kopyalamak için makinayı Damn Small Linux (DSL) ile başlatıp SSH ile dosya kopyalıyordum. Yeni Fedora'da güvenli olmayan SSH cipher'ler kaldırıldığı için (sanırım) DSL'e bağlanamadım.

Öncelikle sorunu ele alırken önümde bir kısıt vardı: VBox'ta NAT'lanan sanal makina, hosta (sanallaştıran) ulaşabilirken; host, sanal makinaya ulaşamıyor veya belki ben yapamadım. Vmware'de her sanal ağa karşılık, hostta sanal bir ağ kartı oluşturuluyor ve bu karta atanan IP'yle ilgili ağa ulaşılabiliyorken VBox'un NAT'ında bu olanaklı değil. Bu yüzden DSL kullanırken, sanal makinadan hosta bağlanıyordum (veya Host-only Network oluşturuyordum). Şimdi aynısını yapmak istersem DSL'de bulunan cipher'leri güncellemem gerek. Bu bir kenarda dursun.

Öte yandan daha önce bahsetmemiştim ama FreeDOS aslında zengin ağ araçlarıyla geliyor: Ağ kartı aygıt sürücüsü, TCP/IP stack, ethtools (paket çözümleyicisi), mtcp (dhcp, irc, ftp, netcat, sntp vb. araçlar) ve sshdos. Çok umutlu olmasam da belki FreeDOS'tan Fedora'ya ssh yapabilirim diye düşündüm. ssh yapabilirsem, scp de yapabilirim. Sözünü ettiğim araçları yüklemek için FreeDOS CD'sini (hangisi olduğu fark etmez) taktım ve

fdimples

komutunu verdim. Bu, FreeDOS paket yöneticisinin metin arayüzünü açıyor. Buradan "Networking"e gidip fdnet, mtcp ve sshdos paketlerini seçtim (Tab ve boşluk tuşuyla). curl ve wget de dosya transferi için kullanılabilir ama dosya internette değil diskimde ve httpd yüklemek istemiyorum. FreeDOS'ta rsync de var ama ssh desteklemiyor.


Paketleri seçip Tab, Tab, Enter tuş kombinasyonuyla yükledim ve CD'yi çıkarıp makinayı resetledim. Makina açılırken "VirtualBox network detected" diyip DHCP'den aldığı IP'yi gösterdi. SSH dizinine geçip sshdos komutunu verdiğimde (yanda) yalnızca 3des ve blowfish cipher'larının olduğunu gördüm. Fedora'da /etc/ssh/sshd_config'de "Protocol 2,1" ve "Ciphers 3des-cbc" satırlarını ekleyip sshd'yi yeniden başlatsam da "Unsupported remote protocol version" hatasını geçemedim.

Çözüm
Hosta ssh ile ulaşamıyorum. Hosttan sanal makinaya da ulaşamıyorum. Önce hosttan sanal makinaya ulaşmak için ağ ayarlarını değiştirmeliyim:

Sanal makina ağ ayarları

Bu adımda üç seçeneğim var:
1- Host-only Adapter: Bu, sanal makinayı hostun da içinde bulunduğu bir ağa bağlar fakat önce VBox Manager'la bu ağın oluşturulması gerektiği için bu seçeneği atlıyorum.
2- Bridged Adapter: Sanal makina, hostun bulunduğu ağa doğrudan bağlanır. Bu zahmetsiz bir çözümdür ama iş yeri gibi yüksek güvenlikli ağlarda sorun olabilir. Birden fazla ağ kartı olan bir makinada, hangi kart ağa bağlıysa onu seçmek gerekir. Bir de NAT'tan bu ayara geçiliyorsa, makinanın yeni IP alması için \FDOS\bin\fdnet.bat'ı çalıştırmak veya makinayı yeniden başlatmak gerek.
3- NAT + Port Forwarding: Hosttan sanal makinaya bir port açılır, bu porta gelen paketler sanal makinaya iletilir. Bunu ayarlamak için, sanal makina ağ ayarlarında NAT seçiliyken, Advanced açılır ve "Port Forwarding"den Host ve Guest Port'a boşta olan bir port değeri girilir. Guest, DOS olduğundan Guest Port herhangi bir port olabilir. Host Port seçilirken 1024'ten büyük olması tercih sebebi olup, kullanımdaki portlar linux'ta netstat -tln (windows'ta netstat -anl olması lazım) çıktısından kontrol edilebilir. Örn. ben ikisini de 1500 seçtim.

Ağ ayarlarını değiştirdikten sonra sanal makinaya ulaşabilirim ama veriyi nasıl alacağım? mtcp paketinde FTP sunucusu var ama onu ayarlamaktansa ben netcat kullanmayı tercih ederim. Fedora'da nc zaten yüklüydü (nmap-ncat paketinden). Windows'ta da nmap portable'la geliyor. Bağlantıyı test için telnet yeterli olsa da dosya aktarımı için nc'nin yüklü olması gerek. Önce test için MTCP dizininde

nc -listen 1500

komutunu çalıştırdım. Buradaki 1500, "Guest Port" değeri (eğer Guest Port ve Host Port değerleri birbirlerinden farklıysa). Sonra kendi makinamda (NAT seçeneğinde) aşağıdaki komutu çalıştırdım:

nc localhost 1500

"Bridged Adapter" seçeneğinde, "localhost" yerine makinanın IP'si gelecek. Birşeyler yazıp Enter'a basınca yazılanların DOS'ta görünüyor olması gerek. Ctrl+D ile nc'yi sonlandırıp bu sefer DOS'ta dosya aktarımı için şu komutu girdim:

nc -bin -listen 1500 > DOSYA.ADI

ve linux'ta;

nc localhost 1500 < DOSYA.ADI

komutuyla dosyayı aktardım. Her iki makinada da dosyaların md5'lerini md5sum komutuyla kontrol edebilirim.


Alternatif Çözüm (SSH)
Sanal makinanın ağ bağlantısını önceki gibi (NAT veya Bridged) değiştirdim. NAT için "Guest Port"u 22 yaptım. Bu değer zorunlu değil ama 22 olsa iyi olur. Makinayı DSL ile açtım ve DSL menüsünden sshd'yi çalıştırdım (yanda). Bir de terminalden dsl kullanıcısına sudo passwd dsl komutuyla bir şifre verdim. "Bridged Adapter" konfigürasyonu yapıldıysa, makinanın IP'si masaüstünde sağda görülüyor. NAT konfigürasyonunda bu IP 10.0.2. ile başlayan NAT IP'si olmalı ama zaten NAT için localhost'a bağlanacağım.

Bu arada NAT'ta "Guest Port" 22'den farklıysa, sudo nano /etc/ssh/sshd_config komutuyla ayar dosyasındaki Port satırını değiştirip (örn. Port 1500), sudo /etc/init.d/ssh restart komutuyla değişikliği uygulamak gerekiyor. Bence NAT ayarlarında Guest Port'u 22 yapmak daha zahmetsiz.

Makinalar birbirini pingleyebilse bile SSH her iki yönde de sorunlu. DSL'den hosta bağlanamıyorum. Her ne kadar ssh -Q ciphers komutuyla makinamda desteklenen şifreleme algoritmalarını listeleyip, DSL'de bunları ssh komutuna -c parametresiyle verdimse de bağlanamadım. Bazı algoritmalar için "Unknown cipher type" hatası aldım. Bu da demek oluyor ki, DSL'deki ssh en yeni algoritmaları içermiyor. Fedora, elbette DSL'den daha güncel. DSL'de eksik olan bir cipher'i tamamlamaya uğraşmaktansa, sorunu Fedora tarafında çözmek daha kolay. Umduğum, Fedora'nın hala eski algoritmalarla bağlanmaya izin vermese de bağlantı kurarken bunları desteklemesi. Bu arada DSL'deki ssh de o kadar eski ki, -Q parametresini desteklemiyor. Bağlanmayı deneyelim:

[user@host ~]$ ssh -p 1500 dsl@localhost
Unable to negotiate with 127.0.0.1 port 1500: no matching key exchange method found. Their offer: diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1

Bu arada yukarıdaki komut "Bridged adapter" networkte ssh dsl@<VM_IP> şeklinde olmalı. DSL, yukarıdaki çıktıda listelenen key exchange metotlarının kullanılmasını istiyor. O halde, bunu elle girip tekrar deniyorum:

[user@host ~]$ ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 -p 1500 dsl@localhost
Unable to negotiate with 127.0.0.1 port 1500: no matching cipher found. Their offer: aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se

Bu sefer de listelenen cipher'ların kullanılmasını istiyor. Bunu de elle giriyorum:

[user@host ~]$ ssh -oKexAlgorithms=+diffie-hellman-group1-sha1 -c aes128-cbc -p 1500 dsl@localhost
The authenticity of host '[localhost]:1500 ([127.0.0.1]:1500)' can't be established.
RSA key fingerprint is SHA256:[SNIP].
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
[SNIP]

Sonunda bağlandı! O halde, aynı parametreleri scp'ye vererek dosyayı kopyalayabilirim, ancak ssh'daki -p parametresi scp'de -P olmalı:

[user@host ~]$ scp -oKexAlgorithms=+diffie-hellman-group-exchange-sha1 -c aes128-cbc -P 1500 dosya.adi dsl@localhost:~
dsl@localhost's password:
dosya.adi                   100%  543   530.9KB/s   00:00  

Son olarak dosyayı diske değil dsl kullanıcısının ev dizinine kopyaladığım için, tekrar DSL'in terminaline girip:

sudo su
mount /dev/hda1 /mnt
cp dosya.adi /mnt
umount /mnt

komutlarıyla dosyayı FreeDOS'un kurulu olduğu diske aktarırım.

Bir diğer alternatif çözümle, FreeDOS'un wikisinde karşılaştım: Eğer sanal disk formatı .vhd ise (MS HyperV formatı) ve libguestfs-tools yüklüyse, sanal disk guestmount komutuyla mount edilebiliyor, ancak bu paket Fedora'da bağlı paketleriyle birlikte 137 MB kurulum alanı istiyor. Windows'lar .vhd dosyaları kendiliğinden disk gibi açabiliyor. Elbette dosyalar qemu-img komutuyla da vhd, vdi (VBox) ve vmdk (vmware) formatları arasında dönüştürülebilir ancak bu aşırı zahmetli olduğundan tercih edilebilir bir çözüm değil.


Kaynaklar:
(metnin içindeki bağlantılar dışında)
http://wiki.freedos.org/wiki/index.php/VirtualBox_-_Chapter_4
http://wiki.freedos.org/wiki/index.php/VirtualBox_-_Chapter_6
How to enable diffie-hellman-group1-sha1 key exchange on Debian 8.0?