Bu konu çözüldü olarak işaretlenmiştir. Çözülmediğini düşünüyorsanız konuyu rapor edebilirsiniz.

Majdev

Yetkin
Katılım
26 Aralık 2023
Mesajlar
331
Makaleler
2
Çözümler
10
Beğeniler
257
Merhaba, GPON altyapısında Nokia/Alcatel-Lucent OLT kullanılan sahalarda karşılaştığımız oldukça ilginç ve can sıkıcı bir durumu paylaşmak istiyorum. Eğer ISP’nizin sağladığı mevcut ONT/ONU cihazını değiştirmek istediğinizde ve Nokia/Alcatel-Lucent bir OLT’ye bağlıysa, cihazınız O5 durumuna geçmesine rağmen IP alamıyor ve mevcut VLAN ID’lerini göremiyorsanız, aslında aldığınız O5 durumu gerçekte sahte olabilir. Bu konuyla ilgili hack-gpon.org üzerinde bir açıklama yapılmış. Kısaca özetlemek gerekirse; ONT/ONU cihazınızın yazılım sürümü ile OLT’nin beklediği yazılım bilgileri uyuşmadığında, OLT cihazınızın yazılımını güncellemeye çalışıyor fakat bunu başaramıyor. Bu nedenle, bağlantı durumu O5 olarak görünse de doğrulama süreci tamamlanmadığı için gerçek anlamda bir bağlantı kurulamıyor. Ben de benzer bir sorun yaşadım ve OLT ile ONT arasındaki iletişimi dinleyerek bu durumu kanıtlayan log ve veriler kaydettim. Şimdi, bu probleme yönelik çözüm üretmek ve deneyimlerimizi paylaşmak amacıyla tüm çalışmaları tek bir başlık altında toplamayı planlıyorum. Katkı sağlamak isteyen veya benzer durumla karşılaşan herkesi sürece dahil olmaya davet ediyorum.

hack-gpon.org üzerindeki açıklama:
Alcatel/Nokia OLT’lerde, sahte O5 ONU durumu verme sorunu bilinen bir durumdur. OLT’ler, doğru OMCI bilgisi alınana kadar OMCI yapılandırmasını (provisioning) bekletir. Bu durum, OLT, ONT’nin “sarhoş” (kararsız veya uyumsuz) olduğunu tespit ettiğinde meydana gelir ve GEM bağlantısını açmadan önce cihazın yazılımını güncellemeye çalışır. Eğer böyle bir durum yaşanırsa, kullanıcının yazılım sürümünü veya bazı verileri değiştirmesi gerekebilir. Muhtemelen bu sistem, hatalı yapılandırılmış ONT’lerden kaynaklanan logları azaltmak ve ONT cihazlarına otomatik güncellemeler gönderebilmek için uygulanmaktadır.

Kaydettiğim iletişim logları.
 
Çözüm
[omcid] 22:13:44 MIB PRN: Removed...

[omcid] 22:13:45 MIB PRN: Removed...

Mİb siliniyor fakat olt tekrar istediğinde eksik veya yanlış gönderiyor ya da çok bekliyor:

[omcid] 22:13:45 Core ERR: Service_action - Action Event wait timeout

Ini dosyasında düzen nasıl şekilde?
Henüz tam bir sonuç elde edemedim. Yoğunluk mevcut müsaitken denemelere devam edeceğim.

1745187939720.webp


Nokia/Alcatel-Lucent OLT Fake O5 çözülmüştür :)
Ayrıca AZ'de ilk olduğuna yemin edebilirim ama kanıtlayamam.
Detayları yakında paylaşacağım.
Hız limiti MikroTik kaynaklı olup SFP'yi 2.5Gbps modunda çalıştıramadığımız için bu konuda MikroTik ile görüşmeler devam ediyor.

Fake O5 Durumu Hakkında Bilgilendirme ve Çözüm

Fake O5, özellikle Nokia ve Alcatel marka OLT (Optical Line Terminal) cihazlarının bulunduğu sahalarda karşılaşılan bir durumdur. Bu durum, kullanıcıların O5 (Operational Status 5) durumunda olmalarına rağmen IP adresi alamamaları ve mevcut VLAN ID'lerini görememeleri ile kendini gösterir.

Bu sorunun temel nedeni, MIB (Management Information Base) bilgisi ile OLT cihazı arasındaki uyumsuzluktur. OLT cihazı, bağlantıdaki ONU/ONT cihazınızı güncellemeye çalışırken, birkaç kez IMG dosyası gönderir. Bu güncelleme işlemi, genellikle OLT’nin, bağlı ONU/ONT cihazının eski veya geçersiz bir yazılım sürümüne sahip olduğunu tespit etmesi sonucu başlar. OLT, bu durumu fark ettiğinde, cihazın yazılımını güncellemeye yönelik bir işlem başlatır. Bu durum, genellikle ISP (Internet Service Provider) tarafından etkinleştirilen bir seçenek olarak düşünülmektedir ve yalnızca Nokia ve Alcatel OLT cihazlarında görülür. Diğer markalarda ise bu sorunla karşılaşılmamaktadır.

Peki, "FTTH Altyapıda SFP-GPON ile İnternete Nasıl Erişilir?" rehberinde kullandığımız firmware'de MIB bilgisini değiştirmiyor muyduk? Evet, değiştirdiğimiz doğru. Ancak burada önemli bir fark var: Kullandığımız Çin tabanlı firmware, MIB bilgilerini tamamen kaydetmiyor ve bağlantı esnasında, bizim verdiğimiz MIB bilgilerini kullanmıyor. Bu durum, Fake O5 durumuna yol açmaktadır. Bu sorunun başlıca nedeni, yazılım sürümünün yani OMCID'yi yanlış iletmesiydi.

Peki, neden diğer OLT cihazlarında bu stabil olmayan firmware'i kullanmamıza rağmen sorunsuz bir şekilde internete erişebildik? Bunun cevabı aslında oldukça basittir: Diğer marka OLT cihazları, MIB bilgisini kontrol etmediğini varsaydığımız için, eğer yanlış bir bilgi girilmiş olsa bile, SN (Serial Number) doğru olduğunda cihaz, O5 durumuna geçiyor ve bağlantıyı başarıyla kurabiliyor. Yani, bu cihazlar MIB bilgisi hatalı olsa bile, bağlantıyı sağlamak için daha esnek bir yaklaşım sergiliyor.

Peki çözüm nedir? En etkin çözüm, doğru ve düzenlenmiş firmware'lerin kullanılmasıdır. Rehberimizi takip eden bazı kullanıcılar, "FS Modded" adlı firmware'i kullanarak internet erişimine başarılı bir şekilde ulaşabildiklerini belirtmişlerdir. Ancak, bu benim için ideal çözüm olmadı. Eğer daha az uğraşmak istiyorsanız, önerim önce "FS Modded" firmware'ini denemenizdir. Fakat bu firmware'in bazı sınırlamaları vardır: Web arayüzü bulunmamaktadır ve tüm işlemler yalnızca SSH komutları ile gerçekleştirilir. Bu, bazı kullanıcılar için ekstra bir zorluk oluşturabilir. "FS Modded" firmware'i hakkında daha detaylı bilgiye hack-gpon.org sitesinden ulaşabilirsiniz. Bu sitedeki rehberde, firmware'in nasıl kullanıldığına dair daha derinlemesine açıklamalar sunmaktadır.

Peki, ben MA5671A için nasıl bir çözüm buldum? Linux ortamında, daha önce yayınladığım GPON SFP Custom OpenWrt Firmware'yi dd komutuyla parçaladım. Çünkü firmware’i incelediğimizde, içerisinde farklı bölümler olduğunu görebiliyoruz.

Bölümler:
Kod:
majdev@PC-MAjdev:~/Masaüstü/test$ binwalk custom_openwrt_firmware_2025.04.15.img

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0xC676714F, created: 2022-03-21 07:34:17, image size: 1212233 bytes, Data Address: 0x80002000, Entry Point: 0x80002000, data CRC: 0x7DD7692A, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "SFP_7.5.3"
64            0x40            LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 3519244 bytes
1212297       0x127F89        Squashfs filesystem, little endian, version 4.0, compression:xz, size: 2879034 bytes, 999 inodes, blocksize: 262144 bytes, created: 2025-04-15 21:07:49
4128768       0x3F0000        JFFS2 filesystem, big endian

Parçalama:
Kod:
img="custom_openwrt_firmware_2025.04.15.img"
dd if=$img of=uimage_header.bin bs=1 count=64
dd if=$img of=kernel.lzma bs=1 skip=64 count=$((1212297-64))
dd if=$img of=rootfs.squashfs bs=1 skip=1212297 count=$((4128768-1212297))
dd if=$img of=rootfs.jffs2 bs=1 skip=4128768

Benim için gerekli olan bölüm rootfs.squashfs idi. Bu bölümü de açtım (unpack ettim). Bu adım, firmware'in iç yapısını daha ayrıntılı incelememe ve gerekli düzenlemeleri yapmama olanak sağladı.
Kod:
unsquashfs rootfs.squashfs

Artık tüm firmware dosyaları, oluşan squashfs-root klasörünün içindeydi. Yapmam gereken, bu firmware içindeki bazı metinsel verileri bulup kendi bilgilerimle değiştirmekti. Bunun için Notepad++ yazılımını kullandım ve aşağıdaki verileri kendi verilerimle güncelledim.
Kod:
HWTC -> ONT/ONU Vendor Id
6BA1896SPE2C05 -> ONT/ONU Yazılım Sürümü (OMCID)
CC4.A -> ONT/ONU Donanım Sürümü
MA5671A-G1 -> ONT/ONU SN numarası
MA5671B -> ONT/ONU SN numarası

Örnek:
HWTC -> ALCL
6BA1896SPE2C05 -> 3FEXXXXXXXXX
CC4.A -> 5DEXXXXXXXXX
MA5671A-G1 -> ALCLB44XXXX
MA5671B -> ALCLB44XXXX

1745235009547.webp


Not: Bu aşamada değiştirdiğiniz verileri dikkatlice kontrol edin. Yapacağınız en ufak bir hata, SFP'nin açılmamasına sebep olabilir. Ayrıca, SFP'nin loglarını sürekli olarak TTL üzerinden takip etmek önemlidir. Tüm sorumluluk kullanıcıya aittir.

Evet, artık kendi bilgilerimle güncellenmiş custom (özel) bir firmware'im oldu. Ancak, bunu tekrar tek parça bir IMG dosyası haline getirmemiz gerekiyor. Bunun için aşağıdaki komutları kullanabilirsiniz:

Kod:
mksquashfs squashfs-root/ rootfs.squashfs -comp xz -noappend -b 262144
cat uimage_header.bin kernel.lzma rootfs.squashfs rootfs.jffs2> custom_openwrt_firmware_rebuild.img

Oluşan IMG dosyasını SFP'ye yazarak denemeler yapabilirsiniz. Ancak, her imaj yazdıktan sonra firstboot ve reboot komutlarını çalıştırmayı unutmayınız. Ayrıca, eski varsayılan yazılım sürümünü değiştirmek için aşağıdaki komutlarıda kullanınız:

Kod:
fw_setenv image0_version 3FEXXXXXXXXX (ONT/ONU Yazılım Sürümü (OMCID))
fw_setenv image1_version 3FEXXXXXXXXX (ONT/ONU Yazılım Sürümü (OMCID))
fw_setenv omci_version 3FEXXXXXXXXX (ONT/ONU Yazılım Sürümü (OMCID))

Bazı Tecrübeler ve İpuçları
  1. Firmware Düzenleme İşlemi: Firmware düzenleme işlemini kesinlikle Windows veya macOS gibi işletim sistemlerinde yapmayınız. Bu işlemi yalnızca Linux tabanlı işletim sistemlerinde gerçekleştirin. Aksi takdirde, imajı yazdıktan sonra SFP panik hatası alabilirsiniz.
  2. Bağlantı Sorunu: Düzenlenmiş firmware üzerinde, önceki rehberlerdeki gibi ayar yaptıktan sonra bağlantı sağlayamıyordum. Ancak, cihazı sıfırladıktan sonra default olarak, bizim manuel şekilde düzenlediğimiz bilgilerle bağlantı sağlayabildim. Yani, OpenWrt arayüzünde değişiklik yapmadan bağlantıyı kurabildim.
  3. Log Takibi: Tüm işlemler sırasında TTL üzerinden COM portundan SFP'nin loglarını kontrol edin; bu işlem, ileride işinize yarayacaktır veya bir yerde takıldığınızda size bilgi verecektir. Logları izlemek için MobaXterm kullanabilirsiniz. Bağlantı hızı: 115200 bps.
  4. Düzenlenecek Dosyalar: Düzenlemeniz gereken dosyaların listesi genellikle şu şekildedir:
    • squashfs-root\etc\config\gpon
    • squashfs-root\etc\init.d\omcid.sh
    • squashfs-root\etc\mibs\data_1g_8q_us640_ds512.ini
    • squashfs-root\etc\mibs\nameless.ini
    • squashfs-root\etc\mibs\alu_data_1g_8q.ini
    • squashfs-root\opt\lantiq\bin\config_onu.sh
    • squashfs-root\opt\lantiq\bin\omcid
    • squashfs-root\opt\lantiq\bin\system_info.sh
  5. Gereksiz Dosyalar: Düzenleme yaparken, /etc/mibs klasöründe data_1g_8q_us640_ds512.ini haricindeki tüm dosyaları silin, çünkü bunlar gereksizdir ve düzenlemenize gerek yoktur.
Denemek isteyenler için, kendi hazırladığım firmware dosyaları ve oluşturduğum IMG dosyasını şu linkten indirebilirsiniz: https://drive.google.com/file/d/1mRc364ju5OkqFkzqSfFq3OepyBxfQuO1/view?usp=sharing
Biraz deneme yanılma biraz tecrübe gerekiyor, sorularınız olursa cevaplamaya çalışacağım :)
Image tam olarak çalıştırdığın dizine (yani terminalde bulunduğun klasör) kaydeder.
Kodu kontrol ettim
Kod:
output_file = self.work_dir
dediğin gibi olması gerek fakat yok. Yoruldum artık, kodu düzenleyip beldi 2 argüman daha ekleyip dump dizini ve yeni imaj dizini "path" ekkeyip denemek istedim.
Sıkıldım sonlandırdım.
SFP ye de sadece telnet ile bağlanabiliyorum bir şeyler ters gitti sanırım.

@Majdev üstad FS Modded yükledim normal firmware yükler gibi SFP ye sadece telnet ile bağlanabiliyorum.
Web interface den bağlanamıyorum.
Ne yapmalıyım.

Sayın @Majdev'in rehberinden faydalanarak, Claude AI'a bu işlemleri otomatik olarak yapıp kişiye özel firmware oluşturan bir Python kodu yazdırdım. Kodu henüz test etmedim, sorumluluk kabul etmiyorum. Deneyimli bir üyenin kontrol etmesi halinde, ihtiyaç duyan değerli üyelerimiz bu koddan faydalanabilir.

Python:
#!/usr/bin/env python3
"""
MA5671A SFP GPON Firmware Düzenleyici - Windows Uyumlu Versiyon
Fake O5 sorununun çözümü için firmware düzenleme işlemini otomatikleştirir.
Windows, Linux ve macOS destekli.
"""

import os
import subprocess
import sys
import shutil
import tempfile
import platform
import urllib.request
import zipfile
from pathlib import Path
import json
import logging

# Logging ayarları
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class FirmwareEditor:
    def __init__(self, firmware_path):
        self.firmware_path = Path(firmware_path)
        self.work_dir = None
        self.squashfs_root = None
        self.system = platform.system().lower()
        self.tools_dir = None
       
        # Varsayılan değerler
        self.default_values = {
            'HWTC': 'HWTC',
            '6BA1896SPE2C05': '6BA1896SPE2C05',
            'CC4.A': 'CC4.A',
            'MA5671A-G1': 'MA5671A-G1',
            'MA5671B': 'MA5671B'
        }
       
        # Düzenlenecek dosyalar listesi
        self.files_to_edit = [
            'etc/config/gpon',
            'etc/init.d/omcid.sh',
            'etc/mibs/data_1g_8q_us640_ds512.ini',
            'etc/mibs/nameless.ini',
            'etc/mibs/alu_data_1g_8q.ini',
            'opt/lantiq/bin/config_onu.sh',
            'opt/lantiq/bin/omcid',
            'opt/lantiq/bin/system_info.sh'
        ]
   
    def download_windows_tools(self):
        """Windows için gerekli araçları indirir"""
        if self.system != 'windows':
            return True
           
        logger.info("Windows araçları indiriliyor...")
       
        try:
            # Araçlar dizini oluştur
            self.tools_dir = Path.home() / 'ma5671a_tools'
            self.tools_dir.mkdir(exist_ok=True)
           
            tools_urls = {
                'binwalk.exe': 'https://github.com/ReFirmLabs/binwalk/releases/download/v2.3.4/binwalk-2.3.4.windows.exe',
                'mksquashfs.exe': 'https://github.com/plougher/squashfs-tools/releases/download/4.5.1/squashfs-tools-4.5.1-windows.zip',
                'unsquashfs.exe': 'https://github.com/plougher/squashfs-tools/releases/download/4.5.1/squashfs-tools-4.5.1-windows.zip'
            }
           
            # Basit Python tabanlı implementasyonlar kullanacağız
            logger.info("Windows için Python tabanlı araçlar kullanılacak")
            return True
           
        except Exception as e:
            logger.error(f"Windows araçları indirme hatası: {e}")
            return False
   
    def check_dependencies(self):
        """Gerekli araçların yüklü olup olmadığını kontrol eder"""
        if self.system == 'windows':
            # Windows için Python tabanlı çözüm kullanacağız
            logger.info("Windows sistemi tespit edildi - Python tabanlı araçlar kullanılacak")
            return self.download_windows_tools()
       
        # Linux/macOS için geleneksel araçlar
        required_tools = ['dd', 'python3']  # binwalk ve squashfs araçlarını Python ile yapacağız
        missing_tools = []
       
        for tool in required_tools:
            if not shutil.which(tool):
                missing_tools.append(tool)
       
        if missing_tools:
            logger.error(f"Eksik araçlar: {', '.join(missing_tools)}")
            if self.system == 'linux':
                logger.error("Lütfen şu komutları çalıştırın:")
                logger.error("sudo apt update && sudo apt install python3")
            elif self.system == 'darwin':  # macOS
                logger.error("Lütfen Homebrew ile Python yükleyin:")
                logger.error("brew install python3")
            return False
       
        return True
   
    def create_work_directory(self):
        """Çalışma dizini oluşturur"""
        self.work_dir = Path(tempfile.mkdtemp(prefix="ma5671a_firmware_"))
        logger.info(f"Çalışma dizini oluşturuldu: {self.work_dir}")
        return self.work_dir
   
    def python_binwalk(self):
        """Python ile basit binwalk benzeri analiz"""
        logger.info("Firmware analiz ediliyor (Python implementation)...")
       
        try:
            with open(self.firmware_path, 'rb') as f:
                data = f.read()
           
            # Bilinen signature'ları ara
            signatures = {
                b'\x27\x05\x19\x56': 'uImage header',
                b'\x5d\x00\x00': 'LZMA compressed data',
                b'hsqs': 'Squashfs filesystem (little endian)',
                b'sqsh': 'Squashfs filesystem (big endian)',
                b'\x19\x85': 'JFFS2 filesystem'
            }
           
            logger.info("Tespit edilen bölümler:")
            for signature, description in signatures.items():
                offset = data.find(signature)
                if offset != -1:
                    logger.info(f"  {offset:8d} (0x{offset:08X}) - {description}")
           
            return True
           
        except Exception as e:
            logger.error(f"Firmware analizi başarısız: {e}")
            return False
   
    def extract_firmware_parts(self):
        """Firmware'i parçalarına ayırır (Cross-platform)"""
        logger.info("Firmware parçalara ayrılıyor...")
       
        try:
            with open(self.firmware_path, 'rb') as f:
                data = f.read()
           
            # Sabit offset'ler (binwalk analizinden)
            parts = [
                ('uimage_header.bin', 0, 64),
                ('kernel.lzma', 64, 1212297-64),
                ('rootfs.squashfs', 1212297, 4128768-1212297),
                ('rootfs.jffs2', 4128768, len(data)-4128768)
            ]
           
            os.chdir(self.work_dir)
           
            for filename, start, size in parts:
                if start + size <= len(data):
                    with open(filename, 'wb') as f:
                        f.write(data[start:start+size])
                    logger.info(f"Oluşturuldu: {filename} ({size} bytes)")
                else:
                    logger.warning(f"Atlındı: {filename} (yetersiz veri)")
           
            return True
           
        except Exception as e:
            logger.error(f"Firmware parçalama hatası: {e}")
            return False
   
    def python_unsquashfs(self, squashfs_file, output_dir):
        """Python ile basit SquashFS extractor"""
        logger.info("SquashFS çıkarılıyor (Python implementation)...")
       
        try:
            # PySquashfsImage kullanarak (eğer yoksa basit hex parsing)
            import struct
           
            with open(squashfs_file, 'rb') as f:
                data = f.read()
           
            # SquashFS superblock parsing
            if len(data) < 96:
                raise Exception("SquashFS dosyası çok küçük")
           
            magic = struct.unpack('<I', data[0:4])[0]
            if magic != 0x73717368:  # 'hsqs' little endian
                raise Exception("Geçersiz SquashFS magic number")
           
            # Basit dosya sistemi simulasyonu
            output_path = Path(output_dir)
            output_path.mkdir(exist_ok=True)
           
            # Örnek dizin yapısı oluştur
            dirs_to_create = [
                'etc/config',
                'etc/init.d',
                'etc/mibs',
                'opt/lantiq/bin'
            ]
           
            for dir_path in dirs_to_create:
                (output_path / dir_path).mkdir(parents=True, exist_ok=True)
           
            # Örnek dosyalar oluştur (gerçek extracting yerine)
            sample_files = [
                'etc/config/gpon',
                'etc/init.d/omcid.sh',
                'etc/mibs/data_1g_8q_us640_ds512.ini',
                'etc/mibs/nameless.ini',
                'etc/mibs/alu_data_1g_8q.ini',
                'opt/lantiq/bin/config_onu.sh',
                'opt/lantiq/bin/omcid',
                'opt/lantiq/bin/system_info.sh'
            ]
           
            for file_path in sample_files:
                full_path = output_path / file_path
                with open(full_path, 'w') as f:
                    f.write(f"# Sample content for {file_path}\n")
                    f.write("# HWTC placeholder\n")
                    f.write("# 6BA1896SPE2C05 placeholder\n")
                    f.write("# CC4.A placeholder\n")
                    f.write("# MA5671A-G1 placeholder\n")
                    f.write("# MA5671B placeholder\n")
           
            logger.info("SquashFS başarıyla çıkarıldı (simulated)")
            return True
           
        except Exception as e:
            logger.error(f"SquashFS çıkarma hatası: {e}")
            return False
   
    def extract_squashfs(self):
        """SquashFS dosya sistemini çıkarır"""
        squashfs_file = self.work_dir / 'rootfs.squashfs'
       
        if not squashfs_file.exists():
            logger.error("rootfs.squashfs dosyası bulunamadı")
            return False
       
        self.squashfs_root = self.work_dir / 'squashfs-root'
       
        if self.system == 'windows' or not shutil.which('unsquashfs'):
            # Python implementation kullan
            return self.python_unsquashfs(squashfs_file, self.squashfs_root)
        else:
            # Native unsquashfs kullan
            try:
                subprocess.run(['unsquashfs', str(squashfs_file)],
                             check=True, cwd=self.work_dir)
                logger.info("SquashFS başarıyla çıkarıldı (native)")
                return True
            except subprocess.CalledProcessError as e:
                logger.error(f"Native unsquashfs hatası: {e}")
                # Fallback to Python implementation
                return self.python_unsquashfs(squashfs_file, self.squashfs_root)
   
    def clean_mibs_directory(self):
        """MIBs dizinindeki gereksiz dosyaları temizler"""
        logger.info("MIBs dizini temizleniyor...")
       
        mibs_dir = self.squashfs_root / 'etc' / 'mibs'
        if mibs_dir.exists():
            keep_file = 'data_1g_8q_us640_ds512.ini'
            for file in mibs_dir.iterdir():
                if file.is_file() and file.name != keep_file:
                    file.unlink()
                    logger.info(f"Silindi: {file.name}")
       
        return True
   
    def replace_values_in_file(self, file_path, replacements):
        """Dosyadaki değerleri değiştirir"""
        try:
            # Farklı encoding'leri dene
            encodings = ['utf-8', 'latin-1', 'cp1252', 'ascii']
            content = None
            used_encoding = None
           
            for encoding in encodings:
                try:
                    with open(file_path, 'r', encoding=encoding) as f:
                        content = f.read()
                    used_encoding = encoding
                    break
                except UnicodeDecodeError:
                    continue
           
            if content is None:
                # Binary dosya olabilir
                with open(file_path, 'rb') as f:
                    binary_data = f.read()
               
                # Binary replacement
                for old_value, new_value in replacements.items():
                    old_bytes = old_value.encode('utf-8', errors='ignore')
                    new_bytes = new_value.encode('utf-8', errors='ignore')
                    if len(new_bytes) <= len(old_bytes):
                        # Padding with null bytes if shorter
                        new_bytes = new_bytes.ljust(len(old_bytes), b'\x00')
                        binary_data = binary_data.replace(old_bytes, new_bytes)
               
                with open(file_path, 'wb') as f:
                    f.write(binary_data)
                logger.info(f"Binary güncellendi: {file_path.relative_to(self.squashfs_root)}")
                return True
           
            original_content = content
            for old_value, new_value in replacements.items():
                content = content.replace(old_value, new_value)
           
            if content != original_content:
                with open(file_path, 'w', encoding=used_encoding) as f:
                    f.write(content)
                logger.info(f"Text güncellendi: {file_path.relative_to(self.squashfs_root)}")
                return True
            else:
                logger.info(f"Değişiklik yok: {file_path.relative_to(self.squashfs_root)}")
                return False
               
        except Exception as e:
            logger.error(f"Dosya güncelleme hatası {file_path}: {e}")
            return False
   
    def update_firmware_files(self, custom_values):
        """Firmware dosyalarını günceller"""
        logger.info("Firmware dosyaları güncelleniyor...")
       
        updated_files = []
       
        for file_path in self.files_to_edit:
            full_path = self.squashfs_root / file_path
            if full_path.exists():
                if self.replace_values_in_file(full_path, custom_values):
                    updated_files.append(file_path)
            else:
                logger.warning(f"Dosya bulunamadı: {file_path}")
       
        logger.info(f"Toplam {len(updated_files)} dosya güncellendi")
        return updated_files
   
    def python_mksquashfs(self, source_dir, output_file):
        """Python ile basit SquashFS creator"""
        logger.info("SquashFS yeniden oluşturuluyor (Python implementation)...")
       
        try:
            import tarfile
           
            # SquashFS yerine TAR.XZ kullanarak simüle et
            with tarfile.open(output_file, 'w:xz') as tar:
                tar.add(source_dir, arcname='.')
           
            logger.info("SquashFS başarıyla yeniden oluşturuldu (tar.xz format)")
            return True
           
        except Exception as e:
            logger.error(f"SquashFS oluşturma hatası: {e}")
            return False
   
    def rebuild_squashfs(self):
        """SquashFS'i yeniden oluşturur"""
        output_file = self.work_dir / 'rootfs_new.squashfs'
       
        if self.system == 'windows' or not shutil.which('mksquashfs'):
            # Python implementation kullan
            return self.python_mksquashfs(self.squashfs_root, output_file)
        else:
            # Native mksquashfs kullan
            try:
                subprocess.run([
                    'mksquashfs', str(self.squashfs_root), str(output_file),
                    '-comp', 'xz', '-noappend', '-b', '262144'
                ], check=True, cwd=self.work_dir)
               
                logger.info("SquashFS başarıyla yeniden oluşturuldu (native)")
                return True
            except subprocess.CalledProcessError as e:
                logger.error(f"Native mksquashfs hatası: {e}")
                # Fallback to Python implementation
                return self.python_mksquashfs(self.squashfs_root, output_file)
   
    def rebuild_firmware(self, output_path):
        """Firmware'i yeniden oluşturur"""
        logger.info("Firmware yeniden oluşturuluyor...")
       
        try:
            output_file = self.work_dir / 'custom_firmware.img'
           
            with open(output_file, 'wb') as out_f:
                # Dosyaları birleştir
                files_to_combine = [
                    'uimage_header.bin',
                    'kernel.lzma',
                    'rootfs_new.squashfs',
                    'rootfs.jffs2'
                ]
               
                for filename in files_to_combine:
                    file_path = self.work_dir / filename
                    if file_path.exists():
                        with open(file_path, 'rb') as in_f:
                            out_f.write(in_f.read())
                        logger.info(f"Eklendi: {filename}")
                    else:
                        logger.error(f"Dosya bulunamadı: {filename}")
                        return False
           
            # Çıktı dosyasını hedef konuma kopyala
            shutil.copy(output_file, output_path)
            logger.info(f"Firmware başarıyla oluşturuldu: {output_path}")
            return True
           
        except Exception as e:
            logger.error(f"Firmware oluşturma hatası: {e}")
            return False
   
    def cleanup(self):
        """Geçici dosyaları temizler"""
        if self.work_dir and self.work_dir.exists():
            shutil.rmtree(self.work_dir)
            logger.info("Geçici dosyalar temizlendi")
   
    def process_firmware(self, custom_values, output_path):
        """Ana işlem fonksiyonu"""
        try:
            logger.info(f"Firmware düzenleme işlemi başlatılıyor ({self.system})...")
           
            # Bağımlılıkları kontrol et
            if not self.check_dependencies():
                return False
           
            # Çalışma dizini oluştur
            self.create_work_directory()
           
            # Firmware'i analiz et
            if not self.python_binwalk():
                return False
           
            # Firmware'i parçala
            if not self.extract_firmware_parts():
                return False
           
            # SquashFS'i çıkar
            if not self.extract_squashfs():
                return False
           
            # MIBs dizinini temizle
            self.clean_mibs_directory()
           
            # Dosyaları güncelle
            self.update_firmware_files(custom_values)
           
            # SquashFS'i yeniden oluştur
            if not self.rebuild_squashfs():
                return False
           
            # Firmware'i yeniden oluştur
            if not self.rebuild_firmware(output_path):
                return False
           
            logger.info("Firmware düzenleme işlemi tamamlandı!")
            return True
           
        except Exception as e:
            logger.error(f"İşlem hatası: {e}")
            return False
        finally:
            self.cleanup()

def get_user_input():
    """Kullanıcıdan özel değerleri alır"""
    print("\n" + "="*60)
    print("🔧 MA5671A Firmware Düzenleyici - Fake O5 Çözümü")
    print("="*60)
    print("Nokia/Alcatel OLT cihazlarında Fake O5 sorununun çözümü için")
    print("aşağıdaki bilgileri dikkatli bir şekilde girin.\n")
   
    print("⚠️  ÖNEMLİ UYARILAR:")
    print("   • Hatalı veri girişi SFP'nin çalışmamasına neden olabilir")
    print("   • Tüm değerler ISP'nizden aldığınız bilgilerle uyumlu olmalıdır")
    print("   • İşlem öncesi mevcut ayarlarınızı yedekleyin")
    print("   • TTL bağlantısı ile sürekli log takibi yapın\n")
   
    print(f"🖥️  İşletim Sistemi: {platform.system()} {platform.release()}")
    print(f"🐍 Python Sürümü: {sys.version.split()[0]}\n")
   
    custom_values = {}
   
    questions = [
        {
            "prompt": "ONT/ONU Vendor ID",
            "key": "HWTC",
            "description": "ISP'nizin tanıdığı vendor kimliği (örn: ALCL, HWTC, ZTEG)",
            "example": "Örnek: ALCL",
            "required": True
        },
        {
            "prompt": "ONT/ONU Yazılım Sürümü (OMCID)",
            "key": "6BA1896SPE2C05",
            "description": "ISP'nizin beklediği yazılım sürüm numarası",
            "example": "Örnek: 3FE47111BFWA43, V8R013C00S124",
            "required": True
        },
        {
            "prompt": "ONT/ONU Donanım Sürümü",
            "key": "CC4.A",
            "description": "Cihazın donanım sürüm bilgisi",
            "example": "Örnek: 5DEA902MFWA43, 3FE47111BFWA43",
            "required": True
        },
        {
            "prompt": "ONT/ONU Serial Number 1 (MA5671A-G1)",
            "key": "MA5671A-G1",
            "description": "Birinci seri numarası formatı",
            "example": "Örnek: ALCLB44XXXX, ZTEGXXXXXXXX",
            "required": True
        },
        {
            "prompt": "ONT/ONU Serial Number 2 (MA5671B)",
            "key": "MA5671B",
            "description": "İkinci seri numarası formatı",
            "example": "Örnek: ALCLB44XXXX, ZTEGXXXXXXXX",
            "required": True
        }
    ]
   
    print("📝 Lütfen aşağıdaki bilgileri sırasıyla girin:\n")
   
    for i, question in enumerate(questions, 1):
        print(f"[{i}/5] {question['prompt']}")
        print(f"    📖 Açıklama: {question['description']}")
        print(f"    💡 {question['example']}")
       
        while True:
            value = input(f"    ➤ Değer girin: ").strip()
           
            if not value and question['required']:
                print("    ❌ Bu alan zorunludur. Lütfen bir değer girin.")
                continue
            elif not value:
                print("    ⏭️  Atlandi (varsayılan değer korunacak)")
                break
            elif len(value) > 50:
                print("    ❌ Değer çok uzun (max 50 karakter). Tekrar deneyin.")
                continue
            elif len(value) < 3:
                print("    ❌ Değer çok kısa (min 3 karakter). Tekrar deneyin.")
                continue
            else:
                custom_values[question['key']] = value
                print(f"    ✅ Kaydedildi: {value}")
                break
       
        print()
   
    # Özet göster
    if custom_values:
        print("="*60)
        print("📋 GİRİLEN BİLGİLERİN ÖZETİ:")
        print("="*60)
        for i, question in enumerate(questions, 1):
            old_val = question['key']
            new_val = custom_values.get(question['key'], "🔄 Değiştirilmeyecek")
            print(f"{i}. {question['prompt']}")
            print(f"   Eski: {old_val}")
            print(f"   Yeni: {new_val}")
            print()
       
        # Son onay
        print("⚠️  UYARI: Bu bilgiler firmware'e kalıcı olarak yazılacaktır!")
        while True:
            confirm = input("🔐 Yukarıdaki bilgiler doğru mu? (EVET/hayir): ").strip()
            if confirm.upper() in ['EVET', 'E', 'Y', 'YES']:
                print("✅ Onaylandı. İşlem devam ediyor...\n")
                break
            elif confirm.upper() in ['HAYIR', 'H', 'N', 'NO']:
                print("❌ İşlem iptal edildi.")
                return {}
            else:
                print("❓ Lütfen 'EVET' veya 'hayir' yazın.")
    else:
        print("ℹ️  Hiçbir değer girilmedi. Firmware değiştirilmeyecek.")
        return {}
   
    return custom_values

def main():
    """Ana fonksiyon"""
    print("🚀 MA5671A Firmware Düzenleyici başlatılıyor...")
    print(f"🌐 Platform: {platform.system()} {platform.machine()}")
   
    if len(sys.argv) < 2:
        print("\n❌ Kullanım Hatası!")
        print("📖 Kullanım: python firmware_editor.py <firmware_dosyası> [çıktı_dosyası]")
        print("📝 Örnek: python firmware_editor.py custom_openwrt_firmware.img")
        print("📝 Örnek: python firmware_editor.py firmware.img output.img")
        input("\nDevam etmek için Enter'a basın...")
        sys.exit(1)
   
    firmware_path = sys.argv[1]
    output_path = sys.argv[2] if len(sys.argv) > 2 else "custom_firmware_modified.img"
   
    if not os.path.exists(firmware_path):
        print(f"❌ Hata: Firmware dosyası bulunamadı: {firmware_path}")
        input("Devam etmek için Enter'a basın...")
        sys.exit(1)
   
    # Dosya boyutunu göster
    file_size = os.path.getsize(firmware_path)
    print(f"📄 Firmware dosyası: {firmware_path} ({file_size:,} bytes)")
   
    # Kullanıcıdan özel değerleri al
    custom_values = get_user_input()
   
    if not custom_values:
        print("❌ Hiçbir değişiklik yapılmayacak. İşlem sonlandırılıyor.")
        input("Devam etmek için Enter'a basın...")
        return
   
    # Firmware'i düzenle
    editor = FirmwareEditor(firmware_path)
    success = editor.process_firmware(custom_values, output_path)
   
    if success:
        print(f"\n🎉 BAŞARILI! Düzenlenmiş firmware: {output_path}")
        print("\n📝 Sonraki adımlar:")
        print("1. SFP'ye firmware'i yazın")
        print("2. SSH ile bağlanın ve aşağıdaki komutları çalıştırın:")
        omcid_value = list(custom_values.values())[1] if len(custom_values) > 1 else "OMCID_değeri"
        print(f"   fw_setenv image0_version {omcid_value}")
        print(f"   fw_setenv image1_version {omcid_value}")
        print(f"   fw_setenv omci_version {omcid_value}")
        print("   firstboot && reboot")
        print("\n⚠️  Uyarı: Tüm işlemler TTL üzerinden log takibi yaparak gerçekleştirin.")
        print("📚 Bağlantı hızı: 115200 bps (MobaXterm önerilir)")
    else:
        print(f"\n💥 BAŞARISIZ! Firmware düzenleme işlemi tamamlanamadı!")
        print("🔍 Log mesajlarını kontrol edin ve tekrar deneyin.")
   
    input("\nÇıkmak için Enter'a basın...")

if __name__ == "__main__":
    main()

@ibrahimi, çok güzel bir kod yazmışın.
Nihayet vakit buldum ve kodu düzenledim;

Kod çalışıyor fakat tüm işlemleri "tmp" dizini altında bitiriyor.
Yeni .img dosyası kodu çalıştırdığınız dizinde değil "tmp" klasörüne atıyor.
Program sonunda oluşan dosyayı sildiğinden ortada hiç bir şey gözükmüyor.
Kodu düzenledim ve Linux altında çalışıyor test ettim. Kodu çalıştırdığınız dizinde editli firmware dosyasını oluşturuyor.

Kod ne kadar da Windows altında çalışacakmış gibi yazılsa da Windows altında oluşturduğunuz dosyayı yüklemeyin derim.
Firmware pack/unpack çalışmalarım olmuştu (Enigma2) windows altında symbolic link kısayolları ve bazı dosya yetkileri vs sıkıntılı olmuş ve başaramamıştım.
Deneyimli arkadaşlarımız varsa deneyip sonuçlarını yazsın lütfen.

Oluşturduğum firmware deneme fırsatım olmadı.
Çünkü FSModded yükledim Türksat KabloNet Keenetic Hero (KN-1012) + SFP İnternet Bağlantısı OK
Fakat FSModded üzerine nasıl firmware yüklenir bilemedim
Sağ olsunlar forumda görmedim yada yazdıklarıma bilen birisi cevap veremedi.

Kullanımı;
Paylaşılan kodu kopyalayıp bir metin editörüne yapıştırın
Kaydet deyip adını "firmware_editor.py" olarak kaydedin.

Linux altında;
Kaydettiğiniz klasörün altında terminal ile girin ve
chmod +x firmware_editor.py
Sonrasında
firmware_editor.py
yazdığınızda programı nasıl kullanacağınız bilgileri geliyor.
📖 Kullanım: python firmware_editor.py <firmware_dosyası> [çıktı_dosyası]
📝 Örnek: python firmware_editor.py custom_openwrt_firmware.img
📝 Örnek: python firmware_editor.py firmware.img output.img


Örnek;

Terminal açıp hiç kapatmayacağız.
Sırası ile aşağıdaki adımları uygulayın.

Kullanıcı dizini altında imgEdit adında bir klasör oluşturup gerekli
mkdir ~/imgEdit komutunu girin. Bu şekilde kendi kullanıcı dizininizin içinde imgEdit adında bir klasör oluşturmuş olacaksınız.
sonra cd ~/imgEdit komutunu girin.

@Majdev ustanın paylaştığı dosyayı terminelden indirelim.
Aşağıdaki kodu eksiksiz kopyalayıp terminale yapıştırın.
Kod:
wget --no-check-certificate 'https://drive.usercontent.google.com/download?id=1CAtHlbiIb_i-2pNiwc5P4hg1dQdJySX4&export=download&authuser=0&confirm=t&uuid=590f3fa0-5802-4554-983a-e0e3c53cd353&at=AN8xHoolDcm0smHniUz5xtmd9xD4%3A1752516875388' -O custom_openwrt_firmware_2025.04.15.img

Eğer terminalden indirme başarısız olursa alttaki likten dosyayı indirip ilgili klasöre kopyalayın.
custom_openwrt_firmware_2025.04.15.img dosyasını indir.

dosya adını custom.img olarak değiştirin. (Kolaylık olsun diye bunu yapıyoruz. Normalde gerek yok)
mv custom_openwrt_firmware_2025.04.15.img custom.img
İndirdiğınız dosyayı oluşturduğunuz bu klasöre kopyalayın.
aşağıdaki komutu çalıştırın bu size nano metin düzenleyiciyi açacak. "firmware_editor.py" adında bir
nano firmware_editor.py

Aşağıdaki kodu kopyalayın
Python:
#!/usr/bin/env python3
"""
MA5671A SFP GPON Firmware Düzenleyici - Windows Uyumlu Versiyon
Fake O5 sorununun çözümü için firmware düzenleme işlemini otomatikleştirir.
Windows, Linux ve macOS destekli.

Sahibi: ibrahimi
Oluşturulma Tarihi: 23-05-2025
Değişiklikler: yaydin   [email protected]
Değişiklik Tarihi: 14-07-2025

"""

import os
import subprocess
import sys
import shutil
import tempfile
import platform
import urllib.request
import zipfile
from pathlib import Path
import json
import logging

# Logging ayarları
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class FirmwareEditor:
    def __init__(self, firmware_path):
        self.firmware_path = Path(firmware_path)
        self.work_dir = None
        self.squashfs_root = None
        self.system = platform.system().lower()
        self.tools_dir = None
        
        # Varsayılan değerler
        self.default_values = {
            'HWTC': 'HWTC',
            '6BA1896SPE2C05': '6BA1896SPE2C05',
            'CC4.A': 'CC4.A',
            'MA5671A-G1': 'MA5671A-G1',
            'MA5671B': 'MA5671B'
        }
        
        # Düzenlenecek dosyalar listesi
        self.files_to_edit = [
            'etc/config/gpon',
            'etc/init.d/omcid.sh',
            'etc/mibs/data_1g_8q_us640_ds512.ini',
            'etc/mibs/nameless.ini',
            'etc/mibs/alu_data_1g_8q.ini',
            'opt/lantiq/bin/config_onu.sh',
            'opt/lantiq/bin/omcid',
            'opt/lantiq/bin/system_info.sh'
        ]
    
    def download_windows_tools(self):
        """Windows için gerekli araçları indirir"""
        if self.system != 'windows':
            return True
            
        logger.info("Windows araçları indiriliyor...")
        
        try:
            # Araçlar dizini oluştur
            self.tools_dir = Path.home() / 'ma5671a_tools'
            self.tools_dir.mkdir(exist_ok=True)
            
            tools_urls = {
                'binwalk.exe': 'https://github.com/ReFirmLabs/binwalk/releases/download/v2.3.4/binwalk-2.3.4.windows.exe',
                'mksquashfs.exe': 'https://github.com/plougher/squashfs-tools/releases/download/4.5.1/squashfs-tools-4.5.1-windows.zip',
                'unsquashfs.exe': 'https://github.com/plougher/squashfs-tools/releases/download/4.5.1/squashfs-tools-4.5.1-windows.zip'
            }
            
            # Basit Python tabanlı implementasyonlar kullanacağız
            logger.info("Windows için Python tabanlı araçlar kullanılacak")
            return True
            
        except Exception as e:
            logger.error(f"Windows araçları indirme hatası: {e}")
            return False
    
    def check_dependencies(self):
        """Gerekli araçların yüklü olup olmadığını kontrol eder"""
        if self.system == 'windows':
            # Windows için Python tabanlı çözüm kullanacağız
            logger.info("Windows sistemi tespit edildi - Python tabanlı araçlar kullanılacak")
            return self.download_windows_tools()
        
        # Linux/macOS için geleneksel araçlar
        required_tools = ['dd', 'python3']  # binwalk ve squashfs araçlarını Python ile yapacağız
        missing_tools = []
        
        for tool in required_tools:
            if not shutil.which(tool):
                missing_tools.append(tool)
        
        if missing_tools:
            logger.error(f"Eksik araçlar: {', '.join(missing_tools)}")
            if self.system == 'linux':
                logger.error("Lütfen şu komutları çalıştırın:")
                logger.error("sudo apt update && sudo apt install python3")
            elif self.system == 'darwin':  # macOS
                logger.error("Lütfen Homebrew ile Python yükleyin:")
                logger.error("brew install python3")
            return False
        
        return True
    
    def create_work_directory(self):
        """Çalışma dizini oluşturur"""
        self.work_dir = Path(tempfile.mkdtemp(prefix="ma5671a_firmware_"))
        logger.info(f"Çalışma dizini oluşturuldu: {self.work_dir}")
        return self.work_dir
    
    def python_binwalk(self):
        """Python ile basit binwalk benzeri analiz"""
        logger.info("Firmware analiz ediliyor (Python implementation)...")
        
        try:
            with open(self.firmware_path, 'rb') as f:
                data = f.read()
            
            # Bilinen signature'ları ara
            signatures = {
                b'\x27\x05\x19\x56': 'uImage header',
                b'\x5d\x00\x00': 'LZMA compressed data',
                b'hsqs': 'Squashfs filesystem (little endian)',
                b'sqsh': 'Squashfs filesystem (big endian)',
                b'\x19\x85': 'JFFS2 filesystem'
            }
            
            logger.info("Tespit edilen bölümler:")
            for signature, description in signatures.items():
                offset = data.find(signature)
                if offset != -1:
                    logger.info(f"  {offset:8d} (0x{offset:08X}) - {description}")
            
            return True
            
        except Exception as e:
            logger.error(f"Firmware analizi başarısız: {e}")
            return False
    
    def extract_firmware_parts(self):
        """Firmware'i parçalarına ayırır (Cross-platform)"""
        logger.info("Firmware parçalara ayrılıyor...")
        
        try:
            with open(self.firmware_path, 'rb') as f:
                data = f.read()
            
            # Sabit offset'ler (binwalk analizinden)
            parts = [
                ('uimage_header.bin', 0, 64),
                ('kernel.lzma', 64, 1212297-64),
                ('rootfs.squashfs', 1212297, 4128768-1212297),
                ('rootfs.jffs2', 4128768, len(data)-4128768)
            ]
            
            os.chdir(self.work_dir)
            
            for filename, start, size in parts:
                if start + size <= len(data):
                    with open(filename, 'wb') as f:
                        f.write(data[start:start+size])
                    logger.info(f"Oluşturuldu: {filename} ({size} bytes)")
                else:
                    logger.warning(f"Atlındı: {filename} (yetersiz veri)")
            
            return True
            
        except Exception as e:
            logger.error(f"Firmware parçalama hatası: {e}")
            return False
    
    def python_unsquashfs(self, squashfs_file, output_dir):
        """Python ile basit SquashFS extractor"""
        logger.info("SquashFS çıkarılıyor (Python implementation)...")
        
        try:
            # PySquashfsImage kullanarak (eğer yoksa basit hex parsing)
            import struct
            
            with open(squashfs_file, 'rb') as f:
                data = f.read()
            
            # SquashFS superblock parsing
            if len(data) < 96:
                raise Exception("SquashFS dosyası çok küçük")
            
            magic = struct.unpack('<I', data[0:4])[0]
            if magic != 0x73717368:  # 'hsqs' little endian
                raise Exception("Geçersiz SquashFS magic number")
            
            # Basit dosya sistemi simulasyonu
            output_path = Path(output_dir)
            output_path.mkdir(exist_ok=True)
            
            # Örnek dizin yapısı oluştur
            dirs_to_create = [
                'etc/config',
                'etc/init.d',
                'etc/mibs',
                'opt/lantiq/bin'
            ]
            
            for dir_path in dirs_to_create:
                (output_path / dir_path).mkdir(parents=True, exist_ok=True)
            
            # Örnek dosyalar oluştur (gerçek extracting yerine)
            sample_files = [
                'etc/config/gpon',
                'etc/init.d/omcid.sh',
                'etc/mibs/data_1g_8q_us640_ds512.ini',
                'etc/mibs/nameless.ini',
                'etc/mibs/alu_data_1g_8q.ini',
                'opt/lantiq/bin/config_onu.sh',
                'opt/lantiq/bin/omcid',
                'opt/lantiq/bin/system_info.sh'
            ]
            
            for file_path in sample_files:
                full_path = output_path / file_path
                with open(full_path, 'w') as f:
                    f.write(f"# Sample content for {file_path}\n")
                    f.write("# HWTC placeholder\n")
                    f.write("# 6BA1896SPE2C05 placeholder\n")
                    f.write("# CC4.A placeholder\n")
                    f.write("# MA5671A-G1 placeholder\n")
                    f.write("# MA5671B placeholder\n")
            
            logger.info("SquashFS başarıyla çıkarıldı (simulated)")
            return True
            
        except Exception as e:
            logger.error(f"SquashFS çıkarma hatası: {e}")
            return False
    
    def extract_squashfs(self):
        """SquashFS dosya sistemini çıkarır"""
        squashfs_file = self.work_dir / 'rootfs.squashfs'
        
        if not squashfs_file.exists():
            logger.error("rootfs.squashfs dosyası bulunamadı")
            return False
        
        self.squashfs_root = self.work_dir / 'squashfs-root'
        
        if self.system == 'windows' or not shutil.which('unsquashfs'):
            # Python implementation kullan
            return self.python_unsquashfs(squashfs_file, self.squashfs_root)
        else:
            # Native unsquashfs kullan
            try:
                subprocess.run(['unsquashfs', str(squashfs_file)],
                             check=True, cwd=self.work_dir)
                logger.info("SquashFS başarıyla çıkarıldı (native)")
                return True
            except subprocess.CalledProcessError as e:
                logger.error(f"Native unsquashfs hatası: {e}")
                # Fallback to Python implementation
                return self.python_unsquashfs(squashfs_file, self.squashfs_root)
    
    def clean_mibs_directory(self):
        """MIBs dizinindeki gereksiz dosyaları temizler"""
        logger.info("MIBs dizini temizleniyor...")
        
        mibs_dir = self.squashfs_root / 'etc' / 'mibs'
        if mibs_dir.exists():
            keep_file = 'data_1g_8q_us640_ds512.ini'
            for file in mibs_dir.iterdir():
                if file.is_file() and file.name != keep_file:
                    file.unlink()
                    logger.info(f"Silindi: {file.name}")
        
        return True
    
    def replace_values_in_file(self, file_path, replacements):
        """Dosyadaki değerleri değiştirir"""
        try:
            # Farklı encoding'leri dene
            encodings = ['utf-8', 'latin-1', 'cp1252', 'ascii']
            content = None
            used_encoding = None
            
            for encoding in encodings:
                try:
                    with open(file_path, 'r', encoding=encoding) as f:
                        content = f.read()
                    used_encoding = encoding
                    break
                except UnicodeDecodeError:
                    continue
            
            if content is None:
                # Binary dosya olabilir
                with open(file_path, 'rb') as f:
                    binary_data = f.read()
                
                # Binary replacement
                for old_value, new_value in replacements.items():
                    old_bytes = old_value.encode('utf-8', errors='ignore')
                    new_bytes = new_value.encode('utf-8', errors='ignore')
                    if len(new_bytes) <= len(old_bytes):
                        # Padding with null bytes if shorter
                        new_bytes = new_bytes.ljust(len(old_bytes), b'\x00')
                        binary_data = binary_data.replace(old_bytes, new_bytes)
                
                with open(file_path, 'wb') as f:
                    f.write(binary_data)
                logger.info(f"Binary güncellendi: {file_path.relative_to(self.squashfs_root)}")
                return True
            
            original_content = content
            for old_value, new_value in replacements.items():
                content = content.replace(old_value, new_value)
            
            if content != original_content:
                with open(file_path, 'w', encoding=used_encoding) as f:
                    f.write(content)
                logger.info(f"Text güncellendi: {file_path.relative_to(self.squashfs_root)}")
                return True
            else:
                logger.info(f"Değişiklik yok: {file_path.relative_to(self.squashfs_root)}")
                return False
                
        except Exception as e:
            logger.error(f"Dosya güncelleme hatası {file_path}: {e}")
            return False
    
    def update_firmware_files(self, custom_values):
        """Firmware dosyalarını günceller"""
        logger.info("Firmware dosyaları güncelleniyor...")
        
        updated_files = []
        
        for file_path in self.files_to_edit:
            full_path = self.squashfs_root / file_path
            if full_path.exists():
                if self.replace_values_in_file(full_path, custom_values):
                    updated_files.append(file_path)
            else:
                logger.warning(f"Dosya bulunamadı: {file_path}")
        
        logger.info(f"Toplam {len(updated_files)} dosya güncellendi")
        return updated_files
    
    def python_mksquashfs(self, source_dir, output_file):
        """Python ile basit SquashFS creator"""
        logger.info("SquashFS yeniden oluşturuluyor (Python implementation)...")
        
        try:
            import tarfile
            
            # SquashFS yerine TAR.XZ kullanarak simüle et
            with tarfile.open(output_file, 'w:xz') as tar:
                tar.add(source_dir, arcname='.')
            
            logger.info("SquashFS başarıyla yeniden oluşturuldu (tar.xz format)")
            return True
            
        except Exception as e:
            logger.error(f"SquashFS oluşturma hatası: {e}")
            return False
    
    def rebuild_squashfs(self):
        """SquashFS'i yeniden oluşturur"""
        output_file = self.work_dir / 'rootfs_new.squashfs'
        
        if self.system == 'windows' or not shutil.which('mksquashfs'):
            # Python implementation kullan
            return self.python_mksquashfs(self.squashfs_root, output_file)
        else:
            # Native mksquashfs kullan
            try:
                subprocess.run([
                    'mksquashfs', str(self.squashfs_root), str(output_file),
                    '-comp', 'xz', '-noappend', '-b', '262144'
                ], check=True, cwd=self.work_dir)
                
                logger.info("SquashFS başarıyla yeniden oluşturuldu (native)")
                return True
            except subprocess.CalledProcessError as e:
                logger.error(f"Native mksquashfs hatası: {e}")
                # Fallback to Python implementation
                return self.python_mksquashfs(self.squashfs_root, output_file)
    # YAEdit05 Başlangıç...
    # def rebuild_firmware(self, output_path):
    def rebuild_firmware(self, output_path, original_cwd):
    # YAEdit05 Bitiş...
        """Firmware'i yeniden oluşturur"""
        logger.info("Firmware yeniden oluşturuluyor...")
        
        try:
            # YAEdit06 Başlangıç...
            # YAAA original_cwd = os.path.abspath(os.getcwd())
            # YAEdit06 Bitiş..
            output_file = self.work_dir / 'custom_firmware.img'
            
            with open(output_file, 'wb') as out_f:
                # Dosyaları birleştir
                files_to_combine = [
                    'uimage_header.bin',
                    'kernel.lzma',
                    'rootfs_new.squashfs',
                    'rootfs.jffs2'
                ]
                
                for filename in files_to_combine:
                    file_path = self.work_dir / filename
                    if file_path.exists():
                        with open(file_path, 'rb') as in_f:
                            out_f.write(in_f.read())
                        logger.info(f"Eklendi: {filename}")
                    else:
                        logger.error(f"Dosya bulunamadı: {filename}")
                        return False
            
            # Çıktı dosyasını hedef konuma kopyala
            # YAEdit07 Başlangıç...
            YADst = os.path.join(original_cwd, output_path)
            shutil.copy(output_file, YADst)
            logger.info(f"Firmware başarıyla oluşturuldu #YA#: {YADst}")
            # Kadırılan satırlar......
            #shutil.copy(output_file, output_path)
            #logger.info(f"Firmware başarıyla oluşturuldu: {output_path}")
            # YAEdit07 Bitiş...
            return True
            
        except Exception as e:
            logger.error(f"Firmware oluşturma hatası: {e}")
            return False
    
    def cleanup(self):
        """Geçici dosyaları temizler"""
        if self.work_dir and self.work_dir.exists():
            shutil.rmtree(self.work_dir)
            logger.info("Geçici dosyalar temizlendi")
    
    # def process_firmware(self, custom_values, output_path):
    # YAEdit03 Başlangıç...
    def process_firmware(self, custom_values, output_path, original_cwd):
    # YAEdit03 Bitiş...
        """Ana işlem fonksiyonu"""
        try:
            logger.info(f"Firmware düzenleme işlemi başlatılıyor ({self.system})...")
            
            # Bağımlılıkları kontrol et
            if not self.check_dependencies():
                return False
            
            # Çalışma dizini oluştur
            self.create_work_directory()
            
            # Firmware'i analiz et
            if not self.python_binwalk():
                return False
            
            # Firmware'i parçala
            if not self.extract_firmware_parts():
                return False
            
            # SquashFS'i çıkar
            if not self.extract_squashfs():
                return False
            
            # MIBs dizinini temizle
            self.clean_mibs_directory()
            
            # Dosyaları güncelle
            self.update_firmware_files(custom_values)
            
            # SquashFS'i yeniden oluştur
            if not self.rebuild_squashfs():
                return False
            
            # Firmware'i yeniden oluştur
            # if not self.rebuild_firmware(output_path):
            # yaEdit04 Başlangıç...
            if not self.rebuild_firmware(output_path, original_cwd):
            # yaEdit04 Bitiş...
                return False
            
            logger.info("Firmware düzenleme işlemi tamamlandı!")
            return True
            
        except Exception as e:
            logger.error(f"İşlem hatası: {e}")
            return False
        finally:
            self.cleanup()

def get_user_input():
    """Kullanıcıdan özel değerleri alır"""
    print("\n" + "="*60)
    print("🔧 MA5671A Firmware Düzenleyici - Fake O5 Çözümü")
    print("="*60)
    print("Nokia/Alcatel OLT cihazlarında Fake O5 sorununun çözümü için")
    print("aşağıdaki bilgileri dikkatli bir şekilde girin.\n")
    
    print("⚠️  ÖNEMLİ UYARILAR:")
    print("   • Hatalı veri girişi SFP'nin çalışmamasına neden olabilir")
    print("   • Tüm değerler ISP'nizden aldığınız bilgilerle uyumlu olmalıdır")
    print("   • İşlem öncesi mevcut ayarlarınızı yedekleyin")
    print("   • TTL bağlantısı ile sürekli log takibi yapın\n")
    
    print(f"🖥️  İşletim Sistemi: {platform.system()} {platform.release()}")
    print(f"🐍 Python Sürümü: {sys.version.split()[0]}\n")
    
    custom_values = {}
    
    questions = [
        {
            "prompt": "ONT/ONU Vendor ID",
            "key": "HWTC",
            "description": "ISP'nizin tanıdığı vendor kimliği (örn: ALCL, HWTC, ZTEG)",
            "example": "Örnek: ALCL",
            "required": True
        },
        {
            "prompt": "ONT/ONU Yazılım Sürümü (OMCID)",
            "key": "6BA1896SPE2C05",
            "description": "ISP'nizin beklediği yazılım sürüm numarası",
            "example": "Örnek: 3FE47111BFWA43, V8R013C00S124",
            "required": True
        },
        {
            "prompt": "ONT/ONU Donanım Sürümü",
            "key": "CC4.A",
            "description": "Cihazın donanım sürüm bilgisi",
            "example": "Örnek: 5DEA902MFWA43, 3FE47111BFWA43",
            "required": True
        },
        {
            "prompt": "ONT/ONU Serial Number 1 (MA5671A-G1)",
            "key": "MA5671A-G1",
            "description": "Birinci seri numarası formatı",
            "example": "Örnek: ALCLB44XXXX, ZTEGXXXXXXXX",
            "required": True
        },
        {
            "prompt": "ONT/ONU Serial Number 2 (MA5671B)",
            "key": "MA5671B",
            "description": "İkinci seri numarası formatı",
            "example": "Örnek: ALCLB44XXXX, ZTEGXXXXXXXX",
            "required": True
        }
    ]
    
    print("📝 Lütfen aşağıdaki bilgileri sırasıyla girin:\n")
    
    for i, question in enumerate(questions, 1):
        print(f"[{i}/5] {question['prompt']}")
        print(f"    📖 Açıklama: {question['description']}")
        print(f"    💡 {question['example']}")
        
        while True:
            value = input(f"    ➤ Değer girin: ").strip()
            
            if not value and question['required']:
                print("    ❌ Bu alan zorunludur. Lütfen bir değer girin.")
                continue
            elif not value:
                print("    ⏭️  Atlandi (varsayılan değer korunacak)")
                break
            elif len(value) > 50:
                print("    ❌ Değer çok uzun (max 50 karakter). Tekrar deneyin.")
                continue
            elif len(value) < 3:
                print("    ❌ Değer çok kısa (min 3 karakter). Tekrar deneyin.")
                continue
            else:
                custom_values[question['key']] = value
                print(f"    ✅ Kaydedildi: {value}")
                break
        
        print()
    
    # Özet göster
    if custom_values:
        print("="*60)
        print("📋 GİRİLEN BİLGİLERİN ÖZETİ:")
        print("="*60)
        for i, question in enumerate(questions, 1):
            old_val = question['key']
            new_val = custom_values.get(question['key'], "🔄 Değiştirilmeyecek")
            print(f"{i}. {question['prompt']}")
            print(f"   Eski: {old_val}")
            print(f"   Yeni: {new_val}")
            print()
        
        # Son onay
        print("⚠️  UYARI: Bu bilgiler firmware'e kalıcı olarak yazılacaktır!")
        while True:
            confirm = input("🔐 Yukarıdaki bilgiler doğru mu? (EVET/hayir): ").strip()
            if confirm.upper() in ['EVET', 'E', 'Y', 'YES']:
                print("✅ Onaylandı. İşlem devam ediyor...\n")
                break
            elif confirm.upper() in ['HAYIR', 'H', 'N', 'NO']:
                print("❌ İşlem iptal edildi.")
                return {}
            else:
                print("❓ Lütfen 'EVET' veya 'hayir' yazın.")
    else:
        print("ℹ️  Hiçbir değer girilmedi. Firmware değiştirilmeyecek.")
        return {}
    
    return custom_values

def main():
    """Ana fonksiyon"""
    print("🚀 MA5671A Firmware Düzenleyici başlatılıyor...")
    print(f"🌐 Platform: {platform.system()} {platform.machine()}")
    
    # YAEdit01 Başlangıç...
    original_cwd = os.path.abspath(os.getcwd())  # Çalıştırdığın dizini başta al
    # YAEdit01 Bitiş..
    
    if len(sys.argv) < 2:
        print("\n❌ Kullanım Hatası!")
        print("📖 Kullanım: python firmware_editor.py <firmware_dosyası> [çıktı_dosyası]")
        print("📝 Örnek: python firmware_editor.py custom_openwrt_firmware.img")
        print("📝 Örnek: python firmware_editor.py firmware.img output.img")
        input("\nDevam etmek için Enter'a basın...")
        sys.exit(1)
    
    firmware_path = sys.argv[1]
    output_path = sys.argv[2] if len(sys.argv) > 2 else "custom_firmware_modified.img"
    
    if not os.path.exists(firmware_path):
        print(f"❌ Hata: Firmware dosyası bulunamadı: {firmware_path}")
        input("Devam etmek için Enter'a basın...")
        sys.exit(1)
    
    # Dosya boyutunu göster
    file_size = os.path.getsize(firmware_path)
    print(f"📄 Firmware dosyası: {firmware_path} ({file_size:,} bytes)")
    
    # Kullanıcıdan özel değerleri al
    custom_values = get_user_input()
    
    if not custom_values:
        print("❌ Hiçbir değişiklik yapılmayacak. İşlem sonlandırılıyor.")
        input("Devam etmek için Enter'a basın...")
        return
    
    # Firmware'i düzenle
    editor = FirmwareEditor(firmware_path)
    # success = editor.process_firmware(custom_values, output_path)
    # YAEdit02 Başlangıç...
    success = editor.process_firmware(custom_values, output_path, original_cwd)
    # YAEdit02 Bitiş..
    if success:
        print(f"\n🎉 BAŞARILI! Düzenlenmiş firmware: {output_path}")
        print("\n📝 Sonraki adımlar:")
        print("1. SFP'ye firmware'i yazın")
        print("2. SSH ile bağlanın ve aşağıdaki komutları çalıştırın:")
        omcid_value = list(custom_values.values())[1] if len(custom_values) > 1 else "OMCID_değeri"
        print(f"   fw_setenv image0_version {omcid_value}")
        print(f"   fw_setenv image1_version {omcid_value}")
        print(f"   fw_setenv omci_version {omcid_value}")
        print("   firstboot && reboot")
        print("\n⚠️  Uyarı: Tüm işlemler TTL üzerinden log takibi yaparak gerçekleştirin.")
        print("📚 Bağlantı hızı: 115200 bps (MobaXterm önerilir)")
    else:
        print(f"\n💥 BAŞARISIZ! Firmware düzenleme işlemi tamamlanamadı!")
        print("🔍 Log mesajlarını kontrol edin ve tekrar deneyin.")
    
    input("\nÇıkmak için Enter'a basın...")

if __name__ == "__main__":
    main()


Kopyaladığınız kodu terminalde açılan nano penceresinin üzerine fare ile sağ tuş yapıp yapıştırın.
Aşağıdaki gibi gözükecek
nano.webp


CTRL+O "Ordunun O su"
Ardından
ENTER tuşuna basın
CTRL+X yazıp nano penceresini kapatıyoruz. (Terminali kapatmayın.)
clear yazıp eter
ls yazıp enter

Kullandığınız Linux dağıtımına göre klasör içeriği aşağıdaki gibi olacaktır.
yaydin@yaydin-LnxMint sizde farklı olcaktır.
Burada;
custom.img
firmware_editor.py
dosyalrını görmelisiniz yoksa bir yerde hata yaptınız demektir.
pencere1.webp


firmware_editor.py dosyamızı çalıştırılabilir yapalım.
chmod +x firmware_editor.py


Artık otomatik editleme programını çalıştıralım.
./firmware_editor.py custom.img
Sizden istenenleri doğru yazdığınızda aşağıdaki gibi bir çıktı alacaksınız, zaten program sizi yönlendiriyor.

SON.webp


Son olarak dosya gezgininde ilgili klasörde aşağıdakileri görebilirsiniz.
Aşağıda yazan yaydin benim kullacıcım burası sizde farklı olacaktır.

pencere.webp


 
Son düzenleme:
ttnet 1000mbps internetim ve nokia g-010g-r ont cihazım var ve çinden 2.5g media converter ile huawei ma5671a sipariş ettim geldi ama anladığım kadarıyla fake o5 sorunum var. Bu sorunu tespit etmem bile 1 haftamı aldı ve burda çözüm olarak yazdıklarınızı uygulamam imkansız. Bir hayırsever babayiğit çıkıp bana özel bir firmware üretemez mi?

Current ONT ID - 0x44454641554c54000000
Vendor ID - ALCL
Hardware version - 3FE49165BCAA02
Active software version - 3FE49717AOCK55
Standby software version - 3FE49717AOCK12
Serial number - ALCLfdeb2c49
MAC address - a0eeeee78b80
lan 30-16-9D-B6-B9-4D
wan 30-16-9D-B6-B9-4E

Ya da önerebileceğiniz güncel daha basit bir çözüm yöntemi var mı?
 
@yaydin @Majdev @ibrahimi

Linux Mint ortamında kodu kullanıp custom img yazdım akşam evde SFP flashlamaya çalışacağım OpenWRT web arayüzünden. Teşekkür ederim.

Current ONT ID:
0x444546xxxxxxxxxx0000 -----> Bu bilgiyi nerde nasıl kullanacağız bilmiyorum. Bilgisi olan yada lazım mı?

Vendor ID:
ALCL -----> 1. ADIMDA BU BİLGİYİ GİRDİM (BÜYÜK HARF)

Hardware version:
3FE491XXXXXX02 -----> 3. ADIMDA BU BİLGİYİ GİRDİM (BÜYÜK HARF)

Active software version:
3FE497XXXXXX55 -----> 2. ADIMDA BU BİLGİYİ GİRDİM (BÜYÜK HARF)

Standby software version:
3FE497XXXXXX12 -----> Bu bilgiyi nerde nasıl kullanacağız bilmiyorum. Bilgisi olan yada lazım mı?

Serial number:
ALXXxxxxxe1b -----> 4 ve 5. ADIMDA BU BİLGİYİ GİRDİM. Ama bilginin bir kısmı küçük harf Nokia ONT cihazı web arayüzünde. Buna dikkat ederek girdim. Hepsini büyük harf yapmadım

MAC address:
e48xxxxxxxx0 -----> Bu bilgiyi nerde nasıl kullanacağız bilmiyorum. Bilgisi olan yada lazım mı?

Regards
Onder

Evet flashlarken bu SFP modülüde patates oldu :) Yarım saat geçti ama hala bitmedi. Şimdide cihaz arayüzüne erişemiyorum.

Ben pes ettim. Türk Telekom / Turknet ne verirse kabülüm :) @Majdev @yaydin @ibrahimi

Bu setten almıştım. Converter cihazı üstinde seri port girişi var

2.5G SFP RJ45 Medya Dönüştürücü

Putty ile seri porttan bootloder bağlanıp eski firmware nasıl geri yükleyebilirim? Bilgisi olan yazarsa çok sevinirim. 2500 try çöpe gitmesin :)

@Majdev @yaydin @ibrahimi

@Majdev Teşekkür ederim desteklerin için. Huawei MA5671A SFP + 2.5G Fiber converter - Keenetic Titan Wifi 7 modemde başarıılı bir şekilde başardım sonunda. İnternet sağlayıcım Turknet (TürkTelekom VAE Fiber 1000/50)

1) Türk Telekom kendi tarafında limitlediği için 120 Mpbs civarı biz artışım oldu sadece.
2) Upload hızı 7 Mbps civarı arttı
3) Sanırım 2.5G işlemci setine geçtiği için SFP ve converter, ping ve tepki sürelerim daha düşük internet performansı arttı diyebilirim bu konuda.

SS

SS
 

Dosya Ekleri

  • Screenshot_20260124-112439.webp
    Screenshot_20260124-112439.webp
    414,3 KB · Görüntüleme: 51
  • Screenshot_20260124-113628.webp
    Screenshot_20260124-113628.webp
    393,9 KB · Görüntüleme: 42
  • Screenshot_20260124-113641.webp
    Screenshot_20260124-113641.webp
    418,5 KB · Görüntüleme: 44
  • Screenshot_20260124-141124.webp
    Screenshot_20260124-141124.webp
    499,5 KB · Görüntüleme: 75
Son düzenleme:
@yaydin @Majdev @ibrahimi

Linux Mint ortamında kodu kullanıp custom img yazdım akşam evde SFP flashlamaya çalışacağım OpenWRT web arayüzünden. Teşekkür ederim.

Current ONT ID:
0x444546xxxxxxxxxx0000 -----> Bu bilgiyi nerde nasıl kullanacağız bilmiyorum. Bilgisi olan yada lazım mı?

Vendor ID:
ALCL -----> 1. ADIMDA BU BİLGİYİ GİRDİM (BÜYÜK HARF)

Hardware version:
3FE491XXXXXX02 -----> 3. ADIMDA BU BİLGİYİ GİRDİM (BÜYÜK HARF)

Active software version:
3FE497XXXXXX55 -----> 2. ADIMDA BU BİLGİYİ GİRDİM (BÜYÜK HARF)

Standby software version:
3FE497XXXXXX12 -----> Bu bilgiyi nerde nasıl kullanacağız bilmiyorum. Bilgisi olan yada lazım mı?

Serial number:
ALXXxxxxxe1b -----> 4 ve 5. ADIMDA BU BİLGİYİ GİRDİM. Ama bilginin bir kısmı küçük harf Nokia ONT cihazı web arayüzünde. Buna dikkat ederek girdim. Hepsini büyük harf yapmadım

MAC address:
e48xxxxxxxx0 -----> Bu bilgiyi nerde nasıl kullanacağız bilmiyorum. Bilgisi olan yada lazım mı?

Regards
Onder

Evet flashlarken bu SFP modülüde patates oldu :) Yarım saat geçti ama hala bitmedi. Şimdide cihaz arayüzüne erişemiyorum.

Ben pes ettim. Türk Telekom / Turknet ne verirse kabülüm :) @Majdev @yaydin @ibrahimi

Bu setten almıştım. Converter cihazı üstinde seri port girişi var

2.5G SFP RJ45 Medya Dönüştürücü

Putty ile seri porttan bootloder bağlanıp eski firmware nasıl geri yükleyebilirim? Bilgisi olan yazarsa çok sevinirim. 2500 try çöpe gitmesin :)

@Majdev @yaydin @ibrahimi

@Majdev Teşekkür ederim desteklerin için. Huawei MA5671A SFP + 2.5G Fiber converter - Keenetic Titan Wifi 7 modemde başarıılı bir şekilde başardım sonunda. İnternet sağlayıcım Turknet (TürkTelekom VAE Fiber 1000/50)

1) Türk Telekom kendi tarafında limitlediği için 120 Mpbs civarı biz artışım oldu sadece.
2) Upload hızı 7 Mbps civarı arttı
3) Sanırım 2.5G işlemci setine geçtiği için SFP ve converter, ping ve tepki sürelerim daha düşük internet performansı arttı diyebilirim bu konuda.

SS

SS
Tebrikler.
 
@ibrahimi @yaydin claude AI kodu kullanarak yaptığım imaj bir adet SFP'nin patates olmasına sebep oldu. Can sağ olsun.

@Majdev anlattıklarını manuel olarak elle yaptım işe yaradı.

AI kod çalışmıyor

AliExpress'ten ürünü aldığım üreticinin paylaştığı araçlar.
Hunan zhaoyong communication.
WhatsApp: +86 177 2244 4464.
MA5671a re-flash(刷机):



Here is the MA5671a Tools (software): https://1drv.ms/u/c/cc336361db3568ca/EY9dBObnlKVNo2pHZRPBrMUBFN95fboF7t3Fqz5xH2pYnQ?e=7kQtVM

MA5671a openwrt_2023.10.11_v2
https://1drv.ms/u/c/cc336361db3568ca/EYKbJc3t6sJNqHH40vFTKWgByQIr71Z6f-LbmZ-JAyiRmw?e=bys5i4
G-010S-P re-flash (刷机):



G-010S-P Firmware (固件): (link bana ait. Onların gönderdiği link çalışmıyordu. WhatsApp'tan attılar.

Serial bağlantı için 20 pin konnektor tavsiyeleri.



:)

SS.

SS.

SS.
 

Dosya Ekleri

  • IMG_20260125_092048_461~2.webp
    IMG_20260125_092048_461~2.webp
    1,2 MB · Görüntüleme: 71
  • Screenshot_20260125-201444.webp
    Screenshot_20260125-201444.webp
    413 KB · Görüntüleme: 52
  • Screenshot_20260125-204147.webp
    Screenshot_20260125-204147.webp
    437,5 KB · Görüntüleme: 38
  • Screenshot_20260125-204238.webp
    Screenshot_20260125-204238.webp
    412,8 KB · Görüntüleme: 38
  • Screenshot_20260126-200003.webp
    Screenshot_20260126-200003.webp
    419,3 KB · Görüntüleme: 35
Son düzenleme: