#!/usr/bin/env python3 import os from fcntl import ioctl from time import sleep import struct from collections import namedtuple import cffi import datetime import sys ffi = cffi.FFI() # Per cbd, "SS310 modem", "shannon310". This is a Samsung Galaxy S7 SM-G930F. # ["/sbin/cbd", "-d", "-tss310", "-bm", "-mm", "-P", "platform/155a0000.ufs/by-name/RADIO"] # Aha! If we stay as root, then the security_request(2, 0, 0) fails # with error code 11. cbd does setuid(1001) (while retaining # capabilities!) before doing security_request(2, 0, 0), and in that # case it succeeds with error code 0. HOWEVER it seems like you can # ask cbd to stay as root with `-or`, in which case it gets the error # code 11 too - which it ignores! The modem seems (?) well-configured # afterward, so perhaps it's not required? def mkstruct(name, fields, spec): cls = namedtuple(name, fields) def iter_load(bs): return map(cls._make, struct.iter_unpack(spec, bs)) cls.iter_load = iter_load def load(bs): return cls._make(struct.unpack(spec, bs)) cls.load = load def iter_save(items): return b''.join(struct.pack(spec, *item) for item in items) cls.iter_save = iter_save def save(item): return struct.pack(spec, *item) cls.save = save return cls TOC = mkstruct('TOC', 'name offset loadaddr size crc entryid', '<12sIIIII') # struct modem_firmware FirmwareChunk = mkstruct('FirmwareChunk', 'binary size m_offset b_offset mode len', ' 0: chunksize = min(remaining, 62 * 1024) chunk = fh.read(chunksize) send_chunk(fd, total_size, load_offset, chunk, file_offset) load_offset = load_offset + chunksize file_offset = file_offset + chunksize remaining = remaining - chunksize print('poke_modem') boot0_path = '/dev/umts_boot0' firmware_partition = '/dev/disk/by-partlabel/RADIO' nv_data_path = '/efs/nv_data.bin' with open('/sys/power/wake_lock', 'wb') as f: f.write(b'ss310') boot0_fd = os.open(boot0_path, os.O_RDWR) with open(firmware_partition, 'rb') as f: toc = list(TOC.iter_load(f.read(512))) (boot_toc_entry, main_toc_entry, nv_toc_entry) = toc[1:4] print(toc[0]) print(boot_toc_entry) print(main_toc_entry) print(nv_toc_entry) # get_srinfo(boot0_fd) # modem_status(boot0_fd) modem_reset(boot0_fd) security_request(boot0_fd, SecReq(2, 0, 0)) with open(firmware_partition, 'rb') as f: send_region(boot0_fd, f, boot_toc_entry, boot_toc_entry.loadaddr) send_region(boot0_fd, f, main_toc_entry, boot_toc_entry.loadaddr) with open(nv_data_path, 'rb') as f: send_region(boot0_fd, f, nv_toc_entry, boot_toc_entry.loadaddr) security_request(boot0_fd, SecReq(0, boot_toc_entry.size, main_toc_entry.size)) modem_on(boot0_fd) modem_boot_on(boot0_fd) modem_dl_start(boot0_fd) os.write(boot0_fd, bytearray(struct.pack('I', 0x0000900d))) print(hex(struct.unpack('I', os.read(boot0_fd, 4))[0])) os.write(boot0_fd, bytearray(struct.pack('I', 0x00009f00))) print(hex(struct.unpack('I', os.read(boot0_fd, 4))[0])) modem_boot_off(boot0_fd) os.close(boot0_fd) with open('/sys/power/wake_unlock', 'wb') as f: f.write(b'ss310') sys.stdout.flush() with open(boot0_path, 'rb') as f: while True: i = f.read(512) if len(i) > 0: print(str(datetime.datetime.now()), '({:03x})'.format(len(i)), modem_status(f.raw.fileno()), i.hex()) sys.stdout.flush() else: sleep(1)