Wiz-IO / platform-quectel

Quectel development platform for PlatformIO
97 stars 42 forks source link

OpenCPU FOTA Package format #16

Closed glaucopgomes closed 4 years ago

glaucopgomes commented 4 years ago

Do you have any documentation or knowledge of the OpenCPU FOTA Package format?

I'd like to automate the creation of the update package after build the application.

Wiz-IO commented 4 years ago

Hi, ask Quectel.... FOTA is normal application plus header DFOTA is differencial between two applications - old and new

На сб, 26 окт. 2019 г., 14:44 Glauco P. Gomes notifications@github.com написа:

Do you have any documentation or knowledge of the OpenCPU FOTA Package format?

I'd like to automate the creation of the update package after build the application.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/Wiz-IO/platform-quectel/issues/16?email_source=notifications&email_token=ADPGJ4W5CHV6O6G5P4NDOL3QQQUQPA5CNFSM4JFM6XH2YY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4HURDHSQ, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADPGJ4WVYMHEAI4N4HMV46DQQQUQPANCNFSM4JFM6XHQ .

rurban commented 3 years ago

Apparently it is EC20 as reverse engineered here: https://penthertz.com/blog/mobile-iot-modules-FOTA-backdooring-at-scale.html and described here: https://osmocom.org/projects/quectel-modems/wiki/EC20_DFOTA

But you are supposed use the DFOTA diff generation service. See Quectel_BC66\&BC66-NA-OpenCPU_DFOTA_Tool_User_Guide_V1.0.pdf This is a webservice which creates the delta for your APP update. Haven't checked Georgi's bc66.py makeFota() functionality yet. Looks simple enough though.

def makeFotaInfo(dst, offset, start, size):
    dst.write( struct.pack('<i',     offset) )      # m_bin_offset
    dst.write( struct.pack('<i', 0x08292000) )      # m_bin_start_addr
    dst.write( struct.pack('<i',       size) )      # m_bin_length
    dst.write( struct.pack('<i', 0x000BF000) )      # m_partition_length
    dst.write( struct.pack('<i', 0x00000000) )      # m_sig_offset
    dst.write( struct.pack('<i', 0x00000000) )      # m_sig_length
    dst.write( struct.pack('<i', 0x00000000) )      # m_is_compressed 
    for i in range(16):
        dst.write( struct.pack('<i', i) )  # m_version_info[16]    
    dst.write( struct.pack('<i', 0x00000000) )      # m_bin_type       
    dst.write( struct.pack('<i', 0x00000000) )      # m_bin_reserved[4]         

def makeFota(src):
    print( "FOTA SRC:", src )
    #print( "FOTA DIR:", os.path.dirname(src) )
    binfile = "FOTA_" + os.path.basename(src)
    print( "FOTA BIN:", binfile )
    print( "FOTA SIZ:", os.path.getsize(src) )

    binSize = os.path.getsize(src)
    dst = open(os.path.dirname(src) + "/" + binfile, "wb")
    arr = [0x4D,0x4D,0x4D,0x00,   0x01,0x00,0x00,0x00,] # m_magic_ver, m_bin_num, m_bin_info[4]
    data = bytearray(arr)
    dst.write(data)
    makeFotaInfo(dst, 0x6C, 0x08292000, binSize)
    bin = open(src, "rb")
    dst.write( bin.read() )
    bin.close()
    dst.close()