Refactor, improve xml + xflash / da handling. Add da sla support. Brom sla untested.

This commit is contained in:
Bjoern Kerler 2024-06-14 22:47:00 +02:00
parent e64c544d38
commit 6c2f94662e
No known key found for this signature in database
GPG key ID: A3E0FAF79F2F4578
64 changed files with 2700 additions and 2597 deletions

112
mtk.py
View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# MTK Flash Client (c) B.Kerler 2018-2023.
# MTK Flash Client (c) B.Kerler 2018-2024.
# Licensed under GPLv3 License
import argparse
from mtkclient.Library.mtk_main import Main, metamodes
@ -47,8 +47,8 @@ if __name__ == '__main__':
subparsers = parser.add_subparsers(dest="cmd",
help='Valid commands are: \n' +
'printgpt, gpt, r, rl, rf, fs, rs, w, wf, wl, e, es, footer, reset, \n' +
'dumpbrom, dumpsram, dumppreloader, payload, crash, brute, gettargetconfig, \n' +
'peek, stage, plstage, da, script\n')
'dumpbrom, dumpsram, dumppreloader, payload, crash, brute, \n' +
'gettargetconfig, peek, stage, plstage, da, script\n')
parser_script = subparsers.add_parser("script", help="Run text script")
parser_printgpt = subparsers.add_parser("printgpt", help="Print GPT Table information")
@ -202,8 +202,8 @@ if __name__ == '__main__':
parser_printgpt.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_printgpt.add_argument('--gpt_file', help='Use a gpt file instead of trying to read gpt from flash')
parser_printgpt.add_argument('--ptype',
help='Set the payload type ("amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by ' +
'default)')
help='Set the payload type ("amonet","kamakiri","kamakiri2","carbonara" '
'kamakiri2/da used by default)')
parser_printgpt.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_printgpt.add_argument('--crash', help='Enforce crash if device is in pl mode to enter brom mode')
parser_printgpt.add_argument('--socid', help='Read Soc ID')
@ -229,7 +229,8 @@ if __name__ == '__main__':
parser_gpt.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_gpt.add_argument('--gpt_file', help='Use a gpt file instead of trying to read gpt from flash')
parser_gpt.add_argument('--ptype',
help='Set the payload type ("amonet","kamakiri","kamakiri2","carbonara", kamakiri2/da used by default)')
help='Set the payload type ("amonet","kamakiri","kamakiri2","carbonara", kamakiri2/da ' +
'used by default)')
parser_gpt.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_gpt.add_argument('--parttype', help='Partition type\n' +
'\t\tEMMC: [user, boot1, boot2, gp1, gp2, gp3, gp4, rpmb]' +
@ -259,7 +260,8 @@ if __name__ == '__main__':
parser_r.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_r.add_argument('--gpt_file', help='Use a gpt file instead of trying to read gpt from flash')
parser_r.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da ' +
'used by default)')
parser_r.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_r.add_argument('--parttype', help='Partition type\n' +
'\t\tEMMC: [user, boot1, boot2, gp1, gp2, gp3, gp4, rpmb]' +
@ -288,7 +290,8 @@ if __name__ == '__main__':
parser_rl.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_rl.add_argument('--gpt_file', help='Use a gpt file instead of trying to read gpt from flash')
parser_rl.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da ' +
'used by default)')
parser_rl.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_rl.add_argument('--parttype', help='Partition type\n' +
'\t\tEMMC: [user, boot1, boot2, gp1, gp2, gp3, gp4, rpmb]' +
@ -318,7 +321,8 @@ if __name__ == '__main__':
parser_rf.add_argument('--da_addr', help='Set a specific da payload addr')
parser_rf.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_rf.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da ' +
'used by default)')
parser_rf.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_rf.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_rf.add_argument('--parttype', help='Partition type\n' +
@ -328,7 +332,8 @@ if __name__ == '__main__':
parser_rf.add_argument('--filename', help='Optional filename')
parser_rf.add_argument('--crash', help='Enforce crash if device is in pl mode to enter brom mode')
parser_rf.add_argument('--socid', help='Read Soc ID')
parser_rf.add_argument('--iot', help='Use special mode for iot MT6261/2301', action="store_true", default=False)
parser_rf.add_argument('--iot', help='Use special mode for iot MT6261/2301', action="store_true",
default=False)
parser_rf.add_argument('--auth', type=str, help="Use auth file (auth_sv5.auth)")
parser_rf.add_argument('--cert', type=str, help="Use cert file")
@ -342,7 +347,8 @@ if __name__ == '__main__':
parser_rs.add_argument('--debugmode', action='store_true', default=False, help='Enable verbose mode')
parser_rs.add_argument('--gpt-num-part-entries', default='0', help='Set GPT entry count')
parser_rs.add_argument('--gpt-part-entry-size', default='0', help='Set GPT entry size')
parser_rs.add_argument('--gpt-part-entry-start-lba', default='0', help='Set GPT entry start lba sector')
parser_rs.add_argument('--gpt-part-entry-start-lba', default='0',
help='Set GPT entry start lba sector')
parser_rs.add_argument('--gpt_file', help='Use a gpt file instead of trying to read gpt from flash')
parser_rs.add_argument('--skip', help='Skip reading partition with names "partname1,partname2,etc."')
parser_rs.add_argument('--skipwdt', help='Skip wdt init')
@ -353,7 +359,8 @@ if __name__ == '__main__':
parser_rs.add_argument('--da_addr', help='Set a specific da payload addr')
parser_rs.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_rs.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da ' +
'used by default)')
parser_rs.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_rs.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_rs.add_argument('--parttype', help='Partition type\n' +
@ -376,7 +383,8 @@ if __name__ == '__main__':
parser_ro.add_argument('--debugmode', action='store_true', default=False, help='Enable verbose mode')
parser_ro.add_argument('--gpt-num-part-entries', default='0', help='Set GPT entry count')
parser_ro.add_argument('--gpt-part-entry-size', default='0', help='Set GPT entry size')
parser_ro.add_argument('--gpt-part-entry-start-lba', default='0', help='Set GPT entry start lba sector')
parser_ro.add_argument('--gpt-part-entry-start-lba', default='0',
help='Set GPT entry start lba sector')
parser_ro.add_argument('--gpt_file', help='Use a gpt file instead of trying to read gpt from flash')
parser_ro.add_argument('--skip', help='Skip reading partition with names "partname1,partname2,etc."')
parser_ro.add_argument('--skipwdt', help='Skip wdt init')
@ -387,7 +395,8 @@ if __name__ == '__main__':
parser_ro.add_argument('--da_addr', help='Set a specific da payload addr')
parser_ro.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_ro.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da ' +
'used by default)')
parser_ro.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_ro.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_ro.add_argument('--parttype', help='Partition type\n' +
@ -398,10 +407,13 @@ if __name__ == '__main__':
parser_ro.add_argument('--cert', type=str, help="Use cert file")
parser_fs.add_argument('mountpoint', help='Directory to mount the FUSE filesystem in')
parser_fs.add_argument('--rw', help='Mount the filesystem as writeable', default=False, action='store_true')
parser_fs.add_argument('--rw', help='Mount the filesystem as writeable', default=False,
action='store_true')
parser_w.add_argument('partitionname', help='Partition to write (separate by comma for multiple partitions)')
parser_w.add_argument('filename', help='Filename for writing (separate by comma for multiple filenames)')
parser_w.add_argument('partitionname',
help='Partition to write (separate by comma for multiple partitions)')
parser_w.add_argument('filename',
help='Filename for writing (separate by comma for multiple filenames)')
parser_w.add_argument('--loader', type=str, help='Use specific DA loader, disable autodetection')
parser_w.add_argument('--vid', type=str, help='Set usb vendor id used for MTK Preloader')
parser_w.add_argument('--pid', type=str, help='Set usb product id used for MTK Preloader')
@ -420,7 +432,8 @@ if __name__ == '__main__':
parser_w.add_argument('--da_addr', help='Set a specific da payload addr')
parser_w.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_w.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da ' +
'used by default)')
parser_w.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_w.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_w.add_argument('--parttype', help='Partition type\n' +
@ -452,7 +465,8 @@ if __name__ == '__main__':
parser_wf.add_argument('--da_addr', help='Set a specific da payload addr')
parser_wf.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_wf.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da ' +
'used by default)')
parser_wf.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_wf.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_wf.add_argument('--parttype', help='Partition type\n' +
@ -482,7 +496,8 @@ if __name__ == '__main__':
parser_wl.add_argument('--da_addr', help='Set a specific da payload addr')
parser_wl.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_wl.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ("amonet","kamakiri","kamakiri2",' +
'"carbonara" kamakiri2/da used by default)')
parser_wl.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_wl.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_wl.add_argument('--parttype', help='Partition type\n' +
@ -515,7 +530,8 @@ if __name__ == '__main__':
parser_wo.add_argument('--da_addr', help='Set a specific da payload addr')
parser_wo.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_wo.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" ' +
'kamakiri2/da used by default)')
parser_wo.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_wo.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_wo.add_argument('--parttype', help='Partition type\n' +
@ -546,7 +562,8 @@ if __name__ == '__main__':
parser_e.add_argument('--da_addr', help='Set a specific da payload addr')
parser_e.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_e.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" ' +
'kamakiri2/da used by default)')
parser_e.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_e.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_e.add_argument('--parttype', help='Partition type\n' +
@ -578,7 +595,8 @@ if __name__ == '__main__':
parser_es.add_argument('--da_addr', help='Set a specific da payload addr')
parser_es.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_es.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da ' +
'used by default)')
parser_es.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_es.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_es.add_argument('--parttype', help='Partition type\n' +
@ -610,7 +628,8 @@ if __name__ == '__main__':
parser_ess.add_argument('--da_addr', help='Set a specific da payload addr')
parser_ess.add_argument('--brom_addr', help='Set a specific brom payload addr')
parser_ess.add_argument('--ptype',
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da used by default)')
help='Set the payload type ( "amonet","kamakiri","kamakiri2","carbonara" kamakiri2/da ' +
'used by default)')
parser_ess.add_argument('--preloader', help='Set the preloader filename for dram config')
parser_ess.add_argument('--verifystage2', help='Verify if stage2 data has been written correctly')
parser_ess.add_argument('--parttype', help='Partition type\n' +
@ -872,21 +891,36 @@ if __name__ == '__main__':
parser_gpt.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
parser_r.add_argument('--generatekeys', action="store_true", help='Option for deriving hw keys')
parser_printgpt.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_footer.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_e.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_es.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_wl.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_wf.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_w.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_rs.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_rf.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_rl.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_gpt.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_r.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_reset.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_payload.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_script.add_argument('--serialport', help='Use serial port', default=None, const='DETECT', action='store', type=str, nargs='?')
parser_printgpt.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_footer.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_e.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_es.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_wl.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_wf.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_w.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_rs.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_rf.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_rl.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_gpt.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_r.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_reset.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_payload.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_script.add_argument('--serialport', help='Use serial port', default=None, const='DETECT',
action='store', type=str, nargs='?')
parser_script.add_argument('--noreconnect', action="store_true", help='Disable reconnect')
parser_printgpt.add_argument('--noreconnect', action="store_true", help='Disable reconnect')

View file

@ -15,16 +15,17 @@ from PySide6.QtWidgets import QMainWindow, QApplication, QWidget, QCheckBox, QVB
QPushButton
from mtkclient.Library.mtk_class import Mtk
from mtkclient.Library.DA.mtk_da_handler import DA_handler
from mtkclient.Library.gpt import gpt_settings
from mtkclient.Library.mtk_main import Main, Mtk_Config
from mtkclient.Library.DA.mtk_da_handler import DaHandler
from mtkclient.Library.gpt import GptSettings
from mtkclient.Library.mtk_main import Main
from mtkclient.config.mtk_config import MtkConfig
from mtkclient.gui.readFlashPartitions import ReadFlashWindow
from mtkclient.gui.writeFlashPartitions import WriteFlashWindow
from mtkclient.gui.eraseFlashPartitions import EraseFlashWindow
from mtkclient.gui.toolsMenu import generateKeysMenu, UnlockMenu
from mtkclient.gui.toolkit import asyncThread, trap_exc_during_debug, convert_size, CheckBox, FDialog, TimeEstim
from mtkclient.config.payloads import pathconfig
from mtkclient.config.payloads import PathConfig
from mtkclient.gui.main_gui import Ui_MainWindow
import os
@ -39,7 +40,7 @@ sys.excepthook = trap_exc_during_debug
variables = mock.Mock()
variables.cmd = "stage"
variables.debugmode = True
path = pathconfig()
path = PathConfig()
# if sys.platform.startswith('darwin'):
# config.ptype = "kamakiri" #Temp for Mac testing
MtkTool = Main(variables)
@ -56,47 +57,47 @@ class DeviceHandler(QObject):
def __init__(self, parent, preloader: str = None, loglevel=logging.INFO, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
config = Mtk_Config(loglevel=logging.INFO, gui=self.sendToLogSignal, guiprogress=self.sendToProgressSignal,
update_status_text=self.update_status_text)
config.gpt_settings = gpt_settings(gpt_num_part_entries='0', gpt_part_entry_size='0',
gpt_part_entry_start_lba='0') # This actually sets the right GPT settings..
config = MtkConfig(loglevel=logging.INFO, gui=self.sendToLogSignal, guiprogress=self.sendToProgressSignal,
update_status_text=self.update_status_text)
config.gpt_settings = GptSettings(gpt_num_part_entries='0', gpt_part_entry_size='0',
gpt_part_entry_start_lba='0') # This actually sets the right GPT settings..
config.reconnect = True
config.uartloglevel = 2
self.loglevel = logging.DEBUG
self.da_handler = DA_handler(Mtk(config=config, loglevel=logging.INFO), loglevel)
self.da_handler = DaHandler(Mtk(config=config, loglevel=logging.INFO), loglevel)
def getDevInfo(self, parameters):
# loglevel = parameters[0]
phoneInfo = parameters[1]
devhandler = parameters[2]
phone_info = parameters[1]
_devhandler = parameters[2]
mtkClass = devhandler.da_handler.mtk
da_handler = devhandler.da_handler
mtk_class = _devhandler.da_handler.mtk
da_handler = _devhandler.da_handler
try:
if not mtkClass.port.cdc.connect():
mtkClass.preloader.init()
if not mtk_class.port.cdc.connect():
mtk_class.preloader.init()
else:
phoneInfo['cdcInit'] = True
phone_info['cdcInit'] = True
except Exception:
phoneInfo['cantConnect'] = True
phoneInfo['chipset'] = (str(mtkClass.config.chipconfig.name) + " (" + str(mtkClass.config.chipconfig.description) +
")")
phone_info['cantConnect'] = True
phone_info['chipset'] = (str(mtk_class.config.chipconfig.name) +
" (" + str(mtk_class.config.chipconfig.description) + ")")
self.sendUpdateSignal.emit()
mtkClass = da_handler.configure_da(mtkClass, preloader=None)
if mtkClass:
phoneInfo['daInit'] = True
phoneInfo['chipset'] = (str(mtkClass.config.chipconfig.name) + " (" +
str(mtkClass.config.chipconfig.description) + ")")
if mtkClass.config.is_brom:
phoneInfo['bootMode'] = "Bootrom mode"
elif mtkClass.config.chipconfig.damode:
phoneInfo['bootMode'] = "DA mode"
mtk_class = da_handler.configure_da(mtk_class, preloader=None)
if mtk_class:
phone_info['daInit'] = True
phone_info['chipset'] = (str(mtk_class.config.chipconfig.name) +
" (" + str(mtk_class.config.chipconfig.description) + ")")
if mtk_class.config.is_brom:
phone_info['bootMode'] = "Bootrom mode"
elif mtk_class.config.chipconfig.damode:
phone_info['bootMode'] = "DA mode"
else:
phoneInfo['bootMode'] = "Preloader mode"
phone_info['bootMode'] = "Preloader mode"
self.sendUpdateSignal.emit()
else:
phoneInfo['cantConnect'] = True
phone_info['cantConnect'] = True
self.sendUpdateSignal.emit()
@ -124,6 +125,7 @@ def load_translations(application):
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.readpartitionCheckboxes = None
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.fdialog = FDialog(self)
@ -153,39 +155,45 @@ class MainWindow(QMainWindow):
def updateState(self):
global lock
lock.acquire()
doneBytes = 0
curpartBytes = self.Status[f"currentPartitionSize{'Done' if 'currentPartitionSizeDone' in self.Status else ''}"]
done_bytes = 0
curpart_bytes = (
self.Status)[f"currentPartitionSize{'Done' if 'currentPartitionSizeDone' in self.Status else ''}"]
if "allPartitions" in self.Status:
for partition in self.Status["allPartitions"]:
if self.Status["allPartitions"][partition]['done'] and partition != self.Status["currentPartition"]:
doneBytes = doneBytes + self.Status["allPartitions"][partition]['size']
doneBytes = curpartBytes + doneBytes
totalBytes = self.Status["totalsize"]
fullPercentageDone = int((doneBytes / totalBytes) * 100)
self.ui.fullProgress.setValue(fullPercentageDone)
timeinfototal = self.timeEstTotal.update(fullPercentageDone, 100)
self.ui.fullProgressText.setText(f"<table width='100%'><tr><td><b>Total:</b> {convert_size(doneBytes)} / {convert_size(totalBytes)}</td><td align='right'>{timeinfototal}{QCoreApplication.translate('main', ' left')}</td></tr></table>")
done_bytes = done_bytes + self.Status["allPartitions"][partition]['size']
done_bytes = curpart_bytes + done_bytes
total_bytes = self.Status["totalsize"]
full_percentage_done = int((done_bytes / total_bytes) * 100)
self.ui.fullProgress.setValue(full_percentage_done)
timeinfototal = self.timeEstTotal.update(full_percentage_done, 100)
self.ui.fullProgressText.setText(f"<table width='100%'><tr><td><b>Total:</b> " +
f"{convert_size(done_bytes)} / {convert_size(total_bytes)}" +
f"</td><td align='right'>{timeinfototal}" +
f"{QCoreApplication.translate('main', ' left')}" +
f"</td></tr></table>")
else:
partBytes = self.Status["currentPartitionSize"]
doneBytes = self.Status["currentPartitionSizeDone"]
fullPercentageDone = int((doneBytes / partBytes) * 100)
self.ui.fullProgress.setValue(fullPercentageDone)
timeinfototal = self.timeEstTotal.update(fullPercentageDone, 100)
part_bytes = self.Status["currentPartitionSize"]
done_bytes = self.Status["currentPartitionSizeDone"]
full_percentage_done = int((done_bytes / part_bytes) * 100)
self.ui.fullProgress.setValue(full_percentage_done)
timeinfototal = self.timeEstTotal.update(full_percentage_done, 100)
self.ui.fullProgressText.setText("<table width='100%'><tr><td><b>Total:</b> " +
convert_size(doneBytes) + " / " + convert_size(partBytes) +
convert_size(done_bytes) + " / " + convert_size(part_bytes) +
"</td><td align='right'>" +
timeinfototal + QCoreApplication.translate("main",
" left") + "</td></tr></table>")
if "currentPartitionSize" in self.Status:
partBytes = self.Status["currentPartitionSize"]
partDone = (curpartBytes / partBytes) * 100
self.ui.partProgress.setValue(partDone)
timeinfo = self.timeEst.update(curpartBytes, partBytes)
txt = "<table width='100%'><tr><td><b>Current partition:</b> " + self.Status["currentPartition"] + \
" (" + convert_size(curpartBytes) + " / " + convert_size(partBytes) + ") </td><td align='right'>" + \
timeinfo + QCoreApplication.translate("main", " left") + "</td></tr></table>"
part_bytes = self.Status["currentPartitionSize"]
part_done = (curpart_bytes / part_bytes) * 100
self.ui.partProgress.setValue(part_done)
timeinfo = self.timeEst.update(curpart_bytes, part_bytes)
txt = ("<table width='100%'><tr><td><b>Current partition:</b> " + self.Status["currentPartition"] +
" (" + convert_size(curpart_bytes) + " / " + convert_size(part_bytes) +
") </td><td align='right'>" +
timeinfo + QCoreApplication.translate("main", " left") + "</td></tr></table>")
self.ui.partProgressText.setText(txt)
lock.release()
@ -331,11 +339,13 @@ class MainWindow(QMainWindow):
def getpartitions(self):
data, guid_gpt = self.devhandler.da_handler.mtk.daloader.get_gpt()
self.ui.readtitle.setText(QCoreApplication.translate("main", "Error reading gpt" if guid_gpt is None else "Select partitions to dump"))
readpartitionListWidgetVBox = QVBoxLayout()
readpartitionListWidget = QWidget(self)
readpartitionListWidget.setLayout(readpartitionListWidgetVBox)
self.ui.readpartitionList.setWidget(readpartitionListWidget)
self.ui.readtitle.setText(QCoreApplication.translate("main",
"Error reading gpt" if guid_gpt is None
else "Select partitions to dump"))
readpartition_list_widget_v_box = QVBoxLayout()
readpartition_list_widget = QWidget(self)
readpartition_list_widget.setLayout(readpartition_list_widget_v_box)
self.ui.readpartitionList.setWidget(readpartition_list_widget)
self.ui.readpartitionList.setWidgetResizable(True)
# self.ui.readpartitionList.setGeometry(10,40,380,320)
self.ui.readpartitionList.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
@ -346,15 +356,14 @@ class MainWindow(QMainWindow):
self.readpartitionCheckboxes[partition.name] = {}
self.readpartitionCheckboxes[partition.name]['size'] = (partition.sectors * guid_gpt.sectorsize)
self.readpartitionCheckboxes[partition.name]['box'] = QCheckBox()
self.readpartitionCheckboxes[partition.name]['box'].setText(partition.name + " (" +
convert_size(
partition.sectors * guid_gpt.sectorsize) + ")")
readpartitionListWidgetVBox.addWidget(self.readpartitionCheckboxes[partition.name]['box'])
self.readpartitionCheckboxes[partition.name]['box'].setText(
partition.name + " (" + convert_size(partition.sectors * guid_gpt.sectorsize) + ")")
readpartition_list_widget_v_box.addWidget(self.readpartitionCheckboxes[partition.name]['box'])
writepartitionListWidgetVBox = QVBoxLayout()
writepartitionListWidget = QWidget(self)
writepartitionListWidget.setLayout(writepartitionListWidgetVBox)
self.ui.writepartitionList.setWidget(writepartitionListWidget)
writepartition_list_widget_v_box = QVBoxLayout()
writepartition_list_widget = QWidget(self)
writepartition_list_widget.setLayout(writepartition_list_widget_v_box)
self.ui.writepartitionList.setWidget(writepartition_list_widget)
self.ui.writepartitionList.setWidgetResizable(True)
# self.ui.writepartitionList.setGeometry(10,40,380,320)
self.ui.writepartitionList.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
@ -377,12 +386,12 @@ class MainWindow(QMainWindow):
vb.addLayout(hc)
ll.setDisabled(True)
self.writepartitionCheckboxes[partition.name]['box'] = [qc, ll, lb]
writepartitionListWidgetVBox.addLayout(vb)
writepartition_list_widget_v_box.addLayout(vb)
erasepartitionListWidgetVBox = QVBoxLayout()
erasepartitionListWidget = QWidget(self)
erasepartitionListWidget.setLayout(erasepartitionListWidgetVBox)
self.ui.erasepartitionList.setWidget(erasepartitionListWidget)
erasepartition_list_widget_v_box = QVBoxLayout()
erasepartition_list_widget = QWidget(self)
erasepartition_list_widget.setLayout(erasepartition_list_widget_v_box)
self.ui.erasepartitionList.setWidget(erasepartition_list_widget)
self.ui.erasepartitionList.setWidgetResizable(True)
# self.ui.erasepartitionList.setGeometry(10,40,380,320)
self.ui.erasepartitionList.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
@ -392,10 +401,9 @@ class MainWindow(QMainWindow):
self.erasepartitionCheckboxes[partition.name] = {}
self.erasepartitionCheckboxes[partition.name]['size'] = (partition.sectors * guid_gpt.sectorsize)
self.erasepartitionCheckboxes[partition.name]['box'] = QCheckBox()
self.erasepartitionCheckboxes[partition.name]['box'].setText(partition.name + " (" +
convert_size(
partition.sectors * guid_gpt.sectorsize) + ")")
erasepartitionListWidgetVBox.addWidget(self.erasepartitionCheckboxes[partition.name]['box'])
self.erasepartitionCheckboxes[partition.name]['box'].setText(
partition.name + " (" + convert_size(partition.sectors * guid_gpt.sectorsize) + ")")
erasepartition_list_widget_v_box.addWidget(self.erasepartitionCheckboxes[partition.name]['box'])
def selectWriteFile(self, partition, checkbox, lineedit):
fname = self.fdialog.open(partition + ".bin")
@ -427,7 +435,8 @@ class MainWindow(QMainWindow):
"Phone detected:\n" + phoneInfo[
'chipset'] + "\n" + phoneInfo['bootMode']))
# Disabled due to graphical steps. Maybe this should come back somewhere else.
# self.ui.status.setText(QCoreApplication.translate("main","Device detected, please wait.\nThis can take a while..."))
# self.ui.status.setText(QCoreApplication.translate("main","Device detected, please wait.\n" +
# "This can take a while..."))
if phoneInfo['daInit']:
# self.ui.status.setText(QCoreApplication.translate("main","Device connected :)"))
self.ui.menubar.setEnabled(True)
@ -459,10 +468,10 @@ class MainWindow(QMainWindow):
def spinnerAnimRot(self, angle):
# trans = QTransform()
# dimension = self.pixmap.width() / math.sqrt(2)
newPixmap = self.pixmap.transformed(QTransform().rotate(angle), Qt.SmoothTransformation)
xoffset = (newPixmap.width() - self.pixmap.width()) / 2
yoffset = (newPixmap.height() - self.pixmap.height()) / 2
rotated = newPixmap.copy(xoffset, yoffset, self.pixmap.width(), self.pixmap.height())
new_pixmap = self.pixmap.transformed(QTransform().rotate(angle), Qt.SmoothTransformation)
xoffset = (new_pixmap.width() - self.pixmap.width()) // 2
yoffset = (new_pixmap.height() - self.pixmap.height()) // 2
rotated = new_pixmap.copy(xoffset, yoffset, self.pixmap.width(), self.pixmap.height())
self.ui.spinner_pic.setPixmap(rotated)
def initpixmap(self):
@ -479,8 +488,8 @@ class MainWindow(QMainWindow):
logo = QPixmap(path.get_images_path("logo_256.png"))
self.ui.logoPic.setPixmap(logo)
initSteps = QPixmap(path.get_images_path("initsteps.png"))
self.ui.initStepsImage.setPixmap(initSteps)
init_steps = QPixmap(path.get_images_path("initsteps.png"))
self.ui.initStepsImage.setPixmap(init_steps)
self.spinnerAnim = QVariantAnimation()
self.spinnerAnim.setDuration(3000)
@ -519,7 +528,7 @@ if __name__ == '__main__':
addTopMargin = 20
if sys.platform.startswith('darwin'): # MacOS has the toolbar in the top bar insted of in the app...
addTopMargin = 0
win.setWindowTitle("MTKClient - Version 2.0")
win.setWindowTitle("MTKClient - Version 2.01")
# lay = QVBoxLayout(self)
win.show()

View file

View file

@ -0,0 +1,43 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2024 GPLv3 License
from Cryptodome.Hash import SHA256
from Cryptodome.Util.number import bytes_to_long, ceil_div, size, long_to_bytes
from Cryptodome.Cipher import PKCS1_OAEP
from Cryptodome.PublicKey import RSA
def customized_sign(n, e, msg):
mod_bits = size(n)
k = ceil_div(mod_bits, 8)
ps = b'\xFF' * (k - len(msg) - 3)
em = b'\x00\x01' + ps + b'\x00' + msg
em_int = bytes_to_long(em)
m_int = pow(em_int, e, n)
signature = long_to_bytes(m_int, k)
return signature
def generate_brom_sla_challenge(d, e, data):
d = bytes_to_long(bytes.fromhex(d))
e = bytes_to_long(bytes.fromhex(e))
for i in range(0, len(data), 2):
data[i], data[i + 1] = data[i + 1], data[i]
msg = bytearray(customized_sign(d, e, data))
for i in range(0, len(msg), 2):
msg[i], msg[i + 1] = msg[i + 1], msg[i]
return msg
def generate_da_sla_signature(data, d, n, e):
d_da = bytes_to_long(bytes.fromhex(d))
n_da = bytes_to_long(bytes.fromhex(n))
e_da = bytes_to_long(bytes.fromhex(e))
pprivate_key = RSA.construct((n_da, d_da, e_da))
cipher = PKCS1_OAEP.new(pprivate_key, SHA256, mgfunc=lambda x, y: PKCS1_OAEP.MGF1(x, y, SHA256))
ciphertext = cipher.encrypt(data)
return ciphertext

View file

@ -0,0 +1,244 @@
class SlaKey:
vendor = None
da_codes = None
name = None
d = None
n = None
e = None
def __init__(self, vendor, da_codes, name, d, n, e):
self.vendor = vendor
self.da_codes = da_codes
self.name = name
self.d = d
self.n = n
self.e = e
da_sla_keys = [
SlaKey(vendor="Generic",
da_codes=[],
name="",
d="707C8892D0DE8CE0CA116914C8BD277B821E784D298D00D3473EDE236399435F8541009525C2786CB3ED3D7530D47C9163692B0D588209E7E0E8D06F4A69725498B979599DC576303B5D8D96F874687A310D32E8C86E965B844BC2ACE51DC5E06859EA087BD536C39DCB8E1262FDEAF6DA20035F14D3592AB2C1B58734C5C62AC86FE44F98C602BABAB60A6C8D09A199D2170E373D9B9A5D9B6DE852E859DEB1BDF33034DCD91EC4EEBFDDBECA88E29724391BB928F40EFD945299DFFC4595BB8D45F426AC15EC8B1C68A19EB51BEB2CC6611072AE5637DF0ABA89ED1E9CB8C9AC1EB05B1F01734DB303C23BE1869C9013561B9F6EA65BD2516DE950F08B2E81",
n="A243F6694336D527C5B3ED569DDD0386D309C6592841E4C033DCB461EEA7B6F8535FC4939E403060646A970DD81DE367CF003848146F19D259F50A385015AF6309EAA71BFED6B098C7A24D4871B4B82AAD7DC6E2856C301BE7CDB46DC10795C0D30A68DD8432B5EE5DA42BA22124796512FCA21D811D50B34C2F672E25BCC2594D9C012B34D473EE222D1E56B90E7D697CEA97E8DD4CCC6BED5FDAECE1A43F96495335F322CCE32612DAB462B024281841F553FF7FF33E0103A7904037F8FE5D9BE293ACD7485CDB50957DB11CA6DB28AF6393C3E78D9FBCD4567DEBCA2601622F0F2EB19DA9192372F9EA3B28B1079409C0A09E3D51D64A4C4CE026FAD24CD7",
e="010001"),
]
brom_sla_keys = [
SlaKey(vendor="Generic",
da_codes=[],
name="AuthGen_SV5.ini",
d="009a3c3d4da0650cef38ed96ef833904c9c13835199367c7b9cb03a55e7aa482016a820dfe597cd54dd1f81fd879cf070ec0c25899ac5a49822db09675a92acf6a01e0f8f538bbe66de48ca9bdca313b616470d9ec2914356d03c95f7d9236549e5a21457e4dd5fcaf09046c47ca7436f06cd7b82cb6d2a936fca88b707f6ce28f33110fea1ec363e8482419db901cb0d38e574fe0c02ad117166b40ec78f59aaa7f3eafa425010a95614e046651273a6cb1371380c4e6ce81bdb892db6ff4892cc4d8c613a8fb3fec1e72c279052896872fc23da07fba63783374f3be8e16a15e0a04a139108dd6ac239f191135f4a895e27c670de065d2248e3f9c7e920fd001",
n="008C8BF38EB2FC7FC06D567DBF70E9C34BE4281C4239ED9C58A6B598C3AE7821815D94D0B463463EEBBD69FF6AF990AE0499B6C3B3CADCD91D54499CD66E5314DB610FC0C6CAEEB1F16B6F2D451E3F2B2D515008917FCEC50ADA4CE0699BCF247D5AE2A1DDD34C48624A657CCB11CE5F8C6CE92CAB6038EFC2A89E42E029488C02C3CF21947C86D51BBA8EF540A2A7CE85356F431891261D860B518E89DD73B2D240461ACB66BCC213403145DE83F6963147E65274EA1E45DB2D231E0774ECC86E4F2328F8A90835C4FDEF1088DDBA1D8F7CA0CA732A64BDA6816162C0F88F02CF97634D85530968CBF8B7CE6A8B67D53BBFB4910843EA413135D56FB5074445",
e="010001"),
SlaKey(vendor="Generic",
da_codes=[],
name="ROWAN / 0_2048_key.pem / CHIP_TEST_KEY.ini / lk/files/pbp/keys/toolauth/sla_prvk.pem",
d="09976537029b4362591c5b13873f223de5525d55df52dde283e52afa67f6c9dbf1408d2fb586a624efc93426f5f3be981f80e861ddd975a1e5e662db84f5164804a3ae717605d7f15866df9ed1497c38fdd6197243163ef22f958d7b822c57317203e9a1e7d18dad01f15054facdbddb9261a1272638da661fe4f9f0714ecf00e6541cc435afb1fd75a27d34b17ad400e9474ba850dafce266799caff32a058ff71e4c2daacaf8ba709e9ca4dc87584a7ffe8aa9a0a160ed069c3970b7dae3987ded71bd0bc824356987bd74363d46682c71913c3edbdb2a911f701f23aee3f8dd98180b5a138fd5ad74743682d2d2d1bb3d92786710248f316dd8391178ea81",
n="D16403466C530EF9BB53C1E8A96A61A4E332E17DC0F55BB46D207AC305BAE9354EAAC2CB3077B33740D275036B822DB268200DE17DA3DB7266B27686B8970B85737050F084F8D576904E74CD6C53B31F0BB0CD60686BF67C60DA0EC20F563EEA715CEBDBF76D1C5C10E982AB2955D833DE553C9CDAFD7EA2388C02823CFE7DD9AC83FA2A8EB0685ABDAB56A92DF1A7805E8AC0BD10C0F3DCB1770A9E6BBC3418C5F84A48B7CB2316B2C8F64972F391B116A58C9395A9CE9E743569A367086D7771D39FEC8EBBBA3DD2B519785A76A9F589D36D637AF884543FD65BAC75BE823C0C50AA16D58187B97223625C54C66B5A5E4DBAEAB7BE89A4E340A2E241B09B2F",
e="010001"),
SlaKey(vendor="Generic",
da_codes=[],
name="SetRsaKey in libsla_challenge.so, secure_chip_tools/keys/toolauth/sla_prvk.pem V5",
d="8E02CDB389BBC52D5383EBB5949C895B0850E633CF7DD3B5F7B5B8911B0DDF2A80387B46FAF67D22BC2748978A0183B5B420BA579B6D847082EA0BD14AB21B6CCCA175C66586FCE93756C2F426C85D7DF07629A47236265D1963B8354CB229AFA2E560B7B3641DDB8A0A839ED8F39BA8C7CDB94104650E8C7790305E2FF6D18206F49B7290B1ADB7B4C523E10EBF53630D438EF49C877402EA3C1BD6DD903892FD662FBDF1DFF5D7B095712E58E728BD7F6A8B5621175F4C08EBD6143CDACD65D9284DFFECAB64F70FD63182E4981551522727A2EE9873D0DB78180C26553AD0EE1CAAA21BCEBC5A8C0B331FE7FD8710F905A7456AF675A04AF1118CE71E36C9",
n="C43469A95B143CDC63CE318FE32BAD35B9554A136244FA74D13947425A32949EE6DC808CDEBF4121687A570B83C51E657303C925EC280B420C757E5A63AD3EC6980AAD5B6CA6D1BBDC50DB793D2FDDC0D0361C06163CFF9757C07F96559A2186322F7ABF1FFC7765F396673A48A4E8E3296427BC5510D0F97F54E5CA1BD7A93ADE3F6A625056426BDFE77B3B502C68A18F08B470DA23B0A2FAE13B8D4DB3746255371F43306582C74794D1491E97FDE504F0B1ECAC9DDEF282D674B817B7FFA8522672CF6281790910378FEBFA7DC6C2B0AF9DA03A58509D60AA1AD6F9BFDC84537CD0959B8735FE0BB9B471104B458A38DF846366926993097222F90628528F",
e="010001"),
SlaKey(vendor="Generic",
da_codes=[],
name="bootloader/preloader/platform/mt6781/flash/custom/oemkey.h V6",
d="607C8892D0DE8CE0CA116914C8BD277B821E784D298D00D3473EDE236399435F8541009525C2786CB3ED3D7530D47C9163692B0D588209E7E0E8D06F4A69725498B979599DC576303B5D8D96F874687A310D32E8C86E965B844BC2ACE51DC5E06859EA087BD536C39DCB8E1262FDEAF6DA20035F14D3592AB2C1B58734C5C62AC86FE44F98C602BABAB60A6C8D09A199D2170E373D9B9A5D9B6DE852E859DEB1BDF33034DCD91EC4EEBFDDBECA88E29724391BB928F40EFD945299DFFC4595BB8D45F426AC15EC8B1C68A19EB51BEB2CC6611072AE5637DF0ABA89ED1E9CB8C9AC1EB05B1F01734DB303C23BE1869C9013561B9F6EA65BD2516DE950F08B2E81",
n="B243F6694336D527C5B3ED569DDD0386D309C6592841E4C033DCB461EEA7B6F8535FC4939E403060646A970DD81DE367CF003848146F19D259F50A385015AF6309EAA71BFED6B098C7A24D4871B4B82AAD7DC6E2856C301BE7CDB46DC10795C0D30A68DD8432B5EE5DA42BA22124796512FCA21D811D50B34C2F672E25BCC2594D9C012B34D473EE222D1E56B90E7D697CEA97E8DD4CCC6BED5FDAECE1A43F96495335F322CCE32612DAB462B024281841F553FF7FF33E0103A7904037F8FE5D9BE293ACD7485CDB50957DB11CA6DB28AF6393C3E78D9FBCD4567DEBCA2601622F0F2EB19DA9192372F9EA3B28B1079409C0A09E3D51D64A4C4CE026FAD24CD7",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_U91",
d="8553e31d7a73f6c9294e961815c23f31f2b5ea1116e3c613ae12b26cf285e4c5ca0e2dc8e17d52f96b30cef6ad544e43205933f20ad17eb8712097aaa23116c68eb6328980b8ba26706105656fa65315688b8232758607b8936d0abc27dbc97d94e95b4f1957fd1965082e5849c4185ebba8afc7d558d4f5f001ac5363423ac1",
n="9a97c44b0768424b6bbb0b6aa987a2d373448c6fee1f61fb81f8cf53d70856f0f77e76c06a6901de90ed3b4d9ad4b9e04eaed42e5657bf2fccf390fe9f5abe1abe8575f07916da69acef95d38874223ec51cb501148a1feea2be2b8ccda08672aa423a4099203c6aa4777fed7353c57696b8e0d4020bd6930b828b9846a454cd",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_OTMINI",
d="6bc0e84b4f38415bc575dd0d5248c2d182ec55e2ba7a11dfe86815155c709a25bbe34fafa6a9c19344adcfb32eb3d2eca465c2dc0fd7528a00cc268c6657cdff0b0da1b2ac6a95b94865facb7e1494cedf44358e29ec7e8f091172e4ef29856d1f45032aa644efc273f141c10cb8281a12cebe202b65f176e1a145c326d75841",
n="bc7b5107bcf46c2cd7758f4bd4d4e9f06b731d9cff383dffe48156d1ad91ff74a7925fa3027669766b3d4c6e28c1c9310194c34a59e672c8ced38588e998d7b162889dcf06668345f93e4efca34b5fee5bb57dfc38d7623a48f31b382de2db656ec1f3b5267a9a8f5e441c61448a283e4717ace6983d01b163e34f959c9972cd",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="ST513",
d="9ea0f7256bcca9099e5db80757a5f3ddeb3292475c01d2e6eaff8da905d9537a5875e874d26872a8c04b552dd310f194ef5a5ea445a50d5c1e6670e5126ef01e5fb1af24a67d07b5a9f72197bc66d5743faab54759fbedcf1fd8ac1aabede2c6fb29601b4734334db92a92fc25f7ed8700d307b74a2c435c9ce5b5caba4b3801",
n="df836c16bc8e129dac8e6efcd3f41636981687c29c465b481cbe874ffb14d592de024b70f4fa20ad96c96e4e3eded3625f314dedb4d8635782f6d668d04ab1167982229e03ede17a7857a22cbf72444a6bee2bba54f32099e0eabe654c3da4933926db4d97dcaeb68236df4b3e51bd3c4bfa8b2d47c2534405e4f1c1d43e1069",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MPK_U7",
d="c5829b5bc34253f090db831f5085cd5a6f88da7f6f90e3a3cb6fff6e53218c5a616719971b3f64ef02de526719a7b709978bf1ed48c821981b32ea77c9e536bbda206fad74946d02a20d17120f89419b0daee2d8a47275768930ad53c876afebffb6805483c1ddcf6c19f3566f0de494838afb51b18080beff66364de5294581",
n="db0b6e89fabdc24e6e7379d25b0c402686537ab6375d8b2407beaf44cbbef27e04e90b556801bbce5eee2a7ec636ac825667dae3578eb7bbb66701bc62ee86f28fc14d57e8637a2ddcee00cc3ab87dff4155250c2dbde9ae62f3d7a9d5e4a265fb0a8b23c082be263d7788e44d59780b47a31b25dc588f81902be419f917933b",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_U8",
d="76ca90a16bcf7552db2b716b8531fe5617bfe86635627647e3d27291fdf47e67ba8f953ac362dbbce2977f05a9f24aff4250f8f3a14d3ef09b7b99c9384aad0c53104f87b47d7daea3ca725beb233d127ec342ce0619b16bd3d5e44371cffce9f23178ff48dd42fc4450ccdb3e2d63437ef9dfc0296b12840ae85d472cf0135d",
n="9bc517a0dfa87a7e240000c5f42cf31905ab93d4bcb95694dee85282867d5c83270aea0b0948d66eb39d8500aa6c8b1069b8ee784f75948958f7bbf627d6ed5f286fd3bd4df60a6c9490cb319448b22765aba9329820eec50f62f1ca0b6b3322aa27747b26855a1f1719cf0c4060c9f5a6a3a60ec60fe6e04e7b044e5da994e9",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MPK_U91",
d="8553e31d7a73f6c9294e961815c23f31f2b5ea1116e3c613ae12b26cf285e4c5ca0e2dc8e17d52f96b30cef6ad544e43205933f20ad17eb8712097aaa23116c68eb6328980b8ba26706105656fa65315688b8232758607b8936d0abc27dbc97d94e95b4f1957fd1965082e5849c4185ebba8afc7d558d4f5f001ac5363423ac1",
n="9a97c44b0768424b6bbb0b6aa987a2d373448c6fee1f61fb81f8cf53d70856f0f77e76c06a6901de90ed3b4d9ad4b9e04eaed42e5657bf2fccf390fe9f5abe1abe8575f07916da69acef95d38874223ec51cb501148a1feea2be2b8ccda08672aa423a4099203c6aa4777fed7353c57696b8e0d4020bd6930b828b9846a454cd",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[0x6577],
name="MTK_6577_HUIZHOU",
d="3d6ff33ae0ec1d029db4a6fb9ca3e41890f5cb5a53bfc0ab3cb2053d85243c7715a07ebfad719bea67c252a223ad0fe65074a5d26ea14ba63ff8d92e553e879b6ce51e065f05b23e5d27deed116ec751c9556ea0cec11e80f3bd206da9e9072fbe1695b19a8a9fcb576f00f7a268df8d6d262127ab3f3246941004f25534ac8d2f418815d15f4a5a663a2f1383115cb3e8bd263ebcd92c5bd1b92644497e15a1b41e77e648cac179182d83c496728fb52b9a1c600954ad0c3eac5d4633d519c88daf775fe090c2f2568c7c91a8938a2859245f100fce764033147d84d79075a81331ecdd170d2541832ab9161dc473cadc1dfbc17df2be89fa6d6c13d9db3611",
n="ac2a2c19bf4beef4272df8899cb648f90453e53faa1dd8143327978620ec74e6068a8fd051fac856a59ff0a2f3051b7512f55fcd6eea57262a5a24e141b2a9c105509b79976b952a4cfa0367535aa1db83290f18f62e2f604bfd5fee3fb6fa863ca5546e359e0348937e5b62e47f645e9552ebd2e7e516c13a192a6075c55351192dd545dd90c34fa28c695d6643a2449c0c7acc9d003b9bb4f9d249bc19beb8ffdc2d6115260499156461eea896361aac9a24ace3bf6c81db3e8c32fd6d74d876882382618c7ae920ce63b0c33a3ed6a59642acdcdccd68f2e84f6b1dfe8e4dd33fd78208c750f877a8eddbf32b7f6cd28bc7f62a79e1281cad49b29ea1aeeb",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_S_2019",
d="68d01875ee507057075dd8cf2e3007aebeaf767f350c130684911c483eb918a5e235ab71c2eaec62aa7bbeecdac518cb8962272e83a2943cb0e486b66da8e244fbf3e3d8e4a065198032fdb045f011784127cdfd63d285f7f20dcc37b0ebbdc8b49020b9a16333f196e8e3e8246835b1e76615985ba6e221241d096cc5bdd7336d8b22704dc1576ae0ac252fea8dab129756a609f347d60e25d8d085cf0c8775631d3c0e54e50fc67dff2c55148b4e78cf36987febb23e14ffc1da9cb0adfc139d509826aa98f6fe0e25ec6ab6442e5a7cebbe6454ff06b897467512cdd8f0460201125d0bc9cc2bae259840722ae56d16b06f9e0515a2d128a23b5b0a1896e1",
n="e4607e6cf78f5e4857bdaea441f8ddd35a7576f552b4ad2c8b4ee7f578c0590d747b049bb5014e06f8350dc6b78d5e0ddff1b4bb8af695e4a338a154596555738cccbe6b58eb43ae221df9babfe9dda6ca770c25ab42ff986f946756b46ec553daf7616f2843dcd6a48f48d9011c050e7ed11c99f61624f057695d622088f868bf6a3966f25bd8ad58db81623fd63f2b91f3ded1a5be0efb69a64bb40d8bbfc251d9c32fbf0a1bad516751e9e04439392c59ba6f856b5c0bebe0dcc67d7d4f25da5342aba94680583ed76d94823c6f62e5e7484f7e2d2a467d167ad3f5647f958dbba3eb66f756c851a55138d1ce465333592969470fa8652df2e38bc380ff4f",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[0x6577],
name="MTK_6577_SHENZHEN",
d="6d209285b39ee78c7cfa17a34473855463c8a42d7b494ff0d6885c16d672aed0219193ef388b5aafb3ab10bef394d6fb7831b122ce47564abb084f68f3f7be113bcfc4e8ad3774fbc8eaa8a6fe030e96a56022cd0891f59eb2564ffa2700056e50a8cce72357d3f7ac7ef7b4fdaa69e0ceae1ab3d0f5b90e00414a3cd7bd17afc3b6463ef43bfd22788b68fcfcc2964421b1b622907d8c75e8d83193a579e50c26b0beb93e53e2888cfddafefa03c368c68e6d357087f1bf0800e1bb4f0fc97c092a7e7098cb60cad71e292b506c0cd1f428aff3192da6818351a780aa1b4cce0dccd15adad815b610f445a6571d3c65d2c44da9057b5c8970cded0dfc3072c1",
n="a29274e3085c260de63f571646cd2c69737ba5a0bf604ad31cf6a86d6a9e08dc931ecdddb7404f4c9255c72b5debdb69114146bdd7edf6b38505b19c4d18eb0e71516d4faa871cbe1d2e24e15c1877b33587a8bdd1e7dfe1b17235d1ac431c27cae07804014c287fbf2479e6b4b80665898f7cbaa7edcf23daa8dd95f63039fe7eb641ad7c05e221d29adc62cf84893ffc6acfd44a9d2cd60d5e0f94d1c29d317bbddb3f5a324648069c72857cfc708fc9bd8a3f7a98051fa9835af1f9c71d80236334ea51cbd52e57e5a7950beb394d9c97bcc32591d9700106b0abfe1dd2db9617fb7dd2eaa3885630c3ce1dfcf087c814b480f30c411f3071f12aedee4077",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_S_2022",
d="3be4c4d89124e53d12cdc922c0c6571224e8925fba160186068855c5032de6655be49233899432008faef8ba5037f1a0b237e169f6f9f05be2694bf53d04b44507fceb1480007d2f49c8191ced7528e6b4fb06070851c85f2025ccb60271631def9f831822b351ed17ca9a165aae97516a6c3940971d17e927f3befb43432c1b689cc660a896237f090d7b311d9e39aa1eee5a4e3af00843c965c30ca9aa5dd7767809d27d4f66777661779d2a1fb90b014329a1973e67b8989de924e8ac98673667e4f734382f87f0dd0300d360142afa772d5beca2ef248e90a7bd32240c4a5b5f41aed3f4b63f90642f138186fe17afd713a3242eea7b2dd0f32b06b67681",
n="af823063550d6e5adcca01a1ae1fe357f73d7e5c60cfa25e4beac24304b70623654fd13547de869899be532f45f3c5ff26b50292dccd112dda1478721c05304445058499bd00f6b104e16fcf2d0af55781be147787227eff54a25dca42b9d6f1fc8f4b821c099f483c402addd178330167aa9b1021dae121bb2bdcb0127ac47ae866a1579f2399c70e69293ddd3b0bacec2df9dc518aa0c58c2d7561c5783ac32e57b91d16d6c57764755894963733b85f19f9a3bcbf624199cdd1b31cbecc5448b132c3799e2d0e569f0ba61245796db5876820ef125f4a230039c5cd16b2414855bf3a3b565f81787a4e9b264c9bc855b4fe7ac17caca1bc5f070594a9c175",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_B3G",
d="12ff6a160cda225ddc898cc6ef7dd3c69d05dc24d23b7a0334568dc85191f3b63d278ab1c8449507dea8533496e04c77225a12a27b7abcf34d10c3cd67b1b41d7c19c44114e344a74396541d998d7b76ca06d0322bf3333684652528df22021c190bc38acdac2a3be6e2d0bce7f1e3c77a71750ff17895cff9c6225275a3ce81",
n="cf8243d13128ed39fadad9ca97c15585d634f4d9b38dd59e4eec4b0b93e4eb2fd2d96c425855e69706d5c11021a8c2e08bff87b424bed2dc3efa9360bf1bcf80c96cd4ba9c39eb79bfa2bf9d4efc5a56798ccd9c6599ede595aea644086605fbe55b2f7719fccbafe0c95956fcffb0ce77a9637c9ed66e067165cbe901eb041b",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_E8",
d="95b32d61a10e6c2a54fa4e5e020d590f6bf0f295fa87fa03b3d00dcdc4982dc997ad5c7ff872255141ec1b77f714c14587ffb87c985531c937b245062ee03514aa796ad79698c40c49a8b3c54ec66fc20deb874a8bbce87239c414f541367a350d525fa6bdea77e4cd3078cf7ddf22a8aefb0c595a6c76285d837008c0a77e29",
n="bdef438901dfa726cfc2cca59d12f009108b8e1fd7dd9b91a5cc71fa7b1e36c8783f9de5850050e6505fc715c50bddd59a3064b05214c4365360cb98d080cc38658a94695184b564e8e8dcc28f70eb0122a4bb7662e3a1f34c057ea523819ed02ed46bae0cd9530b0536cbe7a1ba3f33a45feb2f92ff5104dc32ebe94f249eed",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_C3G",
d="4375be875664fad432cb6476f1c7aeecaea3166a51eadeaa32e96d0d79dd159b6287f4cd42685330fc15391eb4ee83dc6fd22a913c5fd5023d8fd6b71af8b530209b5355acf1cc6e6397aa6e5d2dc92b7d37635d391cd22a3aa337d8fc0a274cdd7d6630395d13517e32c91daab2f5378ed7a1be86c81c2e775c249201f2c221",
n="c04e6a1be49c5a57accaebc837099b40890180fc046c3dca58745749d0979cadb63b8b4573fafc129c2f89ebb64c4ec81339e862f5638ae145e2c8bc291097e6b90434ff3f3a1e620fa77dcb6d963f53b79abaf4eefb8a5d4378cdf4ab3060a9901909fd455cf850ae5adbdf035cb3cbcf572ac4dce4bc1321562273a461ddf1",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_K6",
d="4f65cda0c3ac66753c58d748db46bfb8cb8dbd1f849c7444afcf37dc6bb218904c5a2fe08808680d2a6e7587681256a6ed9751046fa42ce44874bf2061f40dca4953c345c2f156e8ee7e2f497ebc59b3ddccda98584dfc999d213d6782f2b0faff59a9671cee801defeb5a51178a7b95c487aa735b463e8b1321b6ebe58c7401",
n="a7e3089840bb7a9a7a972e8c88d7c464fe40dc4771a2df0da981079cc800f5d3cd45ed9eb34efac6bf7d2aa6dbc1266285f50d7e86e6e0e5dc6d062bc8fe871672139904e5ffe64c6ffb4ff00817ffc0ad4c18787a253ba5f7f7bd8412e5f46e2c264cedf174ed5163943331a658b434c59ec9e11b269e829ab638c80c4ebe51",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="OPK_VLE5",
d="4befe0eb0c424d83cd2dacb59740cddec599ab3c8833dee354717425993d12ba5441056297153bb3d2667c3e9c76caabc349a07cfab60efa9e5e7b35e971fe7eedac090a1a5a7d8a2cd59de84762f09cacffecb65bf70ed504243721fd0e094c3f216fbb85778ad82829658232a2f472919e992060394e79f2aada9e8a42ce21",
n="cb676a5de86e2c7d75a17f10fb2e3f81a473e5d2d088833d8c1928ce78caf1000aaa607c83f55b57dc07fac7a9ecad1600df5d033986c02c003884620661a9674042a835b99cf8a024c27a10410eb379ac69e72d6f5a9cf72c185262331c98879cbc225de835d864983d2bd085f1df99341d3cbb0ba3b0a50491c8ee98d691b5",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="OPK_U7_1",
d="18e2fa361f4e7fc86574d9a93f2113a4d99d272710f303e29e07ebf71444335ce789dbf9816d472b27935ad49202379e44023071706bd0058e2bae45ace0938e75610579240ec87086d27fc0844ba25bba09214ae43037cb902801a58915ce58c6f805fb3ad6cf7996f25e0cf0a94c13e04eb4370ed6b93c39ba2136f8cfd101",
n="de15dc10818e30c363bd0a87d5f8d89b832329fa25b8388709d94e9b0ee4efdd3e24eed3d931f01ea1b0e2b76265d7dc270ea8012545bb7245c286761210bf46c6dd1fadefc257fabebba29bbbd86e8336460e5d21888a319156e8ba529e4b6a200136ae4aba447fb37a357028142d8b16d79a421d513ecd9b9ec0d908ba8217",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MPK_U7_1",
d="88a4477997b57337cb144d0656bd2d5f0ef59d6b574b631a79ac8015a4c20d454e1df85682ad25eccc7fb92be373259fffe58741b5a85e50caa68b9fe84f6e295d2176b96c20ff819e8bb889702c474effe1a77710ff3b93e896fa488f1717c75e46a1b0f5898fcacfa35943f1abf80ebb665ba7fde59c4baa61dd2f6c5ec001",
n="b6a33b825b0cf6abd3c9d39d1c8bdce50a41f9bd5ca2de52c4c447afa9943f5c1365d2e9cb7961ffd877fd38696b4479a8bb7eb8da15bd8d59a1cd7e5ee517d1a20f29bc66974f87796a11f7537529f8f46ac57861484808bfce9ee6cd6527f7fe3bfd57b4a7fd46f8dc047d6c8370de6507620c2b9a3bf864e8ee4c4d2abda1",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_S_AT_META",
d="8294e45929b8f95a380c59fe715da5225fd518920a85fdc9a8b2ade6675b7680293c21539fa4466907cb3601b072d8adebb0481ecf069baaee00d0f5cb4396f4ffea11dfd41f3c62fdeb312ee9b4be2026bc40aacd9ff928130fa7af0305228dd5e47c551c2a701653dd6841b9566099de99e2731194ae617ca8d9df99a47c49d9f514620ea1e3742da8dc7dec6756403631a274dc226c6121863e4a571a120b63c38d134853df5b986fac1565e1f3bd8a02d239462967e9c71cedd9ae0c0eec330018ca553cc7cc2fbc73d6ba37be2fe360644ff69ab7c734264675c057417857df4ca206dfdac9a5621f9d8e45dd2e58dc8b4198667de3efd1d5bd7ce007a1",
n="d1eee63f19d148c904076c507aa8d4f6c7e931a65476fe5231c06036fea2ecbcb8c811882c4f70e6e3523be73f5c7a83570f3a40bd894399a5ee9f903e8e745ec4e4e034495175b167192535843f06241d6477e3ce1ad5270e590db9cb905404c01aa407433fa2c2ca1f8366c1623fa45bd5ee68e3145a57f9af3e6e68fce41b8c682c0e07f3c48f4b377951b23b467fea0d4ee0e67c0235d0e83ae27e40ad1c060063ceb966835a0ac1eb68066f8b55775ceb7b444ffaeec19548a42247ebe687f881a0c8e5277beec22241e2ddae1c21cec8046eb005302812b7ef42ac153cab317bbeaad73f7ccaced38c433530b7e0ad464150026025a9a3ff5d45e025db",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_B7",
d="776b1deb8c3e943b3dae67cf2b597ba55c439dc1fa10e4e9ea530df96bd0815cc3ec3ef0267f89a699c5cb64bdb91e5e9ae4c7af03cbcfbfb4755cda55e3a31d510f96a102b5aed90731788a426e371f8ae24f660403377cc0836a06b2a8e159bd177f4cf68e36d447e4b52ca63611cd8416c1efcac52143106c272f7474387d",
n="e3e3166f47177de4915e915a9d555d980afad96be22cbb8a02516ac8fe69657bd10bc6d072046dcd33e4476e24f128cb7ac613df140cefe71abf080a74d27c114635d3954c55299f6f81c2a0aa14c4c678307f4b3bbf0c64f0006051ea7573b5b0cc290201c76c4d272c981b1bb19bd0a0a0ac046e6e63b0f4cf88d2c98a5c91",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_BACHATA",
d="09fe029a23ff7e37c749386fcc9a640450546b95e5127489d364d380393c99f5c10da6d7cf0ed955f4a5f3d8d90d97cc7c49069d394206f9b59c11568ffe66163eae377447abb103cd5d4256885cf7984b28cff8a096dc479b9196d66cd534cbdfece7a61de04110bb14a3ba5e0f20ae0bb4d82e18fbff0335904dc09b829e91",
n="94cc529bb1af0ab8043f09e3ca612d787cc19485d3769546e750f6edb844979ba8f1f9afb8b93b521330b74713831a78a584f7b24780f92dd00e5d56ce8defa3cd39d01752e514a4c2ba7499f334729622049491b1aecee6c9e1c867e996c294b10f5d62ea4504e333424b280162087296c300c01fdf75f47d874df40dbdb94f",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MPK_VLE5",
d="7005d1bf5be81db7b17c9b16b1d407b308b42e3490e75a93e9d00fd6c812d1d8db2f1041a342964808a037f315a448ecaf0502a5215c58f0de709c5bd87e3a65e0291a1a23547c76cf437ef1d9b434b70dbb417049a31de9ee7becf218a5bb63b05fb84ff49d1e6aaa4b9b4376f47417435ecd85ccda63be9070e7892ecd4a41",
n="a62bf756a70657b6b560588e85e662e181b6a61ae466ac3d0d2e971f160e88216792cedfb1979b3d6b665068eee8a8699888cd74ec9482c61ae7eae3571e50beccdcb336477c26040d09b46dbd93efc0fece4adde2e00c1cbedafd6ad7c43bd621675a6a46425c5cf6182fc5602be443a372fb4ead4531e64285ce29be913285",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_C7",
d="31d28ed040a8ace0d56fc94b4a7d29dbb135d62c7905621818d657499fd6ff6fe7417592cececdd3f3d37ec0a361228da34d3e7a2724b7832ced00008fb4ae500357fc3d285c64fbf7efd4bd1ee48ed40190296171acc3c2d0c69e89da5a8fde7e0ba7048aec6bef1bb19646f883fe9d77d8d263545e7c00e8604be38210d065",
n="c1d6c392828f4620e455c138840ab448cfcd4aca821663335dba9c51dec9b8198301ca6b069adefcd1887f1cec31c15674ab264daeeb82398b419f08b4236904203c48a7db8724f1773d04a6b8c88cb38907a00bc53e86cdb2bbf479a68b8241382bdc5ac6105270efc2da4cb91a36459ccf6a2a87dd56ec4c331dd419ba5931",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_MARTELL",
d="985e549fd42c0b4955d3db8c3ee601f65e10a3db08f957fab4016dbad0f60c7e09e8b7a782404cb0fc7c805dfd67fed814765ed58b7a146ed2c1d31b80e3f845a45b6ccda5a0344247be404c23debf027c7b5082373372b49bf78d9058caa66c57d3be829088c3610034faf1ea9f24a21110bbb3865182747ca1779e83c6983c189b3f19f3df49e5f9cdfa57f4f69dfae53e19ee0b1ec30986d59ad11f52bdc022a9499dfa89f8546d266f6026aa307501ca5a619f5413a45ef38f139c3ea8b52f02fbc8983aa878052d9108668ecfc8605057a298355d2f680c34630e224c57dd4c4f2dc0d51766ef7070daddfa3c885a3f94d76c943c6c1054d338e2323b99",
n="a800d061e4a42e4c3453a17cc8daa974e23bfaa403b4a60fad6d3516d8ec035c1ebabdcd60009d9b8c639954e616c6cb6cf821e31e58772ffc366e6ffb7314657567b12279a34dd69e46b8a4a628dc2dfabc68fa1d89388d2058a97d2e31520b4fb04bc2f963e110e8541eefd22d90a03eca806b3c6a20c6bd1a7468e61ea1ab283ed1bc462dfae189eb5fb451f802fb868cda9a7409aa52e42b18882e79f4f1c2377829fafd9760468bd1db823bd9080378cf46ef405d91636cafc03acad9fada6b0446dbaf51e9d533887e4a3a8f62114063e0b8920684c28bfbe256aab26e98751166358c201347ba6c3b36d49aab6302fc248eea3c254e15a08429fd2149",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="OPK_U7",
d="61ed86791440c26491b763730f483c18c32fcd77bdb6f9e9e3e11cdfb9716d22c392c68556219e2b6c1ada57649ce2de559c239a9ff8f33252480421e4a2649df8e3ee0095c9bec361f25a5ec67d0b4d96c73404ff8a115fecf1173a6568845480fd4423b5dba2e5111335655f3bc2f3fec65510648571992e010ba0aaf243e1",
n="9f94e8f1171fed4b427629c928e807b2220f109ac70a3d5b1b8cbd295bc3fa3226d3903298cd81319b9b08a6f8e77efad0b04139b686ee0d1586175913ad6f65d6cf21bbc7f769885381ba6d840414b26fe7b9b3e393acacb3453e3a0cb79ca21cb38a42685a03462244fdb2a5f1d8b9e20745fb3206e799655c47146310911b",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_S_2020",
d="b86887499d157d3b1feb1041b9d2e94065732b41d22feebce317676321d66d1babcc7a53544e35a714c207811e62d134291d616417295e5b0c4aa3d65e40b41a352822263c22cbb4041a1883c76b97a8c925cb428a7b2300622ddaec62209d8dc0c60159f6c7ccfc26768bc469deec22bcd62f49f4c2ca1b2cf0be49d6e5ec563279cdee79c92800c6c965200d316c79285551a54359b37ec4173eadf4c0506d857ddca4831ade7ea8f13097b4e2b630a2d3eb9c57abcc65f84d693c55e361763d8d37bb40cd6e2520684ae05edc62a36cda6747509600f4605b7ed924ee1ad49e66eca1176a20794600173dbb42fced2f1fa0cccc0af3b56d58453bee420099",
n="e4cc4967bec817bb348468024c3084b15fd4f7810c8a9d078a4f51cf9974d2e3bae8d5a19a85c0a73befd0675100e642a3f425e3192dfb1de56928c37f45fc142adaa65798ada863b84d4b5f22c3f79b95cc201ac7c292c99475453a62b7b7e06e84833dfca7a0df931084932a80129e543c6d24a13c5f2cba6ef5ffed9efd4dbc20496f5194f0d1aad9d789f32577f8846df9a14778504ccb5dd7507114c148c1937fb99da15f9596d4fa052cdaf1f66d7e5e0c0793628752bf9af3c4ac67e21c21d170ad448160761bddf586a4900fbb7dcc44467f1550d15db774d7cacfe3105b465321a5f95fec22c2011d616a5c0e22f0535dd1f969202be56ec015f891",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_U82",
d="3f5d99a61561d70c6c335a30d9a11fa8a3ad70fbecf46c9e233d57aa827cccbb137c060a47e693e234ba1b532851053e17446d5582b9fee205c0d12c7613378c8b8c8c0184cdba90d56a308014aac0458c5572699d599a15ba36146b6f2e230034708cf67d31ab837b7bd8e5967fd9a7bf413b7d9314302b18e48962d01cf6f1",
n="ed2055a7b95db86f7e3101196ae6218015d70d03df6fd5787de150e82927443097a90485757743447e2f4641afcf510acf585f73e79c45b2908d5de8835221a76d93e48ca465ffbe0dd76cdaa98550ab2e7b84a6470d48595742fb54a204442ce67bab989c69adf86457e313eb24c87d80aa7d635449fab0d97b6b08c5f7c86f",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_JADE",
d="69fd6b9e25ba604e204ec90e8e0769b28417e6b52dda7ac53deb712c549f398a48ea8ad20bf065a093ac85f336f92f1221d3413f3793bc8c7c6057a091828c04f6fb695f43747d0d22de100bccce70ac7a8f9d092afaa7d44fcda99b12454f8c887e383c69e7e21ad15203eaae51d803cf35da09c8d536139c658bebfddccf01",
n="e8490dcbd3488278442f78ec5634ccdb8befee081ed0d19071480a10c299416ab8d0e9eb19e8975cac260606463c51bb62875ab24690d07905b9c48fe60086da12899bce3dbed91e0157cff76f27a1c09b37e837e7acb71da3c0e30564223ae20216fbcb3de5e93c2d7f98827d61441b988e57497c1ddacb87cec1e73139bf67",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_B82",
d="88a4477997b57337cb144d0656bd2d5f0ef59d6b574b631a79ac8015a4c20d454e1df85682ad25eccc7fb92be373259fffe58741b5a85e50caa68b9fe84f6e295d2176b96c20ff819e8bb889702c474effe1a77710ff3b93e896fa488f1717c75e46a1b0f5898fcacfa35943f1abf80ebb665ba7fde59c4baa61dd2f6c5ec001",
n="b6a33b825b0cf6abd3c9d39d1c8bdce50a41f9bd5ca2de52c4c447afa9943f5c1365d2e9cb7961ffd877fd38696b4479a8bb7eb8da15bd8d59a1cd7e5ee517d1a20f29bc66974f87796a11f7537529f8f46ac57861484808bfce9ee6cd6527f7fe3bfd57b4a7fd46f8dc047d6c8370de6507620c2b9a3bf864e8ee4c4d2abda1",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_S_2021",
d="cf553c03ac3cf21fdb4097d4a97f35fc6c305a2e30dfbebb7667ba2adfdec99d3277bccd314281c592ade680b42849fde6122659a68cd7e525b764520d612c7c6c141bc4b2594bc88732d4ca0a97e464d7c1ecf4fc2788f1920cb030c1b2b3ea84e8d6191d5e53d56c5fc495051a1d0fdbea947d58a9d773a68152d157d4bf57f2b4fba8182f96ea4c9b798018361054f95b251089c786be542c7881c49b077ad52af25a359bb26257170706217f66533cf4b8379a1fb7a30c955c8ed4c1c6dca905ce6e7e5e92ec7e1bda1db44cd187a9e5137fe44a37cfdbee173a49654994926cb2fdd7857dfc8978d9de73e899e18f5dfe33a64e6414fc5d93738f8c5591",
n="df85f4c4ae8c98e78142d403d002276a5bf9edd17870caa848fc45720e8b4be94f6f9a47181417840a5b7d4fc36575129afd6a848a0de3f62fac5b5f687a2219cab8cdf2e7527d6af3c6be84eb99bf519b0b210960fc8f5223c9bc38e8f20d0267642153cf370312b955143e10490c6a207868ac7ac314bbe10f6063a1ba606e28d248a1ee3e7000d12e9c4ebd47ae483b625156b82026fcfdc36118198cac1463aeb56bdfe260efa38ac1d4123c13fe59e0fb0f2f895609c117f7a39fb9f27c356d4748cf7af41e15ea68c6c7c64c4d0a1acb4632965e0260d9b08de9fd81b82050c9929b79ee865f89272483b6fed8a409d6a1af2429d24fd358a4b4da4e77",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_MINIQ2",
d="a475ba952a9f2f9e58d6ec91b41a03158354ea1e451656d83d15691c07eca3410e7a2401283462f66a0ebf1f91682a80ae61168b2260f4368f93e197a9db65f4139523ef5449a6fa77568a9ffe90e0a34a37f99b7c1ec6ed1683a574d9045993679ef73299991cd43b96fdba6673ae4318f2f635a816f8559d325f9ebe428a01",
n="ba1d10a245e60471e8d3138611615170f213cae5b895c8af35eb720e2671915f07dd6ccb5384d7580200d18f430c89405dcb0be6a5e91cff0fda970e292d5f0704720473bc61e19590539b1bb08ce2b306755db1f70cf1193933802ca44281fe01699f75e56fb7660fce0342ccc284d497a17ad7d3d15eaa20ad4c67bd92de61",
e="010001"),
SlaKey(vendor="Alcatel",
da_codes=[],
name="MTK_HIGHWAY",
d="5407571c851f5b877a2255c6887c5d832369698b481c81db8ac07062dfabc7229d4b00f95956665743f7deeedbf54a17c9a404c97433f46d983bd0c5f49fa4b013b9d86e5f1377f563d8299675c0ea2b81f51c33ad74a265184df9389eefb8e72d2f0585e4a41826b8846b0ee6da5ef8cce471536109fe4c658735247ebbc301",
n="beca753fd31ef104bbb01b0a7c560c7bc040d30ea18f216b64b7de416b695af2b3350ecc02fa5224b412793f876a7bdbd8cbe7fecd754aa8214a27bfe7ececd8caa16959df83bdaeed524880a820f8dfe601dc70f164ff1921baaa06efd8c584c22269a109d16287356fd30e7eb02a1365ca93fcb8088278f119a2c7298306a9",
e="010001"),
SlaKey(vendor="Motorola",
da_codes=[],
name="G13",
d="AEAC47CD11A5DD6C5EEEC43D8F2C536A2917CEF95AD02F5A7C978E88C35702B590F7A72A2AF28AEB9B5F5B2D8056D03F916595D189C9B6927AC0874980537178AACE8E1831DD654E0B72FF2F44670196A57A43C340355CAF828B331A5715AED4E06D5D18896BCF25B201A0DC9760B0B2EF1CFB4EAB6940D7F8E2EBD86DC1E678AA69F6B0BBF55C688BF72C2123CF42E367F789E2592CE281C7C4752E14F6FD00D54610977DEF753E3890F12F704688537E860D81142805750B805E7CAE3AACDE1CD7A272D227E9F8CCAADCB4D06489664627BAC46CAF5DA0F0740CEEDEBC7ED1C1D1EB1E37C6A8A9E6A0454F742B3248448B20C93D5FF6E5C789907A862C90A1",
n="DA61964924F441559A1F8B5264CEB01DACE8E417413BBA4657F4556811D07B85074FD6987F315A7492E003D03C57FC83D3B889F2D4F136D0989E515A08628A7B16A300217162DC35C340B1127046AA86649B763AF97F7C9871964483DE6695CDA2E8CCE82E1F6A0F701AF8BE767BB16927489524F8FC9A2C280F5692E850E4C4E2606436CF2E253147AFAB32E6B92A19FA180C43CF480619B71B3D6A7863C7CC376C0A36BCF8BA3DA89CBF3E6DAA4691DCD769C0AE4535E502A9966AFF3F123C7A0EDA2DF04593B0E1FC60DC688F2BA7617DFE67D31854443ED95D2645323728C594CA49DAA9351A572E3182D0A1B3146C92CEF87380CBD2DEFFEBC4E8F420D3",
e="010001"),
]

12
mtkclient/Library/Connection/devicehandler.py Normal file → Executable file
View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023
# (c) B.Kerler 2018-2024
import inspect
import traceback
import logging
@ -45,7 +45,7 @@ class DeviceClass(metaclass=LogBase):
def get_write_packetsize(self):
raise NotImplementedError()
def connect(self, EP_IN=-1, EP_OUT=-1):
def connect(self, ep_in=-1, ep_out=-1):
raise NotImplementedError()
def setportname(self, portname: str):
@ -63,16 +63,16 @@ class DeviceClass(metaclass=LogBase):
def detectdevices(self):
raise NotImplementedError()
def getInterfaceCount(self):
def get_interface_count(self):
raise NotImplementedError()
def setLineCoding(self, baudrate=None, parity=0, databits=8, stopbits=1):
def set_line_coding(self, baudrate=None, parity=0, databits=8, stopbits=1):
raise NotImplementedError()
def setbreak(self):
raise NotImplementedError()
def setcontrollinestate(self, RTS=None, DTR=None, isFTDI=False):
def setcontrollinestate(self, rts=None, dtr=None, is_ftdi=False):
raise NotImplementedError()
def write(self, command, pktsize=None):
@ -87,7 +87,7 @@ class DeviceClass(metaclass=LogBase):
def usbxmlread(self, maxtimeout=100):
raise NotImplementedError()
def ctrl_transfer(self, bmRequestType, bRequest, wValue, wIndex, data_or_wLength):
def ctrl_transfer(self, bm_request_type, b_request, w_value, w_index, data_or_w_length):
raise NotImplementedError()
def usbreadwrite(self, data, resplen):

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2022
# (c) B.Kerler 2018-2024
import time
import sys
import logging
@ -22,21 +22,20 @@ def _reset_input_buffer_org(self):
return termios.tcflush(self.fd, termios.TCIFLUSH)
class serial_class(DeviceClass):
class SerialClass(DeviceClass):
def __init__(self, loglevel=logging.INFO, portconfig=None, devclass=-1):
super().__init__(loglevel, portconfig, devclass)
self.is_serial = True
self.device = None
def connect(self, EP_IN=-1, EP_OUT=-1):
def connect(self, ep_in=-1, ep_out=-1):
if self.connected:
self.close()
self.connected = False
ports = self.detectdevices()
if ports:
port = None
if self.portname != "DETECT":
if self.portname not in ports:
self.debug("{} not in detected ports: {}".format(self.portname, ports))
@ -71,7 +70,7 @@ class serial_class(DeviceClass):
def set_fast_mode(self, enabled):
pass
def changeBaud(self):
def change_baud(self):
print("Changing Baudrate")
self.write(b'\xD2' + b'\x02' + b'\x01')
self.read(1)
@ -102,7 +101,7 @@ class serial_class(DeviceClass):
ids.append(port.device)
return sorted(ids)
def setLineCoding(self, baudrate=None, parity=0, databits=8, stopbits=1):
def set_line_coding(self, baudrate=None, parity=0, databits=8, stopbits=1):
self.device.baudrate = baudrate
self.device.parity = parity
self.device.stopbbits = stopbits
@ -113,11 +112,11 @@ class serial_class(DeviceClass):
self.device.send_break()
self.debug("Break set")
def setcontrollinestate(self, RTS=None, DTR=None, isFTDI=False):
if RTS == 1:
self.device.setRTS(RTS)
if DTR == 1:
self.device.setDTR(DTR)
def setcontrollinestate(self, rts=None, dtr=None, is_ftdi=False):
if rts == 1:
self.device.setRTS(rts)
if dtr == 1:
self.device.setDTR(dtr)
self.debug("Linecoding set")
def write(self, command, pktsize=None):
@ -130,7 +129,7 @@ class serial_class(DeviceClass):
try:
self.device.write(b'')
except Exception as err:
error = str(err.strerror)
error = str(err)
if "timeout" in error:
# time.sleep(0.01)
try:
@ -180,7 +179,7 @@ class serial_class(DeviceClass):
length = self.device.in_waiting
return self.usbread(resplen=length, maxtimeout=timeout)
def getDevice(self):
def get_device(self):
return self.device
def get_read_packetsize(self):
@ -190,7 +189,7 @@ class serial_class(DeviceClass):
return 0x200
def flush(self):
if self.getDevice() is not None:
if self.get_device() is not None:
self.device.flushOutput()
return self.device.flush()

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import os
import sys
@ -44,7 +44,7 @@ USB_RECIP_RPIPE = 0x05
tag = 0
class CDC_CMDS:
class CdcCmds:
SEND_ENCAPSULATED_COMMAND = 0x00
GET_ENCAPSULATED_RESPONSE = 0x01
SET_COMM_FEATURE = 0x02
@ -93,12 +93,11 @@ class CDC_CMDS:
SET_CRC_MODE = 0x8A
class usb_class(DeviceClass):
class UsbClass(DeviceClass):
@staticmethod
def load_windows_dll():
if os.name == 'nt':
windows_dir = None
try:
# add pygame folder to Windows DLL search paths
windows_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "..", "Windows")
@ -177,7 +176,7 @@ class usb_class(DeviceClass):
self.debug(pre + hexlify(data).decode('utf-8'))
return data
def getInterfaceCount(self):
def get_interface_count(self):
if self.vid is not None:
self.device = usb.core.find(idVendor=self.vid, idProduct=self.pid, backend=self.backend)
if self.device is None:
@ -195,7 +194,7 @@ class usb_class(DeviceClass):
self.__logger.error("No device detected. Is it connected ?")
return 0
def setLineCoding(self, baudrate=None, parity=0, databits=8, stopbits=1):
def set_line_coding(self, baudrate=None, parity=0, databits=8, stopbits=1):
sbits = {1: 0, 1.5: 1, 2: 2}
dbits = {5, 6, 7, 8, 16}
pmodes = {0, 1, 2, 3, 4}
@ -250,8 +249,8 @@ class usb_class(DeviceClass):
req_type = (txdir << 7) + (req_type << 5) + recipient
data = bytearray(linecode)
wlen = self.device.ctrl_transfer(
req_type, CDC_CMDS.SET_LINE_CODING,
data_or_wLength=data, wIndex=1)
req_type, CdcCmds.SET_LINE_CODING,
data_or_w_length=data, w_index=1)
self.debug(f"Linecoding set, {wlen}b sent")
def setbreak(self):
@ -260,34 +259,34 @@ class usb_class(DeviceClass):
recipient = 1 # 0:device, 1:interface, 2:endpoint, 3:other
req_type = (txdir << 7) + (req_type << 5) + recipient
wlen = self.device.ctrl_transfer(
bmRequestType=req_type, bRequest=CDC_CMDS.SEND_BREAK,
wValue=0, data_or_wLength=0, wIndex=1)
bm_request_type=req_type, b_request=CdcCmds.SEND_BREAK,
w_value=0, data_or_w_length=0, w_index=1)
self.debug(f"Break set, {wlen}b sent")
def setcontrollinestate(self, RTS=None, DTR=None, isFTDI=False):
cmds = CDC_CMDS()
ctrlstate = (2 if RTS else 0) + (1 if DTR else 0)
if isFTDI:
ctrlstate += (1 << 8) if DTR is not None else 0
ctrlstate += (2 << 8) if RTS is not None else 0
def setcontrollinestate(self, rts=None, dtr=None, is_ftdi=False):
cmds = CdcCmds()
ctrlstate = (2 if rts else 0) + (1 if dtr else 0)
if is_ftdi:
ctrlstate += (1 << 8) if dtr is not None else 0
ctrlstate += (2 << 8) if rts is not None else 0
txdir = 0 # 0:OUT, 1:IN
req_type = 2 if isFTDI else 1 # 0:std, 1:class, 2:vendor
req_type = 2 if is_ftdi else 1 # 0:std, 1:class, 2:vendor
# 0:device, 1:interface, 2:endpoint, 3:other
recipient = 0 if isFTDI else 1
recipient = 0 if is_ftdi else 1
req_type = (txdir << 7) + (req_type << 5) + recipient
wlen = self.device.ctrl_transfer(
bmRequestType=req_type,
bRequest=1 if isFTDI else cmds.SET_CONTROL_LINE_STATE,
wValue=ctrlstate,
wIndex=1,
data_or_wLength=0)
bm_request_type=req_type,
b_request=1 if is_ftdi else cmds.SET_CONTROL_LINE_STATE,
w_value=ctrlstate,
w_index=1,
data_or_w_length=0)
self.debug(f"Linecoding set, {wlen}b sent")
def flush(self):
return
def connect(self, EP_IN=-1, EP_OUT=-1):
def connect(self, ep_in=-1, ep_out=-1):
if self.connected:
self.close()
self.connected = False
@ -365,19 +364,19 @@ class usb_class(DeviceClass):
except Exception:
return False
self.EP_OUT = EP_OUT
self.EP_IN = EP_IN
if EP_OUT == -1:
self.EP_OUT = ep_out
self.EP_IN = ep_in
if ep_out == -1:
self.EP_OUT = usb.util.find_descriptor(itf,
# match the first OUT endpoint
custom_match=lambda e:
usb.util.endpoint_direction(e.bEndpointAddress) ==
custom_match=lambda xe:
usb.util.endpoint_direction(xe.bEndpointAddress) ==
usb.util.ENDPOINT_OUT)
if EP_IN == -1:
if ep_in == -1:
self.EP_IN = usb.util.find_descriptor(itf,
# match the first OUT endpoint
custom_match=lambda e: \
usb.util.endpoint_direction(e.bEndpointAddress) ==
custom_match=lambda xe: \
usb.util.endpoint_direction(xe.bEndpointAddress) ==
usb.util.ENDPOINT_IN)
self.connected = True
return True
@ -466,10 +465,10 @@ class usb_class(DeviceClass):
timeout = 0
loglevel = self.loglevel
epr = self.EP_IN.read
wMaxPacketSize = self.EP_IN.wMaxPacketSize
w_max_packet_size = self.EP_IN.wMaxPacketSize
extend = res.extend
buffer = None
buflen = min(resplen, wMaxPacketSize)
buflen = min(resplen, w_max_packet_size)
if self.fast:
buffer = self.buffer[:buflen]
while len(res) < resplen:
@ -505,18 +504,18 @@ class usb_class(DeviceClass):
timeout = 0
loglevel = self.loglevel
epr = self.EP_IN.read
wMaxPacketSize = self.EP_IN.wMaxPacketSize
w_max_packet_size = self.EP_IN.wMaxPacketSize
extend = res.extend
buffer = None
if self.fast:
buffer = self.buffer[:wMaxPacketSize]
buffer = self.buffer[:w_max_packet_size]
while len(res) < max_xml_data_length:
try:
if self.fast:
rlen = epr(buffer, timeout)
extend(buffer[:rlen])
else:
extend(epr(wMaxPacketSize))
extend(epr(w_max_packet_size))
except usb.core.USBError as e:
error = str(e.strerror)
if "timed out" in error:
@ -540,12 +539,13 @@ class usb_class(DeviceClass):
self.verify_data(res, "RX:")
return res
def ctrl_transfer(self, bmRequestType, bRequest, wValue, wIndex, data_or_wLength):
ret = self.device.ctrl_transfer(bmRequestType=bmRequestType, bRequest=bRequest, wValue=wValue, wIndex=wIndex,
data_or_wLength=data_or_wLength)
def ctrl_transfer(self, bm_request_type, b_request, w_value, w_index, data_or_w_length):
ret = self.device.ctrl_transfer(bm_request_type=bm_request_type, b_request=b_request,
w_value=w_value, w_index=w_index,
data_or_w_length=data_or_w_length)
return ret[0] | (ret[1] << 8)
class deviceclass:
class DeviceClass:
vid = 0
pid = 0
@ -555,7 +555,7 @@ class usb_class(DeviceClass):
def detectdevices(self):
dev = usb.core.find(find_all=True, backend=self.backend)
ids = [self.deviceclass(cfg.idVendor, cfg.idProduct) for cfg in dev]
ids = [self.DeviceClass(cfg.idVendor, cfg.idProduct) for cfg in dev]
return ids
def usbwrite(self, data, pktsize=None):
@ -572,7 +572,7 @@ class usb_class(DeviceClass):
return res
class scsi_cmds(Enum):
class ScsiCmds(Enum):
SC_TEST_UNIT_READY = 0x00,
SC_REQUEST_SENSE = 0x03,
SC_FORMAT_UNIT = 0x04,
@ -659,7 +659,7 @@ class Scsi:
self.loglevel = loglevel
def connect(self):
self.usb = usb_class(loglevel=self.loglevel, portconfig=[self.vid, self.pid, self.interface], devclass=8)
self.usb = UsbClass(loglevel=self.loglevel, portconfig=[self.vid, self.pid, self.interface], devclass=8)
if self.usb.connect():
self.usb.connected = True
return True

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023
# (c) B.Kerler 2018-2024
import argparse
from mtkclient.Library.Connection.usblib import Scsi

View file

@ -1,13 +1,13 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import os
from struct import unpack
from mtkclient.Library.utils import LogBase, logsetup
from mtkclient.config.payloads import pathconfig
from mtkclient.config.brom_config import damodes
from mtkclient.Library.utils import structhelper
from mtkclient.config.payloads import PathConfig
from mtkclient.config.brom_config import DAmodes
from mtkclient.Library.utils import Structhelper
class Storage:
@ -33,7 +33,7 @@ class DaStorage:
MTK_DA_STORAGE_NOR_PARALLEL = 0x22
class EMMC_PartitionType:
class EmmcPartitionType:
MTK_DA_EMMC_PART_BOOT1 = 1
MTK_DA_EMMC_PART_BOOT2 = 2
MTK_DA_EMMC_PART_RPMB = 3
@ -46,7 +46,7 @@ class EMMC_PartitionType:
MTK_DA_EMMC_BOOT1_BOOT2 = 10
class UFS_PartitionType:
class UFSPartitionType:
UFS_LU0 = 0
UFS_LU1 = 1
UFS_LU2 = 2
@ -75,7 +75,7 @@ class NandCellUsage:
CELL_OCT = 7
class entry_region:
class EntryRegion:
m_buf = None
m_len = None
m_start_addr = None
@ -83,7 +83,7 @@ class entry_region:
m_sig_len = None
def __init__(self, data):
sh = structhelper(data)
sh = Structhelper(data)
self.m_buf = sh.dword()
self.m_len = sh.dword()
self.m_start_addr = sh.dword()
@ -98,7 +98,7 @@ class entry_region:
class DA:
def __init__(self, data):
self.loader = None
sh = structhelper(data)
sh = Structhelper(data)
self.magic = sh.short()
self.hw_code = sh.short()
self.hw_sub_code = sh.short()
@ -111,7 +111,7 @@ class DA:
self.entry_region_count = sh.short()
self.region = []
for _ in range(self.entry_region_count):
entry_tmp = entry_region(sh.bytes(20))
entry_tmp = EntryRegion(sh.bytes(20))
self.region.append(entry_tmp)
def setfilename(self, loaderfilename: str):
@ -125,9 +125,12 @@ class DA:
class DAconfig(metaclass=LogBase):
def __init__(self, mtk, loader=None, preloader=None, loglevel=logging.INFO):
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.emi = None
self.emiver = 0
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.mtk = mtk
self.pathconfig = pathconfig()
self.pathconfig = PathConfig()
self.config = self.mtk.config
self.usbwrite = self.mtk.port.usbwrite
self.usbread = self.mtk.port.usbread
@ -182,7 +185,7 @@ class DAconfig(metaclass=LogBase):
idx = data.find(bldrstring)
if idx == -1:
return None
elif idx == 0 and self.config.chipconfig.damode == damodes.XFLASH:
elif idx == 0 and self.config.chipconfig.damode == DAmodes.XFLASH:
ver = int(data[idx + len_bldrstring:idx + len_bldrstring + 2].rstrip(b"\x00"))
return ver, data
else:
@ -262,10 +265,9 @@ class DAconfig(metaclass=LogBase):
if __name__ == "__main__":
from mtkclient.Library.mtk_class import Mtk
from mtkclient.Library.mtk_main import Mtk_Config
from mtkclient.config.mtk_config import MtkConfig
config = Mtk_Config(loglevel=logging.INFO, gui=None,
guiprogress=None)
config = MtkConfig(loglevel=logging.INFO, gui=None, guiprogress=None)
mtkg = Mtk(config=config)
dac = DAconfig(mtk=mtkg)
dac.extract_emi("/home/bjk/Projects/mtkclient_github/preloader_meizu6795_lwt_l1.bin")

View file

@ -1,18 +1,18 @@
from binascii import hexlify
from mtkclient.Library.utils import structhelper
from mtkclient.config.mtk_config import Mtk_Config
from mtkclient.Library.utils import Structhelper
from mtkclient.config.mtk_config import MtkConfig
from struct import pack
class sdcinfo:
class SdcInfo:
m_sdmmc_info = None
m_sdmmc_ua_size = None
m_sdmmc_cid = None
def __init__(self, config: Mtk_Config, data=None):
def __init__(self, config: MtkConfig, data=None):
if data is None:
return
sh = structhelper(data)
sh = Structhelper(data)
self.config = config
self.m_sdmmc_info = sh.dword(True)
self.m_sdmmc_ua_size = sh.qword(True)
@ -27,7 +27,7 @@ class sdcinfo:
print(f"m_sdmmc_cid = {hexlify(cid).decode('utf-8')}")
class configinfo:
class ConfigInfo:
m_int_sram_ret = None
m_int_sram_size = None
m_ext_ram_ret = None
@ -37,7 +37,7 @@ class configinfo:
randomid = None
def __init__(self, data):
sh = structhelper(data)
sh = Structhelper(data)
self.m_int_sram_ret = sh.dword(True)
self.m_int_sram_size = sh.dword(True)
self.m_ext_ram_ret = sh.dword(True)
@ -58,7 +58,7 @@ class configinfo:
return res
class nandinfo64:
class NandInfo64:
m_nand_info = None
m_nand_chip_select = None
m_nand_flash_id = None
@ -69,7 +69,7 @@ class nandinfo64:
def __init__(self, data=None):
if data is None:
return
sh = structhelper(data)
sh = Structhelper(data)
self.m_nand_info = sh.dword(True)
self.m_nand_chip_select = sh.bytes()
self.m_nand_flash_id = sh.short(True)
@ -88,7 +88,7 @@ class nandinfo64:
# ('m_nand_flash_dev_code', '>7H'),
class nandinfo2:
class NandInfo2:
m_nand_pagesize = None
m_nand_sparesize = None
m_nand_pages_per_block = None
@ -99,7 +99,7 @@ class nandinfo2:
def __init__(self, data=None):
if data is None:
return
sh = structhelper(data)
sh = Structhelper(data)
self.m_nand_pagesize = sh.short(True)
self.m_nand_sparesize = sh.short(True)
self.m_nand_pages_per_block = sh.short(True)
@ -117,7 +117,7 @@ class nandinfo2:
return res
class emmcinfo:
class EmmcInfo:
m_emmc_ret = None
m_emmc_boot1_size = None
m_emmc_boot2_size = None
@ -127,10 +127,10 @@ class emmcinfo:
m_emmc_cid = None
m_emmc_fwver = None
def __init__(self, config: Mtk_Config, data=None):
def __init__(self, config: MtkConfig, data=None):
if data is None:
return
sh = structhelper(data)
sh = Structhelper(data)
self.config = config
self.m_emmc_ret = sh.dword(True)
self.m_emmc_boot1_size = sh.qword(True)
@ -159,7 +159,7 @@ class emmcinfo:
return res
class nandinfo32:
class NandInfo32:
m_nand_info = None
m_nand_chip_select = None
m_nand_flash_id = None
@ -170,7 +170,7 @@ class nandinfo32:
def __init__(self, data=None):
if data is None:
return
sh = structhelper(data)
sh = Structhelper(data)
self.m_nand_info = sh.dword(True)
self.m_nand_chip_select = sh.bytes()
self.m_nand_flash_id = sh.short(True)
@ -187,7 +187,7 @@ class nandinfo32:
return res
class norinfo:
class NorInfo:
m_nor_ret = None
m_nor_chip_select = None
m_nor_flash_id = None
@ -200,7 +200,7 @@ class norinfo:
def __init__(self, data=None):
if data is None:
return
sh = structhelper(data)
sh = Structhelper(data)
self.m_nor_ret = sh.dword(True)
self.m_nor_chip_select = sh.bytes(2)
self.m_nor_flash_id = sh.short(True)

View file

@ -1,10 +1,10 @@
from binascii import hexlify
from mtkclient.Library.utils import structhelper
from mtkclient.config.mtk_config import Mtk_Config
from mtkclient.Library.utils import Structhelper
from mtkclient.config.mtk_config import MtkConfig
from struct import pack
class configinfo_iot:
class ConfigInfoIoT:
m_int_sram_ret = None
m_int_sram_size = None
m_ext_ram_ret = None
@ -13,7 +13,7 @@ class configinfo_iot:
m_ext_ram_size = None
def __init__(self, data):
sh = structhelper(data)
sh = Structhelper(data)
self.m_int_sram_ret = sh.dword(True)
self.m_int_sram_size = sh.dword(True)
self.m_ext_ram_ret = sh.dword(True)
@ -34,7 +34,7 @@ class configinfo_iot:
return res
class emmcinfo_iot:
class EmmcInfoIoT:
m_emmc_ret = None
m_emmc_boot1_size = None
m_emmc_boot2_size = None
@ -44,10 +44,10 @@ class emmcinfo_iot:
m_emmc_cid = None
m_emmc_fwver = None
def __init__(self, config: Mtk_Config, data=None):
def __init__(self, config: MtkConfig, data=None):
if data is None:
return
sh = structhelper(data)
sh = Structhelper(data)
self.config = config
self.m_emmc_ret = sh.dword(True)
self.m_emmc_manufacturer_id = sh.bytes()
@ -75,7 +75,7 @@ class emmcinfo_iot:
return res
class nandinfo_iot:
class NandInfoIoT:
m_nand_info = None
m_nand_chip_select = None
m_nand_flash_id = None
@ -86,7 +86,7 @@ class nandinfo_iot:
def __init__(self, data=None):
if data is None:
return
sh = structhelper(data)
sh = Structhelper(data)
self.m_nand_info = sh.dword(True)
self.m_nand_chip_select = sh.bytes()
self.m_nand_flash_id = sh.short(True)
@ -120,7 +120,7 @@ class nandinfo_iot:
return res
class norinfo_iot:
class NorInfoIoT:
m_nor_ret = None
m_nor_chip_select = None
m_nor_flash_id = None
@ -132,7 +132,7 @@ class norinfo_iot:
def __init__(self, data=None):
if data is None:
return
sh = structhelper(data)
sh = Structhelper(data)
self.m_nor_ret = sh.dword(True)
self.m_nor_chip_select = sh.bytes(2)
self.m_nor_flash_id = sh.short(True)

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import os
import sys
@ -8,17 +8,17 @@ import time
from struct import pack, unpack
from binascii import hexlify
from mtkclient.Library.DA.legacy.dalegacy_flash_param import nandinfo64, norinfo, nandinfo32, emmcinfo, nandinfo2, \
sdcinfo, \
configinfo
from mtkclient.Library.DA.legacy.dalegacy_iot_flash_param import norinfo_iot, nandinfo_iot, emmcinfo_iot, configinfo_iot
from mtkclient.Library.DA.legacy.dalegacy_flash_param import NandInfo64, NorInfo, NandInfo32, EmmcInfo, NandInfo2, \
SdcInfo, \
ConfigInfo
from mtkclient.Library.DA.legacy.dalegacy_iot_flash_param import NorInfoIoT, NandInfoIoT, EmmcInfoIoT, ConfigInfoIoT
from mtkclient.Library.DA.legacy.dalegacy_param import PortValues, Rsp, Cmd
from mtkclient.Library.utils import LogBase, logsetup, structhelper
from mtkclient.Library.utils import LogBase, logsetup, Structhelper
from mtkclient.Library.error import ErrorHandler
from mtkclient.Library.DA.daconfig import DaStorage, EMMC_PartitionType
from mtkclient.Library.DA.daconfig import DaStorage, EmmcPartitionType
from mtkclient.Library.partition import Partition
from mtkclient.config.payloads import pathconfig
from mtkclient.Library.DA.legacy.extension.legacy import legacyext
from mtkclient.config.payloads import PathConfig
from mtkclient.Library.DA.legacy.extension.legacy import LegacyExt
from mtkclient.Library.thread_handling import writedata
from queue import Queue
from threading import Thread
@ -26,14 +26,14 @@ from threading import Thread
rq = Queue()
class passinfo:
class PassInfo:
ack = None
m_download_status = None
m_boot_style = None
soc_ok = None
def __init__(self, data):
sh = structhelper(data)
sh = Structhelper(data)
self.ack = sh.bytes()
self.m_download_status = sh.dword(True)
self.m_boot_style = sh.dword(True)
@ -47,7 +47,8 @@ def crc_word(data, chs=0):
class DALegacy(metaclass=LogBase):
def __init__(self, mtk, daconfig, loglevel=logging.INFO):
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.Cmd = Cmd()
self.Rsp = Rsp()
self.PortValues = PortValues()
@ -69,12 +70,12 @@ class DALegacy(metaclass=LogBase):
self.sectorsize = self.daconfig.pagesize
self.totalsectors = self.daconfig.flashsize
self.partition = Partition(self.mtk, self.readflash, self.read_pmt, loglevel)
self.pathconfig = pathconfig()
self.pathconfig = PathConfig()
self.patch = False
self.generatekeys = self.mtk.config.generatekeys
if self.generatekeys:
self.patch = True
self.lft = legacyext(self.mtk, self, loglevel)
self.lft = LegacyExt(self.mtk, self, loglevel)
def boot_to(self, addr, data, display=True, timeout=0.5):
pass
@ -341,7 +342,6 @@ class DALegacy(metaclass=LogBase):
return False
if ret == self.Rsp.ACK:
self.info(f"Sending dram info ... EMI-Version {hex(self.daconfig.emiver)}")
dramlength = len(self.daconfig.emi)
if self.daconfig.emiver in [0xF, 0x10, 0x11, 0x14, 0x15]:
dramlength = unpack(">I", self.usbread(0x4))[0] # 0x000000BC
self.info(f"RAM-Length: {hex(dramlength)}")
@ -419,7 +419,7 @@ class DALegacy(metaclass=LogBase):
# except:
# pass
try:
self.mtk.port.cdc.setLineCoding(baudrate=921600, parity=0, databits=8, stopbits=1)
self.mtk.port.cdc.set_line_coding(baudrate=921600, parity=0, databits=8, stopbits=1)
except Exception as err:
print(err)
pass
@ -469,10 +469,10 @@ class DALegacy(metaclass=LogBase):
return True
def read_flash_info_iot(self):
self.nor = norinfo_iot(self.usbread(0x36))
self.nand = nandinfo_iot(self.usbread(0x23))
self.emmc = emmcinfo_iot(self.config, self.usbread(0x2C))
self.flashconfig = configinfo_iot(self.usbread(0x1E))
self.nor = NorInfoIoT(self.usbread(0x36))
self.nand = NandInfoIoT(self.usbread(0x23))
self.emmc = EmmcInfoIoT(self.config, self.usbread(0x2C))
self.flashconfig = ConfigInfoIoT(self.usbread(0x1E))
# ack
self.usbread(1)
# ack
@ -505,23 +505,23 @@ class DALegacy(metaclass=LogBase):
return False
def read_flash_info(self):
self.nor = norinfo(self.usbread(0x1C))
self.nor = NorInfo(self.usbread(0x1C))
data = self.usbread(0x11)
self.nand = nandinfo64(data)
self.nand = NandInfo64(data)
nandcount = self.nand.m_nand_flash_id_count
if nandcount == 0:
self.nand = nandinfo32(data)
self.nand = NandInfo32(data)
nandcount = self.nand.m_nand_flash_id_count
nc = data[-4:] + self.usbread(nandcount * 2 - 4)
else:
nc = self.usbread(nandcount * 2)
m_nand_dev_code = unpack(">" + str(nandcount) + "H", nc)
self.nand.m_nand_flash_dev_code = m_nand_dev_code
self.nand.info2 = nandinfo2(self.usbread(9))
self.emmc = emmcinfo(self.config, self.usbread(0x5C))
self.sdc = sdcinfo(self.config, self.usbread(0x1C))
self.flashconfig = configinfo(self.usbread(0x26))
pi = passinfo(self.usbread(0xA))
self.nand.info2 = NandInfo2(self.usbread(9))
self.emmc = EmmcInfo(self.config, self.usbread(0x5C))
self.sdc = SdcInfo(self.config, self.usbread(0x1C))
self.flashconfig = ConfigInfo(self.usbread(0x26))
pi = PassInfo(self.usbread(0xA))
if pi.ack == 0x5A:
return True
elif pi.m_download_status & 0xFF == 0x5A:
@ -788,7 +788,8 @@ class DALegacy(metaclass=LogBase):
buffer = self.usbread(1)
if buffer != self.Rsp.ACK:
self.error(
f"Error on sending brom stage {stage} addr {hex(address+pos)}: {hexlify(buffer).decode('utf-8')}")
f"Error on sending brom stage {stage} addr {hex(address+pos)}: " +
f"{hexlify(buffer).decode('utf-8')}")
self.config.set_gui_status(self.config.tr("Error on sending brom stage"))
break
time.sleep(0.5)
@ -991,39 +992,39 @@ class DALegacy(metaclass=LogBase):
if self.daconfig.flashtype == "emmc":
if parttype is None or parttype == "user" or parttype == "":
length = min(length, self.emmc.m_emmc_ua_size)
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_USER
elif parttype == "boot1":
length = min(length, self.emmc.m_emmc_boot1_size)
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_BOOT1
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_BOOT1
elif parttype == "boot2":
length = min(length, self.emmc.m_emmc_boot2_size)
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_BOOT2
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_BOOT2
elif parttype == "gp1":
length = min(length, self.emmc.m_emmc_gp_size[0])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP1
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_GP1
elif parttype == "gp2":
length = min(length, self.emmc.m_emmc_gp_size[1])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP2
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_GP2
elif parttype == "gp3":
length = min(length, self.emmc.m_emmc_gp_size[2])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP3
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_GP3
elif parttype == "gp4":
length = min(length, self.emmc.m_emmc_gp_size[3])
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP4
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_GP4
elif parttype == "rpmb":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_RPMB
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_RPMB
elif self.daconfig.flashtype == "nand":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_USER
length = min(length, self.nand.m_nand_flash_size)
elif self.daconfig.flashtype == "nor":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_USER
length = min(length, self.nor.m_nor_flash_size)
else:
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_USER
length = min(length, self.sdc.m_sdmmc_ua_size)
return length, parttype
def readflash(self, addr: int, length: int, filename: str, parttype=None, display=True) -> bytes:
def readflash(self, addr: int, length: int, filename: str, parttype=None, display=True) -> (bytes, bool):
global rq
self.mtk.daloader.progress.clear()
length, parttype = self.get_parttype(length, parttype)

View file

@ -2,13 +2,13 @@ import os
import sys
from struct import unpack, pack
from mtkclient.config.payloads import pathconfig
from mtkclient.config.payloads import PathConfig
from mtkclient.Library.error import ErrorHandler
from mtkclient.Library.Hardware.hwcrypto import crypto_setup, hwcrypto
from mtkclient.Library.Hardware.hwcrypto import CryptoSetup, HwCrypto
from mtkclient.Library.utils import LogBase, logsetup, find_binary
from mtkclient.Library.Hardware.seccfg import seccfgV4, seccfgV3
from mtkclient.Library.Hardware.seccfg import SecCfgV4, SecCfgV3
from binascii import hexlify
from mtkclient.Library.utils import mtktee
from mtkclient.Library.utils import MTKTee
import hashlib
import json
@ -20,10 +20,11 @@ class LCmd:
NACK = b"\xA5"
class legacyext(metaclass=LogBase):
class LegacyExt(metaclass=LogBase):
def __init__(self, mtk, legacy, loglevel):
self.pathconfig = pathconfig()
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.pathconfig = PathConfig()
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.mtk = mtk
self.loglevel = loglevel
self.__logger = self.__logger
@ -72,9 +73,10 @@ class legacyext(metaclass=LogBase):
POP.W {R4-R6,LR}
BX R3
"""
cmdF0 = bytes.fromhex(
"70 B5 4A F2 C8 64 C8 F2 04 04 63 6A 98 47 63 6A 05 46 98 47 06 46 4F F0 00 01 28 68 05 F1 04 05 A3 6A 98 47 A6 F1 01 06 00 2E F6 D1 5A 20 23 69 BD E8 70 40 18 47")
da2patched[check_addr2:check_addr2 + len(cmdF0)] = cmdF0
cmd_f0 = bytes.fromhex(
"70 B5 4A F2 C8 64 C8 F2 04 04 63 6A 98 47 63 6A 05 46 98 47 06 46 4F F0 00 01 28 68 05 F1 04 05 A3 " +
"6A 98 47 A6 F1 01 06 00 2E F6 D1 5A 20 23 69 BD E8 70 40 18 47")
da2patched[check_addr2:check_addr2 + len(cmd_f0)] = cmd_f0
self.info("Legacy DA2 CMD F0 is patched.")
else:
self.warning("Legacy DA2 CMD F0 not patched.")
@ -148,7 +150,7 @@ class legacyext(metaclass=LogBase):
hwc.sej.sej_set_otp(otp)
def cryptosetup(self):
setup = crypto_setup()
setup = CryptoSetup()
setup.blacklist = self.config.chipconfig.blacklist
setup.gcpu_base = self.config.chipconfig.gcpu_base
setup.dxcc_base = self.config.chipconfig.dxcc_base
@ -158,7 +160,7 @@ class legacyext(metaclass=LogBase):
setup.read32 = self.readmem
setup.write32 = self.writeregister
setup.writemem = self.writemem
return hwcrypto(setup, self.loglevel, self.config.gui)
return HwCrypto(setup, self.loglevel, self.config.gui)
def seccfg(self, lockflag):
if lockflag not in ["unlock", "lock"]:
@ -180,10 +182,10 @@ class legacyext(metaclass=LogBase):
hwc = self.cryptosetup()
if seccfg_data[:0xC] == b"AND_SECCFG_v":
self.info("Detected V3 Lockstate")
sc_org = seccfgV3(hwc, self.mtk)
sc_org = SecCfgV3(hwc, self.mtk)
elif seccfg_data[:4] == b"\x4D\x4D\x4D\x4D":
self.info("Detected V4 Lockstate")
sc_org = seccfgV4(hwc, self.mtk)
sc_org = SecCfgV4(hwc, self.mtk)
else:
return False, "Unknown lockstate or no lockstate"
if not sc_org.parse(seccfg_data):
@ -205,7 +207,7 @@ class legacyext(metaclass=LogBase):
while idx != -1:
idx = data.find(b"EET KTM ", idx + 1)
if idx != -1:
mt = mtktee()
mt = MTKTee()
mt.parse(data[idx:])
rdata = hwc.mtee(data=mt.data, keyseed=mt.keyseed, ivseed=mt.ivseed,
aeskey1=aeskey1, aeskey2=aeskey2)

View file

@ -5,17 +5,21 @@ import logging
from struct import pack, unpack
from binascii import hexlify
from mtkclient.Library.utils import LogBase, logsetup, getint
from mtkclient.config.payloads import pathconfig
from mtkclient.config.payloads import PathConfig
from mtkclient.Library.error import ErrorHandler
from mtkclient.Library.utils import progress
from mtkclient.config.brom_config import efuse, damodes
from mtkclient.Library.utils import Progress
from mtkclient.config.brom_config import Efuse, DAmodes
from mtkclient.Library.Filesystem.mtkdafs import MtkDaFS
from fuse import FUSE
try:
from fuse import FUSE
except ImportError:
FUSE = None
class DA_handler(metaclass=LogBase):
class DaHandler(metaclass=LogBase):
def __init__(self, mtk, loglevel=logging.INFO):
self.__logger = self.__logger
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.info = self.__logger.info
self.debug = self.__logger.debug
self.error = self.__logger.error
@ -25,8 +29,9 @@ class DA_handler(metaclass=LogBase):
self.vid = mtk.config.vid
self.pid = mtk.config.pid
self.interface = mtk.config.interface
self.pathconfig = pathconfig()
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.pathconfig = PathConfig()
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.eh = ErrorHandler()
self.mtk = mtk
@ -69,7 +74,8 @@ class DA_handler(metaclass=LogBase):
with open(filename, "wb") as wf:
wf.write(preloader)
print(f"Successfully extracted preloader for this device to: {filename}")
except Exception:
except Exception as err:
self.error(err)
pass
return preloader
except Exception as err:
@ -83,7 +89,7 @@ class DA_handler(metaclass=LogBase):
else:
if mtk.serialportname is not None:
mtk.preloader.init()
if mtk.port.cdc.connected and os.path.exists(os.path.join(mtk.config.hwparam_path,".state")):
if mtk.port.cdc.connected and os.path.exists(os.path.join(mtk.config.hwparam_path, ".state")):
mtk.daloader.reinit()
return mtk
if mtk.config.target_config is None:
@ -179,7 +185,7 @@ class DA_handler(metaclass=LogBase):
self.close()
if parttype == "user" or parttype is None:
i = 0
countDump = 0
count_dump = 0
self.info("Requesting available partitions ....")
gpttable = self.mtk.daloader.get_partition_data(parttype=parttype)
for partition in partitions:
@ -189,7 +195,7 @@ class DA_handler(metaclass=LogBase):
self.mtk.daloader.readflash(addr=0,
length=0x16000,
filename=partfilename, parttype=parttype)
countDump += 1
count_dump += 1
continue
else:
rpartition = None
@ -204,18 +210,18 @@ class DA_handler(metaclass=LogBase):
filename=partfilename, parttype=parttype):
self.info(f"Dumped sector {str(rpartition.sector)} with sector count " +
f"{str(rpartition.sectors)} as {partfilename}.")
countDump += 1
count_dump += 1
else:
self.info(f"Failed to dump sector {str(rpartition.sector)} with sector count " +
f"{str(rpartition.sectors)} as {partfilename}.")
countDump += 1
count_dump += 1
else:
self.error(f"Error: Couldn't detect partition: {partition}\nAvailable partitions:")
for rpartition in gpttable:
self.info(rpartition.name)
if countDump > 1 and countDump == len(filenames):
if count_dump > 1 and count_dump == len(filenames):
self.info("All partitions were dumped")
elif countDump > 1 and countDump != len(filenames):
elif count_dump > 1 and count_dump != len(filenames):
self.info("Failed to dump some partitions")
else:
i = 0
@ -249,7 +255,7 @@ class DA_handler(metaclass=LogBase):
with open(sfilename, "wb") as wf:
wf.write(data[self.config.pagesize * 2:])
countGPT = 0
count_gpt = 0
for partition in guid_gpt.partentries:
partitionname = partition.name
if partition.name in skip:
@ -264,14 +270,14 @@ class DA_handler(metaclass=LogBase):
filename=filename,
parttype=parttype):
countGPT += 1
count_gpt += 1
self.info(f"Dumped partition {str(partition.name)} as {str(filename)}.")
else:
countGPT -= 1
count_gpt -= 1
self.error(f"Failed to dump partition {str(partition.name)} as {str(filename)}.")
partitionsForRead = len(guid_gpt.partentries) - len(skip)
if countGPT == partitionsForRead:
partitions_for_read = len(guid_gpt.partentries) - len(skip)
if count_gpt == partitions_for_read:
self.info("All Dumped partitions success.")
else:
self.error("Failed to dump all partitions")
@ -448,7 +454,7 @@ class DA_handler(metaclass=LogBase):
parttype=parttype)
def da_erase(self, partitions: list, parttype: str):
countFP = 0
count_fp = 0
if parttype == "user" or parttype is None:
i = 0
for partition in partitions:
@ -462,19 +468,19 @@ class DA_handler(metaclass=LogBase):
print(
f"Formatted sector {str(rpartition.sector)} with " +
f"sector count {str(rpartition.sectors)}.")
countFP += 1
count_fp += 1
else:
print(
f"Failed to format sector {str(rpartition.sector)} with " +
f"sector count {str(rpartition.sectors)}.")
countFP -= 1
count_fp -= 1
else:
self.error(f"Error: Couldn't detect partition: {partition}\nAvailable partitions:")
for rpartition in res[1]:
self.info(rpartition.name)
if countFP == len(partitions) and countFP > 1:
if count_fp == len(partitions) and count_fp > 1:
print("All partitions formatted.")
elif countFP != len(partitions) and countFP > 1:
elif count_fp != len(partitions) and count_fp > 1:
print("Failed to format all partitions.")
def da_ess(self, sector: int, sectors: int, parttype: str):
@ -576,7 +582,7 @@ class DA_handler(metaclass=LogBase):
if self.mtk.config.chipconfig.efuse_addr is not None:
base = self.mtk.config.chipconfig.efuse_addr
hwcode = self.mtk.config.hwcode
efuseconfig = efuse(base, hwcode)
efuseconfig = Efuse(base, hwcode)
for idx in range(len(efuseconfig.efuses)):
addr = efuseconfig.efuses[idx]
if addr < 0x1000:
@ -592,9 +598,9 @@ class DA_handler(metaclass=LogBase):
bytestoread = length
pos = 0
pagesize = 0x200
if self.mtk.daloader.flashmode == damodes.XFLASH:
if self.mtk.daloader.flashmode == DAmodes.XFLASH:
pagesize = self.mtk.daloader.get_packet_length()
pg = progress(pagesize)
pg = Progress(pagesize)
bytesread = 0
wf = None
if filename is not None:
@ -612,7 +618,8 @@ class DA_handler(metaclass=LogBase):
pos += len(data)
bytesread += len(data)
bytestoread -= len(data)
except Exception:
except Exception as err:
self.error(err)
pass
pg.show_progress("Dump:", 100, 100)
if filename is not None:
@ -690,9 +697,10 @@ class DA_handler(metaclass=LogBase):
else:
print(f"Failed to dump offset {hex(start)} with length {hex(length)} as {filename}.")
elif cmd == "fs":
print(f'Mounting FUSE fs at: {args.mountpoint}...')
fs = FUSE(MtkDaFS(self, rw=args.rw), mountpoint=args.mountpoint, foreground=True, allow_other=True,
nothreads=True)
if FUSE is not None:
print(f'Mounting FUSE fs at: {args.mountpoint}...')
fs = FUSE(MtkDaFS(self, rw=args.rw), mountpoint=args.mountpoint, foreground=True, allow_other=True,
nothreads=True)
elif cmd == "footer":
filename = args.filename
self.da_footer(filename=filename)

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import json
import logging
import os
@ -8,23 +8,25 @@ import hashlib
from binascii import hexlify
from mtkclient.Library.DA.xml.xml_lib import DAXML
from mtkclient.Library.utils import LogBase, logsetup, progress
from mtkclient.Library.utils import LogBase, logsetup, Progress
from mtkclient.Library.error import ErrorHandler
from mtkclient.Library.DA.daconfig import DAconfig
from mtkclient.Library.DA.legacy.dalegacy_lib import DALegacy
from mtkclient.Library.DA.legacy.dalegacy_flash_param import norinfo, emmcinfo, sdcinfo, nandinfo64
from mtkclient.Library.DA.legacy.dalegacy_flash_param import NorInfo, EmmcInfo, SdcInfo, NandInfo64
from mtkclient.Library.DA.xflash.xflash_lib import DAXFlash
from mtkclient.config.brom_config import damodes
from mtkclient.Library.DA.xflash.extension.xflash import xflashext
from mtkclient.Library.DA.legacy.extension.legacy import legacyext
from mtkclient.Library.DA.xml.extension.v6 import xmlflashext
from mtkclient.Library.settings import hwparam
from mtkclient.config.brom_config import DAmodes
from mtkclient.Library.DA.xflash.extension.xflash import XFlashExt
from mtkclient.Library.DA.legacy.extension.legacy import LegacyExt
from mtkclient.Library.DA.xml.extension.v6 import XmlFlashExt
from mtkclient.Library.settings import HwParam
class DAloader(metaclass=LogBase):
def __init__(self, mtk, loglevel=logging.INFO):
self.xmlft = None
self.patch = False
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.mtk = mtk
self.config = mtk.config
self.loglevel = loglevel
@ -38,7 +40,7 @@ class DAloader(metaclass=LogBase):
self.rword = self.mtk.port.rword
self.daconfig = DAconfig(mtk=self.mtk, loader=self.mtk.config.loader,
preloader=self.mtk.config.preloader, loglevel=loglevel)
self.progress = progress(self.daconfig.pagesize, self.mtk.config.guiprogress)
self.progress = Progress(self.daconfig.pagesize, self.mtk.config.guiprogress)
self.xft = None
self.lft = None
self.da = None
@ -46,11 +48,11 @@ class DAloader(metaclass=LogBase):
def writestate(self):
config = {}
if self.mtk.config.chipconfig.damode == damodes.LEGACY:
if self.mtk.config.chipconfig.damode == DAmodes.LEGACY:
config["flashmode"] = "LEGACY"
elif self.mtk.config.chipconfig.damode == damodes.XFLASH:
elif self.mtk.config.chipconfig.damode == DAmodes.XFLASH:
config["flashmode"] = "XFLASH"
elif self.mtk.config.chipconfig.damode == damodes.XML:
elif self.mtk.config.chipconfig.damode == DAmodes.XML:
config["flashmode"] = "XML"
config["hwcode"] = self.config.hwcode
if self.config.meid is not None:
@ -59,7 +61,8 @@ class DAloader(metaclass=LogBase):
config["socid"] = hexlify(self.config.socid).decode('utf-8')
config["flashtype"] = self.daconfig.flashtype
config["flashsize"] = self.daconfig.flashsize
if not self.mtk.config.chipconfig.damode == damodes.XFLASH and not self.mtk.config.chipconfig.damode == damodes.XML:
if (not self.mtk.config.chipconfig.damode == DAmodes.XFLASH and not
self.mtk.config.chipconfig.damode == DAmodes.XML):
config["m_emmc_ua_size"] = self.da.emmc.m_emmc_ua_size
config["m_emmc_boot1_size"] = self.da.emmc.m_emmc_boot1_size
config["m_emmc_boot2_size"] = self.da.emmc.m_emmc_boot2_size
@ -79,10 +82,10 @@ class DAloader(metaclass=LogBase):
hashmode, idx = self.calc_da_hash(da1, da2[:hashlen])
if idx == -1 and not v6:
hashlen = len(da2) - da2sig_len
idx, hashmode = self.find_da_hash_V5(da1)
idx, hashmode = self.find_da_hash_v5(da1)
elif idx == -1 and v6:
hashlen = len(da2) - da2sig_len
idx, hashmode = self.find_da_hash_V6(da1, da1sig_len)
idx, hashmode = self.find_da_hash_v6(da1, da1sig_len)
if idx == -1:
self.error("Hash computation failed.")
return None, None, None
@ -90,14 +93,14 @@ class DAloader(metaclass=LogBase):
return idx, hashmode, hashlen
@staticmethod
def find_da_hash_V6(da1, siglen):
def find_da_hash_v6(da1, siglen):
pos = len(da1) - siglen - 0x30
hash = da1[pos:pos + 0x30]
if hash[-4:] == b"\x00\x00\x00\x00":
_hash = da1[pos:pos + 0x30]
if _hash[-4:] == b"\x00\x00\x00\x00":
return pos, 2
return -1, -1
def find_da_hash_V5(self, da1):
def find_da_hash_v5(self, da1):
idx1 = da1.find(b"MMU MAP: VA")
if idx1 != -1:
hashed = da1[idx1 - 0x30:idx1]
@ -143,42 +146,42 @@ class DAloader(metaclass=LogBase):
if "socid" in config:
self.config.socid = bytes.fromhex(config["socid"])
if config["flashmode"] == "LEGACY":
self.mtk.config.chipconfig.damode = damodes.LEGACY
self.flashmode = damodes.LEGACY
self.mtk.config.chipconfig.damode = DAmodes.LEGACY
self.flashmode = DAmodes.LEGACY
elif config["flashmode"] == "XFLASH":
self.mtk.config.chipconfig.damode = damodes.XFLASH
self.flashmode = damodes.XFLASH
self.mtk.config.chipconfig.damode = DAmodes.XFLASH
self.flashmode = DAmodes.XFLASH
elif config["flashmode"] == "XML":
self.mtk.config.chipconfig.damode = damodes.XML
self.flashmode = damodes.XML
self.mtk.config.chipconfig.damode = DAmodes.XML
self.flashmode = DAmodes.XML
self.config.init_hwcode(self.config.hwcode)
if self.config.meid is not None:
self.config.hwparam = hwparam(self.mtk.config, self.config.meid.hex(), self.mtk.config.hwparam_path)
if self.flashmode == damodes.XML:
self.config.hwparam = HwParam(self.mtk.config, self.config.meid.hex(), self.mtk.config.hwparam_path)
if self.flashmode == DAmodes.XML:
self.da = DAXML(self.mtk, self.daconfig, self.loglevel)
self.daconfig.flashtype = config["flashtype"]
self.daconfig.flashsize = config["flashsize"]
self.da.reinit()
self.xmlft = xmlflashext(self.mtk, self.da, self.loglevel)
self.xmlft = XmlFlashExt(self.mtk, self.da, self.loglevel)
self.xft = None
self.lft = None
elif self.flashmode == damodes.XFLASH:
elif self.flashmode == DAmodes.XFLASH:
self.da = DAXFlash(self.mtk, self.daconfig, self.loglevel)
self.daconfig.flashtype = config["flashtype"]
self.daconfig.flashsize = config["flashsize"]
self.da.reinit()
self.xft = xflashext(self.mtk, self.da, self.loglevel)
self.xft = XFlashExt(self.mtk, self.da, self.loglevel)
self.lft = None
self.xmlft = None
elif self.flashmode == damodes.LEGACY:
elif self.flashmode == DAmodes.LEGACY:
self.da = DALegacy(self.mtk, self.daconfig, self.loglevel)
self.daconfig.flashtype = config["flashtype"]
self.daconfig.flashsize = config["flashsize"]
self.da.nor = norinfo()
self.da.nand = nandinfo64()
self.da.emmc = emmcinfo(self.config)
self.da.sdc = sdcinfo(self.config)
self.lft = legacyext(self.mtk, self.da, self.loglevel)
self.da.nor = NorInfo()
self.da.nand = NandInfo64()
self.da.emmc = EmmcInfo(self.config)
self.da.sdc = SdcInfo(self.config)
self.lft = LegacyExt(self.mtk, self.da, self.loglevel)
self.da.emmc.m_emmc_ua_size = config["m_emmc_ua_size"]
self.da.emmc.m_emmc_boot1_size = config["m_emmc_boot1_size"]
self.da.emmc.m_emmc_boot2_size = config["m_emmc_boot2_size"]
@ -193,40 +196,40 @@ class DAloader(metaclass=LogBase):
return False
def patch_da2(self, da2):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
return self.xft.patch_da2(da2)
elif self.flashmode == damodes.LEGACY:
elif self.flashmode == DAmodes.LEGACY:
return self.lft.patch_da2(da2)
elif self.flashmode == damodes.XML:
elif self.flashmode == DAmodes.XML:
return self.xmlft.patch_da2(da2)
return False
def set_da(self):
self.flashmode = damodes.LEGACY
self.flashmode = DAmodes.LEGACY
if self.mtk.config.plcap is not None:
PL_CAP0_XFLASH_SUPPORT = (0x1 << 0)
if (self.mtk.config.plcap[0] & PL_CAP0_XFLASH_SUPPORT == PL_CAP0_XFLASH_SUPPORT and
self.mtk.config.blver > 1):
self.flashmode = damodes.XFLASH
if self.mtk.config.chipconfig.damode == damodes.XFLASH:
self.flashmode = damodes.XFLASH
elif self.mtk.config.chipconfig.damode == damodes.XML or self.daconfig.da_loader.v6:
self.flashmode = damodes.XML
if self.flashmode == damodes.XFLASH:
self.flashmode = DAmodes.XFLASH
if self.mtk.config.chipconfig.damode == DAmodes.XFLASH:
self.flashmode = DAmodes.XFLASH
elif self.mtk.config.chipconfig.damode == DAmodes.XML or self.daconfig.da_loader.v6:
self.flashmode = DAmodes.XML
if self.flashmode == DAmodes.XFLASH:
self.da = DAXFlash(self.mtk, self.daconfig, self.loglevel)
self.da.patch = self.patch
self.xft = xflashext(self.mtk, self.da, self.loglevel)
elif self.flashmode == damodes.LEGACY:
self.xft = XFlashExt(self.mtk, self.da, self.loglevel)
elif self.flashmode == DAmodes.LEGACY:
self.da = DALegacy(self.mtk, self.daconfig, self.loglevel)
self.da.patch = self.patch
self.lft = legacyext(self.mtk, self.da, self.loglevel)
elif self.flashmode == damodes.XML:
self.lft = LegacyExt(self.mtk, self.da, self.loglevel)
elif self.flashmode == DAmodes.XML:
self.da = DAXML(self.mtk, self.daconfig, self.loglevel)
self.da.patch = self.patch
self.xmlft = xmlflashext(self.mtk, self.da, self.loglevel)
self.xmlft = XmlFlashExt(self.mtk, self.da, self.loglevel)
def setmetamode(self, porttype: str):
if self.mtk.config.chipconfig.damode == damodes.XFLASH:
if self.mtk.config.chipconfig.damode == DAmodes.XFLASH:
self.da = DAXFlash(self.mtk, self.daconfig, self.loglevel)
if porttype not in ["off", "usb", "uart"]:
self.error('Only "off","usb" or "uart" are allowed.')
@ -295,7 +298,7 @@ class DAloader(metaclass=LogBase):
return self.da.upload_da()
def boot_to(self, addr, data, display=True, timeout=0.5):
if self.da.boot_to(addr, data):
if self.da.boot_to(addr, data, display=display):
return True
return False
@ -304,44 +307,44 @@ class DAloader(metaclass=LogBase):
parttype=parttype, wdata=wdata, display=display)
def formatflash(self, addr, length, partitionname, parttype, display=True):
return self.da.formatflash(addr=addr, length=length, parttype=parttype)
return self.da.formatflash(addr=addr, length=length, parttype=parttype, display=display)
def readflash(self, addr, length, filename, parttype, display=True):
return self.da.readflash(addr=addr, length=length, filename=filename, parttype=parttype, display=display)
def get_packet_length(self):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
pt = self.da.get_packet_length()
return pt.read_packet_length
else:
return 512
def peek(self, addr: int, length: int):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
return self.xft.custom_read(addr=addr, length=length)
elif self.flashmode == damodes.LEGACY:
elif self.flashmode == DAmodes.LEGACY:
return self.lft.custom_read(addr=addr, length=length)
elif self.flashmode == damodes.XML:
elif self.flashmode == DAmodes.XML:
return self.xmlft.custom_read(addr=addr, length=length)
def peek_reg(self, addr: int, length: int):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
return self.xft.custom_read_reg(addr=addr, length=length)
elif self.flashmode == damodes.LEGACY:
elif self.flashmode == DAmodes.LEGACY:
return self.lft.custom_read_reg(addr=addr, length=length)
elif self.flashmode == damodes.XML:
elif self.flashmode == DAmodes.XML:
return self.xmlft.custom_read_reg(addr=addr, length=length)
def dump_brom(self, filename):
rm = None
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
rm = self.xft.readmem
elif self.flashmode == damodes.LEGACY:
elif self.flashmode == DAmodes.LEGACY:
rm = self.lft.readmem
elif self.flashmode == damodes.XML:
elif self.flashmode == DAmodes.XML:
rm = self.xmlft.readmem
pg = progress(4)
pg = Progress(4)
with open(filename, "wb") as wf:
length = 0x200000
bytesread = 0
@ -359,60 +362,60 @@ class DAloader(metaclass=LogBase):
return "GPT"
def poke(self, addr: int, data: bytes or bytearray):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
return self.xft.custom_write(addr=addr, data=data)
elif self.flashmode == damodes.LEGACY:
elif self.flashmode == DAmodes.LEGACY:
return self.lft.custom_write(addr=addr, data=data)
elif self.flashmode == damodes.XML:
elif self.flashmode == DAmodes.XML:
return self.xmlft.custom_write(addr=addr, data=data)
def keys(self):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
return self.xft.generate_keys()
elif self.flashmode == damodes.LEGACY:
elif self.flashmode == DAmodes.LEGACY:
return self.lft.generate_keys()
elif self.flashmode == damodes.XML:
elif self.flashmode == DAmodes.XML:
return self.xmlft.generate_keys()
def readfuses(self):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
pass
elif self.flashmode == damodes.LEGACY:
elif self.flashmode == DAmodes.LEGACY:
pass
elif self.flashmode == damodes.XML:
elif self.flashmode == DAmodes.XML:
return self.xmlft.readfuses()
def is_patched(self):
return self.da.patch
def seccfg(self, lockflag):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
return self.xft.seccfg(lockflag)
elif self.flashmode == damodes.LEGACY:
elif self.flashmode == DAmodes.LEGACY:
return self.lft.seccfg(lockflag)
elif self.flashmode == damodes.XML:
elif self.flashmode == DAmodes.XML:
return self.xmlft.seccfg(lockflag)
def read_rpmb(self, filename=None):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
return self.xft.read_rpmb(filename)
elif self.flashmode == damodes.XML:
elif self.flashmode == DAmodes.XML:
return self.xmlft.read_rpmb(filename)
self.error("Device is not in xflash/xml mode, cannot run read rpmb cmd.")
return False
def write_rpmb(self, filename=None):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
return self.xft.write_rpmb(filename)
elif self.flashmode == damodes.XML:
elif self.flashmode == DAmodes.XML:
return self.xmlft.write_rpmb(filename)
self.error("Device is not in xflash/xml mode, cannot run write rpmb cmd.")
return False
def erase_rpmb(self):
if self.flashmode == damodes.XFLASH:
if self.flashmode == DAmodes.XFLASH:
return self.xft.erase_rpmb()
if self.flashmode == damodes.XML:
if self.flashmode == DAmodes.XML:
return self.xmlft.erase_rpmb()
self.error("Device is not in xflash/xml mode, cannot run erase rpmb cmd.")
return False

View file

@ -1,13 +1,13 @@
import os
from struct import unpack, pack
from mtkclient.config.payloads import pathconfig
from mtkclient.config.brom_config import efuse
from mtkclient.config.payloads import PathConfig
from mtkclient.config.brom_config import Efuse
from mtkclient.Library.error import ErrorHandler, ErrorCodes_XFlash
from mtkclient.Library.Hardware.hwcrypto import crypto_setup, hwcrypto
from mtkclient.Library.utils import LogBase, progress, logsetup, find_binary
from mtkclient.Library.Hardware.seccfg import seccfgV3, seccfgV4
from mtkclient.Library.utils import mtktee
from mtkclient.Library.Hardware.hwcrypto import CryptoSetup, HwCrypto
from mtkclient.Library.utils import LogBase, Progress, logsetup, find_binary
from mtkclient.Library.Hardware.seccfg import SecCfgV3, SecCfgV4
from mtkclient.Library.utils import MTKTee
import json
@ -38,10 +38,12 @@ rpmb_error = [
]
class xflashext(metaclass=LogBase):
class XFlashExt(metaclass=LogBase):
def __init__(self, mtk, xflash, loglevel):
self.pathconfig = pathconfig()
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.lasterror = None
self.pathconfig = PathConfig()
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.mtk = mtk
self.loglevel = loglevel
self.__logger = self.__logger
@ -174,6 +176,7 @@ class xflashext(metaclass=LogBase):
def patch_da1(self, da1):
# Patch error 0xC0020039
self.info("Patching da1 ...")
da1patched = None
if da1 is not None:
da1patched = bytearray(da1)
da1patched = self.mtk.patch_preloader_security_da1(da1patched)
@ -200,25 +203,44 @@ class xflashext(metaclass=LogBase):
huawei = find_binary(da2, b"\x01\x2B\x03\xD1\x01\x23", pos)
if huawei is not None:
da2patched[huawei:huawei + 4] = b"\x00\x00\x00\x00"
# Patch oppo security mt6765
oppo = find_binary(da2, b"\x01\x4B\x18\x78\x70\x47")
if oppo is not None:
da2patched[oppo:oppo + 4] = b"\x4F\xF0\x01\x00"
# Patch oppo security
oppo = 0
pos = 0
while oppo is not None:
oppo = find_binary(da2, b"\x01\x3B\x01\x2B\x08\xD9", pos)
if find_binary(da2, b"[oplus]") or find_binary(da2, b"[OPPO]"):
# Patch oppo security mt6765
oppo = find_binary(da2, b"\x0A\x00\x00\xE0.\x00\x00\xE0")
if oppo is not None:
da2patched[oppo:oppo + 4] = b"\x01\x20\x08\xBD"
pos = oppo + 1
# Patch security
is_security_enabled = find_binary(da2, b"\x01\x23\x03\x60\x00\x20\x70\x47")
if is_security_enabled != -1:
da2patched[is_security_enabled:is_security_enabled + 2] = b"\x00\x23"
auth_flag_ptr = int.from_bytes(da2patched[oppo - 4:oppo], 'little')
auth_flag_offset = auth_flag_ptr - self.mtk.daloader.daconfig.da_loader.region[2].m_start_addr
if int.from_bytes(da2patched[auth_flag_offset:auth_flag_offset + 4], 'little') == 3:
da2patched[auth_flag_offset:auth_flag_offset + 1] = b"\x01"
self.info("Oppo g_oppo_auth_status patched.")
else:
oppo = find_binary(da2, b"\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03")
if oppo is not None:
da2patched[oppo + 0x10:oppo + 0x10 + 1] = b"\x01"
self.info("Oppo g_oppo_auth_status patched.")
else:
# 20271
oppo = find_binary(da2, b"\x63\x88\x74\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03")
if oppo is not None:
da2patched[oppo + 0x10:oppo + 0x10 + 1] = b"\x01"
self.info("Oppo g_oppo_auth_status patched.")
# Patch oppo security
oppo = 0
pos = 0
while oppo is not None:
oppo = find_binary(da2, b"\x01\x3B\x01\x2B\x08\xD9", pos)
if oppo is not None:
da2patched[oppo:oppo + 4] = b"\x01\x20\x08\xBD"
pos = oppo + 1
# Patch hash binding 0xC0020004 or 0xC0020005
hashbind = find_binary(da2, b"\x01\x23\x03\x60\x00\x20\x70\x47\x70\xB5")
if hashbind is not None:
da2patched[hashbind:hashbind + 1] = b"\x00"
else:
self.warning("Security check not patched.")
# Patch hash check
self.warning("Hash binding not patched.")
# Patch hash check cmd_boot_to
authaddr = find_binary(da2, int.to_bytes(0xC0070004, 4, 'little'))
if authaddr:
da2patched[authaddr:authaddr + 4] = int.to_bytes(0, 4, 'little')
@ -235,12 +257,22 @@ class xflashext(metaclass=LogBase):
# Disable security checks
security_check = find_binary(da2, b"\x01\x23\x03\x60\x00\x20\x70\x47\x70\xB5")
if security_check:
da2patched[security_check:security_check+2]=b"\x00\x23"
da2patched[security_check:security_check + 2] = b"\x00\x23"
self.info("Security check patched")
# Disable da anti rollback version check
antirollback = find_binary(da2, int.to_bytes(0xC0020053, 4, 'little'))
if antirollback:
da2patched[antirollback:antirollback + 4] = int.to_bytes(0, 4, 'little')
self.info("DA version anti-rollback patched")
disable_sbc = find_binary(da2, b"\x02\x4B\x18\x68\xC0\xF3\x40\x00\x70\x47")
if disable_sbc:
# MOV R0, #0
da2patched[disable_sbc + 4:disable_sbc + 8] = b"\x4F\xF0\x00\x00"
self.info("SBC patched to be disabled")
register_readwrite = find_binary(da2, int.to_bytes(0xC004000D, 4, 'little'))
if register_readwrite:
da2patched[register_readwrite:register_readwrite + 4] = int.to_bytes(0, 4, 'little')
self.info("Register read/write not allowed patched")
# Patch write not allowed
# open("da2.bin","wb").write(da2patched)
idx = 0
@ -442,7 +474,7 @@ class xflashext(metaclass=LogBase):
hwc.sej.sej_set_otp(otp)
def read_rpmb(self, filename=None, display=True):
progressbar = progress(1, self.mtk.config.guiprogress)
progressbar = Progress(1, self.mtk.config.guiprogress)
sectors = 0
# val = self.custom_rpmb_init()
ufs = False
@ -469,7 +501,7 @@ class xflashext(metaclass=LogBase):
return False
def write_rpmb(self, filename=None, display=True):
progressbar = progress(1, self.mtk.config.guiprogress)
progressbar = Progress(1, self.mtk.config.guiprogress)
if filename is None:
self.error("Filename has to be given for writing to rpmb")
return False
@ -496,7 +528,7 @@ class xflashext(metaclass=LogBase):
return False
def erase_rpmb(self, display=True):
progressbar = progress(1, self.mtk.config.guiprogress)
progressbar = Progress(1, self.mtk.config.guiprogress)
ufs = False
sectors = 0
if self.xflash.emmc.rpmb_size != 0:
@ -516,7 +548,7 @@ class xflashext(metaclass=LogBase):
return False
def cryptosetup(self):
setup = crypto_setup()
setup = CryptoSetup()
setup.blacklist = self.config.chipconfig.blacklist
setup.gcpu_base = self.config.chipconfig.gcpu_base
setup.dxcc_base = self.config.chipconfig.dxcc_base
@ -527,7 +559,7 @@ class xflashext(metaclass=LogBase):
setup.write32 = self.writeregister
setup.writemem = self.writemem
setup.hwcode = self.config.hwcode
return hwcrypto(setup, self.loglevel, self.config.gui)
return HwCrypto(setup, self.loglevel, self.config.gui)
def seccfg(self, lockflag):
if lockflag not in ["unlock", "lock"]:
@ -552,10 +584,10 @@ class xflashext(metaclass=LogBase):
hwc = self.cryptosetup()
if seccfg_data[:0xC] == b"AND_SECCFG_v":
self.info("Detected V3 Lockstate")
sc_org = seccfgV3(hwc, self.mtk)
sc_org = SecCfgV3(hwc, self.mtk)
elif seccfg_data[:4] == b"\x4D\x4D\x4D\x4D":
self.info("Detected V4 Lockstate")
sc_org = seccfgV4(hwc, self.mtk)
sc_org = SecCfgV4(hwc, self.mtk)
else:
return False, "Unknown lockstate or no lockstate"
if not sc_org.parse(seccfg_data):
@ -577,7 +609,7 @@ class xflashext(metaclass=LogBase):
while idx != -1:
idx = data.find(b"EET KTM ", idx + 1)
if idx != -1:
mt = mtktee()
mt = MTKTee()
mt.parse(data[idx:])
rdata = hwc.mtee(data=mt.data, keyseed=mt.keyseed, ivseed=mt.ivseed,
aeskey1=aeskey1, aeskey2=aeskey2)
@ -587,7 +619,7 @@ class xflashext(metaclass=LogBase):
if self.mtk.config.chipconfig.efuse_addr is not None:
base = self.mtk.config.chipconfig.efuse_addr
hwcode = self.mtk.config.hwcode
efuseconfig = efuse(base, hwcode)
efuseconfig = Efuse(base, hwcode)
addr = efuseconfig.efuses[idx]
if addr < 0x1000:
return int.to_bytes(addr, 4, 'little')
@ -607,7 +639,7 @@ class xflashext(metaclass=LogBase):
if self.mtk.config.chipconfig.efuse_addr is not None:
base = self.mtk.config.chipconfig.efuse_addr
hwcode = self.mtk.config.hwcode
efuseconfig = efuse(base, hwcode)
efuseconfig = Efuse(base, hwcode)
data = []
for idx in range(len(efuseconfig.efuses)):
addr = efuseconfig.efuses[idx]
@ -640,14 +672,16 @@ class xflashext(metaclass=LogBase):
data = b"".join([pack("<I", val) for val in self.readmem(base + 0x8EC, 0x16 // 4)])
self.config.meid = data
self.config.set_meid(data)
except Exception:
except Exception as err:
self.lasterror = err
return
if self.config.socid is None:
try:
data = b"".join([pack("<I", val) for val in self.readmem(base + 0x934, 0x20 // 4)])
self.config.socid = data
self.config.set_socid(data)
except Exception:
except Exception as err:
self.lasterror = err
return
hwc = self.cryptosetup()
meid = self.config.get_meid()
@ -656,7 +690,8 @@ class xflashext(metaclass=LogBase):
cid = self.config.get_cid()
otp = self.config.get_otp()
retval = {}
# data=hwc.aes_hwcrypt(data=bytes.fromhex("A9 E9 DC 38 BF 6B BD 12 CC 2E F9 E6 F5 65 E8 C6 88 F7 14 11 80 2E 4D 91 8C 2B 48 A5 BB 03 C3 E5"), mode="sst", btype="sej",
# data=hwc.aes_hwcrypt(data=bytes.fromhex("A9 E9 DC 38 BF 6B BD 12 CC 2E F9 E6 F5 65 E8 C6 88 F7 14 11 80 " +
# "2E 4D 91 8C 2B 48 A5 BB 03 C3 E5"), mode="sst", btype="sej",
# encrypt=False)
# self.info(data.hex())
pubk = self.read_pubk()

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import time
import os
@ -10,22 +10,23 @@ from mtkclient.Library.DA.xflash.xflash_flash_param import NandExtension
from mtkclient.Library.DA.xflash.xflash_param import Cmd, ChecksumAlgorithm, FtSystemOSE, DataType
from mtkclient.Library.utils import LogBase, logsetup
from mtkclient.Library.error import ErrorHandler
from mtkclient.Library.DA.daconfig import EMMC_PartitionType, UFS_PartitionType, DaStorage, DAconfig
from mtkclient.Library.DA.daconfig import EmmcPartitionType, UFSPartitionType, DaStorage, DAconfig
from mtkclient.Library.partition import Partition
from mtkclient.config.payloads import pathconfig
from mtkclient.Library.DA.xflash.extension.xflash import xflashext, XCmd
from mtkclient.Library.settings import hwparam
from mtkclient.config.payloads import PathConfig
from mtkclient.Library.DA.xflash.extension.xflash import XFlashExt, XCmd
from mtkclient.Library.settings import HwParam
from mtkclient.Library.thread_handling import writedata
from queue import Queue
from threading import Thread
rq = Queue()
class DAXFlash(metaclass=LogBase):
def __init__(self, mtk, daconfig, loglevel=logging.INFO):
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.daversion = None
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.Cmd = Cmd()
self.ChecksumAlgorithm = ChecksumAlgorithm()
self.FtSystemOSE = FtSystemOSE()
@ -52,16 +53,16 @@ class DAXFlash(metaclass=LogBase):
self.rword = self.mtk.port.rword
self.daconfig = daconfig
self.partition = Partition(self.mtk, self.readflash, self.read_pmt, loglevel)
self.pathconfig = pathconfig()
self.pathconfig = PathConfig()
self.patch = False
self.generatekeys = self.mtk.config.generatekeys
if self.generatekeys:
self.patch = True
self.xft = xflashext(self.mtk, self, loglevel)
self.xft = XFlashExt(self.mtk, self, loglevel)
try:
from mtkclient.Library.Exploit.kamakiri_pl import Kamakiri_Pl
self.kamakiri_pl = Kamakiri_Pl(self.mtk, loglevel)
from mtkclient.Library.Exploit.kamakiripl import KamakiriPl
self.kamakiri_pl = KamakiriPl(self.mtk, loglevel)
# self.kamakiri_pl = None
except Exception:
self.kamakiri_pl = None
@ -195,7 +196,7 @@ class DAXFlash(metaclass=LogBase):
return self.send_devctrl(self.Cmd.SET_RESET_KEY, param)
def set_meta(self, porttype="off"):
class mtk_boot_mode_flag:
class MtkBootModeFlag:
boot_mode = b"\x00" # 0:normal, 1:meta
com_type = b"\x00" # 0:unknown, 1:uart, 2:usb
com_id = b"\x00" # 0:single interface device (meta,adb)
@ -221,7 +222,7 @@ class DAXFlash(metaclass=LogBase):
def get(self):
return self.boot_mode + self.com_type + self.com_id
metamode = mtk_boot_mode_flag(porttype).get()
metamode = MtkBootModeFlag(porttype).get()
return self.send_devctrl(self.Cmd.SET_META_BOOT_MODE, metamode)
def set_checksum_level(self, checksum_level=0x0):
@ -280,9 +281,11 @@ class DAXFlash(metaclass=LogBase):
if self.usbwrite(param):
if self.send_data(da):
if addr == 0x68000000:
self.info("Extensions were accepted. Jumping to extensions...")
if display:
self.info("Extensions were accepted. Jumping to extensions...")
else:
self.info("Upload data was accepted. Jumping to stage 2...")
if display:
self.info("Upload data was accepted. Jumping to stage 2...")
if timeout:
time.sleep(timeout)
status = -1
@ -296,7 +299,8 @@ class DAXFlash(metaclass=LogBase):
return False
if status == 0x434E5953 or status == 0x0:
self.info(f"Boot to succeeded.")
if display:
self.info(f"Boot to succeeded.")
return True
else:
self.error(f"Error on boot to: {self.eh.status(status)}, addr: {hex(addr)}")
@ -307,7 +311,7 @@ class DAXFlash(metaclass=LogBase):
else:
self.error(f"Error on boot usbwrite, addr: {hex(addr)}")
else:
self.error(f"Error on boot to: {self.eh.status(status)}, addr: {hex(addr)}")
self.error(f"Error on boot to, addr: {hex(addr)}")
return False
def get_connection_agent(self):
@ -333,33 +337,33 @@ class DAXFlash(metaclass=LogBase):
if storage == DaStorage.MTK_DA_STORAGE_EMMC or storage == DaStorage.MTK_DA_STORAGE_SDMMC:
storage = 1
if parttype is None or parttype == "user":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_USER
elif parttype == "boot1":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_BOOT1
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_BOOT1
if self.daconfig.flashtype == "emmc":
length = min(length, self.emmc.boot1_size)
elif parttype == "boot2":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_BOOT2
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_BOOT2
if self.daconfig.flashtype == "emmc":
length = min(length, self.emmc.boot2_size)
elif parttype == "gp1":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP1
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_GP1
if self.daconfig.flashtype == "emmc":
length = min(length, self.emmc.gp1_size)
elif parttype == "gp2":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP2
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_GP2
if self.daconfig.flashtype == "emmc":
length = min(length, self.emmc.gp2_size)
elif parttype == "gp3":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP3
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_GP3
if self.daconfig.flashtype == "emmc":
length = min(length, self.emmc.gp3_size)
elif parttype == "gp4":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_GP4
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_GP4
if self.daconfig.flashtype == "emmc":
length = min(length, self.emmc.gp4_size)
elif parttype == "rpmb":
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_RPMB
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_RPMB
if self.daconfig.flashtype == "emmc":
length = min(length, self.emmc.rpmb_size)
else:
@ -367,16 +371,16 @@ class DAXFlash(metaclass=LogBase):
return []
elif storage == DaStorage.MTK_DA_STORAGE_UFS:
if parttype is None or parttype == "lu3" or parttype == "user": # USER
parttype = UFS_PartitionType.UFS_LU3
parttype = UFSPartitionType.UFS_LU3
length = min(length, self.ufs.lu0_size)
elif parttype in ["lu1", "boot1"]: # BOOT1
parttype = UFS_PartitionType.UFS_LU1
parttype = UFSPartitionType.UFS_LU1
length = min(length, self.ufs.lu1_size)
elif parttype in ["lu2", "boot2"]: # BOOT2
parttype = UFS_PartitionType.UFS_LU2
parttype = UFSPartitionType.UFS_LU2
length = min(length, self.ufs.lu2_size)
elif parttype in ["lu4", "rpmb"]: # RPMB
parttype = UFS_PartitionType.UFS_LU4
parttype = UFSPartitionType.UFS_LU4
length = min(length, self.ufs.lu2_size)
else:
self.error('Unknown parttype. Known parttypes are "lu1","lu2","lu3","lu4"')
@ -384,23 +388,25 @@ class DAXFlash(metaclass=LogBase):
elif storage in [DaStorage.MTK_DA_STORAGE_NAND, DaStorage.MTK_DA_STORAGE_NAND_MLC,
DaStorage.MTK_DA_STORAGE_NAND_SLC, DaStorage.MTK_DA_STORAGE_NAND_TLC,
DaStorage.MTK_DA_STORAGE_NAND_SPI, DaStorage.MTK_DA_STORAGE_NAND_AMLC]:
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_USER
length = min(length, self.nand.total_size)
elif storage in [DaStorage.MTK_DA_STORAGE_NOR, DaStorage.MTK_DA_STORAGE_NOR_PARALLEL,
DaStorage.MTK_DA_STORAGE_NOR_SERIAL]:
parttype = EMMC_PartitionType.MTK_DA_EMMC_PART_USER
parttype = EmmcPartitionType.MTK_DA_EMMC_PART_USER
length = min(length, self.nor.available_size)
return [storage, parttype, length]
def formatflash(self, addr, length, storage=None,
parttype=None, display=False):
self.mtk.daloader.progress.clear()
if display:
self.mtk.daloader.progress.clear()
part_info = self.getstorage(parttype, length)
if not part_info:
return False
storage, parttype, length = part_info
self.info(f"Formatting addr {hex(addr)} with length {hex(length)}, please standby....")
self.mtk.daloader.progress.show_progress("Erasing", 0, length, True)
if display:
self.info(f"Formatting addr {hex(addr)} with length {hex(length)}, please standby....")
self.mtk.daloader.progress.show_progress("Erasing", 0, length, True)
if self.xsend(self.Cmd.FORMAT):
status = self.status()
if status == 0:
@ -418,8 +424,9 @@ class DAXFlash(metaclass=LogBase):
time.sleep(self.status() / 1000.0)
status = self.ack()
if status == 0x40040005: # STATUS_COMPLETE
self.mtk.daloader.progress.show_progress("Erasing", length, length, True)
self.info(f"Successsfully formatted addr {hex(addr)} with length {length}.")
if display:
self.mtk.daloader.progress.show_progress("Erasing", length, length, True)
self.info(f"Successsfully formatted addr {hex(addr)} with length {length}.")
return True
if status != 0x0:
@ -449,9 +456,8 @@ class DAXFlash(metaclass=LogBase):
chipid = Chipid
data = self.send_devctrl(self.Cmd.GET_CHIP_ID)
if data != b"":
chipid.hw_code, chipid.hw_sub_code, chipid.hw_version, chipid.sw_version, chipid.chip_evolution = unpack(
"<HHHHH",
data[:(5 * 2)])
chipid.hw_code, chipid.hw_sub_code, chipid.hw_version, chipid.sw_version, chipid.chip_evolution = (
unpack("<HHHHH", data[:(5 * 2)]))
status = self.status()
if status == 0:
self.info("HW-CODE : 0x%X" % chipid.hw_code)
@ -757,7 +763,7 @@ class DAXFlash(metaclass=LogBase):
return False
def cmd_write_data(self, addr, size, storage=DaStorage.MTK_DA_STORAGE_EMMC,
parttype=EMMC_PartitionType.MTK_DA_EMMC_PART_USER):
parttype=EmmcPartitionType.MTK_DA_EMMC_PART_USER):
if self.xsend(self.Cmd.WRITE_DATA):
status = self.status()
if status == 0:
@ -774,7 +780,7 @@ class DAXFlash(metaclass=LogBase):
return False
def cmd_read_data(self, addr, size, storage=DaStorage.MTK_DA_STORAGE_EMMC,
parttype=EMMC_PartitionType.MTK_DA_EMMC_PART_USER):
parttype=EmmcPartitionType.MTK_DA_EMMC_PART_USER):
if self.xsend(self.Cmd.READ_DATA):
status = self.status()
if status == 0:
@ -792,7 +798,7 @@ class DAXFlash(metaclass=LogBase):
self.error(f"Error on reading data: {self.eh.status(status)}")
return False
def readflash(self, addr, length, filename, parttype=None, display=True) -> bytes:
def readflash(self, addr, length, filename, parttype=None, display=True) -> (bytes, bool):
global rq
partinfo = self.getstorage(parttype, length)
if not partinfo and not filename:
@ -870,7 +876,7 @@ class DAXFlash(metaclass=LogBase):
if status == 0:
hasflags = 0
# bootmode 0: shutdown 1: home screen, 2: fastboot
if async_mode or dl_bit or bootmode > 0:
if async_mode or dl_bit or bootmode != bootmode.NORMAL:
hasflags = 1
enablewdt = 0 # Disable wdt
dont_resetrtc = 0 # Reset RTC
@ -893,8 +899,8 @@ class DAXFlash(metaclass=LogBase):
storage = DaStorage.MTK_DA_STORAGE_NAND
elif self.daconfig.flashtype == "ufs":
storage = DaStorage.MTK_DA_STORAGE_UFS
if parttype == EMMC_PartitionType.MTK_DA_EMMC_PART_USER:
parttype = UFS_PartitionType.UFS_LU3
if parttype == EmmcPartitionType.MTK_DA_EMMC_PART_USER:
parttype = UFSPartitionType.UFS_LU3
elif self.daconfig.flashtype == "sdc":
storage = DaStorage.MTK_DA_STORAGE_SDMMC
else:
@ -1188,7 +1194,8 @@ class DAXFlash(metaclass=LogBase):
if status == 0x0 and unpack("<I", ret)[0] == 0xA1A2A3A4:
self.info("DA Extensions successfully added")
self.daext = True
self.config.hwparam = hwparam(self.mtk.config, self.mtk.config.meid, self.mtk.config.hwparam_path)
self.config.hwparam = HwParam(self.mtk.config, self.mtk.config.meid,
self.mtk.config.hwparam_path)
self.config.hwparam.writesetting("hwcode", hex(self.config.hwcode))
if not self.daext:
self.warning("DA Extensions failed to enable")
@ -1206,8 +1213,8 @@ class DAXFlash(metaclass=LogBase):
def main():
from mtkclient.Library.mtk_class import Mtk
from mtkclient.config.mtk_config import Mtk_Config
config = Mtk_Config(logging.INFO)
from mtkclient.config.mtk_config import MtkConfig
config = MtkConfig(logging.INFO)
config.init_hwcode(0x717)
config.hwver = 0xca00
config.swver = 0

View file

@ -4,13 +4,13 @@ import sys
from struct import unpack, pack
# from keystone import *
from mtkclient.config.payloads import pathconfig
from mtkclient.config.brom_config import efuse
from mtkclient.config.payloads import PathConfig
from mtkclient.config.brom_config import Efuse
from mtkclient.Library.error import ErrorHandler
from mtkclient.Library.Hardware.hwcrypto import crypto_setup, hwcrypto
from mtkclient.Library.utils import LogBase, progress, logsetup, find_binary
from mtkclient.Library.Hardware.seccfg import seccfgV3, seccfgV4
from mtkclient.Library.utils import mtktee
from mtkclient.Library.Hardware.hwcrypto import CryptoSetup, HwCrypto
from mtkclient.Library.utils import LogBase, Progress, logsetup, find_binary
from mtkclient.Library.Hardware.seccfg import SecCfgV3, SecCfgV4
from mtkclient.Library.utils import MTKTee
import json
rpmb_error = [
@ -25,11 +25,12 @@ rpmb_error = [
]
class xmlflashext(metaclass=LogBase):
def __init__(self, mtk, xmlflash, loglevel):
self.pathconfig = pathconfig()
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.mtk = mtk
class XmlFlashExt(metaclass=LogBase):
def __init__(self, _mtk, _xmlflash, loglevel):
self.pathconfig = PathConfig()
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.mtk = _mtk
self.loglevel = loglevel
self.__logger = self.__logger
self.eh = ErrorHandler()
@ -40,15 +41,15 @@ class xmlflashext(metaclass=LogBase):
self.rbyte = self.mtk.port.rbyte
self.rdword = self.mtk.port.rdword
self.rword = self.mtk.port.rword
self.xflash = xmlflash
self.xflash = _xmlflash
self.xsend = self.xflash.xsend
self.xread = self.xflash.xread
self.da2 = None
self.da2address = None
def patch_command(self, da2):
def patch_command(self, _da2):
self.da2address = self.xflash.daconfig.da_loader.region[2].m_start_addr # at_address
data = bytearray(da2)
data = bytearray(_da2)
idx = data.find(b"\x00CMD:SET-HOST-INFO\x00")
base = self.da2address
if idx != -1:
@ -95,7 +96,8 @@ class xmlflashext(metaclass=LogBase):
# newdata = b"".join(int.to_bytes(val, 1, 'little') for val in encoding)
newdata = bytes.fromhex(
"704c2de910b08de20080a0e100000fe3000846e30410a0e3002098e532ff2fe100000fe3000846e3000000e3000846e3002098e532ff2fe1000000e3000846e330ff2fe1708cbde8")
"704c2de910b08de20080a0e100000fe3000846e30410a0e3002098e532ff2fe100000fe3000846e3000000e3000846e3" +
"002098e532ff2fe1000000e3000846e330ff2fe1708cbde8")
sys.stdout.flush()
data[addr:addr + len(newdata)] = newdata
newcmd = b"CMD:CUSTOM\x00"
@ -200,16 +202,17 @@ class xmlflashext(metaclass=LogBase):
return daextdata
return None
def patch_da1(self, da1):
return da1
def patch_da1(self, _da1):
return _da1
def patch_da2(self, da2):
def patch_da2(self, _da2):
self.info("Patching da2 ...")
da2patched = bytearray(da2)
patched = False
da2patched = bytearray(_da2)
pos = 0
idx = 0
while idx is not None:
idx = find_binary(da2, b"\x00\x00\xA0\xE3\x04\x10\xA0\xE1\x00\x20\xA0\xE3..\x00\xEB\x01\x40\x00\xE3",
idx = find_binary(_da2, b"\x00\x00\xA0\xE3\x04\x10\xA0\xE1\x00\x20\xA0\xE3..\x00\xEB\x01\x40\x00\xE3",
pos)
if idx is not None:
offset = int.from_bytes(da2patched[idx + 0xC:idx + 0xE], 'little') - 1
@ -220,33 +223,79 @@ class xmlflashext(metaclass=LogBase):
pos += 0x14
if patched:
self.info("Patched read_register / write_register")
da2patched = self.patch_command(da2)
da2patched = self.patch_command(_da2)
idx = find_binary(da2patched,
b"\x00\xA0\xE3\x1E\xFF\x2F\xE1.\x00\xA0\xE3\x1E\xFF\x2F\xE1.\x00\xA0\xE3\x1E\xFF\x2F\xE1\x70\x4C")
b"\x00\xA0\xE3\x1E\xFF\x2F\xE1.\x00\xA0\xE3\x1E\xFF\x2F\xE1." +
b"\x00\xA0\xE3\x1E\xFF\x2F\xE1\x70\x4C")
if idx is not None:
da2patched[idx - 1:idx - 1 + (
3 * 8)] = b"\x01\x00\xA0\xE3\x1E\xFF\x2F\xE1\x01\x00\xA0\xE3\x1E\xFF\x2F\xE1\x01\x00\xA0\xE3\x1E\xFF\x2F\xE1"
da2patched[idx - 1:idx - 1 + (3 * 8)] = (b"\x01\x00\xA0\xE3\x1E\xFF\x2F\xE1\x01\x00\xA0" +
b"\xE3\x1E\xFF\x2F\xE1\x01\x00\xA0\xE3\x1E\xFF\x2F\xE1")
patched = True
self.info("Patched write partitions / allow_read / allow_write")
if not patched:
self.warning("Write not allowed not patched.")
idx = find_binary(da2patched, b"\x01\x10\xA0\xE3\x00\x10\x80\xE5")
if idx is not None:
da2patched[idx:idx + 8] = b"\x00\x10\xA0\xE3\x00\x10\x80\xE5"
patched = True
self.info("Patched hash binding")
if not patched:
self.warning("Hash binding not patched.")
"""idx = find_binary(da2patched,b"\xA4\x43\x00\xEB\x66\x18\x00\xEB")
if idx is not None:
da2patched[idx:idx+8] = b"\xA4\x43\x00\xEB\x08\x00\x00\xEB"
patched = True
self.info("Bypass SEC policy")
if not patched:
self.warning("SEC policy bypass not patched.")
"""
idx2 = find_binary(da2patched, b"\x30\x48\x2D\xE9\x08\xB0\x8D\xE2\x20\xD0\x4D\xE2\x01\x50\xA0\xE1")
if idx2 is not None:
da2patched[idx2:idx2+8] = b"\x00\x00\xA0\xE3\x1E\xFF\x2F\xE1"
self.info("Patched Infinix SLA authentification.")
da2patched[idx2:idx2 + 8] = b"\x00\x00\xA0\xE3\x1E\xFF\x2F\xE1"
self.info("Patched Infinix Remote SLA authentification.")
else:
idx2 = find_binary(da2patched, b"\x70\x4C\x2D\xE9\x10\xB0\x8D\xE2\x00\x60\xA0\xE1\x02\x06\xA0\xE3")
if idx2 is not None:
da2patched[idx2:idx2 + 8] = b"\x00\x00\xA0\xE3\x1E\xFF\x2F\xE1"
self.info("Patched Oppo SLA authentification.")
idx3 = find_binary(da2patched,b"\x03\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x01\x00\x00\x00")
self.info("Patched Oppo Remote SLA authentification.")
idx3 = find_binary(da2patched, b"\x03\x00\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x01\x00\x00\x00")
if idx3 is not None:
da2patched[idx3:idx3+4]=b"\xFF\x00\x00\x00"
da2patched[idx3:idx3 + 4] = b"\xFF\x00\x00\x00"
self.info("Patched Oppo Allowance flag.")
else:
idx2 = find_binary(da2patched,
b"\xF0\x4D\x2D\xE9\x18\xB0\x8D\xE2\x82\xDF\x4D\xE2\x01\x60\xA0" +
"\xE1\x38\x19\x0F\xE3\x00\x70\xA0\xE1\x42\x0F\x8D\xE2")
if idx2 is not None:
da2patched[idx2:idx2 + 8] = b"\x00\x00\xA0\xE3\x1E\xFF\x2F\xE1"
self.info("Patched Vivo Remote SLA authentification.")
else:
pubkey = bytes.fromhex(
"A243F6694336D527C5B3ED569DDD0386D309C6592841E4C033DCB461EEA7B6F8535FC4939E403060" +
"646A970DD81DE367CF003848146F19D259F50A385015AF6309EAA71BFED6B098C7A24D4871B4B82A" +
"AD7DC6E2856C301BE7CDB46DC10795C0D30A68DD8432B5EE5DA42BA22124796512FCA21D811D50B3" +
"4C2F672E25BCC2594D9C012B34D473EE222D1E56B90E7D697CEA97E8DD4CCC6BED5FDAECE1A43F96" +
"495335F322CCE32612DAB462B024281841F553FF7FF33E0103A7904037F8FE5D9BE293ACD7485CDB" +
"50957DB11CA6DB28AF6393C3E78D9FBCD4567DEBCA2601622F0F2EB19DA9192372F9EA3B28B10794" +
"09C0A09E3D51D64A4C4CE026FAD24CD")
# Generic SLA patch, just replace the public key with a known one
idx2 = find_binary(da2patched, b"01000100")
# Infinix / Tecno
if idx2 is not None:
da2patched[idx2 - 0x100:idx2] = pubkey
else:
# Oppo / Oneplus
idx2 = find_binary(da2patched, b"0123456789ABCDEF0123456789abcdef")
if idx2 is not None:
da2patched[idx2 - 0x100:idx2] = pubkey
self.warning("SLA authentification not patched.")
#open("/home/bjk/Projects/mtkclient_le/Loaders/V6/infinix/mt6789/DA_BR_2_40000000.patched.bin", "wb").write(da2patched)
# open("da.patched.bin",
# "wb").write(da2patched)
return da2patched
def custom_rpmb_read(self, sector, ufs=False):
@ -373,7 +422,7 @@ class xmlflashext(metaclass=LogBase):
hwc.sej.sej_set_otp(otp)
def read_rpmb(self, filename=None, display=True):
progressbar = progress(1, self.mtk.config.guiprogress)
progressbar = Progress(1, self.mtk.config.guiprogress)
sectors = 0
# val = self.custom_rpmb_init()
ufs = False
@ -400,7 +449,7 @@ class xmlflashext(metaclass=LogBase):
return False
def write_rpmb(self, filename=None, display=True):
progressbar = progress(1, self.mtk.config.guiprogress)
progressbar = Progress(1, self.mtk.config.guiprogress)
if filename is None:
self.error("Filename has to be given for writing to rpmb")
return False
@ -427,7 +476,7 @@ class xmlflashext(metaclass=LogBase):
return False
def erase_rpmb(self, display=True):
progressbar = progress(1, self.mtk.config.guiprogress)
progressbar = Progress(1, self.mtk.config.guiprogress)
ufs = False
sectors = 0
if self.xflash.emmc.rpmb_size != 0:
@ -567,7 +616,7 @@ class xmlflashext(metaclass=LogBase):
return True
def cryptosetup(self):
setup = crypto_setup()
setup = CryptoSetup()
setup.blacklist = self.config.chipconfig.blacklist
setup.gcpu_base = self.config.chipconfig.gcpu_base
setup.dxcc_base = self.config.chipconfig.dxcc_base
@ -578,7 +627,7 @@ class xmlflashext(metaclass=LogBase):
setup.write32 = self.writeregister
setup.writemem = self.writemem
setup.hwcode = self.config.hwcode
return hwcrypto(setup, self.loglevel, self.config.gui)
return HwCrypto(setup, self.loglevel, self.config.gui)
def seccfg(self, lockflag):
if lockflag not in ["unlock", "lock"]:
@ -603,10 +652,10 @@ class xmlflashext(metaclass=LogBase):
hwc = self.cryptosetup()
if seccfg_data[:0xC] == b"AND_SECCFG_v":
self.info("Detected V3 Lockstate")
sc_org = seccfgV3(hwc, self.mtk)
sc_org = SecCfgV3(hwc, self.mtk)
elif seccfg_data[:4] == b"\x4D\x4D\x4D\x4D":
self.info("Detected V4 Lockstate")
sc_org = seccfgV4(hwc, self.mtk)
sc_org = SecCfgV4(hwc, self.mtk)
else:
return False, "Unknown lockstate or no lockstate"
if not sc_org.parse(seccfg_data):
@ -628,7 +677,7 @@ class xmlflashext(metaclass=LogBase):
while idx != -1:
idx = data.find(b"EET KTM ", idx + 1)
if idx != -1:
mt = mtktee()
mt = MTKTee()
mt.parse(data[idx:])
rdata = hwc.mtee(data=mt.data, keyseed=mt.keyseed, ivseed=mt.ivseed,
aeskey1=aeskey1, aeskey2=aeskey2)
@ -638,7 +687,7 @@ class xmlflashext(metaclass=LogBase):
if self.mtk.config.chipconfig.efuse_addr is not None:
base = self.mtk.config.chipconfig.efuse_addr
hwcode = self.mtk.config.hwcode
efuseconfig = efuse(base, hwcode)
efuseconfig = Efuse(base, hwcode)
addr = efuseconfig.efuses[idx]
if addr < 0x1000:
return int.to_bytes(addr, 4, 'little')
@ -658,7 +707,7 @@ class xmlflashext(metaclass=LogBase):
if self.mtk.config.chipconfig.efuse_addr is not None:
base = self.mtk.config.chipconfig.efuse_addr
hwcode = self.mtk.config.hwcode
efuseconfig = efuse(base, hwcode)
efuseconfig = Efuse(base, hwcode)
data = []
for idx in range(len(efuseconfig.efuses)):
addr = efuseconfig.efuses[idx]
@ -698,7 +747,8 @@ class xmlflashext(metaclass=LogBase):
cid = self.config.get_cid()
otp = self.config.get_otp()
retval = {}
# data=hwc.aes_hwcrypt(data=bytes.fromhex("A9 E9 DC 38 BF 6B BD 12 CC 2E F9 E6 F5 65 E8 C6 88 F7 14 11 80 2E 4D 91 8C 2B 48 A5 BB 03 C3 E5"), mode="sst", btype="sej",
# data=hwc.aes_hwcrypt(data=bytes.fromhex("A9 E9 DC 38 BF 6B BD 12 CC 2E F9 E6 F5 65 E8 C6 88 F7 14 11 80 " +
# "2E 4D 91 8C 2B 48 A5 BB 03 C3 E5"), mode="sst", btype="sej",
# encrypt=False)
# self.info(data.hex())
pubk = self.read_pubk()

View file

@ -30,7 +30,12 @@ class XMLCmd(metaclass=LogBase):
def cmd_notify_init_hw(self):
"""
<?xml version="1.0" encoding="utf-8"?><da><version>1.0</version><command>CMD:NOTIFY-INIT-HW</command><arg></arg></da>
<?xml version="1.0" encoding="utf-8"?>
<da>
<version>1.0</version>
<command>CMD:NOTIFY-INIT-HW</command>
<arg></arg>
</da>
"""
cmd = self.create_cmd("NOTIFY-INIT-HW")
return cmd
@ -38,7 +43,8 @@ class XMLCmd(metaclass=LogBase):
def cmd_security_set_flash_policy(self, host_offset: int = 0x8000000,
length: int = 0x100000):
"""
<?xml version="1.0" encoding="utf-8"?><da><version>1.0</version><command>CMD:SECURITY-SET-FLASH-POLICY</command><arg>
<?xml version="1.0" encoding="utf-8"?><da><version>1.0</version>
<command>CMD:SECURITY-SET-FLASH-POLICY</command><arg>
<source_file>MEM://0x8000000:0x100000</source_file></arg></da>
"""
content = {
@ -219,7 +225,8 @@ class XMLCmd(metaclass=LogBase):
def cmd_can_higher_usb_speed(self, host_mem_offset: int = 0x7fe8463ed240, length: int = 0x40):
"""
<?xml version="1.0" encoding="utf-8"?><da><version>1.0</version><command>CMD:CAN-HIGHER-USB-SPEED</command><arg><target_file>MEM://0x7fe8463ed240:0x40</target_file></arg></da>
<?xml version="1.0" encoding="utf-8"?><da><version>1.0</version>
<command>CMD:CAN-HIGHER-USB-SPEED</command><arg><target_file>MEM://0x7fe8463ed240:0x40</target_file></arg></da>
"""
content = {
"arg": [
@ -238,7 +245,9 @@ class XMLCmd(metaclass=LogBase):
cmd = self.create_cmd("WRITE-EFUSE", content)
# resp =
"""
<?xml version=\"1.0\" encoding=\"utf-8\"?><host><version>1.0</version><command>CMD:DOWNLOAD-FILE</command><a"rg><checksum>%s</checksum><info>%s</info><source_file>%s</source_file><packet_length>0x%x</packet_length></arg></host>
<?xml version=\"1.0\" encoding=\"utf-8\"?><host><version>1.0</version>
<command>CMD:DOWNLOAD-FILE</command><a"rg><checksum>%s</checksum>
<info>%s</info><source_file>%s</source_file><packet_length>0x%x</packet_length></arg></host>
"""
return cmd
@ -251,11 +260,41 @@ class XMLCmd(metaclass=LogBase):
cmd = self.create_cmd("READ-EFUSE", content)
# resp =
"""
<?xml version=\"1.0\" encoding=\"utf-8\"?><host><version>1.0</version><command>CMD:UPLOAD-FILE</command><arg><"checksum>CHK_NO</checksum><info>%s</info><target_file>%s</target_file><packet_length>0x%x</packet_length></arg></host>
<?xml version=\"1.0\" encoding=\"utf-8\"?><host><version>1.0</version>
<command>CMD:UPLOAD-FILE</command><arg><"checksum>CHK_NO</checksum><info>%s</info>
<target_file>%s</target_file><packet_length>0x%x</packet_length></arg></host>
OK@0x%x (length)
"""
return cmd
def cmd_get_dev_info(self, host_mem_offset=0x8000000, length=0x100000):
"""
<?xml version="1.0" encoding="utf-8"?>
<da>
<version>1.0</version>
<command>CMD:SECURITY-GET-DEV-FW-INFO</command>
<arg>
<target_file>MEM://0x8000000:0x100000</target_file>
</arg>
</da>
"""
content = {
"arg": [
f"<target_file>MEM://{hex(host_mem_offset)}:{hex(length)}</target_file>"
]
}
cmd = self.create_cmd("SECURITY-GET-DEV-FW-INFO", content)
"""
resp:
<?xml version="1.0" encoding="utf-8"?>
<sla version="1.0">
<rnd>xxxx</rnd>
<hrid>xxxx</hrid>
<socid>xxxx</socid>
</sla>'
"""
return cmd
def cmd_get_hw_info(self, host_mem_offset=0x7fe83c138700, length=0x200000):
"""
<?xml version="1.0" encoding="utf-8"?>
@ -509,8 +548,11 @@ class XMLCmd(metaclass=LogBase):
cmd = self.create_cmd("GET-DA-INFO", content)
# resp =
"""
<?xml version=\"1.0\" encoding=\"utf-8\"?><host><version>1.0</version><command>CMD:UPLOAD-FILE</command><arg><checksum>CHK_NO</checksum><info>WriteLocalFile</info><target_file>%s</target_file><packet_length>0x%x</packet_length></arg></host>
<?xml version=\"1.0\" encoding=\"utf-8\"?><da_info><version>1.0</version><da_version>2021</da_version><build>May 24 2022:19:03:56</build></da_info>"
<?xml version=\"1.0\" encoding=\"utf-8\"?><host><version>1.0</version>
<command>CMD:UPLOAD-FILE</command><arg><checksum>CHK_NO</checksum><info>WriteLocalFile</info>
<target_file>%s</target_file><packet_length>0x%x</packet_length></arg></host>
<?xml version=\"1.0\" encoding=\"utf-8\"?><da_info><version>1.0</version>
<da_version>2021</da_version><build>May 24 2022:19:03:56</build></da_info>"
OK
OK@0x%x
"""
@ -539,11 +581,13 @@ class XMLCmd(metaclass=LogBase):
def cmd_set_host_info(self, hostinfo: str = ""):
"""
<?xml version="1.0" encoding="utf-8"?><da><version>1.0</version><command>CMD:SET-HOST-INFO</command><arg><info>20230901T234721</info></arg></da>
<?xml version="1.0" encoding="utf-8"?><da><version>1.0</version>
<command>CMD:SET-HOST-INFO</command>
<arg><info>20230901T234721</info></arg>
"""
if hostinfo == "":
currentDateAndTime = datetime.datetime.now()
hostinfo = currentDateAndTime.strftime("%Y%m%dT%H%M%S")
current_date_and_time = datetime.datetime.now()
hostinfo = current_date_and_time.strftime("%Y%m%dT%H%M%S")
content = {
"arg": [
f"<info>{hostinfo}</info>",

View file

@ -1,21 +1,26 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import os
from struct import pack, unpack
from queue import Queue
from threading import Thread
from Cryptodome.Hash import SHA256
from Cryptodome.Util.number import bytes_to_long, size
from Cryptodome.Cipher import PKCS1_OAEP
from Cryptodome.PublicKey import RSA
from mtkclient.Library.DA.xml.xml_param import DataType, FtSystemOSE, LogLevel
from mtkclient.Library.utils import logsetup, LogBase
from mtkclient.Library.error import ErrorHandler
from mtkclient.Library.DA.daconfig import EMMC_PartitionType, UFS_PartitionType, DaStorage
from mtkclient.Library.DA.daconfig import EmmcPartitionType, UFSPartitionType, DaStorage
from mtkclient.Library.partition import Partition
from mtkclient.config.payloads import pathconfig
from mtkclient.config.payloads import PathConfig
from mtkclient.Library.thread_handling import writedata
from queue import Queue
from threading import Thread
from mtkclient.Library.DA.xml.xml_cmd import XMLCmd, BootModes
from mtkclient.Library.DA.xml.extension.v6 import xmlflashext
from mtkclient.Library.DA.xml.extension.v6 import XmlFlashExt
from mtkclient.Library.Auth.sla import generate_da_sla_signature
from mtkclient.Library.Auth.sla_keys import da_sla_keys
rq = Queue()
@ -39,7 +44,7 @@ def get_field(data, fieldname):
return ""
class file_sys_op:
class FileSysOp:
key = None
file_path = None
@ -48,7 +53,7 @@ class file_sys_op:
self.file_path = file_path
class upfile:
class UpFile:
checksum = None
info = None
source_file = None
@ -61,7 +66,7 @@ class upfile:
self.packet_length = packet_length
class dwnfile:
class DwnFile:
checksum = None
info = None
source_file = None
@ -76,7 +81,8 @@ class dwnfile:
class DAXML(metaclass=LogBase):
def __init__(self, mtk, daconfig, loglevel=logging.INFO):
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.Cmd = XMLCmd(mtk)
self.mtk = mtk
self.loglevel = loglevel
@ -100,7 +106,7 @@ class DAXML(metaclass=LogBase):
self.rword = self.mtk.port.rword
self.daconfig = daconfig
self.partition = Partition(self.mtk, self.readflash, self.read_partition_table, loglevel)
self.pathconfig = pathconfig()
self.pathconfig = PathConfig()
self.patch = False
self.generatekeys = self.mtk.config.generatekeys
if self.generatekeys:
@ -111,7 +117,7 @@ class DAXML(metaclass=LogBase):
except Exception:
self.carbonara = None
self.xmlft = xmlflashext(self.mtk, self, loglevel)
self.xmlft = XmlFlashExt(self.mtk, self, loglevel)
def xread(self):
try:
@ -275,7 +281,7 @@ class DAXML(metaclass=LogBase):
bootldr.seek(da2offset)
da2 = bootldr.read(self.daconfig.da_loader.region[2].m_len)
if self.patch or not self.config.target_config["sbc"]:
da1, da2 = self.patch_da(da1,da2)
da1, da2 = self.patch_da(da1, da2)
self.patch = True
else:
self.patch = False
@ -310,7 +316,7 @@ class DAXML(metaclass=LogBase):
def write_register(self, addr, data):
result = self.send_command(self.Cmd.cmd_write_reg(bit_width=32, base_address=addr))
if type(result) is dwnfile:
if type(result) is DwnFile:
if self.upload(result, data):
self.info("Successfully wrote data.")
return True
@ -399,22 +405,26 @@ class DAXML(metaclass=LogBase):
source_file = get_field(data, "source_file")
packet_length = int(get_field(data, "packet_length"), 16)
self.ack()
return cmd, dwnfile(checksum, info, source_file, packet_length)
return cmd, DwnFile(checksum, info, source_file, packet_length)
elif cmd == "CMD:UPLOAD-FILE":
checksum = get_field(data, "checksum")
info = get_field(data, "info")
target_file = get_field(data, "target_file")
packet_length = get_field(data, "packet_length")
self.ack()
return cmd, upfile(checksum, info, target_file, packet_length)
return cmd, UpFile(checksum, info, target_file, packet_length)
elif cmd == "CMD:FILE-SYS-OPERATION":
"""
'<?xml version="1.0" encoding="utf-8"?><host><version>1.0</version><command>CMD:FILE-SYS-OPERATION</command><arg><key>FILE-SIZE</key><file_path>MEM://0x8000000:0x4000000</file_path></arg></host>'
'<?xml version="1.0" encoding="utf-8"?>
<host><version>1.0</version>
<command>CMD:FILE-SYS-OPERATION</command>
<arg><key>FILE-SIZE</key><file_path>MEM://0x8000000:0x4000000</file_path></arg>
</host>'
"""
key = get_field(data, "key")
file_path = get_field(data, "file_path")
self.ack()
return cmd, file_sys_op(key, file_path)
return cmd, FileSysOp(key, file_path)
if cmd == "CMD:END":
result = get_field(data, "result")
if "message" in data and result != "OK":
@ -422,8 +432,8 @@ class DAXML(metaclass=LogBase):
return cmd, message
return cmd, result
def upload(self, result: dwnfile, data, display=True, raw=False):
if type(result) is dwnfile:
def upload(self, result: DwnFile, data, display=True, raw=False):
if type(result) is DwnFile:
# checksum = result.checksum
# info = result.info
source_file = result.source_file
@ -440,9 +450,9 @@ class DAXML(metaclass=LogBase):
self.ack_value(0)
resp = self.get_response()
if "OK" not in resp:
msg = get_field(resp, "message")
rmsg = get_field(resp, "message")
self.error(f"Error on writing stage2 ACK0 at pos {hex(pos)}")
self.error(msg)
self.error(rmsg)
return False
tmp = data[pos:pos + packet_length]
tmplen = len(tmp)
@ -474,7 +484,7 @@ class DAXML(metaclass=LogBase):
global rq
if display:
self.mtk.daloader.progress.clear()
if type(result) is upfile:
if type(result) is UpFile:
# checksum = result.checksum
# info = result.info
# target_file = result.target_file
@ -522,7 +532,7 @@ class DAXML(metaclass=LogBase):
return False
def download(self, result):
if type(result) is upfile:
if type(result) is UpFile:
# checksum = result.checksum
# info = result.info
# target_file = result.target_file
@ -553,7 +563,7 @@ class DAXML(metaclass=LogBase):
def boot_to(self, addr, data, display=True, timeout=0.5):
result = self.send_command(self.Cmd.cmd_boot_to(at_addr=addr, jmp_addr=addr, length=len(data)))
if type(result) is dwnfile:
if type(result) is DwnFile:
self.info("Uploading stage 2...")
if self.upload(result, data):
self.info("Successfully uploaded stage 2.")
@ -562,9 +572,9 @@ class DAXML(metaclass=LogBase):
self.error("Wrong boot_to response :(")
return False
def handle_sla(self, data=b"\x00"*0x100, display=True, timeout=0.5):
result = self.send_command(self.Cmd.cmd_security_set_flash_policy(host_offset=0x8000000,length=len(data)))
if type(result) is dwnfile:
def handle_sla(self, data=b"\x00" * 0x100, display=True, timeout=0.5):
result = self.send_command(self.Cmd.cmd_security_set_flash_policy(host_offset=0x8000000, length=len(data)))
if type(result) is DwnFile:
self.info("Running sla auth...")
if self.upload(result, data):
self.info("Successfully uploaded sla auth.")
@ -572,17 +582,53 @@ class DAXML(metaclass=LogBase):
return False
def upload_da(self):
self.daext = False
loaded = False
if self.upload_da1():
self.info("Stage 1 successfully loaded.")
da2 = self.daconfig.da2
da2offset = self.daconfig.da_loader.region[2].m_start_addr
if not self.mtk.daloader.patch:
loaded = self.boot_to(da2offset, da2)
self.daext = False
if self.carbonara is not None:
loaded = self.boot_to(da2offset, da2)
if loaded:
self.patch = True
else:
loaded = self.boot_to(da2offset, da2)
if not loaded:
self.daext = False
self.patch = False
elif self.mtk.config.target_config["sbc"]:
self.patch = True
else:
loaded = self.boot_to(da2offset, da2)
sla_signature = b"\x00" * 0x100
self.handle_sla(data=sla_signature)
if loaded:
self.info("Successfully uploaded stage 2")
self.setup_hw_init()
self.change_usb_speed()
res = self.check_sla()
if isinstance(res, bool):
if not res:
self.info("SLA is disabled")
else:
self.info("SLA is enabled")
self.dev_info = self.get_dev_info()
found = False
for key in da_sla_keys:
if da2.find(bytes.fromhex(key.n)) != -1:
sla_signature = generate_da_sla_signature(data=self.dev_info["rnd"], d=key.d, n=key.n,
e=key.e)
self.handle_sla(data=sla_signature)
found = True
break
if not found:
print("No valid sla key found, using dummy auth ....")
sla_signature = b"\x00" * 0x100
self.handle_sla(data=sla_signature)
else:
self.error(res)
if self.patch:
xmlcmd = self.Cmd.create_cmd("CUSTOM")
if self.xsend(xmlcmd):
# result =
@ -610,21 +656,6 @@ class DAXML(metaclass=LogBase):
else:
self.error("DA XML Extensions failed.")
self.daext = False
if loaded:
self.info("Successfully uploaded stage 2")
self.setup_hw_init()
self.change_usb_speed()
res = self.check_sla()
if isinstance(res, bool):
if not res:
self.info("SLA is disabled")
else:
self.info("SLA is enabled")
else:
self.error(res)
self.storage = self.get_hw_info()
self.reinit(True)
self.check_lifecycle()
# parttbl = self.read_partition_table()
@ -632,10 +663,32 @@ class DAXML(metaclass=LogBase):
return True
return False
def get_dev_info(self):
self.send_command(self.Cmd.cmd_get_dev_info(), noack=True)
cmd, result = self.get_command_result()
if not isinstance(result, UpFile):
return False
data = self.download(result)
# CMD:END
scmd, sresult = self.get_command_result()
self.ack()
if sresult == "OK":
content = {}
if b"rnd" in data:
content["rnd"] = bytes.fromhex(get_field(data, "rnd"))
if b"hrid" in data:
content["hrid"] = bytes.fromhex(get_field(data, "hrid"))
if b"socid" in data:
content["socid"] = bytes.fromhex(get_field(data, "socid"))
tcmd, tresult = self.get_command_result()
if tresult == "START":
return content
return None
def get_hw_info(self):
self.send_command(self.Cmd.cmd_get_hw_info(), noack=True)
cmd, result = self.get_command_result()
if not isinstance(result, upfile):
if not isinstance(result, UpFile):
return False
data = self.download(result)
"""
@ -664,7 +717,7 @@ class DAXML(metaclass=LogBase):
if tresult == "START":
storage = get_field(data, "storage")
class storage_info:
class StorageInfo:
def __init__(self, storagetype, data):
self.storagetype = storagetype
if self.storagetype == "UFS":
@ -700,61 +753,10 @@ class DAXML(metaclass=LogBase):
else:
self.error(f"Unknown storage type: {storage}")
return storage_info(storagetype=storage, data=data)
return StorageInfo(storagetype=storage, data=data)
def check_sla(self):
"""
;private_key_d="009a3c3d4da0650cef38ed96ef833904c9c13835199367c7b9cb03a55e7aa482016a820dfe597cd54dd1f81fd879cf0
70ec0c25899ac5a49822db09675a92acf6a01e0f8f538bbe66de48ca9bdca313b616470d9ec2914356d03c95f7d9236549e5a21457e4dd5
fcaf09046c47ca7436f06cd7b82cb6d2a936fca88b707f6ce28f33110fea1ec363e8482419db901cb0d38e574fe0c02ad117166b40ec78f
59aaa7f3eafa425010a95614e046651273a6cb1371380c4e6ce81bdb892db6ff4892cc4d8c613a8fb3fec1e72c279052896872fc23da07f
ba63783374f3be8e16a15e0a04a139108dd6ac239f191135f4a895e27c670de065d2248e3f9c7e920fd001"
;public_key_e = "00010001"
;public_key_n = "008C8BF38EB2FC7FC06D567DBF70E9C34BE4281C4239ED9C58A6B598C3AE7821815D94D0B463463EEBBD69FF6AF990
AE0499B6C3B3CADCD91D54499CD66E5314DB610FC0C6CAEEB1F16B6F2D451E3F2B2D515008917FCEC50ADA4CE0699BCF247D5AE2A1DDD34
C48624A657CCB11CE5F8C6CE92CAB6038EFC2A89E42E029488C02C3CF21947C86D51BBA8EF540A2A7CE85356F431891261D860B518E89DD
73B2D240461ACB66BCC213403145DE83F6963147E65274EA1E45DB2D231E0774ECC86E4F2328F8A90835C4FDEF1088DDBA1D8F7CA0CA732
A64BDA6816162C0F88F02CF97634D85530968CBF8B7CE6A8B67D53BBFB4910843EA413135D56FB5074445"
ROWAN / 0_2048_key.pem / CHIP_TEST_KEY.ini
e_brom = 010001
n_brom = D16403466C530EF9BB53C1E8A96A61A4E332E17DC0F55BB46D207AC305BAE9354EAAC2CB3077B33740D275036B822DB268200D
E17DA3DB7266B27686B8970B85737050F084F8D576904E74CD6C53B31F0BB0CD60686BF67C60DA0EC20F563EEA715CEBDBF76D1C5C10E98
2AB2955D833DE553C9CDAFD7EA2388C02823CFE7DD9AC83FA2A8EB0685ABDAB56A92DF1A7805E8AC0BD10C0F3DCB1770A9E6BBC3418C5F8
4A48B7CB2316B2C8F64972F391B116A58C9395A9CE9E743569A367086D7771D39FEC8EBBBA3DD2B519785A76A9F589D36D637AF884543FD
65BAC75BE823C0C50AA16D58187B97223625C54C66B5A5E4DBAEAB7BE89A4E340A2E241B09B2F
d_brom = 09976537029b4362591c5b13873f223de5525d55df52dde283e52afa67f6c9dbf1408d2fb586a624efc93426f5f3be981f80e8
61ddd975a1e5e662db84f5164804a3ae717605d7f15866df9ed1497c38fdd6197243163ef22f958d7b822c57317203e9a1e7d18dad01f15
054facdbddb9261a1272638da661fe4f9f0714ecf00e6541cc435afb1fd75a27d34b17ad400e9474ba850dafce266799caff32a058ff71e
4c2daacaf8ba709e9ca4dc87584a7ffe8aa9a0a160ed069c3970b7dae3987ded71bd0bc824356987bd74363d46682c71913c3edbdb2a911
f701f23aee3f8dd98180b5a138fd5ad74743682d2d2d1bb3d92786710248f316dd8391178ea81
SetRsaKey in libsla_challenge.so :
e_brom = 010001
n_brom = C43469A95B143CDC63CE318FE32BAD35B9554A136244FA74D13947425A32949EE6DC808CDEBF4121687A570B83C51E657303C92
5EC280B420C757E5A63AD3EC6980AAD5B6CA6D1BBDC50DB793D2FDDC0D0361C06163CFF9757C07F96559A2186322F7ABF1FFC7765F39667
3A48A4E8E3296427BC5510D0F97F54E5CA1BD7A93ADE3F6A625056426BDFE77B3B502C68A18F08B470DA23B0A2FAE13B8D4DB3746255371F
43306582C74794D1491E97FDE504F0B1ECAC9DDEF282D674B817B7FFA8522672CF6281790910378FEBFA7DC6C2B0AF9DA03A58509D60AA1A
D6F9BFDC84537CD0959B8735FE0BB9B471104B458A38DF846366926993097222F90628528F
d_brom = 8E02CDB389BBC52D5383EBB5949C895B0850E633CF7DD3B5F7B5B8911B0DDF2A80387B46FAF67D22BC2748978A0183B5B420BA
579B6D847082EA0BD14AB21B6CCCA175C66586FCE93756C2F426C85D7DF07629A47236265D1963B8354CB229AFA2E560B7B3641DDB8A0A83
9ED8F39BA8C7CDB94104650E8C7790305E2FF6D18206F49B7290B1ADB7B4C523E10EBF53630D438EF49C877402EA3C1BD6DD903892FD662
FBDF1DFF5D7B095712E58E728BD7F6A8B5621175F4C08EBD6143CDACD65D9284DFFECAB64F70FD63182E4981551522727A2EE9873D0DB78
180C26553AD0EE1CAAA21BCEBC5A8C0B331FE7FD8710F905A7456AF675A04AF1118CE71E36C9
d_da = 707C8892D0DE8CE0CA116914C8BD277B821E784D298D00D3473EDE236399435F8541009525C2786CB3ED3D7530D47C9163692B0D5
88209E7E0E8D06F4A69725498B979599DC576303B5D8D96F874687A310D32E8C86E965B844BC2ACE51DC5E06859EA087BD536C39DCB8E126
2FDEAF6DA20035F14D3592AB2C1B58734C5C62AC86FE44F98C602BABAB60A6C8D09A199D2170E373D9B9A5D9B6DE852E859DEB1BDF33034
DCD91EC4EEBFDDBECA88E29724391BB928F40EFD945299DFFC4595BB8D45F426AC15EC8B1C68A19EB51BEB2CC6611072AE5637DF0ABA89ED
1E9CB8C9AC1EB05B1F01734DB303C23BE1869C9013561B9F6EA65BD2516DE950F08B2E81
n_da = A243F6694336D527C5B3ED569DDD0386D309C6592841E4C033DCB461EEA7B6F8535FC4939E403060646A970DD81DE367CF003848
146F19D259F50A385015AF6309EAA71BFED6B098C7A24D4871B4B82AAD7DC6E2856C301BE7CDB46DC10795C0D30A68DD8432B5EE5DA42BA2
2124796512FCA21D811D50B34C2F672E25BCC2594D9C012B34D473EE222D1E56B90E7D697CEA97E8DD4CCC6BED5FDAECE1A43F96495335F3
22CCE32612DAB462B024281841F553FF7FF33E0103A7904037F8FE5D9BE293ACD7485CDB50957DB11CA6DB28AF6393C3E78D9FBCD4567DE
BCA2601622F0F2EB19DA9192372F9EA3B28B1079409C0A09E3D51D64A4C4CE026FAD24CD7
e_da = 010001
int RSA_private_encrypt(int flen, unsigned char *from, unsigned char *to, RSA *rsa, int padding);
0x10, , 1
"""
@ -771,7 +773,7 @@ class DAXML(metaclass=LogBase):
def get_sys_property(self, key: str = "DA.SLA", length: int = 0x200000):
self.send_command(self.Cmd.cmd_get_sys_property(key=key, length=length), noack=True)
cmd, result = self.get_command_result()
if type(result) is not upfile:
if type(result) is not UpFile:
return False
data = self.download(result)
# CMD:END
@ -791,7 +793,7 @@ class DAXML(metaclass=LogBase):
def read_partition_table(self) -> tuple:
self.send_command(self.Cmd.cmd_read_partition_table(), noack=True)
cmd, result = self.get_command_result()
if type(result) is not upfile:
if type(result) is not UpFile:
return b"", None
data = self.download(result)
# CMD:END
@ -800,7 +802,7 @@ class DAXML(metaclass=LogBase):
if sresult == "OK":
tcmd, tresult = self.get_command_result()
class partitiontable:
class PartitionTable:
def __init__(self, name, start, size):
self.name = name
self.start = start
@ -813,13 +815,13 @@ class DAXML(metaclass=LogBase):
name = get_field(item, "name")
if name != '':
start = get_field(item, "start")
size = get_field(item, "size")
rsize = get_field(item, "size")
if size == "":
continue
size = int(size, 16)
rsize = int(rsize, 16)
start = int(start, 16)
parttbl.append(
partitiontable(name, start // self.config.pagesize, size // self.config.pagesize))
PartitionTable(name, start // self.config.pagesize, rsize // self.config.pagesize))
return data, parttbl
return b"", None
@ -880,8 +882,8 @@ class DAXML(metaclass=LogBase):
storage = DaStorage.MTK_DA_STORAGE_NAND
elif self.daconfig.flashtype == "ufs":
storage = DaStorage.MTK_DA_STORAGE_UFS
if parttype == EMMC_PartitionType.MTK_DA_EMMC_PART_USER:
parttype = UFS_PartitionType.UFS_LU3
if parttype == EmmcPartitionType.MTK_DA_EMMC_PART_USER:
parttype = UFSPartitionType.UFS_LU3
elif self.daconfig.flashtype == "sdc":
storage = DaStorage.MTK_DA_STORAGE_SDMMC
else:
@ -905,7 +907,7 @@ class DAXML(metaclass=LogBase):
self.send_command(self.Cmd.cmd_read_flash(parttype, addr, length), noack=True)
cmd, result = self.get_command_result()
if type(result) is not upfile:
if type(result) is not UpFile:
return b""
data = self.download_raw(result=result, filename=filename, display=display)
scmd, sresult = self.get_command_result()
@ -947,12 +949,12 @@ class DAXML(metaclass=LogBase):
self.send_command(self.Cmd.cmd_write_flash(partition=parttype, offset=addr, mem_length=length), noack=True)
cmd, fileopresult = self.get_command_result()
if type(fileopresult) is file_sys_op:
if type(fileopresult) is FileSysOp:
if fileopresult.key != "FILE-SIZE":
return False
self.ack_value(length)
cmd, result = self.get_command_result()
if type(result) is dwnfile:
if type(result) is DwnFile:
data = fh.read(length)
if not self.upload(result, data, raw=True):
self.error("Error on writing flash at 0x%08X" % addr)
@ -967,7 +969,7 @@ class DAXML(metaclass=LogBase):
def check_lifecycle(self):
self.send_command(self.Cmd.cmd_emmc_control(function="LIFE-CYCLE-STATUS"), noack=True)
cmd, result = self.get_command_result()
if not isinstance(result, upfile):
if not isinstance(result, UpFile):
return False
data = self.download(result)
scmd, sresult = self.get_command_result()
@ -987,6 +989,7 @@ class DAXML(metaclass=LogBase):
self.ufs = self.get_ufs_info(display)
"""
self.storage = self.get_hw_info()
display = display
if isinstance(self.storage, bool):
self.error("Error: Cannot Reinit daconfig")
return
@ -1075,15 +1078,17 @@ class DAXML(metaclass=LogBase):
if not part_info:
return False
storage, parttype, length = part_info
self.info(f"Formatting addr {hex(addr)} with length {hex(length)}, please standby....")
if display:
self.info(f"Formatting addr {hex(addr)} with length {hex(length)}, please standby....")
self.mtk.daloader.progress.show_progress("Erasing", 0, length, True)
self.send_command(self.Cmd.cmd_erase_flash(partition=parttype, offset=addr, length=length))
result = self.get_response()
if result == "OK":
self.info(f"Successsfully formatted addr {hex(addr)} with length {length}.")
if display:
self.info(f"Successsfully formatted addr {hex(addr)} with length {length}.")
return True
self.error("Error on format.")
if display:
self.error("Error on format.")
return False
def shutdown(self, async_mode: int = 0, dl_bit: int = 0, bootmode: ShutDownModes = ShutDownModes.NORMAL):

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
from binascii import hexlify
from struct import pack, unpack
@ -18,10 +18,10 @@ class Amonet(Exploitation, metaclass=LogBase):
pass
def da_read_write(self, address, length, data=None, check_result=True):
old = 0
if self.chipconfig.blacklist:
self.hwcrypto.disable_range_blacklist("gcpu", self.mtk)
if data is None:
old = 0
data = bytearray()
for addr in range(address, address + length, 16):
prog = int(addr / length * 100)

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
from struct import pack, unpack
@ -68,7 +68,7 @@ class Hashimoto(Exploitation, metaclass=LogBase):
if filename is None:
data = bytearray()
for addr in range(0x200000, 0x240000, 16):
data.extend(self.hwcrypto.cqdma.mem_read(addr, 16, not self.chipconfig.blacklist))
data.extend(self.hwcrypto.Cqdma.mem_read(addr, 16, not self.chipconfig.blacklist))
return data, filename
else:
print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50)
@ -80,7 +80,7 @@ class Hashimoto(Exploitation, metaclass=LogBase):
print_progress(prog, 100, prefix='Progress:', suffix='Complete, addr %08X' % addr,
bar_length=50)
old = round(prog, 1)
wf.write(self.hwcrypto.cqdma.mem_read(addr, 16, not self.chipconfig.blacklist))
wf.write(self.hwcrypto.Cqdma.mem_read(addr, 16, not self.chipconfig.blacklist))
print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50)
return True
@ -101,6 +101,6 @@ class Hashimoto(Exploitation, metaclass=LogBase):
print_progress(prog, 100, prefix='Progress:', suffix='Complete, addr %08X' % addr,
bar_length=50)
old = round(prog, 1)
wf.write(self.hwcrypto.cqdma.mem_read(addr, 16, not self.chipconfig.blacklist))
wf.write(self.hwcrypto.Cqdma.mem_read(addr, 16, not self.chipconfig.blacklist))
print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50)
return True

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import time
import os

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import hashlib
import logging
import array
@ -17,6 +17,7 @@ class Kamakiri2(Exploitation, metaclass=LogBase):
def __init__(self, mtk, loglevel=logging.INFO):
super().__init__(mtk, loglevel)
self.udev = None
self.linecode = None
def kamakiri2(self, addr):

View file

@ -1,99 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
import logging
import array
from struct import pack
from mtkclient.Library.exploit_handler import Exploitation
from mtkclient.Library.utils import LogBase
from mtkclient.Library.Connection.usblib import usb
class Kamakiri_Pl(Exploitation, metaclass=LogBase):
def __init__(self, mtk, loglevel=logging.INFO):
super().__init__(mtk, loglevel)
self.linecode = None
def initbrom(self):
# bypass1stda
for i in range(5):
getVal = self.mtk.port.cdc.device.ctrl_transfer(bmRequestType=0xa1,
bRequest=0x21,
wValue=0,
wIndex=0,
data_or_wLength=7)
data = pack("<Q", 0x800000001C200)
self.mtk.port.cdc.device.ctrl_transfer(bmRequestType=0x21,
bRequest=0x20,
wValue=0,
wIndex=0,
data_or_wLength=array.array('B', data))
for i in range(2):
self.mtk.port.cdc.device.ctrl_transfer(bmRequestType=0x21,
bRequest=0x22,
wValue=0x3,
wIndex=0,
data_or_wLength=0)
getVal = self.mtk.port.cdc.device.ctrl_transfer(bmRequestType=0xa1,
bRequest=0x21,
wValue=0,
wIndex=0,
data_or_wLength=7)
self.mtk.port.cdc.device.ctrl_transfer(bmRequestType=0x21,
bRequest=0x20,
wValue=0,
wIndex=0,
data_or_wLength=getVal)
self.mtk.port.cdc.device.ctrl_transfer(bmRequestType=0x21,
bRequest=0x23,
wValue=0,
wIndex=0,
data_or_wLength=0)
for i in range(2):
self.mtk.port.cdc.device.ctrl_transfer(bmRequestType=0x21,
bRequest=0x22,
wValue=0x3,
wIndex=0,
data_or_wLength=0)
def bypass2ndDA(self):
usb.util.claim_interface(self.mtk.port.cdc.device, 0)
try:
# ret =
self.mtk.port.cdc.device.ctrl_transfer(bmRequestType=0x80,
bRequest=0x6,
wValue=0x02FF,
wIndex=0xFFFF,
data_or_wLength=9)
except Exception:
pass
try:
# value =
self.mtk.port.cdc.device.ctrl_transfer(0xA1, 0x21, 0, 0, 7) + array.array('B', [0])
except Exception:
pass
data = pack("<QI", 0x800000001C200, 0x22C3B0)
try:
self.mtk.port.cdc.device.ctrl_transfer(bmRequestType=0x21,
bRequest=0x20,
wValue=0,
wIndex=0,
data_or_wLength=array.array('B', data))
except Exception:
pass
try:
# ret =
self.mtk.port.cdc.device.ctrl_transfer(bmRequestType=0x80,
bRequest=0x6,
wValue=0x02FF,
wIndex=0xFFFF,
data_or_wLength=9)
except Exception:
pass

View file

@ -0,0 +1,99 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import array
from struct import pack
from mtkclient.Library.exploit_handler import Exploitation
from mtkclient.Library.utils import LogBase
from mtkclient.Library.Connection.usblib import usb
class KamakiriPl(Exploitation, metaclass=LogBase):
def __init__(self, mtk, loglevel=logging.INFO):
super().__init__(mtk, loglevel)
self.linecode = None
def initbrom(self):
# bypass1stda
for i in range(5):
get_val = self.mtk.port.cdc.device.ctrl_transfer(bm_request_type=0xa1,
b_request=0x21,
w_value=0,
w_index=0,
data_or_w_length=7)
data = pack("<Q", 0x800000001C200)
self.mtk.port.cdc.device.ctrl_transfer(bm_request_type=0x21,
b_request=0x20,
w_value=0,
w_index=0,
data_or_w_length=array.array('B', data))
for i in range(2):
self.mtk.port.cdc.device.ctrl_transfer(bm_request_type=0x21,
b_request=0x22,
w_value=0x3,
w_index=0,
data_or_w_length=0)
get_val = self.mtk.port.cdc.device.ctrl_transfer(bm_request_type=0xa1,
b_request=0x21,
w_value=0,
w_index=0,
data_or_w_length=7)
self.mtk.port.cdc.device.ctrl_transfer(bm_request_type=0x21,
b_request=0x20,
w_value=0,
w_index=0,
data_or_w_length=get_val)
self.mtk.port.cdc.device.ctrl_transfer(bm_request_type=0x21,
b_request=0x23,
w_value=0,
w_index=0,
data_or_w_length=0)
for i in range(2):
self.mtk.port.cdc.device.ctrl_transfer(bm_request_type=0x21,
b_request=0x22,
w_value=0x3,
w_index=0,
data_or_w_length=0)
def bypass_2nd_da(self):
usb.util.claim_interface(self.mtk.port.cdc.device, 0)
try:
# ret =
self.mtk.port.cdc.device.ctrl_transfer(bm_request_type=0x80,
b_request=0x6,
w_value=0x02FF,
w_index=0xFFFF,
data_or_w_length=9)
except Exception:
pass
try:
# value =
self.mtk.port.cdc.device.ctrl_transfer(0xA1, 0x21, 0, 0, 7) + array.array('B', [0])
except Exception:
pass
data = pack("<QI", 0x800000001C200, 0x22C3B0)
try:
self.mtk.port.cdc.device.ctrl_transfer(bm_request_type=0x21,
b_request=0x20,
w_value=0,
w_index=0,
data_or_w_length=array.array('B', data))
except Exception:
pass
try:
# ret =
self.mtk.port.cdc.device.ctrl_transfer(bm_request_type=0x80,
b_request=0x6,
w_value=0x02FF,
w_index=0xFFFF,
data_or_w_length=9)
except Exception:
pass

View file

@ -1,11 +1,17 @@
try:
from fuse import Operations, LoggingMixIn
except ImportError:
raise ImportError('fuse library not installed')
from stat import S_IFDIR, S_IFREG
from tempfile import NamedTemporaryFile
from time import time
import sys
import os
if not os.environ.get('FUSE_LIBRARY_PATH') and os.name == 'nt':
os.environ.setdefault('FUSE_LIBRARY_PATH', os.path.join(os.path.dirname(__file__), r"bin\winfsp-%s.dll" % ("x64" if sys.maxsize > 0xffffffff else "x86")))
from fuse import Operations, LoggingMixIn
os.environ.setdefault('FUSE_LIBRARY_PATH',
os.path.join(os.path.dirname(__file__),
r"bin\winfsp-%s.dll" % ("x64" if sys.maxsize > 0xffffffff else "x86")))
class MtkDaFS(LoggingMixIn, Operations):

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import os
from struct import pack, unpack
@ -21,7 +21,7 @@ regval = {
}
class cqdma_reg:
class CqdmaReg:
def __init__(self, setup):
self.cqdma_base = setup.cqdma_base
self.read32 = setup.read32
@ -29,25 +29,26 @@ class cqdma_reg:
def __setattr__(self, key, value):
if key in ("cqdma_base", "read32", "write32", "regval"):
return super(cqdma_reg, self).__setattr__(key, value)
return super(CqdmaReg, self).__setattr__(key, value)
if key in regval:
addr = regval[key] + self.cqdma_base
return self.write32(addr, value)
else:
return super(cqdma_reg, self).__setattr__(key, value)
return super(CqdmaReg, self).__setattr__(key, value)
def __getattribute__(self, item):
if item in ("cqdma_base", "read32", "write32", "regval"):
return super(cqdma_reg, self).__getattribute__(item)
return super(CqdmaReg, self).__getattribute__(item)
if item in regval:
addr = regval[item] + self.cqdma_base
return self.read32(addr)
else:
return super(cqdma_reg, self).__getattribute__(item)
return super(CqdmaReg, self).__getattribute__(item)
class cqdma(metaclass=LogBase):
class Cqdma(metaclass=LogBase):
def __init__(self, setup, loglevel=logging.INFO):
self.chipconfig = None
self.setup = setup
self.hwcode = setup.hwcode
self.__logger = self.__logger
@ -56,7 +57,7 @@ class cqdma(metaclass=LogBase):
self.info = self.__logger.info
self.cqdma_base = setup.cqdma_base
self.ap_dma_mem = setup.ap_dma_mem
self.reg = cqdma_reg(setup)
self.reg = CqdmaReg(setup)
if loglevel == logging.DEBUG:
logfilename = os.path.join("logs", "log.txt")
fh = logging.FileHandler(logfilename, encoding='utf-8')

View file

@ -1,17 +1,17 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import sys
from mtkclient.Library.utils import LogBase, logsetup
from mtkclient.Library.Hardware.hwcrypto_gcpu import GCpu
from mtkclient.Library.Hardware.hwcrypto_dxcc import dxcc
from mtkclient.Library.Hardware.hwcrypto_sej import sej
from mtkclient.Library.Hardware.cqdma import cqdma
from mtkclient.Library.Hardware.hwcrypto_dxcc import Dxcc
from mtkclient.Library.Hardware.hwcrypto_sej import Sej
from mtkclient.Library.Hardware.cqdma import Cqdma
class crypto_setup:
class CryptoSetup:
hwcode = None
dxcc_base = None
gcpu_base = None
@ -29,13 +29,13 @@ class crypto_setup:
efuse_base = None
class hwcrypto(metaclass=LogBase):
class HwCrypto(metaclass=LogBase):
def __init__(self, setup, loglevel=logging.INFO, gui: bool = False):
self.__logger = logsetup(self, self.__logger, loglevel, gui)
self.dxcc = dxcc(setup, loglevel, gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger, loglevel, gui)
self.dxcc = Dxcc(setup, loglevel, gui)
self.gcpu = GCpu(setup, loglevel, gui)
self.sej = sej(setup, loglevel)
self.cqdma = cqdma(setup, loglevel)
self.sej = Sej(setup, loglevel)
self.cqdma = Cqdma(setup, loglevel)
self.hwcode = setup.hwcode
self.setup = setup
self.read32 = setup.read32
@ -62,7 +62,7 @@ class hwcrypto(metaclass=LogBase):
elif mode == "sst":
self.sej.sej_base = 0xC0016000
data2 = self.sej.generate_hw_meta(encrypt=True, data=data)
data3 = self.sej.SST_Secure_Algo_With_Level(buf=data, encrypt=True)
data3 = self.sej.sst_secure_algo_with_level(buf=data, encrypt=True)
print(data2.hex())
print(data3.hex())
sys.stdout.flush()
@ -72,7 +72,7 @@ class hwcrypto(metaclass=LogBase):
return self.sej.hw_aes128_cbc_encrypt(buf=data, encrypt=False)
elif mode == "sst":
self.sej.sej_base = 0xC0016000
data3 = self.sej.SST_Secure_Algo_With_Level(buf=data[:0x20], encrypt=False, aes_top_legacy=False)
data3 = self.sej.sst_secure_algo_with_level(buf=data[:0x20], encrypt=False, aes_top_legacy=False)
print(data3.hex())
sys.stdout.flush()
if mode == "rpmb":

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
# DXCC = Discretix CryptoCell
@ -584,7 +584,7 @@ class DescDirection:
DESC_DIRECTION_END = INT32_MAX
class sep_engine_type:
class SepEngineType:
SEP_ENGINE_NULL = 0
SEP_ENGINE_AES = 1
SEP_ENGINE_DES = 2
@ -593,7 +593,7 @@ class sep_engine_type:
SEP_ENGINE_DOUT = 5
class sep_crypto_alg:
class SepCryptoAlg:
SEP_CRYPTO_ALG_NULL = 0xFFFFFFFF
SEP_CRYPTO_ALG_AES = 0
SEP_CRYPTO_ALG_DES = 1
@ -608,7 +608,7 @@ class sep_crypto_alg:
SEP_CRYPTO_ALG_RESERVE32B = INT32_MAX
class sep_crypto_direction:
class SepCryptoDirection:
SEP_CRYPTO_DIRECTION_NULL = 0xFFFFFFFF
SEP_CRYPTO_DIRECTION_ENCRYPT = 0
SEP_CRYPTO_DIRECTION_DECRYPT = 1
@ -616,7 +616,7 @@ class sep_crypto_direction:
SEP_CRYPTO_DIRECTION_RESERVE32B = INT32_MAX
class sep_cipher_mode:
class SepCipherMode:
SEP_CIPHER_NULL_MODE = 0xFFFFFFFF
SEP_CIPHER_ECB = 0
SEP_CIPHER_CBC = 1
@ -632,7 +632,7 @@ class sep_cipher_mode:
SEP_CIPHER_RESERVE32B = INT32_MAX
class sep_hash_mode:
class SepHashMode:
SEP_HASH_NULL = 0xFFFFFFFF
SEP_HASH_SHA1 = 0
SEP_HASH_SHA256 = 1
@ -647,7 +647,7 @@ class sep_hash_mode:
SEP_HASH_RESERVE32B = INT32_MAX
class sep_hash_hw_mode:
class SepHashHwMode:
SEP_HASH_HW_MD5 = 0
SEP_HASH_HW_SHA1 = 1
SEP_HASH_HW_SHA256 = 2
@ -658,14 +658,14 @@ class sep_hash_hw_mode:
SEP_HASH_HW_RESERVE32B = INT32_MAX
class sep_c2_mode:
class SepC2Mode:
SEP_C2_NULL = 0xFFFFFFFF
SEP_C2_ECB = 0
SEP_C2_CBC = 1
SEP_C2_RESERVE32B = INT32_MAX
class sep_multi2_mode:
class SepMulti2Mode:
SEP_MULTI2_NULL = 0xFFFFFFFF
SEP_MULTI2_ECB = 0
SEP_MULTI2_CBC = 1
@ -673,7 +673,7 @@ class sep_multi2_mode:
SEP_MULTI2_RESERVE32B = INT32_MAX
class sep_crypto_key_type:
class SepCryptoKeyType:
SEP_USER_KEY = 0
SEP_ROOT_KEY = 1
SEP_PROVISIONING_KEY = 2
@ -875,129 +875,129 @@ def tovalue(value, bitsize, shift):
return v << shift
def hw_desc_set_cipher_mode(pDesc, cipherMode):
def hw_desc_set_cipher_mode(p_desc, cipher_mode):
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_MODE"]
pDesc[4] |= tovalue(cipherMode, bitsize, shift)
return pDesc
p_desc[4] |= tovalue(cipher_mode, bitsize, shift)
return p_desc
def hw_desc_set_cipher_config0(pDesc, cipherConfig):
def hw_desc_set_cipher_config0(p_desc, cipher_config):
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_CONF0"]
pDesc[4] |= tovalue(cipherConfig, bitsize, shift)
return pDesc
p_desc[4] |= tovalue(cipher_config, bitsize, shift)
return p_desc
def hw_desc_set_cipher_config1(pDesc, cipherConfig):
def hw_desc_set_cipher_config1(p_desc, cipher_config):
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_CONF1"]
pDesc[4] |= tovalue(cipherConfig, bitsize, shift)
return pDesc
p_desc[4] |= tovalue(cipher_config, bitsize, shift)
return p_desc
def hw_desc_set_setup_mode(pDesc, setupMode):
def hw_desc_set_setup_mode(p_desc, setup_mode):
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["SETUP_OPERATION"]
pDesc[4] |= tovalue(setupMode, bitsize, shift)
return pDesc
p_desc[4] |= tovalue(setup_mode, bitsize, shift)
return p_desc
def hw_desc_set_flow_mode(pDesc, flowMode):
def hw_desc_set_flow_mode(p_desc, flow_mode):
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["DATA_FLOW_MODE"]
pDesc[4] |= tovalue(flowMode, bitsize, shift)
return pDesc
p_desc[4] |= tovalue(flow_mode, bitsize, shift)
return p_desc
def hw_desc_set_dout_sram(pDesc, doutAdr, doutSize):
def hw_desc_set_dout_sram(p_desc, dout_adr, dout_size):
v = DSCRPTR["DSCRPTR_QUEUE0_WORD2"]
shift, bitsize = v[1], v[2]
pDesc[2] |= tovalue((doutAdr & 0xFFFFFFFF), bitsize, shift)
p_desc[2] |= tovalue((dout_adr & 0xFFFFFFFF), bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["DOUT_DMA_MODE"]
pDesc[3] |= tovalue(DmaMode.DMA_SRAM, bitsize, shift)
p_desc[3] |= tovalue(DmaMode.DMA_SRAM, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["DOUT_SIZE"]
pDesc[3] |= tovalue(doutSize, bitsize, shift)
return pDesc
p_desc[3] |= tovalue(dout_size, bitsize, shift)
return p_desc
def hw_desc_set_dout_dlli(pDesc, doutAdr, doutSize, axiNs, lastind):
def hw_desc_set_dout_dlli(p_desc, dout_adr, dout_size, axi_ns, lastind):
v = DSCRPTR["DSCRPTR_QUEUE0_WORD2"]
shift, bitsize = v[1], v[2]
pDesc[2] |= tovalue((doutAdr & 0xFFFFFFFF), bitsize, shift)
p_desc[2] |= tovalue((dout_adr & 0xFFFFFFFF), bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD5"][1]["DOUT_ADDR_HIGH"]
pDesc[5] |= tovalue((doutAdr >> 32 & 0xFFFFFFFF) << 16, bitsize, shift)
p_desc[5] |= tovalue((dout_adr >> 32 & 0xFFFFFFFF) << 16, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["DOUT_DMA_MODE"]
pDesc[3] |= tovalue(DmaMode.DMA_DLLI, bitsize, shift)
p_desc[3] |= tovalue(DmaMode.DMA_DLLI, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["DOUT_SIZE"]
pDesc[3] |= tovalue(doutSize, bitsize, shift)
p_desc[3] |= tovalue(dout_size, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["DOUT_LAST_IND"]
pDesc[3] |= tovalue(lastind, bitsize, shift)
p_desc[3] |= tovalue(lastind, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD3"][1]["NS_BIT"]
pDesc[3] |= tovalue(lastind, bitsize, shift)
return pDesc
p_desc[3] |= tovalue(lastind, bitsize, shift)
return p_desc
def hw_desc_set_key_size_aes(pDesc, keySize):
def hw_desc_set_key_size_aes(p_desc, key_size):
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["KEY_SIZE"]
pDesc[4] |= tovalue(((keySize >> 3) - 2), bitsize, shift)
return pDesc
p_desc[4] |= tovalue(((key_size >> 3) - 2), bitsize, shift)
return p_desc
def hw_desc_set_din_sram(pDesc, dinAdr, dinSize):
def hw_desc_set_din_sram(p_desc, din_adr, din_size):
v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
shift, bitsize = v[1], v[2]
pDesc[0] |= tovalue(dinAdr & 0xFFFFFFFF, bitsize, shift)
p_desc[0] |= tovalue(din_adr & 0xFFFFFFFF, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_DMA_MODE"]
pDesc[1] |= tovalue(DmaMode.DMA_SRAM, bitsize, shift)
p_desc[1] |= tovalue(DmaMode.DMA_SRAM, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_SIZE"]
pDesc[1] |= tovalue(dinSize, bitsize, shift)
return pDesc
p_desc[1] |= tovalue(din_size, bitsize, shift)
return p_desc
def hw_desc_set_din_const(pDesc, val, dinSize):
def hw_desc_set_din_const(p_desc, val, din_size):
v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
shift, bitsize = v[1], v[2]
pDesc[0] |= tovalue(val & 0xFFFFFFFF, bitsize, shift)
p_desc[0] |= tovalue(val & 0xFFFFFFFF, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_CONST_VALUE"]
pDesc[1] |= tovalue(1, bitsize, shift)
p_desc[1] |= tovalue(1, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_DMA_MODE"]
pDesc[1] |= tovalue(DmaMode.DMA_SRAM, bitsize, shift)
p_desc[1] |= tovalue(DmaMode.DMA_SRAM, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_SIZE"]
pDesc[1] |= tovalue(dinSize, bitsize, shift)
return pDesc
p_desc[1] |= tovalue(din_size, bitsize, shift)
return p_desc
def hw_desc_set_cipher_do(pDesc, cipherDo):
def hw_desc_set_cipher_do(p_desc, cipher_do):
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD4"][1]["CIPHER_DO"]
pDesc[4] |= tovalue(cipherDo, bitsize, shift)
return pDesc
p_desc[4] |= tovalue(cipher_do, bitsize, shift)
return p_desc
def hw_desc_set_din_nodma(pDesc, dinAdr, dinSize):
def hw_desc_set_din_nodma(p_desc, din_adr, din_size):
v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
shift, bitsize = v[1], v[2]
pDesc[0] |= tovalue(dinAdr & 0xFFFFFFFF, bitsize, shift)
p_desc[0] |= tovalue(din_adr & 0xFFFFFFFF, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_DMA_MODE"]
pDesc[1] |= tovalue(DmaMode.NO_DMA, bitsize, shift)
p_desc[1] |= tovalue(DmaMode.NO_DMA, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_SIZE"]
pDesc[1] |= tovalue(dinSize, bitsize, shift)
return pDesc
p_desc[1] |= tovalue(din_size, bitsize, shift)
return p_desc
def hw_desc_set_din_type(pDesc, dmaMode, dinAdr, dinSize, axiId, axiNs):
def hw_desc_set_din_type(p_desc, dma_mode, din_adr, din_size, axi_id, axi_ns):
v = DSCRPTR["DSCRPTR_QUEUE0_WORD0"]
shift, bitsize = v[1], v[2]
pDesc[0] |= tovalue(dinAdr & 0xFFFFFFFF, bitsize, shift)
p_desc[0] |= tovalue(din_adr & 0xFFFFFFFF, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD5"][1]["DIN_ADDR_HIGH"]
pDesc[5] |= tovalue(dinAdr >> 32 & 0xFFFF, bitsize, shift)
p_desc[5] |= tovalue(din_adr >> 32 & 0xFFFF, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_DMA_MODE"]
pDesc[1] |= tovalue(dmaMode, bitsize, shift)
p_desc[1] |= tovalue(dma_mode, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_SIZE"]
pDesc[1] |= tovalue(dinSize, bitsize, shift)
p_desc[1] |= tovalue(din_size, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["DIN_VIRTUAL_HOST"]
pDesc[1] |= tovalue(axiId, bitsize, shift)
p_desc[1] |= tovalue(axi_id, bitsize, shift)
shift, bitsize = DSCRPTR["DSCRPTR_QUEUE0_WORD1"][1]["NS_BIT"]
pDesc[1] |= tovalue(axiNs, bitsize, shift)
return pDesc
p_desc[1] |= tovalue(axi_ns, bitsize, shift)
return p_desc
class dxcc_reg:
class DxccReg:
def __init__(self, setup):
self.dxcc_base = setup.dxcc_base
self.read32 = setup.read32
@ -1005,24 +1005,24 @@ class dxcc_reg:
def __setattr__(self, key, value):
if key in ("sej_base", "read32", "write32", "regval"):
return super(dxcc_reg, self).__setattr__(key, value)
return super(DxccReg, self).__setattr__(key, value)
if key in regval:
addr = regval[key] + self.sej_base
return self.write32(addr, value)
else:
return super(dxcc_reg, self).__setattr__(key, value)
return super(DxccReg, self).__setattr__(key, value)
def __getattribute__(self, item):
if item in ("sej_base", "read32", "write32", "regval"):
return super(dxcc_reg, self).__getattribute__(item)
return super(DxccReg, self).__getattribute__(item)
if item in regval:
addr = regval[item] + self.sej_base
return self.read32(addr)
else:
return super(dxcc_reg, self).__getattribute__(item)
return super(DxccReg, self).__getattribute__(item)
class dxcc(metaclass=LogBase):
class Dxcc(metaclass=LogBase):
DX_HOST_IRR = 0xA00
DX_HOST_ICR = 0xA08 # DX_CC = (HOST_RGF, HOST_ICR)
DX_DSCRPTR_QUEUE0_WORD0 = 0xE80
@ -1038,10 +1038,10 @@ class dxcc(metaclass=LogBase):
DX_HOST_SEP_HOST_GPR3 = 0xA9C
DX_HOST_SEP_HOST_GPR4 = 0xAA0
def SB_HalClearInterruptBit(self):
def sb_hal_clear_interrupt_bit(self):
self.write32(self.dxcc_base + self.DX_HOST_ICR, 4)
def SB_CryptoWait(self):
def sb_crypto_wait(self):
while True:
value = self.read32(self.dxcc_base + self.DX_HOST_IRR)
if value != 0:
@ -1067,7 +1067,7 @@ class dxcc(metaclass=LogBase):
self.write32(self.dxcc_base + self.DX_DSCRPTR_QUEUE0_WORD5, data[5])
def __init__(self, setup, loglevel=logging.INFO, gui: bool = False):
self.__logger = logsetup(self, self.__logger, loglevel, gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger, loglevel, gui)
self.hwcode = setup.hwcode
self.dxcc_base = setup.dxcc_base
self.read32 = setup.read32
@ -1075,7 +1075,7 @@ class dxcc(metaclass=LogBase):
self.writemem = setup.writemem
self.da_payload_addr = setup.da_payload_addr
self.reg = dxcc_reg(setup)
self.reg = DxccReg(setup)
def tzcc_clk(self, value):
if value:
@ -1091,7 +1091,7 @@ class dxcc(metaclass=LogBase):
for ctr in range(0, key_sz // 16):
itrustee = b"TrustedCorekeymaster" + b"\x07" * 0x10 + appid
seed = itrustee + pack("<B", ctr)
paddr = self.SBROM_AesCmac(1, 0x0, seed, 0x0, len(seed), dstaddr)
paddr = self.sbrom_aes_cmac(1, 0x0, seed, 0x0, len(seed), dstaddr)
for field in self.read32(paddr, 4):
fdekey += pack("<I", field)
self.tzcc_clk(0)
@ -1110,7 +1110,7 @@ class dxcc(metaclass=LogBase):
keylength = 0x10
self.tzcc_clk(1)
dstaddr = self.da_payload_addr - 0x300
rpmbkey = self.SBROM_KeyDerivation(1, rpmb_ikey, rpmb_salt, keylength, dstaddr)
rpmbkey = self.sbrom_key_derivation(1, rpmb_ikey, rpmb_salt, keylength, dstaddr)
self.tzcc_clk(0)
return rpmbkey
@ -1120,7 +1120,7 @@ class dxcc(metaclass=LogBase):
keylength = 0x10
self.tzcc_clk(1)
dstaddr = self.da_payload_addr - 0x300
rpmbkey = self.SBROM_KeyDerivation(1, rpmb_ikey, rpmb_salt, keylength, dstaddr)
rpmbkey = self.sbrom_key_derivation(1, rpmb_ikey, rpmb_salt, keylength, dstaddr)
self.tzcc_clk(0)
return rpmbkey
@ -1149,12 +1149,12 @@ class dxcc(metaclass=LogBase):
for i in range(8):
salt[i*4]=self.salt_func(0x10+i)
"""
provkey = self.SBROM_KeyDerivation(HwCryptoKey.PROVISIONING_KEY, plat_key, salt, 0x10, dstaddr)
provkey = self.sbrom_key_derivation(HwCryptoKey.PROVISIONING_KEY, plat_key, salt, 0x10, dstaddr)
while True:
val = self.read32(self.dxcc_base + 0xAF4) & 1
if val != 0:
break
platkey = self.SBROM_KeyDerivation(HwCryptoKey.PLATFORM_KEY, prov_key, salt, 0x10, dstaddr)
platkey = self.sbrom_key_derivation(HwCryptoKey.PLATFORM_KEY, prov_key, salt, 0x10, dstaddr)
self.write32(self.dxcc_base + 0xAC0, 0)
self.write32(self.dxcc_base + 0xAC4, 0)
self.write32(self.dxcc_base + 0xAC8, 0)
@ -1168,20 +1168,20 @@ class dxcc(metaclass=LogBase):
pdesc[5] = 0
self.sasi_sb_adddescsequence(pdesc)
dstaddr = self.da_payload_addr - 0x300
self.SB_HalWaitDescCompletion()
self.sb_hal_wait_desc_completion()
# data=self.read32(0x200D90)
self.tzcc_clk(0)
return platkey, provkey
def generate_sha256(self, data):
dstaddr = self.da_payload_addr - 0x300
self.sbrom_sha256(buffer=data, destaddr=dstaddr)
self.sbrom_sha256(_buffer=data, destaddr=dstaddr)
result = bytearray()
for field in self.read32(dstaddr, 8):
result.extend(pack("<I", field))
return result
def SBROM_KeyDerivation(self, aeskeytype, label, salt, requestedlen, destaddr):
def sbrom_key_derivation(self, aeskeytype, label, salt, requestedlen, destaddr):
result = bytearray()
if aeskeytype - 1 > 4 or (1 << (aeskeytype - 1) & 0x17) == 0:
return 0xF2000002
@ -1192,36 +1192,36 @@ class dxcc(metaclass=LogBase):
bufferlen = len(salt) + 3 + len(label)
iterlength = (requestedlen + 0xF) >> 4
for i in range(0, iterlength):
buffer = pack("<B", i + 1) + label + b"\x00" + salt + pack("<B", (8 * requestedlen) & 0xFF)
dstaddr = self.SBROM_AesCmac(aeskeytype, 0x0, buffer[:bufferlen], 0, bufferlen, destaddr)
_buffer = pack("<B", i + 1) + label + b"\x00" + salt + pack("<B", (8 * requestedlen) & 0xFF)
dstaddr = self.sbrom_aes_cmac(aeskeytype, 0x0, _buffer[:bufferlen], 0, bufferlen, destaddr)
if dstaddr != 0:
for field in self.read32(dstaddr, 4):
result.extend(pack("<I", field))
return result
def SBROM_AesCmac(self, aesKeyType, InternalKey, DataIn, dmaMode, bufferlen, destaddr):
sramAddr = destaddr
ivSramAddr = sramAddr
inputSramAddr = ivSramAddr + AES_IV_COUNTER_SIZE_IN_BYTES
blockSize = len(DataIn) // 0x20 * 0x20
outputSramAddr = inputSramAddr + blockSize
keySramAddr = outputSramAddr + blockSize
pInternalKey = keySramAddr
if InternalKey != 0:
self.writemem(keySramAddr, InternalKey)
if dmaMode != 0:
dmaMode = dmaMode
self.writemem(inputSramAddr, DataIn[:bufferlen])
if self.SBROM_AesCmacDriver(aesKeyType, pInternalKey, inputSramAddr, dmaMode, bufferlen, sramAddr):
return sramAddr
def sbrom_aes_cmac(self, aes_key_type, internal_key, data_in, dma_mode, bufferlen, destaddr):
sram_addr = destaddr
iv_sram_addr = sram_addr
input_sram_addr = iv_sram_addr + AES_IV_COUNTER_SIZE_IN_BYTES
block_size = len(data_in) // 0x20 * 0x20
output_sram_addr = input_sram_addr + block_size
key_sram_addr = output_sram_addr + block_size
p_internal_key = key_sram_addr
if internal_key != 0:
self.writemem(key_sram_addr, internal_key)
if dma_mode != 0:
dma_mode = dma_mode
self.writemem(input_sram_addr, data_in[:bufferlen])
if self.sbrom_aes_cmac_driver(aes_key_type, p_internal_key, input_sram_addr, dma_mode, bufferlen, sram_addr):
return sram_addr
return 0
def SB_HalInit(self):
return self.SB_HalClearInterruptBit()
def sb_hal_init(self):
return self.sb_hal_clear_interrupt_bit()
def SB_HalWaitDescCompletion(self, destptr=0):
def sb_hal_wait_desc_completion(self, destptr=0):
data = []
self.SB_HalClearInterruptBit()
self.sb_hal_clear_interrupt_bit()
val = self.sasi_paldmamap(0)
data.append(0x0) # 0
data.append(0x8000011) # 1 #DIN_DMA|DOUT_DMA|DIN_CONST
@ -1231,35 +1231,35 @@ class dxcc(metaclass=LogBase):
data.append((destptr >> 32) << 16) # 5
self.sasi_sb_adddescsequence(data)
while True:
if self.SB_CryptoWait() & 4 != 0:
if self.sb_crypto_wait() & 4 != 0:
break
while True:
value = self.read32(self.dxcc_base + 0xBA0)
if value != 0:
break
if value == 1:
self.SB_HalClearInterruptBit()
self.sb_hal_clear_interrupt_bit()
self.sasi_paldmaunmap(val)
return 0
else:
return 0xF6000001
def SBROM_AesCmacDriver(self, aesKeyType, pInternalKey, pDataIn, dmaMode, blockSize, pDataOut):
ivSramAddr = 0
if aesKeyType == HwCryptoKey.ROOT_KEY:
def sbrom_aes_cmac_driver(self, aes_key_type, p_internal_key, p_data_in, dma_mode, block_size, p_data_out):
iv_sram_addr = 0
if aes_key_type == HwCryptoKey.ROOT_KEY:
if self.read32(self.dxcc_base + self.DX_HOST_SEP_HOST_GPR4) & 2 != 0:
keySizeInBytes = 0x20 # SEP_AES_256_BIT_KEY_SIZE
key_size_in_bytes = 0x20 # SEP_AES_256_BIT_KEY_SIZE
else:
keySizeInBytes = 0x10 # SEP_AES_128_BIT_KEY_SIZE
key_size_in_bytes = 0x10 # SEP_AES_128_BIT_KEY_SIZE
else:
keySizeInBytes = 0x10 # SEP_AES_128_BIT_KEY_SIZE
self.SB_HalInit()
key_size_in_bytes = 0x10 # SEP_AES_128_BIT_KEY_SIZE
self.sb_hal_init()
pdesc = hw_desc_init()
pdesc = hw_desc_set_cipher_mode(pdesc, sep_cipher_mode.SEP_CIPHER_CMAC) # desc[4]=0x1C00
pdesc = hw_desc_set_cipher_mode(pdesc, SepCipherMode.SEP_CIPHER_CMAC) # desc[4]=0x1C00
pdesc = hw_desc_set_cipher_config0(pdesc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
pdesc = hw_desc_set_key_size_aes(pdesc, keySizeInBytes) # desc[4]=0x801C00
pdesc = hw_desc_set_din_sram(pdesc, ivSramAddr, AES_IV_COUNTER_SIZE_IN_BYTES)
pdesc = hw_desc_set_key_size_aes(pdesc, key_size_in_bytes) # desc[4]=0x801C00
pdesc = hw_desc_set_din_sram(pdesc, iv_sram_addr, AES_IV_COUNTER_SIZE_IN_BYTES)
pdesc = hw_desc_set_din_const(pdesc, 0, AES_IV_COUNTER_SIZE_IN_BYTES) # desc[1]=0x8000041
pdesc = hw_desc_set_flow_mode(pdesc, FlowMode.S_DIN_to_AES) # desc[4]=0x801C20
pdesc = hw_desc_set_setup_mode(pdesc, SetupOp.SETUP_LOAD_STATE0) # desc[4]=0x1801C20
@ -1268,43 +1268,43 @@ class dxcc(metaclass=LogBase):
# Load key
mdesc = hw_desc_init()
if aesKeyType == HwCryptoKey.USER_KEY:
keySramAddr = pInternalKey
mdesc = hw_desc_set_din_sram(mdesc, keySramAddr, AES_Key128Bits_SIZE_IN_BYTES)
mdesc = hw_desc_set_cipher_do(mdesc, aesKeyType) # desc[4]=0x8000
mdesc = hw_desc_set_cipher_mode(mdesc, sep_cipher_mode.SEP_CIPHER_CMAC) # desc[4]=0x9C00
if aes_key_type == HwCryptoKey.USER_KEY:
key_sram_addr = p_internal_key
mdesc = hw_desc_set_din_sram(mdesc, key_sram_addr, AES_Key128Bits_SIZE_IN_BYTES)
mdesc = hw_desc_set_cipher_do(mdesc, aes_key_type) # desc[4]=0x8000
mdesc = hw_desc_set_cipher_mode(mdesc, SepCipherMode.SEP_CIPHER_CMAC) # desc[4]=0x9C00
mdesc = hw_desc_set_cipher_config0(mdesc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
mdesc = hw_desc_set_key_size_aes(mdesc, keySizeInBytes) # desc[4]=0x809C00
mdesc = hw_desc_set_key_size_aes(mdesc, key_size_in_bytes) # desc[4]=0x809C00
mdesc = hw_desc_set_flow_mode(mdesc, FlowMode.S_DIN_to_AES) # desc[4]=0x809C20
mdesc = hw_desc_set_setup_mode(mdesc, SetupOp.SETUP_LOAD_KEY0) # desc[4]=0x4809C20
mdesc[4] |= ((aesKeyType >> 2) & 3) << 20
mdesc[4] |= ((aes_key_type >> 2) & 3) << 20
self.sasi_sb_adddescsequence(mdesc)
# Process input data
rdesc = hw_desc_init()
if dmaMode == DmaMode.DMA_SRAM:
rdesc = hw_desc_set_din_sram(rdesc, pDataIn, blockSize)
if dma_mode == DmaMode.DMA_SRAM:
rdesc = hw_desc_set_din_sram(rdesc, p_data_in, block_size)
else:
rdesc = hw_desc_set_din_type(rdesc, DmaMode.DMA_DLLI, pDataIn, blockSize, SB_AXI_ID,
rdesc = hw_desc_set_din_type(rdesc, DmaMode.DMA_DLLI, p_data_in, block_size, SB_AXI_ID,
AXI_SECURE) # desc[1]=0x3E, desc[0]=0x200E18
rdesc = hw_desc_set_flow_mode(rdesc, FlowMode.DIN_AES_DOUT) # desc[4]=1
self.sasi_sb_adddescsequence(rdesc)
if aesKeyType != HwCryptoKey.PROVISIONING_KEY:
if aes_key_type != HwCryptoKey.PROVISIONING_KEY:
xdesc = hw_desc_init()
xdesc = hw_desc_set_cipher_mode(xdesc, sep_cipher_mode.SEP_CIPHER_CMAC) # desc[4]=0x1C00
xdesc = hw_desc_set_cipher_mode(xdesc, SepCipherMode.SEP_CIPHER_CMAC) # desc[4]=0x1C00
xdesc = hw_desc_set_cipher_config0(xdesc, DescDirection.DESC_DIRECTION_ENCRYPT_ENCRYPT)
xdesc = hw_desc_set_setup_mode(xdesc, SetupOp.SETUP_WRITE_STATE0) # desc[4]=0x8001C00
xdesc = hw_desc_set_flow_mode(xdesc, FlowMode.S_AES_to_DOUT) # desc[4]=0x8001C26
if dmaMode == DmaMode.DMA_SRAM:
xdesc = hw_desc_set_dout_sram(xdesc, pDataOut, AES_BLOCK_SIZE_IN_BYTES)
if dma_mode == DmaMode.DMA_SRAM:
xdesc = hw_desc_set_dout_sram(xdesc, p_data_out, AES_BLOCK_SIZE_IN_BYTES)
else:
xdesc = hw_desc_set_dout_dlli(xdesc, pDataOut, AES_BLOCK_SIZE_IN_BYTES, SB_AXI_ID,
xdesc = hw_desc_set_dout_dlli(xdesc, p_data_out, AES_BLOCK_SIZE_IN_BYTES, SB_AXI_ID,
0) # desc[2]=0x200E08, desc[3]=0x42
# xdesc = hw_desc_set_din_sram(xdesc, 0, 0)
xdesc = hw_desc_set_din_nodma(xdesc, 0, 0)
self.sasi_sb_adddescsequence(xdesc)
return self.SB_HalWaitDescCompletion() == 0
return self.sb_hal_wait_desc_completion() == 0
@staticmethod
def mtee_decrypt(data):
@ -1319,16 +1319,16 @@ class dxcc(metaclass=LogBase):
ctr = Counter.new(128, initial_value=bytes_to_long(iv))
return AES.new(key=key, counter=ctr, mode=AES.MODE_CTR).decrypt(data)
def sbrom_sha256(self, buffer, destaddr): # TZCC_SHA256_Init
def sbrom_sha256(self, _buffer, destaddr): # TZCC_SHA256_Init
dataptr = destaddr + 0x40
ivptr = destaddr + 0x20
outptr = destaddr
self.writemem(0x1000108C, pack("<I", 0x18000000))
iv = bytes.fromhex("19CDE05BABD9831F8C68059B7F520E513AF54FA572F36E3C85AE67BB67E6096A")
self.writemem(ivptr, iv)
self.writemem(dataptr, buffer)
self.writemem(dataptr, _buffer)
self.sbrom_cryptoinitdriver(aesivptr=ivptr, cryptodrivermode=0)
self.sbrom_cryptoupdate(inputptr=dataptr, outputptr=outptr, blockSize=len(buffer), islastblock=1,
self.sbrom_cryptoupdate(inputptr=dataptr, outputptr=outptr, block_size=len(_buffer), islastblock=1,
cryptodrivermode=0, waitforcrypto=0)
self.sbrom_cryptofinishdriver(outptr)
self.writemem(0x10001088, pack("<I", 0x8000000))
@ -1345,7 +1345,7 @@ class dxcc(metaclass=LogBase):
pdesc = hw_desc_init()
pdesc = hw_desc_set_din_type(pdesc, DmaMode.DMA_DLLI, aesivptr, 0x20, SB_AXI_ID, AXI_SECURE)
pdesc = hw_desc_set_flow_mode(pdesc, FlowMode.S_DIN_to_HASH)
pdesc = hw_desc_set_cipher_mode(pdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
pdesc = hw_desc_set_cipher_mode(pdesc, SepHashHwMode.SEP_HASH_HW_SHA256)
pdesc = hw_desc_set_setup_mode(pdesc, SetupOp.SETUP_LOAD_STATE0)
self.sasi_sb_adddescsequence(pdesc)
# 0=0
@ -1356,13 +1356,13 @@ class dxcc(metaclass=LogBase):
# 5=0
tdesc = hw_desc_init()
tdesc = hw_desc_set_flow_mode(tdesc, FlowMode.S_DIN_to_HASH)
tdesc = hw_desc_set_cipher_mode(tdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
tdesc = hw_desc_set_cipher_mode(tdesc, SepHashHwMode.SEP_HASH_HW_SHA256)
tdesc = hw_desc_set_setup_mode(tdesc, SetupOp.SETUP_LOAD_KEY0)
tdesc = hw_desc_set_din_const(tdesc, 0, 0x10)
self.sasi_sb_adddescsequence(tdesc)
if cryptodrivermode >= 1:
mdesc = hw_desc_init()
mdesc = hw_desc_set_cipher_mode(mdesc, sep_cipher_mode.SEP_CIPHER_CTR)
mdesc = hw_desc_set_cipher_mode(mdesc, SepCipherMode.SEP_CIPHER_CTR)
mdesc = hw_desc_set_setup_mode(mdesc, SetupOp.SETUP_LOAD_STATE1)
mdesc = hw_desc_set_flow_mode(mdesc, FlowMode.S_DIN_to_AES)
mdesc = hw_desc_set_dout_dlli(mdesc, 0, AES_BLOCK_SIZE_IN_BYTES, SB_AXI_ID,
@ -1370,16 +1370,16 @@ class dxcc(metaclass=LogBase):
self.sasi_sb_adddescsequence(mdesc)
mdesc2 = hw_desc_init()
mdesc2 = hw_desc_set_cipher_mode(mdesc2, sep_cipher_mode.SEP_CIPHER_CTR)
mdesc2 = hw_desc_set_cipher_mode(mdesc2, SepCipherMode.SEP_CIPHER_CTR)
mdesc2 = hw_desc_set_setup_mode(mdesc2, SetupOp.SETUP_LOAD_KEY0)
mdesc2 = hw_desc_set_flow_mode(mdesc2, FlowMode.S_DIN_to_AES)
mdesc2 = hw_desc_set_dout_dlli(mdesc2, 0, AES_BLOCK_SIZE_IN_BYTES, SB_AXI_ID,
0)
self.sasi_sb_adddescsequence(mdesc2)
def sbrom_cryptoupdate(self, inputptr, outputptr, blockSize, islastblock, cryptodrivermode, waitforcrypto):
def sbrom_cryptoupdate(self, inputptr, outputptr, block_size, islastblock, cryptodrivermode, waitforcrypto):
if waitforcrypto == 2:
if self.SB_HalWaitDescCompletion() == 1:
if self.sb_hal_wait_desc_completion() == 1:
return True
if islastblock == 1 and (cryptodrivermode & 0xFFFFFFFD) == 0:
# 0=0
@ -1391,17 +1391,17 @@ class dxcc(metaclass=LogBase):
ydesc = hw_desc_init()
ydesc = hw_desc_set_dout_dlli(ydesc, outputptr, 0x10, SB_AXI_ID, 0)
ydesc = hw_desc_set_flow_mode(ydesc, FlowMode.S_HASH_to_DOUT)
ydesc = hw_desc_set_cipher_mode(ydesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
ydesc = hw_desc_set_cipher_config1(ydesc, sep_hash_mode.SEP_HASH_SHA256)
ydesc = hw_desc_set_cipher_mode(ydesc, SepHashHwMode.SEP_HASH_HW_SHA256)
ydesc = hw_desc_set_cipher_config1(ydesc, SepHashMode.SEP_HASH_SHA256)
ydesc = hw_desc_set_setup_mode(ydesc, SetupOp.SETUP_WRITE_STATE1)
self.sasi_sb_adddescsequence(ydesc)
udesc = hw_desc_init()
udesc = hw_desc_set_din_type(udesc, DmaMode.DMA_DLLI, inputptr, blockSize, SB_AXI_ID, AXI_SECURE)
udesc = hw_desc_set_din_type(udesc, DmaMode.DMA_DLLI, inputptr, block_size, SB_AXI_ID, AXI_SECURE)
if not cryptodrivermode:
udesc = hw_desc_set_flow_mode(udesc, FlowMode.DIN_HASH)
self.sasi_sb_adddescsequence(udesc)
if (waitforcrypto == 2 and not islastblock) or waitforcrypto == 3:
self.SB_HalWaitDescCompletion()
self.sb_hal_wait_desc_completion()
elif waitforcrypto == 0:
return 0
else:
@ -1411,9 +1411,9 @@ class dxcc(metaclass=LogBase):
fdesc = hw_desc_init()
fdesc = hw_desc_set_dout_dlli(fdesc, outputptr, 0x20, SB_AXI_ID, 0)
fdesc = hw_desc_set_flow_mode(fdesc, FlowMode.S_HASH_to_DOUT)
fdesc = hw_desc_set_cipher_mode(fdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
fdesc = hw_desc_set_cipher_config0(fdesc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
fdesc = hw_desc_set_cipher_config1(fdesc, sep_hash_mode.SEP_HASH_SHA256)
fdesc = hw_desc_set_cipher_mode(fdesc, SepHashHwMode.SEP_HASH_HW_SHA256)
fdesc = hw_desc_set_cipher_config0(fdesc, SepHashHwMode.SEP_HASH_HW_SHA256)
fdesc = hw_desc_set_cipher_config1(fdesc, SepHashMode.SEP_HASH_SHA256)
fdesc = hw_desc_set_setup_mode(fdesc, SetupOp.SETUP_WRITE_STATE0)
# 0 = 0
# 1 = 0
@ -1422,7 +1422,7 @@ class dxcc(metaclass=LogBase):
# 4 = 0x80C082B
# 5 = outputptr>>32<<16
self.sasi_sb_adddescsequence(fdesc)
return self.SB_HalWaitDescCompletion()
return self.sb_hal_wait_desc_completion()
if __name__ == "__main__":
@ -1435,7 +1435,7 @@ if __name__ == "__main__":
desc = hw_desc_init()
desc = hw_desc_set_dout_dlli(desc, 0, 0x10, SB_AXI_ID, 0)
desc = hw_desc_set_flow_mode(desc, FlowMode.S_HASH_to_DOUT)
desc = hw_desc_set_cipher_mode(desc, sep_hash_hw_mode.SEP_HASH_HW_SHA256)
desc = hw_desc_set_cipher_config1(desc, sep_hash_mode.SEP_HASH_SHA256)
desc = hw_desc_set_cipher_mode(desc, SepHashHwMode.SEP_HASH_HW_SHA256)
desc = hw_desc_set_cipher_config1(desc, SepHashMode.SEP_HASH_SHA256)
desc = hw_desc_set_setup_mode(desc, SetupOp.SETUP_WRITE_STATE1)
print(desc)

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2022 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import hmac
import hashlib
@ -194,7 +194,8 @@ def xor_data(a: bytearray, b: bytearray, length=None):
class GCpu(metaclass=LogBase):
def __init__(self, setup, loglevel=logging.INFO, gui: bool = False):
self.__logger = logsetup(self, self.__logger, loglevel, gui)
self.setup = None
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger, loglevel, gui)
self.read32 = setup.read32
self.write32 = setup.write32
self.reg = GCpuReg(setup)
@ -352,8 +353,8 @@ class GCpu(metaclass=LogBase):
self.__logger.info(", ".join(regs[i * 4:(i * 4) + 4]))
def cmd(self, cmd, addr=0, args=None):
GCPU_INT_MASK = 3 # todo this might be different
CLR_EN = 3 # todo this might be different
gcpu_int_mask = 3 # todo this might be different
clr_en = 3 # todo this might be different
# Setup parameter
if args is not None:
for i in range(1, 48):
@ -363,8 +364,8 @@ class GCpu(metaclass=LogBase):
self.reg.GCPU_REG_INT_CLR = 1
self.reg.GCPU_REG_INT_EN = 0
else:
self.reg.GCPU_REG_INT_CLR = CLR_EN
self.reg.GCPU_REG_INT_EN = GCPU_INT_MASK
self.reg.GCPU_REG_INT_CLR = clr_en
self.reg.GCPU_REG_INT_EN = gcpu_int_mask
# GCPU Decryption Mode
self.reg.GCPU_REG_MEM_CMD = cmd
# GCPU PC
@ -378,13 +379,13 @@ class GCpu(metaclass=LogBase):
pass
result = -1
# Enable GCPU Interrupt
self.reg.GCPU_REG_INT_CLR = CLR_EN
self.reg.GCPU_REG_INT_CLR = clr_en
else:
while not self.reg.GCPU_REG_DRAM_MON & 1:
pass
result = 0
# Enable GCPU Interrupt
self.reg.GCPU_REG_INT_CLR = CLR_EN
self.reg.GCPU_REG_INT_CLR = clr_en
return result
def set_mode_cmd(self, encrypt=False, mode="cbc", encryptedkey=True):
@ -593,7 +594,8 @@ class GCpu(metaclass=LogBase):
self.acquire()
if self.load_hw_key(keyslot):
self.memptr_set(src, bytearray(bytes.fromhex("4B65796D61737465724D617374657200")))
# self.memptr_set(src, bytearray(bytes.fromhex("0102030405060708090A0B0C0D0E0F0102030405060708090A0B0C0D0E0F0000")))
# self.memptr_set(src,
# bytearray(bytes.fromhex("0102030405060708090A0B0C0D0E0F0102030405060708090A0B0C0D0E0F0000")))
if encrypt:
if not self.aes_encrypt_ecb(keyslot, src, dst):
return self.memptr_get(dst, 16)

View file

@ -1,11 +1,11 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import os
from struct import pack, unpack
from mtkclient.Library.utils import LogBase
from mtkclient.Library.cryptutils import cryptutils
from mtkclient.Library.utils import LogBase, logsetup
from mtkclient.Library.cryptutils import CryptUtils
CustomSeed = bytes.fromhex("00be13bb95e218b53d07a089cb935255294f70d4088f3930350bc636cc49c9025ece7a62c292853ef55b23a6e" +
"f7b7464c7f3f2a74ae919416d6b4d9c1d6809655dd82d43d65999cf041a386e1c0f1e58849d8ed09ef07e6a9f" +
@ -24,7 +24,7 @@ def bytes_to_dwords(buf):
return res
class symkey:
class SymKey:
key = None
key_len = 0x10
mode = 1
@ -79,7 +79,7 @@ regval = {
}
class hacc_reg:
class HaccReg:
def __init__(self, setup):
self.sej_base = setup.sej_base
self.read32 = setup.read32
@ -87,24 +87,24 @@ class hacc_reg:
def __setattr__(self, key, value):
if key in ("sej_base", "read32", "write32", "regval"):
return super(hacc_reg, self).__setattr__(key, value)
return super(HaccReg, self).__setattr__(key, value)
if key in regval:
addr = regval[key] + self.sej_base
return self.write32(addr, value)
else:
return super(hacc_reg, self).__setattr__(key, value)
return super(HaccReg, self).__setattr__(key, value)
def __getattribute__(self, item):
if item in ("sej_base", "read32", "write32", "regval"):
return super(hacc_reg, self).__getattribute__(item)
return super(HaccReg, self).__getattribute__(item)
if item in regval:
addr = regval[item] + self.sej_base
return self.read32(addr)
else:
return super(hacc_reg, self).__getattribute__(item)
return super(HaccReg, self).__getattribute__(item)
class sej(metaclass=LogBase):
class Sej(metaclass=LogBase):
encrypt = True
HACC_AES_DEC = 0x00000000
@ -166,12 +166,10 @@ class sej(metaclass=LogBase):
]
def __init__(self, setup, loglevel=logging.INFO):
self.__logger = self.__logger
self.info = self.__logger.info
self.error = self.__logger.error
self.warning = self.__logger.warning
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, None)
self.hwcode = setup.hwcode
self.reg = hacc_reg(setup)
self.reg = HaccReg(setup)
# mediatek,hacc, mediatek,sej
self.sej_base = setup.sej_base
self.read32 = setup.read32
@ -220,7 +218,7 @@ class sej(metaclass=LogBase):
else:
self.write32(0x10216024, 0x0)
def device_APC_dom_setup(self):
def device_apc_dom_setup(self):
self.write32(0x10007F00, 0)
tv = self.read32(0x10007400) & 0xFFFFFFFF
self.write32(0x10007400, tv | (1 << (self.uffs(0xF0000000) - 1)))
@ -277,7 +275,7 @@ class sej(metaclass=LogBase):
# self.crypto_secure(1)
return
def SEJ_Run(self, data):
def sej_run(self, data):
pdst = bytearray()
psrc = bytes_to_dwords(data)
plen = len(psrc)
@ -302,7 +300,7 @@ class sej(metaclass=LogBase):
pos += 4
return pdst
def SEJ_AES_HW_Init(self, attr, key: symkey, sej_param=3):
def sej_aes_hw_init(self, attr, key: SymKey, sej_param=3):
# key.mode 0 = ECB
# key.mode 1 = CBC
if key.key is None:
@ -374,7 +372,7 @@ class sej(metaclass=LogBase):
self.reg.HACC_ACFG2 = key.iv[2]
self.reg.HACC_ACFG3 = key.iv[3]
def SEJ_AES_HW_Internal(self, data, encrypt, attr, sej_param, legacy=True):
def sej_aes_hw_internal(self, data, encrypt, attr, sej_param, legacy=True):
if encrypt:
self.reg.HACC_ACON |= 1
if legacy:
@ -412,7 +410,7 @@ class sej(metaclass=LogBase):
self.reg.HACC_AKEY0[pos] = pdst[pos] ^ self.reg.HACC_AKEY0[pos]
return pdst
def SST_Init(self, attr, iv, keylen=0x10, mparam=5, key=None):
def sst_init(self, attr, iv, keylen=0x10, mparam=5, key=None):
self.reg.HACC_SECINIT0 = 1
if keylen == 0x10 or mparam & 1 != 0 or attr & 1 != 0:
acon_setting = 0
@ -470,16 +468,16 @@ class sej(metaclass=LogBase):
self.reg.HACC_ACON|=acon_setting
"""
def SST_Secure_Algo_With_Level(self, buf, encrypt=True, aes_top_legacy=True):
def sst_secure_algo_with_level(self, buf, encrypt=True, aes_top_legacy=True):
seed = (CustomSeed[2] << 16) | (CustomSeed[1] << 8) | CustomSeed[0] | (CustomSeed[3] << 24)
iv = [seed, (~seed) & 0xFFFFFFFF, (((seed >> 16) | (seed << 16)) & 0xFFFFFFFF),
(~((seed >> 16) | (seed << 16)) & 0xFFFFFFFF)]
key = symkey()
_iv = [seed, (~seed) & 0xFFFFFFFF, (((seed >> 16) | (seed << 16)) & 0xFFFFFFFF),
(~((seed >> 16) | (seed << 16)) & 0xFFFFFFFF)]
key = SymKey()
key.key = None
key.key_len = 0x10
# meta_key_len = 0x10
key.mode = 1 # CBC
key.iv = iv
key.iv = _iv
if aes_top_legacy:
sej_param = 3
else:
@ -501,17 +499,17 @@ class sej(metaclass=LogBase):
if metaflag:
# length=0x10
attr = 0x5B
self.SEJ_AES_HW_Init(attr, key, sej_param)
self.sej_aes_hw_init(attr, key, sej_param)
for pos in range(3):
src = b"".join([int.to_bytes(val, 4, 'little') for val in self.g_CFG_RANDOM_PATTERN])
buf2 = self.SEJ_AES_HW_Internal(src, encrypt=False, attr=attr, sej_param=sej_param)
buf2 = self.sej_aes_hw_internal(src, encrypt=False, attr=attr, sej_param=sej_param)
attr = attr & 0xFFFFFFFA | 4
else:
self.SST_Init(attr=attr, iv=iv, keylen=key.key_len, mparam=sej_param, key=key.key)
buf2 = self.SEJ_AES_HW_Internal(buf, encrypt=encrypt, attr=attr, sej_param=sej_param, legacy=False)
self.sst_init(attr=attr, iv=_iv, keylen=key.key_len, mparam=sej_param, key=key.key)
buf2 = self.sej_aes_hw_internal(buf, encrypt=encrypt, attr=attr, sej_param=sej_param, legacy=False)
return buf2
def SEJ_Terminate(self):
def sej_terminate(self):
self.reg.HACC_ACON2 = self.HACC_AES_CLR
self.reg.HACC_AKEY0 = 0
self.reg.HACC_AKEY1 = 0
@ -607,9 +605,9 @@ class sej(metaclass=LogBase):
self.info("HACC init")
self.SEJ_V3_Init(ben=encrypt, iv=iv)
self.info("HACC run")
buf2 = self.SEJ_Run(buf)
buf2 = self.sej_run(buf)
self.info("HACC terminate")
self.SEJ_Terminate()
self.sej_terminate()
return buf2
def sej_set_otp(self, data):
@ -680,7 +678,7 @@ class sej(metaclass=LogBase):
iv = bytes.fromhex("57325A5A125497661254976657325A5A")
res = self.sej_do_aes(encrypt, iv, data, len(data))
"""
ctx = cryptutils.aes()
ctx = CryptUtils.Aes()
res = ctx.aes_cbc(key=b"25A1763A21BC854CD569DC23B4782B63",
iv=bytes.fromhex("57325A5A125497661254976657325A5A"), data=data,
decrypt=not encrypt)
@ -701,9 +699,9 @@ class sej(metaclass=LogBase):
self.info("HACC init")
self.SEJ_V3_Init(ben=encrypt, iv=self.g_HACC_CFG_1, legacy=True)
self.info("HACC run")
dec = self.SEJ_Run(data)
dec = self.sej_run(data)
self.info("HACC terminate")
self.SEJ_Terminate()
self.sej_terminate()
if not encrypt:
dec = self.xor_data(dec)
return dec
@ -723,24 +721,24 @@ class sej(metaclass=LogBase):
buf.append(meid[i % len(meid)])
return self.hw_aes128_cbc_encrypt(buf=buf, encrypt=True, iv=self.g_HACC_CFG_1)
def sp_hacc_internal(self, buf: bytes, bAC: bool, user: int, bDoLock: bool, aes_type: int, bEn: bool):
def sp_hacc_internal(self, buf: bytes, b_ac: bool, user: int, b_do_lock: bool, aes_type: int, b_en: bool):
dec = None
if user == 0:
iv = self.g_HACC_CFG_1
self.info("HACC init")
self.SEJ_V3_Init(ben=bEn, iv=iv)
self.SEJ_V3_Init(ben=b_en, iv=iv)
self.info("HACC run")
dec = self.SEJ_Run(buf)
dec = self.sej_run(buf)
self.info("HACC terminate")
self.SEJ_Terminate()
self.sej_terminate()
elif user == 1:
iv = self.g_HACC_CFG_2
self.info("HACC init")
self.SEJ_V3_Init(ben=bEn, iv=iv)
self.SEJ_V3_Init(ben=b_en, iv=iv)
self.info("HACC run")
dec = self.SEJ_Run(buf)
dec = self.sej_run(buf)
self.info("HACC terminate")
self.SEJ_Terminate()
self.sej_terminate()
elif user == 2:
self.sej_set_key(key=2, flag=32)
iv = bytes.fromhex("57325A5A125497661254976657325A5A")
@ -748,18 +746,18 @@ class sej(metaclass=LogBase):
elif user == 3:
iv = self.g_HACC_CFG_3
self.info("HACC init")
self.SEJ_V3_Init(ben=bEn, iv=iv)
self.SEJ_V3_Init(ben=b_en, iv=iv)
self.info("HACC run")
dec = self.SEJ_Run(buf)
dec = self.sej_run(buf)
self.info("HACC terminate")
self.SEJ_Terminate()
self.sej_terminate()
return dec
def dev_kdf(self, buf: bytes, derivelen=16):
res = bytearray()
for i in range(derivelen // 16):
res.extend(self.sp_hacc_internal(buf=buf[i * 16:(i * 16) + 16], bAC=True, user=0, bDoLock=False, aes_type=1,
bEn=True))
res.extend(self.sp_hacc_internal(buf=buf[i * 16:(i * 16) + 16], b_ac=True, user=0, b_do_lock=False,
aes_type=1, b_en=True))
return res
def generate_mtee(self, otp=None):
@ -779,9 +777,9 @@ class sej(metaclass=LogBase):
self.info("HACC init")
self.SEJ_V3_Init(ben=True, iv=self.g_HACC_CFG_MTEE)
self.info("HACC run")
dec = self.SEJ_Run(bytes.fromhex("7777772E6D6564696174656B2E636F6D30313233343536373839414243444546"))
dec = self.sej_run(bytes.fromhex("7777772E6D6564696174656B2E636F6D30313233343536373839414243444546"))
self.info("HACC terminate")
self.SEJ_Terminate()
self.sej_terminate()
return dec
def generate_hw_meta(self, otp=None, encrypt=False, data=b""):
@ -804,9 +802,9 @@ class sej(metaclass=LogBase):
self.info("HACC init")
self.SEJ_V3_Init(ben=encrypt, iv=iv)
self.info("HACC run")
dec = self.SEJ_Run(data)
dec = self.sej_run(data)
self.info("HACC terminate")
self.SEJ_Terminate()
self.sej_terminate()
return dec

View file

@ -3,19 +3,17 @@ import os
import hashlib
import logging
from io import BytesIO
from mtkclient.Library.utils import structhelper_io
from mtkclient.Library.utils import StructhelperIo, logsetup
from mtkclient.Library.utils import LogBase
from mtkclient.config.mtk_config import Mtk_Config
from mtkclient.config.mtk_config import MtkConfig
class seccfgV4(metaclass=LogBase):
def __init__(self, hwc, mtk, loglevel=logging.INFO):
self.__logger = self.__logger
self.info = self.__logger.info
self.error = self.__logger.error
self.warning = self.__logger.warning
class SecCfgV4(metaclass=LogBase):
def __init__(self, _hwc, mtk, loglevel=logging.INFO):
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.hwtype = None
self.hwc = hwc
self.hwc = _hwc
self.mtk = mtk
self.magic = 0x4D4D4D4D
self.seccfg_ver = None
@ -33,38 +31,36 @@ class seccfgV4(metaclass=LogBase):
else:
self.__logger.setLevel(logging.INFO)
def parse(self, data):
rf = structhelper_io(BytesIO(bytearray(data)))
self.magic = rf.dword()
self.seccfg_ver = rf.dword()
self.seccfg_size = rf.dword()
self.lock_state = rf.dword()
self.critical_lock_state = rf.dword()
self.sboot_runtime = rf.dword()
self.endflag = rf.dword()
rf.seek(self.seccfg_size - 0x20)
self.hash = rf.bytes(0x20)
def parse(self, indata):
rrf = StructhelperIo(BytesIO(bytearray(indata)))
self.magic = rrf.dword()
self.seccfg_ver = rrf.dword()
self.seccfg_size = rrf.dword()
self.lock_state = rrf.dword()
self.critical_lock_state = rrf.dword()
self.sboot_runtime = rrf.dword()
self.endflag = rrf.dword()
rrf.seek(self.seccfg_size - 0x20)
self.hash = rrf.bytes(0x20)
if self.magic != 0x4D4D4D4D or self.endflag != 0x45454545:
self.error("Unknown V4 seccfg structure !")
return False
seccfg_data = pack("<IIIIIII", self.magic, self.seccfg_ver, self.seccfg_size, self.lock_state,
self.critical_lock_state, self.sboot_runtime, 0x45454545)
hash = hashlib.sha256(seccfg_data).digest()
_hash = hashlib.sha256(seccfg_data).digest()
dec_hash = self.hwc.sej.sej_sec_cfg_sw(self.hash, False)
if hash == dec_hash:
if _hash == dec_hash:
self.hwtype = "SW"
else:
dec_hash = self.hwc.sej.sej_sec_cfg_hw(self.hash, False)
if hash == dec_hash:
if _hash == dec_hash:
self.hwtype = "V2"
else:
dec_hash = self.hwc.sej.sej_sec_cfg_hw_V3(self.hash, False)
if hash == dec_hash:
if _hash == dec_hash:
self.hwtype = "V3"
else:
return False
return True
"""
LKS_DEFAULT = 0x01
LKS_MP_DEFAULT = 0x02
@ -77,6 +73,7 @@ class seccfgV4(metaclass=LogBase):
SBOOT_RUNTIME_OFF = 0
SBOOT_RUNTIME_ON = 1
"""
return True
def create(self, lockflag: str = "unlock"):
if lockflag == "lock" and self.lock_state == 1:
@ -99,18 +96,18 @@ class seccfgV4(metaclass=LogBase):
enc_hash = self.hwc.sej.sej_sec_cfg_hw(dec_hash, True)
elif self.hwtype == "V3":
enc_hash = self.hwc.sej.sej_sec_cfg_hw_V3(dec_hash, True)
data = seccfg_data + enc_hash
while len(data) % 0x200 != 0:
data += b"\x00"
return True, bytearray(data)
indata = seccfg_data + enc_hash
while len(indata) % 0x200 != 0:
indata += b"\x00"
return True, bytearray(indata)
class SECCFG_STATUS:
class SeccfgStatus:
SEC_CFG_COMPLETE_NUM = 0x43434343 # CCCC
SEC_CFG_INCOMPLETE_NUM = 0x49494949 # IIII
class SECCFG_ATTR:
class SeccfgAttr:
ATTR_LOCK = 0x6000
ATTR_VERIFIED = 0x6001
ATTR_CUSTOM = 0x6002
@ -119,35 +116,33 @@ class SECCFG_ATTR:
ATTR_UNLOCK = 0x44444444
class SIU_STATUS:
class SiuStatus:
UBOOT_UPDATED_BY_SIU = 0x0001
BOOT_UPDATED_BY_SIU = 0x0010
RECOVERY_UPDATED_BY_SIU = 0x0100
SYSTEM_UPDATED_BY_SIU = 0x1000
class ROM_TYPE:
class RomType:
NORMAL_ROM = 0x01
YAFFS_IMG = 0x08
class SEC_IMG_ATTR:
class SecImgAttr:
ATTR_SEC_IMG_UPDATE = 0x10,
ATTR_SEC_IMG_COMPLETE = 0x43434343, # CCCC
ATTR_SEC_IMG_INCOMPLETE = 0x49494949, # IIII
ATTR_SEC_IMG_FORCE_UPDATE = 0x46464646 # FFFF
class seccfgV3(metaclass=LogBase):
def __init__(self, hwc, mtk, loglevel=logging.INFO):
self.__logger = self.__logger
self.info = self.__logger.info
self.error = self.__logger.error
self.warning = self.__logger.warning
class SecCfgV3(metaclass=LogBase):
def __init__(self, _hwc, mtk, loglevel=logging.INFO):
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.hwtype = None
self.data = None
self.org_data = None
self.hwc = hwc
self.hwc = _hwc
self.mtk = mtk
self.info_header = b"AND_SECCFG_v\x00\x00\x00\x00"
self.magic = 0x4D4D4D4D
@ -162,11 +157,11 @@ class seccfgV3(metaclass=LogBase):
self.page_count = 0
self.imginfo = b"\x00" * (0x68 * 20)
self.siu_status = 0
self.seccfg_status = SECCFG_STATUS.SEC_CFG_COMPLETE_NUM
self.seccfg_attr = SECCFG_ATTR.ATTR_DEFAULT
self.seccfg_status = SeccfgStatus.SEC_CFG_COMPLETE_NUM
self.seccfg_attr = SeccfgAttr.ATTR_DEFAULT
self.seccfg_ext = b"\x00" * 0x1004
if self.hwc.read32 is not None:
self.setotp(hwc)
self.setotp(_hwc)
if loglevel == logging.DEBUG:
logfilename = os.path.join("logs", "log.txt")
fh = logging.FileHandler(logfilename, encoding='utf-8')
@ -175,7 +170,7 @@ class seccfgV3(metaclass=LogBase):
else:
self.__logger.setLevel(logging.INFO)
def setotp(self, hwc):
def setotp(self, _hwc):
otp = None
if self.mtk.config.preloader is not None:
idx = self.mtk.config.preloader.find(b"\x4D\x4D\x4D\x01\x30")
@ -183,33 +178,33 @@ class seccfgV3(metaclass=LogBase):
otp = self.mtk.config.preloader[idx + 0xC:idx + 0xC + 32]
if otp is None:
otp = 32 * b"\x00"
hwc.sej.sej_set_otp(otp)
_hwc.sej.sej_set_otp(otp)
def parse(self, data):
if data[:0x10] != b"AND_SECCFG_v\x00\x00\x00\x00":
def parse(self, indata):
if indata[:0x10] != b"AND_SECCFG_v\x00\x00\x00\x00":
return False
rf = structhelper_io(BytesIO(bytearray(data)))
self.info_header = rf.bytes(0x10)
self.magic = rf.dword()
self.seccfg_ver = rf.dword()
self.seccfg_size = rf.dword()
self.seccfg_enc_offset = rf.dword()
self.seccfg_enc_len = rf.dword() # 0x1 = Locked, 0xF207 = Unlocked
self.sw_sec_lock_try = rf.bytes(1)
self.sw_sec_lock_done = rf.bytes(1)
self.page_size = rf.short()
self.page_count = rf.dword()
self.data = rf.bytes(self.seccfg_size - 0x2C - 4)
self.endflag = rf.dword()
rrf = StructhelperIo(BytesIO(bytearray(indata)))
self.info_header = rrf.bytes(0x10)
self.magic = rrf.dword()
self.seccfg_ver = rrf.dword()
self.seccfg_size = rrf.dword()
self.seccfg_enc_offset = rrf.dword()
self.seccfg_enc_len = rrf.dword() # 0x1 = Locked, 0xF207 = Unlocked
self.sw_sec_lock_try = rrf.bytes(1)
self.sw_sec_lock_done = rrf.bytes(1)
self.page_size = rrf.short()
self.page_count = rrf.dword()
self.data = rrf.bytes(self.seccfg_size - 0x2C - 4)
self.endflag = rrf.dword()
if self.magic != 0x4D4D4D4D or self.endflag != 0x45454545:
self.error("Unknown V3 seccfg structure !")
return False
ret = self.hwc.sej.sej_sec_cfg_sw(self.data, False)
if ret[:4] not in [b"IIII", b"CCCC", b"\x00\x00\x00\x00"]:
ret = self.hwc.sej.sej_sec_cfg_hw_V3(self.data, False)
if ret[:4] not in [b"IIII", b"CCCC", b"\x00\x00\x00\x00"]:
ret = self.hwc.sej.sej_sec_cfg_hw(self.data, False)
if ret[:4] not in [b"IIII", b"CCCC", b"\x00\x00\x00\x00"]:
err = self.hwc.sej.sej_sec_cfg_sw(self.data, False)
if err[:4] not in [b"IIII", b"CCCC", b"\x00\x00\x00\x00"]:
err = self.hwc.sej.sej_sec_cfg_hw_V3(self.data, False)
if err[:4] not in [b"IIII", b"CCCC", b"\x00\x00\x00\x00"]:
err = self.hwc.sej.sej_sec_cfg_hw(self.data, False)
if err[:4] not in [b"IIII", b"CCCC", b"\x00\x00\x00\x00"]:
self.error("Unknown V3 seccfg encryption !")
return False
else:
@ -218,40 +213,40 @@ class seccfgV3(metaclass=LogBase):
self.hwtype = "V2"
else:
self.hwtype = "SW"
self.org_data = ret
ed = structhelper_io(BytesIO(bytearray(ret)))
self.org_data = err
ed = StructhelperIo(BytesIO(bytearray(err)))
self.imginfo = [ed.bytes(0x68) for _ in range(20)]
self.siu_status = ed.dword()
self.seccfg_status = ed.dword()
if self.seccfg_status not in [SECCFG_STATUS.SEC_CFG_COMPLETE_NUM, SECCFG_STATUS.SEC_CFG_INCOMPLETE_NUM]:
if self.seccfg_status not in [SeccfgStatus.SEC_CFG_COMPLETE_NUM, SeccfgStatus.SEC_CFG_INCOMPLETE_NUM]:
return False
self.seccfg_attr = ed.dword()
if self.seccfg_attr not in [SECCFG_ATTR.ATTR_DEFAULT, SECCFG_ATTR.ATTR_UNLOCK, SECCFG_ATTR.ATTR_MP_DEFAULT,
SECCFG_ATTR.ATTR_LOCK, SECCFG_ATTR.ATTR_CUSTOM, SECCFG_ATTR.ATTR_VERIFIED]:
if self.seccfg_attr not in [SeccfgAttr.ATTR_DEFAULT, SeccfgAttr.ATTR_UNLOCK, SeccfgAttr.ATTR_MP_DEFAULT,
SeccfgAttr.ATTR_LOCK, SeccfgAttr.ATTR_CUSTOM, SeccfgAttr.ATTR_VERIFIED]:
return False
self.seccfg_ext = ed.bytes(0x1000 + 4)
return True
def create(self, lockflag: str = "unlock"):
seccfg_attr_new = SECCFG_ATTR.ATTR_DEFAULT
seccfg_attr_new = SeccfgAttr.ATTR_DEFAULT
if lockflag == "unlock":
self.seccfg_enc_len = 0x07F20000
seccfg_attr_new = SECCFG_ATTR.ATTR_UNLOCK
seccfg_attr_new = SeccfgAttr.ATTR_UNLOCK
elif lockflag == "lock":
self.seccfg_enc_len = 0x01000000
seccfg_attr_new = SECCFG_ATTR.ATTR_DEFAULT
seccfg_attr_new = SeccfgAttr.ATTR_DEFAULT
if lockflag == "lock" and self.seccfg_attr != SECCFG_ATTR.ATTR_UNLOCK:
if lockflag == "lock" and self.seccfg_attr != SeccfgAttr.ATTR_UNLOCK:
return False, "Can't find lock state, current (%#x)" % self.seccfg_attr
elif lockflag == "unlock" and self.seccfg_attr != SECCFG_ATTR.ATTR_DEFAULT \
and self.seccfg_attr != SECCFG_ATTR.ATTR_MP_DEFAULT \
and self.seccfg_attr != SECCFG_ATTR.ATTR_CUSTOM \
and self.seccfg_attr != SECCFG_ATTR.ATTR_VERIFIED \
and self.seccfg_attr != SECCFG_ATTR.ATTR_LOCK:
elif lockflag == "unlock" and self.seccfg_attr != SeccfgAttr.ATTR_DEFAULT \
and self.seccfg_attr != SeccfgAttr.ATTR_MP_DEFAULT \
and self.seccfg_attr != SeccfgAttr.ATTR_CUSTOM \
and self.seccfg_attr != SeccfgAttr.ATTR_VERIFIED \
and self.seccfg_attr != SeccfgAttr.ATTR_LOCK:
return False, "Can't find unlock state, current (%#x)" % self.seccfg_attr
data = bytearray()
wf = BytesIO(data)
indata = bytearray()
wf = BytesIO(indata)
wf.write(self.info_header)
wf.write(int.to_bytes(self.magic, 4, 'little'))
wf.write(int.to_bytes(self.seccfg_ver, 4, 'little'))
@ -265,42 +260,44 @@ class seccfgV3(metaclass=LogBase):
ed = BytesIO()
for imginfo in self.imginfo:
ed.write(imginfo)
ed.write(bytearray(imginfo))
ed.write(int.to_bytes(self.siu_status, 4, 'little'))
ed.write(int.to_bytes(self.seccfg_status, 4, 'little'))
ed.write(int.to_bytes(seccfg_attr_new, 4, 'little'))
ed.write(self.seccfg_ext)
data = ed.getbuffer()
indata = ed.getbuffer()
if self.hwtype == "SW":
data = self.hwc.sej.sej_sec_cfg_sw(data, True)
indata = self.hwc.sej.sej_sec_cfg_sw(indata, True)
elif self.hwtype == "V2":
data = self.hwc.sej.sej_sec_cfg_hw(data, True)
indata = self.hwc.sej.sej_sec_cfg_hw(indata, True)
elif self.hwtype == "V3":
data = self.hwc.sej.sej_sec_cfg_hw_V3(data, True)
indata = self.hwc.sej.sej_sec_cfg_hw_V3(indata, True)
else:
return False, "Unknown error"
wf.write(data)
wf.write(indata)
wf.write(int.to_bytes(self.endflag, 4, 'little'))
data = bytearray(wf.getbuffer())
while len(data) % 0x200 != 0:
data += b"\x00"
return True, bytearray(data)
indata = bytearray(wf.getbuffer())
while len(indata) % 0x200 != 0:
indata += b"\x00"
return True, bytearray(indata)
if __name__ == "__main__":
with open("seccfg.bin", "rb") as rf:
data = rf.read()
from hwcrypto import hwcrypto, crypto_setup
from hwcrypto import HwCrypto, CryptoSetup
setup = crypto_setup()
hwc = hwcrypto(setup)
setup = CryptoSetup()
hwc = HwCrypto(setup)
class mtk:
config = Mtk_Config()
class MTK:
config = MtkConfig()
sej_base = None
v3 = seccfgV3(hwc, mtk)
v3 = SecCfgV3(hwc, MTK)
v3.parse(data)
ret, newdata = v3.create("lock")
print(newdata.hex())

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import os
import sys
import logging
@ -8,12 +8,12 @@ import time
from binascii import hexlify
from struct import pack
from mtkclient.Library.utils import LogBase, logsetup
from mtkclient.Library.Connection.usblib import usb_class
from mtkclient.Library.Connection.seriallib import serial_class
from mtkclient.Library.Connection.usblib import UsbClass
from mtkclient.Library.Connection.seriallib import SerialClass
class Port(metaclass=LogBase):
class deviceclass:
class DeviceClass:
vid = 0
pid = 0
@ -22,15 +22,16 @@ class Port(metaclass=LogBase):
self.pid = pid
def __init__(self, mtk, portconfig, serialportname: str = None, loglevel=logging.INFO):
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.config = mtk.config
self.mtk = mtk
self.serialportname = None
if serialportname is not None:
self.cdc = serial_class(portconfig=portconfig, loglevel=loglevel, devclass=10)
self.cdc = SerialClass(portconfig=portconfig, loglevel=loglevel, devclass=10)
self.cdc.setportname(serialportname)
else:
self.cdc = usb_class(portconfig=portconfig, loglevel=loglevel, devclass=10)
self.cdc = UsbClass(portconfig=portconfig, loglevel=loglevel, devclass=10)
self.usbread = self.cdc.usbread
self.usbwrite = self.cdc.usbwrite
self.close = self.cdc.close
@ -49,29 +50,29 @@ class Port(metaclass=LogBase):
self.__logger.setLevel(logging.INFO)
def run_serial_handshake(self):
try: # Support for serial port where EP_OUT is unknown
if hasattr(self.cdc, 'EP_OUT'):
EP_OUT = self.cdc.EP_OUT.write
# maxinsize = self.cdc.EP_IN.wMaxPacketSize
try: # Support for serial port where ep_out is unknown
if hasattr(self.cdc, 'ep_out'):
ep_out = self.cdc.EP_OUT.write
# maxinsize = self.cdc.ep_in.wMaxPacketSize
else:
EP_OUT = self.cdc.write
ep_out = self.cdc.write
except Exception:
EP_OUT = self.cdc.write
ep_out = self.cdc.write
try:
if hasattr(self.cdc, 'EP_IN'):
EP_IN = self.cdc.EP_IN.read
if hasattr(self.cdc, 'ep_in'):
ep_in = self.cdc.EP_IN.read
else:
EP_IN = self.cdc.read
ep_in = self.cdc.read
except Exception:
EP_IN = self.cdc.read
ep_in = self.cdc.read
i = 0
startcmd = b"\xa0\x0a\x50\x05"
length = len(startcmd)
try:
while i < length:
if EP_OUT(int.to_bytes(startcmd[i], 1, 'little')):
v = EP_IN(1, timeout=20) # Do not wait 1 sec, bootloader is only active for 0.3 sec.
if ep_out(int.to_bytes(startcmd[i], 1, 'little')):
v = ep_in(1, timeout=20) # Do not wait 1 sec, bootloader is only active for 0.3 sec.
if len(v) == 1 and v[0] == ~(startcmd[i]) & 0xFF:
i += 1
else:
@ -125,8 +126,8 @@ class Port(metaclass=LogBase):
return False
def run_handshake(self):
EP_OUT = self.cdc.EP_OUT.write
EP_IN = self.cdc.EP_IN.read
ep_out = self.cdc.EP_OUT.write
ep_in = self.cdc.EP_IN.read
maxinsize = self.cdc.EP_IN.wMaxPacketSize
i = 0
@ -134,8 +135,8 @@ class Port(metaclass=LogBase):
length = len(startcmd)
try:
while i < length:
if EP_OUT(int.to_bytes(startcmd[i], 1, 'little')):
v = EP_IN(maxinsize)
if ep_out(int.to_bytes(startcmd[i], 1, 'little')):
v = ep_in(maxinsize)
if len(v) == 1 and v[0] == ~(startcmd[i]) & 0xFF:
i += 1
else:

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
from capstone import (Cs, CS_MODE_BIG_ENDIAN, CS_MODE_LITTLE_ENDIAN,
CS_ARCH_ARM, CS_ARCH_ARM64, CS_ARCH_MIPS,
CS_ARCH_X86, CS_ARCH_SPARC, CS_ARCH_SYSZ, CS_ARCH_XCORE,
@ -175,12 +175,14 @@ def main():
parser.add_argument(
'--disasm', '-disasm',
help='Disasm: arm[arm,thumb,mclass,v8],arm64[arm],mips[micro,3,32R6,GP64],x86[16,32,64],ppc[64],sparc[32,64,v9],systemz,xcore',
help='Disasm: arm[arm,thumb,mclass,v8],arm64[arm],mips[micro,3,32R6,GP64],' +
'x86[16,32,64],ppc[64],sparc[32,64,v9],systemz,xcore',
default='')
parser.add_argument(
'--asm', '-asm',
help='Asm: arm[arm,thumb,mclass,v8],arm64[arm],mips[micro,32,64,32R6,32R6-Micro],x86[16,32,64],ppc[32,64,qpx],sparc[None,v9],systemz,hexagon',
help='Asm: arm[arm,thumb,mclass,v8],arm64[arm],mips[micro,32,64,32R6,32R6-Micro]' +
',x86[16,32,64],ppc[32,64,qpx],sparc[None,v9],systemz,hexagon',
default='')
parser.add_argument(

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import hashlib
from Cryptodome.Cipher import AES
@ -72,8 +72,8 @@ class InvalidTagException(Exception):
return 'The authentication tag is invalid.'
class cryptutils:
class aes:
class CryptUtils:
class Aes:
# GF(2^128) defined by 1 + a + a^2 + a^7 + a^128
# Please note the MSB is x0 and LSB is x127
@staticmethod
@ -87,7 +87,7 @@ class cryptutils:
assert res < 1 << 128
return res
class AES_GCM:
class AesGcm:
# Galois/Counter Mode with AES-128 and 96-bit IV
"""
Example:
@ -250,24 +250,24 @@ class cryptutils:
return plaintext
@staticmethod
def aes_gcm(input, nounce, aes_key, hdr, tag_auth, decrypt=True):
def aes_gcm(indata, nounce, aes_key, hdr, tag_auth, decrypt=True):
cipher = AES.new(aes_key, AES.MODE_GCM, nounce)
if hdr is not None:
cipher.update(hdr)
if decrypt:
if tag_auth is None:
plaintext = cipher.decrypt(input)
plaintext = cipher.decrypt(indata)
return plaintext
elif tag_auth is not None:
plaintext = cipher.decrypt(input)
plaintext = cipher.decrypt(indata)
cipher.verify(tag_auth)
return plaintext
elif not decrypt:
if tag_auth is None:
ciphertext = cipher.encrypt(input)
ciphertext = cipher.encrypt(indata)
return ciphertext
elif tag_auth is not None:
ciphertext, tag_auth = cipher.encrypt_and_digest(input)
ciphertext, tag_auth = cipher.encrypt_and_digest(indata)
return ciphertext, tag_auth
@staticmethod
@ -316,7 +316,7 @@ class cryptutils:
else:
print("AES-CMAC ok !")
class rsa: # RFC8017
class Rsa: # RFC8017
def __init__(self, hashtype="SHA256"):
if hashtype == "SHA1":
self.hash = self.sha1
@ -326,25 +326,25 @@ class cryptutils:
self.digestLen = 0x20
def pss_test(self):
N = "a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65" + \
n = "a2ba40ee07e3b2bd2f02ce227f36a195024486e49c19cb41bbbdfbba98b22b0e577c2eeaffa20d883a76e65" + \
"e394c69d4b3c05a1e8fadda27edb2a42bc000fe888b9b32c22d15add0cd76b3e7936e19955b220dd17d4ea9" + \
"04b1ec102b2e4de7751222aa99151024c7cb41cc5ea21d00eeb41f7c800834d2c6e06bce3bce7ea9a5"
e = "010001"
D = "050e2c3e38d886110288dfc68a9533e7e12e27d2aa56d2cdb3fb6efa990bcff29e1d2987fb711962860e739" + \
d = "050e2c3e38d886110288dfc68a9533e7e12e27d2aa56d2cdb3fb6efa990bcff29e1d2987fb711962860e739" + \
"1b1ce01ebadb9e812d2fbdfaf25df4ae26110a6d7a26f0b810f54875e17dd5c9fb6d641761245b81e79f8c8" + \
"8f0e55a6dcd5f133abd35f8f4ec80adf1bf86277a582894cb6ebcd2162f1c7534f1f4947b129151b71"
MSG = "859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e5" + \
msg = "859eef2fd78aca00308bdc471193bf55bf9d78db8f8a672b484634f3c9c26e6478ae10260fe0dd8c082e5" + \
"3a5293af2173cd50c6d5d354febf78b26021c25c02712e78cd4694c9f469777e451e7f8e9e04cd3739c6b" + \
"bfedae487fb55644e9ca74ff77a53cb729802f6ed4a5ffa8ba159890fc"
salt = "e3b5d5d002c1bce50c2b65ef88a188d83bce7e61"
N = int(N, 16)
n = int(n, 16)
e = int(e, 16)
D = int(D, 16)
MSG = bytes.fromhex(MSG)
d = int(d, 16)
msg = bytes.fromhex(msg)
salt = bytes.fromhex(salt)
signature = self.pss_sign(D, N, self.hash(MSG), salt, 1024) # pkcs_1_pss_encode_sha256
isvalid = self.pss_verify(e, N, self.hash(MSG), signature, 1024)
signature = self.pss_sign(d, n, self.hash(msg), salt, 1024) # pkcs_1_pss_encode_sha256
isvalid = self.pss_verify(e, n, self.hash(msg), signature, 1024)
if isvalid:
print("Test passed.")
else:
@ -375,12 +375,12 @@ class cryptutils:
# def os2ip(self, X):
# return int.from_bytes(X, byteorder='big')
def mgf1(self, input, length):
def mgf1(self, indata, length):
counter = 0
output = b''
while len(output) < length:
C = self.i2osp(counter, 4)
output += self.hash(input + C)
c = self.i2osp(counter, 4)
output += self.hash(indata + c)
counter += 1
return output[:length]
@ -390,47 +390,45 @@ class cryptutils:
return
raise TypeError('%s should be an integer, not %s' % (name, var.__class__))
def sign(self, tosign, D, N, emBits=1024):
def sign(self, tosign, d, n, em_bits=1024):
self.assert_int(tosign, 'message')
self.assert_int(D, 'D')
self.assert_int(N, 'n')
self.assert_int(d, 'D')
self.assert_int(n, 'n')
if tosign < 0:
raise ValueError('Only non-negative numbers are supported')
if tosign > N:
tosign1 = divmod(tosign, N)[1]
signature = pow(tosign1, D, N)
raise OverflowError("The message %i is too long for n=%i" % (tosign, N))
if tosign > n:
raise OverflowError("The message %i is too long for n=%i" % (tosign, n))
signature = pow(tosign, D, N)
hexsign = self.i2osp(signature, emBits // 8)
signature = pow(tosign, d, n)
hexsign = self.i2osp(signature, em_bits // 8)
return hexsign
def pss_sign(self, D, N, msghash, salt, emBits=1024):
if isinstance(D, str):
D = bytes.fromhex(D)
D = self.os2ip(D)
if isinstance(N, str):
N = bytes.fromhex(N)
N = self.os2ip(N)
def pss_sign(self, d, n, msghash, salt, em_bits=1024):
if isinstance(d, str):
d = bytes.fromhex(d)
d = self.os2ip(d)
if isinstance(n, str):
n = bytes.fromhex(n)
n = self.os2ip(n)
slen = len(salt)
emLen = self.ceil_div(emBits, 8)
inBlock = b"\x00" * 8 + msghash + salt
hash = self.hash(inBlock)
PSlen = emLen - self.digestLen - slen - 1 - 1
DB = (PSlen * b"\x00") + b"\x01" + salt
rlen = emLen - len(hash) - 1
dbMask = self.mgf1(hash, rlen)
maskedDB = bytearray()
for i in range(0, len(dbMask)):
maskedDB.append(dbMask[i] ^ DB[i])
maskedDB[0] = maskedDB[0] & 0x7F
EM = maskedDB + hash + b"\xbc"
tosign = self.os2ip(EM)
em_len = self.ceil_div(em_bits, 8)
in_block = b"\x00" * 8 + msghash + salt
_hash = self.hash(in_block)
ps_len = em_len - self.digestLen - slen - 1 - 1
db = (ps_len * b"\x00") + b"\x01" + salt
rlen = em_len - len(_hash) - 1
db_mask = self.mgf1(_hash, rlen)
masked_db = bytearray()
for i in range(0, len(db_mask)):
masked_db.append(db_mask[i] ^ db[i])
masked_db[0] = masked_db[0] & 0x7F
em = masked_db + _hash + b"\xbc"
tosign = self.os2ip(em)
# EM=hexlify(EM).decode('utf-8')
# tosign = int(EM,16)
return self.sign(tosign, D, N, emBits)
return self.sign(tosign, d, n, em_bits)
# 6B1EAA2042A5C8DA8B1B4A8320111A70A0CBA65233D1C6E418EF8156E82A8F96BD843F047FF25AB9702A6582C8387298753E628F23448B4580E09CBD2A483C623B888F47C4BD2C5EFF09013C6DFF67DB59BAB3037F0BEE05D5660264D28CC6251631FE75CE106D931A04FA032FEA31259715CE0FAB1AE0E2F8130807AF4019A61B9C060ECE59104F22156FEE8108F17DC80D7C2F8397AFB9780994F7C5A0652F93D1B48010B0B248AB9711235787D797FBA4D10A29BCF09628585D405640A866B15EE9D7526A2703E72A19811EF447F6E5C43F915B3808EBC79EA4BCF78903DBDE32E47E239CFB5F2B5986D0CBBFBE6BACDC29B2ADE006D23D0B90775B1AE4DD
@staticmethod
@ -441,58 +439,57 @@ class cryptutils:
else:
return q
def pss_verify(self, e, N, msghash, signature, emBits=1024, salt=None):
def pss_verify(self, e, n, msghash, signature, em_bits=1024, salt=None):
if salt is None:
slen = self.digestLen
else:
slen = len(salt)
sig = self.os2ip(signature)
EM = pow(sig, e, N)
em = pow(sig, e, n)
# EM = bytes.fromhex(hex(EM)[2:])
EM = self.i2osp(EM, emBits // 8)
em = self.i2osp(em, em_bits // 8)
emLen = len(signature)
em_len = len(signature)
valBC = EM[-1]
if valBC != 0xbc:
print("[rsa_pss] : 0xbc check failed, value: 0x%02X" % valBC)
val_bc = em[-1]
if val_bc != 0xbc:
print("[rsa_pss] : 0xbc check failed, value: 0x%02X" % val_bc)
return False
hash = EM[emLen - self.digestLen - 1:-1]
maskedDB = EM[:emLen - self.digestLen - 1]
_hash = em[em_len - self.digestLen - 1:-1]
masked_db = em[:em_len - self.digestLen - 1]
lmask = ~(0xFF >> (8 * emLen + 1 - emBits))
if EM[0] & lmask:
lmask = ~(0xFF >> (8 * em_len + 1 - em_bits))
if em[0] & lmask:
print("[rsa_pss] : lmask check failed")
return False
dbMask = self.mgf1(hash, emLen - self.digestLen - 1)
db_mask = self.mgf1(_hash, em_len - self.digestLen - 1)
DB = bytearray()
for i in range(0, len(dbMask)):
DB.append(dbMask[i] ^ maskedDB[i])
db = bytearray()
for i in range(0, len(db_mask)):
db.append(db_mask[i] ^ masked_db[i])
TS = bytearray()
TS.append(DB[0] & ~lmask)
TS.extend(DB[1:])
ts = bytearray()
ts.append(db[0] & ~lmask)
ts.extend(db[1:])
PS = (b"\x00" * (emLen - self.digestLen - slen - 2)) + b"\x01"
if TS[:len(PS)] != PS:
print(TS[:len(PS)])
print(PS)
ps = (b"\x00" * (em_len - self.digestLen - slen - 2)) + b"\x01"
if ts[:len(ps)] != ps:
print(ts[:len(ps)])
print(ps)
print("[rsa_pss] : 0x01 check failed")
return False
if salt is not None:
inBlock = b"\x00" * 8 + msghash + salt
mhash = self.hash(inBlock)
return mhash == hash
in_block = b"\x00" * 8 + msghash + salt
mhash = self.hash(in_block)
return mhash == _hash
else:
salt = TS[-self.digestLen:]
inBlock = b"\x00" * 8 + msghash + salt
mhash = self.hash(inBlock)
return mhash == hash
return maskedDB
salt = ts[-self.digestLen:]
in_block = b"\x00" * 8 + msghash + salt
mhash = self.hash(in_block)
return mhash == _hash
@staticmethod
def sha1(msg):

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
ErrorCodes = {
0x0: "OK",
# COMMON

View file

@ -1,18 +1,19 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
import time
from struct import pack, unpack
from mtkclient.Library.Hardware.hwcrypto import hwcrypto, crypto_setup
from mtkclient.Library.Hardware.hwcrypto import HwCrypto, CryptoSetup
from mtkclient.Library.utils import LogBase, logsetup
from mtkclient.config.payloads import pathconfig
from mtkclient.config.payloads import PathConfig
class Exploitation(metaclass=LogBase):
def __init__(self, mtk, loglevel=logging.INFO):
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.lasterror = ""
self.mtk = mtk
self.chipconfig = self.mtk.config.chipconfig
@ -24,7 +25,7 @@ class Exploitation(metaclass=LogBase):
self.hwcode = mtk.config.hwcode
# crypto types
setup = crypto_setup()
setup = CryptoSetup()
setup.hwcode = self.mtk.config.hwcode
setup.dxcc_base = self.mtk.config.chipconfig.dxcc_base
setup.read32 = self.mtk.preloader.read32
@ -38,11 +39,11 @@ class Exploitation(metaclass=LogBase):
setup.ap_dma_mem = self.mtk.config.chipconfig.ap_dma_mem
setup.meid_addr = self.mtk.config.chipconfig.meid_addr
setup.prov_addr = self.mtk.config.chipconfig.prov_addr
self.hwcrypto = hwcrypto(setup, loglevel, self.mtk.config.gui)
self.hwcrypto = HwCrypto(setup, loglevel, self.mtk.config.gui)
self.chipconfig = self.mtk.config.chipconfig
self.var1 = self.chipconfig.var1
self.pathconfig = pathconfig()
self.pathconfig = PathConfig()
def fix_payload(self, payload, da=True):
payload = bytearray(payload)
@ -73,8 +74,8 @@ class Exploitation(metaclass=LogBase):
def da_payload(self, payload, addr, forcekamakiri=True, exploittype=1):
hassecurity = self.mtk.config.target_config["sla"] or self.mtk.config.target_config["daa"] or \
self.mtk.config.target_config["sbc"]
isV6 = self.mtk.config.chipconfig.damode == 6
if isV6:
is_v6 = self.mtk.config.chipconfig.damode == 6
if is_v6:
forcekamakiri = False
if hassecurity or forcekamakiri:
try:
@ -136,6 +137,9 @@ class Exploitation(metaclass=LogBase):
self.error("Error on sending payload.")
return False
def close(self):
pass
def crash(self, mode=0):
self.info("Crashing da...")
try:

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023
# (c) B.Kerler 2018-2024
import argparse
import os
import sys
@ -11,12 +11,12 @@ from struct import unpack
from binascii import hexlify
try:
from mtkclient.Library.utils import LogBase, structhelper
from mtkclient.Library.utils import LogBase, Structhelper, logsetup
except Exception:
from utils import LogBase, structhelper
from utils import LogBase, Structhelper
class gpt_settings:
class GptSettings:
gpt_num_part_entries = 0
gpt_part_entry_size = 0
gpt_part_entry_start_lba = 0
@ -27,10 +27,10 @@ class gpt_settings:
self.gpt_part_entry_start_lba = int(gpt_part_entry_start_lba)
class gpt(metaclass=LogBase):
class gpt_header:
def __init__(self, data):
sh = structhelper(data)
class GPT(metaclass=LogBase):
class GptHeader:
def __init__(self, indata):
sh = Structhelper(indata)
self.signature = sh.bytes(8)
self.revision = sh.dword()
self.header_size = sh.dword()
@ -45,9 +45,9 @@ class gpt(metaclass=LogBase):
self.num_part_entries = sh.dword()
self.part_entry_size = sh.dword()
class gpt_partition:
def __init__(self, data):
sh = structhelper(data)
class GptPartition:
def __init__(self, indata):
sh = Structhelper(indata)
self.type = sh.bytes(16)
self.unique = sh.bytes(16)
self.first_lba = sh.qword()
@ -55,7 +55,7 @@ class gpt(metaclass=LogBase):
self.flags = sh.qword()
self.name = sh.string(72)
class efi_type(Enum):
class EfiType(Enum):
EFI_UNUSED = 0x00000000
EFI_MBR = 0x024DEE41
EFI_SYSTEM = 0xC12A7328
@ -145,7 +145,8 @@ class gpt(metaclass=LogBase):
def __init__(self, num_part_entries=0, part_entry_size=0, part_entry_start_lba=0, loglevel=logging.INFO, *args,
**kwargs):
self.num_part_entries = num_part_entries
self.__logger = self.__logger
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, None)
self.part_entry_size = part_entry_size
self.part_entry_start_lba = part_entry_start_lba
self.totalsectors = None
@ -153,18 +154,17 @@ class gpt(metaclass=LogBase):
self.sectorsize = None
self.partentries = []
self.error = self.__logger.error
self.__logger.setLevel(loglevel)
if loglevel == logging.DEBUG:
logfilename = "log.txt"
fh = logging.FileHandler(logfilename, encoding='utf-8')
self.__logger.addHandler(fh)
def parseheader(self, gptdata, sectorsize=512):
return self.gpt_header(gptdata[sectorsize:sectorsize + 0x5C])
def parseheader(self, gptdata, sector_size=512):
return self.GptHeader(gptdata[sector_size:sector_size + 0x5C])
def parse_bpi(self, gptdata, pagesize=0x200):
class partf:
class Partf:
unique = b""
first_lba = 0
last_lba = 0
@ -179,33 +179,33 @@ class gpt(metaclass=LogBase):
self.totalsectors = 0
self.partentries = []
for pos in range(0x800, len(gptdata), 0x80):
data = gptdata[pos:pos + 0x80]
if int(hexlify(data[16:32]), 16) == 0:
rdata = gptdata[pos:pos + 0x80]
if int(hexlify(rdata[16:32]), 16) == 0:
break
rf = BytesIO(bytearray(data))
pf = partf()
rf.read(16)
guid1 = int.from_bytes(rf.read(4), 'little')
guid2 = int.from_bytes(rf.read(2), 'little')
guid3 = int.from_bytes(rf.read(2), 'little')
guid4 = int.from_bytes(rf.read(2), 'little')
guid5 = bytearray(rf.read(6)).hex()
rrf = BytesIO(bytearray(rdata))
pf = Partf()
rrf.read(16)
guid1 = int.from_bytes(rrf.read(4), 'little')
guid2 = int.from_bytes(rrf.read(2), 'little')
guid3 = int.from_bytes(rrf.read(2), 'little')
guid4 = int.from_bytes(rrf.read(2), 'little')
guid5 = bytearray(rrf.read(6)).hex()
pf.unique = "{:08x}-{:04x}-{:04x}-{:04x}-{}".format(guid1, guid2, guid3, guid4, guid5)
pf.first_lba = int.from_bytes(rf.read(8), 'little')
pf.last_lba = int.from_bytes(rf.read(8), 'little')
pf.first_lba = int.from_bytes(rrf.read(8), 'little')
pf.last_lba = int.from_bytes(rrf.read(8), 'little')
pf.sector = pf.first_lba
pf.sectors = pf.last_lba - pf.first_lba + 1
pf.flags = int.from_bytes(rf.read(8), 'little')
pf.name = rf.read(0x48).replace(b"\x00\x00", b"").decode("utf-16")
pf.flags = int.from_bytes(rrf.read(8), 'little')
pf.name = rrf.read(0x48).replace(b"\x00\x00", b"").decode("utf-16")
pf.type = 0
if pf.last_lba > self.totalsectors:
self.totalsectors = pf.last_lba
self.partentries.append(pf)
def parse(self, gptdata, sectorsize=512):
self.header = self.gpt_header(gptdata[sectorsize:sectorsize + 0x5C])
self.sectorsize = sectorsize
def parse(self, gptdata, sector_size=512):
self.header = self.GptHeader(gptdata[sector_size:sector_size + 0x5C])
self.sectorsize = sector_size
if self.header.signature != b"EFI PART":
if gptdata[0:4] == b"BPI\x00":
self.parse_bpi(gptdata)
@ -215,14 +215,14 @@ class gpt(metaclass=LogBase):
self.error("Unknown GPT revision.")
return False
if self.part_entry_start_lba != 0:
start = self.part_entry_start_lba
_start = self.part_entry_start_lba
else:
start = self.header.part_entry_start_lba * sectorsize
_start = self.header.part_entry_start_lba * sector_size
entrysize = self.header.part_entry_size
self.partentries = []
class partf:
class Partf:
unique = b""
first_lba = 0
last_lba = 0
@ -235,11 +235,11 @@ class gpt(metaclass=LogBase):
num_part_entries = self.header.num_part_entries
for idx in range(0, num_part_entries):
data = gptdata[start + (idx * entrysize):start + (idx * entrysize) + entrysize]
if int(hexlify(data[16:32]), 16) == 0:
indata = gptdata[_start + (idx * entrysize):_start + (idx * entrysize) + entrysize]
if int(hexlify(indata[16:32]), 16) == 0:
break
partentry = self.gpt_partition(data)
pa = partf()
partentry = self.GptPartition(indata)
pa = Partf()
guid1 = unpack("<I", partentry.unique[0:0x4])[0]
guid2 = unpack("<H", partentry.unique[0x4:0x6])[0]
guid3 = unpack("<H", partentry.unique[0x6:0x8])[0]
@ -249,11 +249,11 @@ class gpt(metaclass=LogBase):
pa.sector = partentry.first_lba
pa.sectors = partentry.last_lba - partentry.first_lba + 1
pa.flags = partentry.flags
type = int(unpack("<I", partentry.type[0:0x4])[0])
ptype = int(unpack("<I", partentry.type[0:0x4])[0])
try:
pa.type = self.efi_type(type).name
pa.type = self.EfiType(ptype).name
except Exception:
pa.type = hex(type)
pa.type = hex(ptype)
pa.name = partentry.name.replace(b"\x00\x00", b"").decode('utf-16')
if pa.type == "EFI_UNUSED":
continue
@ -266,78 +266,78 @@ class gpt(metaclass=LogBase):
def tostring(self):
mstr = "\nGPT Table:\n-------------\n"
for partition in self.partentries:
for _partition in self.partentries:
mstr += ("{:20} Offset 0x{:016x}, Length 0x{:016x}, Flags 0x{:08x}, UUID {}, Type {}\n".format(
partition.name + ":", partition.sector * self.sectorsize, partition.sectors * self.sectorsize,
partition.flags, partition.unique, partition.type))
_partition.name + ":", _partition.sector * self.sectorsize, _partition.sectors * self.sectorsize,
_partition.flags, _partition.unique, _partition.type))
mstr += ("\nTotal disk size:0x{:016x}, sectors:0x{:016x}\n".format(self.totalsectors * self.sectorsize,
self.totalsectors))
return mstr
def generate_rawprogram(self, lun, sectorsize, directory):
def generate_rawprogram(self, lun, sector_size, directory):
fname = "rawprogram" + str(lun) + ".xml"
with open(os.path.join(directory, fname), "wb") as wf:
with open(os.path.join(directory, fname), "wb") as wwf:
mstr = "<?xml version=\"1.0\" ?>\n<data>\n"
partofsingleimage = "false"
readbackverify = "false"
sparse = "false"
for partition in self.partentries:
filename = partition.name + ".bin"
mstr += f"\t<program SECTOR_SIZE_IN_BYTES=\"{sectorsize}\" " + \
for _partition in self.partentries:
_filename = _partition.name + ".bin"
mstr += f"\t<program SECTOR_SIZE_IN_BYTES=\"{sector_size}\" " + \
f"file_sector_offset=\"0\" " \
f"filename=\"{filename}\" " + \
f"label=\"{partition.name}\" " \
f"num_partition_sectors=\"{partition.sectors}\" " + \
f"_filename=\"{_filename}\" " + \
f"label=\"{_partition.name}\" " \
f"num_partition_sectors=\"{_partition.sectors}\" " + \
f"partofsingleimage=\"{partofsingleimage}\" " \
f"physical_partition_number=\"{str(lun)}\" " + \
f"readbackverify=\"{readbackverify}\" " \
f"size_in_KB=\"{(partition.sectors * sectorsize / 1024):.1f}\" " \
f"size_in_KB=\"{(_partition.sectors * sector_size / 1024):.1f}\" " \
f"sparse=\"{sparse}\" " + \
f"start_byte_hex=\"{hex(partition.sector * sectorsize)}\" " \
f"start_sector=\"{partition.sector}\"/>\n"
f"start_byte_hex=\"{hex(_partition.sector * sector_size)}\" " \
f"start_sector=\"{_partition.sector}\"/>\n"
partofsingleimage = "true"
sectors = self.header.first_usable_lba
mstr += f"\t<program SECTOR_SIZE_IN_BYTES=\"{sectorsize}\" " + \
mstr += f"\t<program SECTOR_SIZE_IN_BYTES=\"{sector_size}\" " + \
"file_sector_offset=\"0\" " + \
f"filename=\"gpt_lun{str(lun)}.bin\" " + \
f"_filename=\"gpt_lun{str(lun)}.bin\" " + \
"label=\"PrimaryGPT\" " + \
f"num_partition_sectors=\"{sectors}\" " + \
f"partofsingleimage=\"{partofsingleimage}\" " + \
f"physical_partition_number=\"{str(lun)}\" " + \
f"readbackverify=\"{readbackverify}\" " + \
f"size_in_KB=\"{(sectors * sectorsize / 1024):.1f}\" " + \
f"size_in_KB=\"{(sectors * sector_size / 1024):.1f}\" " + \
f"sparse=\"{sparse}\" " + \
"start_byte_hex=\"0x0\" " + \
"start_sector=\"0\"/>\n"
sectors = self.header.first_usable_lba - 1
mstr += f"\t<program SECTOR_SIZE_IN_BYTES=\"{sectorsize}\" " + \
mstr += f"\t<program SECTOR_SIZE_IN_BYTES=\"{sector_size}\" " + \
"file_sector_offset=\"0\" " + \
f"filename=\"gpt_backup{str(lun)}.bin\" " + \
f"_filename=\"gpt_backup{str(lun)}.bin\" " + \
"label=\"BackupGPT\" " + \
f"num_partition_sectors=\"{sectors}\" " + \
f"partofsingleimage=\"{partofsingleimage}\" " + \
f"physical_partition_number=\"{str(lun)}\" " + \
f"readbackverify=\"{readbackverify}\" " + \
f"size_in_KB=\"{(sectors * sectorsize / 1024):.1f}\" " + \
f"size_in_KB=\"{(sectors * sector_size / 1024):.1f}\" " + \
f"sparse=\"{sparse}\" " + \
f"start_byte_hex=\"({sectorsize}*NUM_DISK_SECTORS)-{sectorsize * sectors}.\" " + \
f"start_byte_hex=\"({sector_size}*NUM_DISK_SECTORS)-{sector_size * sectors}.\" " + \
f"start_sector=\"NUM_DISK_SECTORS-{sectors}.\"/>\n"
mstr += "</data>"
wf.write(bytes(mstr, 'utf-8'))
print(f"Wrote partition xml as {fname}")
wwf.write(bytes(mstr, 'utf-8'))
print(f"Wrote _partition xml as {fname}")
def print_gptfile(self, filename):
def print_gptfile(self, gptfilename):
try:
with open(filename, "rb") as rf:
size = min(32 * 4096, os.stat(filename).st_size)
data = rf.read(size)
for sectorsize in [512, 4096]:
result = self.parse(data, sectorsize)
if result:
with open(gptfilename, "rb") as rrf:
_sz = min(32 * 4096, os.stat(gptfilename).st_size)
_data = rrf.read(_sz)
for sector_size in [512, 4096]:
res = self.parse(_data, sector_size)
if res:
break
if result:
if res:
print(self.tostring())
return result
return res
except Exception as e:
self.error(str(e))
return ""
@ -365,7 +365,7 @@ if __name__ == "__main__":
if args.command not in ["print", "extract", "test"]:
parser.error("Command is mandatory")
gp = gpt()
gp = GPT()
if args.command == "print":
if not os.path.exists(args.image):
print(f"File {args.image} does not exist. Aborting.")

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import time
import sys
import logging
@ -20,7 +20,8 @@ class META(metaclass=LogBase):
def __init__(self, mtk, loglevel=logging.INFO):
self.mtk = mtk
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.gcpu = None
self.config = mtk.config
self.display = True
@ -47,27 +48,26 @@ class META(metaclass=LogBase):
cdc.connected = cdc.connect()
if cdc.connected and cdc.pid == 0x2000:
counter += 1
EP_OUT = cdc.EP_OUT.write
EP_IN = cdc.EP_IN.read
ep_out = cdc.EP_OUT.write
ep_in = cdc.EP_IN.read
maxinsize = cdc.EP_IN.wMaxPacketSize
while True:
resp = b""
try:
resp = bytearray(EP_IN(maxinsize))
resp = bytearray(ep_in(maxinsize))
except Exception:
break
if resp == b"READY":
EP_OUT(metamode, len(metamode))
ep_out(metamode, len(metamode))
while resp == b"READY":
resp = bytearray(EP_IN(maxinsize))
resp = bytearray(ep_in(maxinsize))
if resp in [b"ATEMEVDX", b"TOOBTSAF", b"ATEMATEM", b"TCAFTCAF", b"MYROTCAF"]:
if resp == b"ATEMATEM":
EP_OUT(b"\x04\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xC0")
EP_OUT(b"\x04\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xC0")
EP_OUT(b"\x06\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xC0\x00\x80\x00\x00")
ep_out(b"\x04\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xC0")
ep_out(b"\x04\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xC0")
ep_out(b"\x06\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xC0\x00\x80\x00\x00")
# INFO =
EP_IN(13) # !READYATEM
EP_OUT(b"DISCONNECT")
ep_in(13) # !READYATEM
ep_out(b"DISCONNECT")
return True
self.warning(resp)
else:

View file

@ -1,11 +1,11 @@
#!/usr/bin/env python3
# MTK Flash Client (c) B.Kerler 2018-2023.
# MTK Flash Client (c) B.Kerler 2018-2024.
# Licensed under GPLv3 License
import os
import logging
from struct import unpack
from mtkclient.config.usb_ids import default_ids
from mtkclient.config.payloads import pathconfig
from mtkclient.config.payloads import PathConfig
from mtkclient.Library.pltools import PLTools
from mtkclient.Library.mtk_preloader import Preloader
from mtkclient.Library.DA.mtk_daloader import DAloader
@ -28,8 +28,9 @@ class Mtk(metaclass=LogBase):
self.vid = config.vid
self.pid = config.pid
self.interface = config.interface
self.pathconfig = pathconfig()
self.__logger = logsetup(self, self.__logger, loglevel, config.gui)
self.pathconfig = PathConfig()
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger, loglevel,
config.gui)
self.eh = ErrorHandler()
self.serialportname = serialportname
if preinit:

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# MTK Flash Client (c) B.Kerler 2018-2023.
# MTK Flash Client (c) B.Kerler 2018-2024.
# Licensed under GPLv3 License
import os
import sys
@ -8,21 +8,23 @@ import time
from binascii import hexlify
from struct import unpack, pack
from mtkclient.Library.mtk_class import Mtk
from mtkclient.config.payloads import pathconfig
from mtkclient.config.payloads import PathConfig
from mtkclient.Library.pltools import PLTools
from mtkclient.Library.meta import META
from mtkclient.Library.utils import LogBase, getint
from mtkclient.config.mtk_config import Mtk_Config
from mtkclient.Library.utils import LogBase, getint, logsetup
from mtkclient.config.mtk_config import MtkConfig
from mtkclient.Library.utils import print_progress
from mtkclient.Library.error import ErrorHandler
from mtkclient.Library.DA.mtk_da_handler import DA_handler
from mtkclient.Library.gpt import gpt_settings
from mtkclient.Library.DA.mtk_da_handler import DaHandler
from mtkclient.Library.gpt import GptSettings
metamodes = "[FASTBOOT, FACTFACT, METAMETA, FACTORYM, ADVEMETA, AT+NBOOT]"
class ArgHandler(metaclass=LogBase):
def __init__(self, args, config):
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
config.loglevel, config.gui)
try:
config.gpt_file = None
if args.gpt_file is not None:
@ -151,17 +153,15 @@ class ArgHandler(metaclass=LogBase):
except Exception:
pass
config.gpt_settings = gpt_settings(gpt_num_part_entries, gpt_part_entry_size,
gpt_part_entry_start_lba)
config.gpt_settings = GptSettings(gpt_num_part_entries, gpt_part_entry_size,
gpt_part_entry_start_lba)
class Main(metaclass=LogBase):
def __init__(self, args):
self.__logger = self.__logger
self.info = self.__logger.info
self.debug = self.__logger.debug
self.error = self.__logger.error
self.warning = self.__logger.warning
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
logging.INFO, None)
self.eh = None
self.args = args
if not os.path.exists("logs"):
os.mkdir("logs")
@ -172,7 +172,7 @@ class Main(metaclass=LogBase):
def cmd_stage(self, mtk, filename, stage2addr, stage2file, verifystage2):
if filename is None:
pc = pathconfig()
pc = PathConfig()
stage1file = os.path.join(pc.get_payloads_path(), "generic_stage1_payload.bin")
else:
stage1file = filename
@ -184,7 +184,7 @@ class Main(metaclass=LogBase):
self.error(f"Error: {stage2file} doesn't exist !")
return False
else:
stage2file = os.path.join(mtk.pathconfig.get_payloads_path(), "stage2.bin")
stage2file = os.path.join(mtk.PathConfig.get_payloads_path(), "stage2.bin")
if mtk.preloader.init():
mtk = mtk.crasher()
if mtk.port.cdc.pid == 0x0003:
@ -269,6 +269,7 @@ class Main(metaclass=LogBase):
self.info("Successfully loaded stage2")
def cmd_peek(self, mtk, addr, length, preloader, filename):
wwf = None
if preloader is not None:
if os.path.exists(preloader):
daaddr, dadata = mtk.parse_preloader(preloader)
@ -284,8 +285,8 @@ class Main(metaclass=LogBase):
if mtk.preloader.jump_da(daaddr):
self.info(f"Jumped to pl {hex(daaddr)}.")
time.sleep(2)
config = Mtk_Config(loglevel=self.__logger.level, gui=mtk.config.gui,
guiprogress=mtk.config.guiprogress)
config = MtkConfig(loglevel=self.__logger.level, gui=mtk.config.gui,
guiprogress=mtk.config.guiprogress)
mtk = Mtk(loglevel=self.__logger.level, config=config,
serialportname=mtk.port.serialportname)
res = mtk.preloader.init()
@ -304,7 +305,7 @@ class Main(metaclass=LogBase):
if length % 4:
dwords += 1
if filename is not None:
wf = open(filename, "wb")
wwf = open(filename, "wb")
sdata = b""
print_progress(0, 100, prefix='Progress:',
suffix='Starting, addr 0x%08X' % addr, bar_length=50)
@ -319,7 +320,7 @@ class Main(metaclass=LogBase):
data = b"".join(int.to_bytes(val, 4, 'little') for val in mtk.preloader.read32(addr + pos, size))
sdata += data
if filename is not None:
wf.write(data)
wwf.write(data)
pos += len(data)
prog = pos / length * 100
if round(prog, 1) > old:
@ -332,7 +333,7 @@ class Main(metaclass=LogBase):
if filename is None:
print(hexlify(sdata).decode('utf-8'))
else:
wf.close()
wwf.close()
self.info(f"Data from {hex(addr)} with size of {hex(length)} was written to " + filename)
def run(self, parser):
@ -347,7 +348,7 @@ class Main(metaclass=LogBase):
loglevel = logging.INFO
self.__logger.setLevel(logging.INFO)
pass
config = Mtk_Config(loglevel=loglevel, gui=None, guiprogress=None)
config = MtkConfig(loglevel=loglevel, gui=None, guiprogress=None)
ArgHandler(self.args, config)
self.eh = ErrorHandler()
serialport = None
@ -393,7 +394,7 @@ class Main(metaclass=LogBase):
preloader = self.args.preloader
except Exception:
preloader = None
da_handler = DA_handler(mtk, loglevel)
da_handler = DaHandler(mtk, loglevel)
mtk = da_handler.configure_da(mtk, preloader)
if mtk is not None:
for rcmd in commands:
@ -525,7 +526,8 @@ class Main(metaclass=LogBase):
mtk.port.close()
self.close()
return
if self.args.startpartition is not None or self.args.offset is not None or self.args.length is not None:
if (self.args.startpartition is not None or self.args.offset is not None or
self.args.length is not None):
time.sleep(1)
res = mtk.preloader.init()
if not res:
@ -649,7 +651,7 @@ class Main(metaclass=LogBase):
preloader = self.args.preloader
except Exception:
preloader = None
da_handler = DA_handler(mtk, loglevel)
da_handler = DaHandler(mtk, loglevel)
mtk = da_handler.configure_da(mtk, preloader)
if mtk is not None:
da_handler.handle_da_cmds(mtk, cmd, self.args)
@ -676,9 +678,9 @@ class Main(metaclass=LogBase):
plt = PLTools(mtk, self.__logger.level)
if payloadfile is None:
if mtk.config.chipconfig.loader is None:
payloadfile = os.path.join(mtk.pathconfig.get_payloads_path(), "generic_patcher_payload.bin")
payloadfile = os.path.join(mtk.PathConfig.get_payloads_path(), "generic_patcher_payload.bin")
else:
payloadfile = os.path.join(mtk.pathconfig.get_payloads_path(), mtk.config.chipconfig.loader)
payloadfile = os.path.join(mtk.PathConfig.get_payloads_path(), mtk.config.chipconfig.loader)
plt.runpayload(filename=payloadfile)
if self.args.metamode:
mtk.port.run_handshake()

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import os
import logging
import time
@ -8,13 +8,12 @@ from enum import Enum
from struct import unpack, pack
from binascii import hexlify
from Cryptodome.Util.number import bytes_to_long, long_to_bytes, ceil_div, size
from Cryptodome.PublicKey import RSA
import mtkclient.Library.settings
from Cryptodome.Util.number import size
from mtkclient.Library.Auth.sla_keys import brom_sla_keys
from mtkclient.Library.Auth.sla import generate_brom_sla_challenge
from mtkclient.Library.utils import LogBase, logsetup
from mtkclient.Library.error import ErrorHandler
from mtkclient.config.brom_config import damodes
from mtkclient.config.brom_config import DAmodes
USBDL_BIT_EN = 0x00000001 # 1: download bit enabled
USBDL_BROM = 0x00000002 # 0: usbdl by brom; 1: usbdl by bootloader
@ -24,29 +23,6 @@ USBDL_MAGIC = 0x444C0000 # Brom will check this magic number
MISC_LOCK_KEY_MAGIC = 0xAD98
def customizedSign(n, e, msg):
modBits = size(n)
k = ceil_div(modBits, 8)
ps = b'\xFF' * (k - len(msg) - 3)
em = b'\x00\x01' + ps + b'\x00' + msg
em_int = bytes_to_long(em)
m_int = pow(em_int, e, n)
signature = long_to_bytes(m_int, k)
return signature
def generate_rsa_challenge(n, e, data):
for i in range(0, len(data), 2):
data[i], data[i + 1] = data[i + 1], data[i]
msg = bytearray(customizedSign(n, e, data))
for i in range(0, len(msg), 2):
msg[i], msg[i + 1] = msg[i + 1], msg[i]
return msg
def calc_xflash_checksum(data):
checksum = 0
pos = 0
@ -146,7 +122,8 @@ class Preloader(metaclass=LogBase):
def __init__(self, mtk, loglevel=logging.INFO):
self.mtk = mtk
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.info = self.__logger.info
self.debug = self.__logger.debug
self.error = self.__logger.error
@ -269,7 +246,7 @@ class Preloader(metaclass=LogBase):
self.send_root_cert(certdata)
else:
self.error(f"Couldn't find cert file {self.config.cert}")
if self.config.target_config["sla"] and self.config.chipconfig.damode == damodes.XML:
if self.config.target_config["sla"] and self.config.chipconfig.damode == DAmodes.XML:
self.handle_sla(func=None, isbrom=self.config.is_brom)
return True
@ -367,12 +344,12 @@ class Preloader(metaclass=LogBase):
usbdlreg |= USBDL_MAGIC # | 0x444C0000
# set BOOT_MISC0 as watchdog resettable
RST_CON = self.config.chipconfig.misc_lock + 8
USBDL_FLAG = self.config.chipconfig.misc_lock - 0x20
rst_con = self.config.chipconfig.misc_lock + 8
usbdl_flag = self.config.chipconfig.misc_lock - 0x20
self.write32(self.config.chipconfig.misc_lock, MISC_LOCK_KEY_MAGIC)
self.write32(RST_CON, 1)
self.write32(rst_con, 1)
self.write32(self.config.chipconfig.misc_lock, 0)
self.write32(USBDL_FLAG, usbdlreg)
self.write32(usbdl_flag, usbdlreg)
return
def run_ext_cmd(self, cmd: bytes = b"\xB1"):
@ -673,501 +650,9 @@ class Preloader(metaclass=LogBase):
return False
def handle_sla(self, func=None, isbrom: bool = True):
rsakeys = [
# libsla_challenge.so, secure_chip_tools/keys/toolauth/sla_prvk.pem V5
(bytes_to_long(bytes.fromhex("010001")),
bytes_to_long(bytes.fromhex(
"C43469A95B143CDC63CE318FE32BAD35B9554A136244FA74D13947425A32949EE6DC808CDEBF4121687A570B83C51E65" +
"7303C925EC280B420C757E5A63AD3EC6980AAD5B6CA6D1BBDC50DB793D2FDDC0D0361C06163CFF9757C07F96559A2186" +
"322F7ABF1FFC7765F396673A48A4E8E3296427BC5510D0F97F54E5CA1BD7A93ADE3F6A625056426BDFE77B3B502C68A1" +
"8F08B470DA23B0A2FAE13B8D4DB3746255371F43306582C74794D1491E97FDE504F0B1ECAC9DDEF282D674B817B7FFA8" +
"522672CF6281790910378FEBFA7DC6C2B0AF9DA03A58509D60AA1AD6F9BFDC84537CD0959B8735FE0BB9B471104B458A" +
"38DF846366926993097222F90628528F")),
bytes_to_long(bytes.fromhex(
"8E02CDB389BBC52D5383EBB5949C895B0850E633CF7DD3B5F7B5B8911B0DDF2A80387B46FAF67D22BC2748978A0183B5" +
"B420BA579B6D847082EA0BD14AB21B6CCCA175C66586FCE93756C2F426C85D7DF07629A47236265D1963B8354CB229AF" +
"A2E560B7B3641DDB8A0A839ED8F39BA8C7CDB94104650E8C7790305E2FF6D18206F49B7290B1ADB7B4C523E10EBF5363" +
"0D438EF49C877402EA3C1BD6DD903892FD662FBDF1DFF5D7B095712E58E728BD7F6A8B5621175F4C08EBD6143CDACD65" +
"D9284DFFECAB64F70FD63182E4981551522727A2EE9873D0DB78180C26553AD0EE1CAAA21BCEBC5A8C0B331FE7FD8710" +
"F905A7456AF675A04AF1118CE71E36C9"))),
# bootloader/preloader/platform/mt6781/flash/custom/oemkey.h V6
(bytes_to_long(bytes.fromhex("010001")),
bytes_to_long(bytes.fromhex(
"B243F6694336D527C5B3ED569DDD0386D309C6592841E4C033DCB461EEA7B6F8535FC4939E403060646A970DD81DE367" +
"CF003848146F19D259F50A385015AF6309EAA71BFED6B098C7A24D4871B4B82AAD7DC6E2856C301BE7CDB46DC10795C0" +
"D30A68DD8432B5EE5DA42BA22124796512FCA21D811D50B34C2F672E25BCC2594D9C012B34D473EE222D1E56B90E7D69" +
"7CEA97E8DD4CCC6BED5FDAECE1A43F96495335F322CCE32612DAB462B024281841F553FF7FF33E0103A7904037F8FE5D" +
"9BE293ACD7485CDB50957DB11CA6DB28AF6393C3E78D9FBCD4567DEBCA2601622F0F2EB19DA9192372F9EA3B28B10794" +
"09C0A09E3D51D64A4C4CE026FAD24CD7")),
bytes_to_long(bytes.fromhex(
"607C8892D0DE8CE0CA116914C8BD277B821E784D298D00D3473EDE236399435F8541009525C2786CB3ED3D7530D47C91" +
"63692B0D588209E7E0E8D06F4A69725498B979599DC576303B5D8D96F874687A310D32E8C86E965B844BC2ACE51DC5E0" +
"6859EA087BD536C39DCB8E1262FDEAF6DA20035F14D3592AB2C1B58734C5C62AC86FE44F98C602BABAB60A6C8D09A199" +
"D2170E373D9B9A5D9B6DE852E859DEB1BDF33034DCD91EC4EEBFDDBECA88E29724391BB928F40EFD945299DFFC4595BB" +
"8D45F426AC15EC8B1C68A19EB51BEB2CC6611072AE5637DF0ABA89ED1E9CB8C9AC1EB05B1F01734DB303C23BE1869C90" +
"13561B9F6EA65BD2516DE950F08B2E81"))),
# lk/files/pbp/keys/toolauth/sla_prvk.pem, rowan
(bytes_to_long(bytes.fromhex("010001")),
bytes_to_long(bytes.fromhex(
"D16403466C530EF9BB53C1E8A96A61A4E332E17DC0F55BB46D207AC305BAE9354EAAC2CB3077B33740D275036B822DB2" +
"68200DE17DA3DB7266B27686B8970B85737050F084F8D576904E74CD6C53B31F0BB0CD60686BF67C60DA0EC20F563EEA" +
"715CEBDBF76D1C5C10E982AB2955D833DE553C9CDAFD7EA2388C02823CFE7DD9AC83FA2A8EB0685ABDAB56A92DF1A780" +
"5E8AC0BD10C0F3DCB1770A9E6BBC3418C5F84A48B7CB2316B2C8F64972F391B116A58C9395A9CE9E743569A367086D77" +
"71D39FEC8EBBBA3DD2B519785A76A9F589D36D637AF884543FD65BAC75BE823C0C50AA16D58187B97223625C54C66B5A" +
"5E4DBAEAB7BE89A4E340A2E241B09B2F")),
bytes_to_long(bytes.fromhex(
"09976537029b4362591c5b13873f223de5525d55df52dde283e52afa67f6c9dbf1408d2fb586a624efc93426f5f3be98" +
"1f80e861ddd975a1e5e662db84f5164804a3ae717605d7f15866df9ed1497c38fdd6197243163ef22f958d7b822c5731" +
"7203e9a1e7d18dad01f15054facdbddb9261a1272638da661fe4f9f0714ecf00e6541cc435afb1fd75a27d34b17ad400" +
"e9474ba850dafce266799caff32a058ff71e4c2daacaf8ba709e9ca4dc87584a7ffe8aa9a0a160ed069c3970b7dae398" +
"7ded71bd0bc824356987bd74363d46682c71913c3edbdb2a911f701f23aee3f8dd98180b5a138fd5ad74743682d2d2d1" +
"bb3d92786710248f316dd8391178ea81"))),
# Alcatel/TCL MTK_U91
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"9a97c44b0768424b6bbb0b6aa987a2d373448c6fee1f61fb81f8cf53d70856f0f77e76c06a6901de90ed3b4d9ad4b" +
"9e04eaed42e5657bf2fccf390fe9f5abe1abe8575f07916da69acef95d38874223ec51cb501148a1feea2be2b8ccd" +
"a08672aa423a4099203c6aa4777fed7353c57696b8e0d4020bd6930b828b9846a454cd")),
bytes_to_long(bytes.fromhex(
"8553e31d7a73f6c9294e961815c23f31f2b5ea1116e3c613ae12b26cf285e4c5ca0e2dc8e17d52f96b30cef6ad544" +
"e43205933f20ad17eb8712097aaa23116c68eb6328980b8ba26706105656fa65315688b8232758607b8936d0abc27" +
"dbc97d94e95b4f1957fd1965082e5849c4185ebba8afc7d558d4f5f001ac5363423ac1"))
),
# Alcatel/TCL MTK_OTMINI
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"bc7b5107bcf46c2cd7758f4bd4d4e9f06b731d9cff383dffe48156d1ad91ff74a7925fa3027669766b3d4c6e28c1c" +
"9310194c34a59e672c8ced38588e998d7b162889dcf06668345f93e4efca34b5fee5bb57dfc38d7623a48f31b382d" +
"e2db656ec1f3b5267a9a8f5e441c61448a283e4717ace6983d01b163e34f959c9972cd")),
bytes_to_long(bytes.fromhex(
"6bc0e84b4f38415bc575dd0d5248c2d182ec55e2ba7a11dfe86815155c709a25bbe34fafa6a9c19344adcfb32eb3d" +
"2eca465c2dc0fd7528a00cc268c6657cdff0b0da1b2ac6a95b94865facb7e1494cedf44358e29ec7e8f091172e4ef" +
"29856d1f45032aa644efc273f141c10cb8281a12cebe202b65f176e1a145c326d75841"))
),
# Alcatel/TCL ST513
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"df836c16bc8e129dac8e6efcd3f41636981687c29c465b481cbe874ffb14d592de024b70f4fa20ad96c96e4e3eded3" +
"625f314dedb4d8635782f6d668d04ab1167982229e03ede17a7857a22cbf72444a6bee2bba54f32099e0eabe654c3d" +
"a4933926db4d97dcaeb68236df4b3e51bd3c4bfa8b2d47c2534405e4f1c1d43e1069")),
bytes_to_long(bytes.fromhex(
"9ea0f7256bcca9099e5db80757a5f3ddeb3292475c01d2e6eaff8da905d9537a5875e874d26872a8c04b552dd310f1" +
"94ef5a5ea445a50d5c1e6670e5126ef01e5fb1af24a67d07b5a9f72197bc66d5743faab54759fbedcf1fd8ac1aabed" +
"e2c6fb29601b4734334db92a92fc25f7ed8700d307b74a2c435c9ce5b5caba4b3801"))
),
# Alcatel/TCL MPK_U7
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"db0b6e89fabdc24e6e7379d25b0c402686537ab6375d8b2407beaf44cbbef27e04e90b556801bbce5eee2a7ec636ac" +
"825667dae3578eb7bbb66701bc62ee86f28fc14d57e8637a2ddcee00cc3ab87dff4155250c2dbde9ae62f3d7a9d5e4" +
"a265fb0a8b23c082be263d7788e44d59780b47a31b25dc588f81902be419f917933b")),
bytes_to_long(bytes.fromhex(
"c5829b5bc34253f090db831f5085cd5a6f88da7f6f90e3a3cb6fff6e53218c5a616719971b3f64ef02de526719a7b7" +
"09978bf1ed48c821981b32ea77c9e536bbda206fad74946d02a20d17120f89419b0daee2d8a47275768930ad53c876" +
"afebffb6805483c1ddcf6c19f3566f0de494838afb51b18080beff66364de5294581"))
),
# Alcatel/TCL MTK_U8
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"9bc517a0dfa87a7e240000c5f42cf31905ab93d4bcb95694dee85282867d5c83270aea0b0948d66eb39d8500aa6c8b" +
"1069b8ee784f75948958f7bbf627d6ed5f286fd3bd4df60a6c9490cb319448b22765aba9329820eec50f62f1ca0b6b" +
"3322aa27747b26855a1f1719cf0c4060c9f5a6a3a60ec60fe6e04e7b044e5da994e9")),
bytes_to_long(bytes.fromhex(
"76ca90a16bcf7552db2b716b8531fe5617bfe86635627647e3d27291fdf47e67ba8f953ac362dbbce2977f05a9f24a" +
"ff4250f8f3a14d3ef09b7b99c9384aad0c53104f87b47d7daea3ca725beb233d127ec342ce0619b16bd3d5e44371cf" +
"fce9f23178ff48dd42fc4450ccdb3e2d63437ef9dfc0296b12840ae85d472cf0135d"))
),
# Alcatel/TCL MPK_U91
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"9a97c44b0768424b6bbb0b6aa987a2d373448c6fee1f61fb81f8cf53d70856f0f77e76c06a6901de90ed3b4d9ad4b9" +
"e04eaed42e5657bf2fccf390fe9f5abe1abe8575f07916da69acef95d38874223ec51cb501148a1feea2be2b8ccda0" +
"8672aa423a4099203c6aa4777fed7353c57696b8e0d4020bd6930b828b9846a454cd")),
bytes_to_long(bytes.fromhex(
"8553e31d7a73f6c9294e961815c23f31f2b5ea1116e3c613ae12b26cf285e4c5ca0e2dc8e17d52f96b30cef6ad544e" +
"43205933f20ad17eb8712097aaa23116c68eb6328980b8ba26706105656fa65315688b8232758607b8936d0abc27db" +
"c97d94e95b4f1957fd1965082e5849c4185ebba8afc7d558d4f5f001ac5363423ac1"))
),
# Alcatel/TCL MTK_6577_HUIZHOU
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"ac2a2c19bf4beef4272df8899cb648f90453e53faa1dd8143327978620ec74e6068a8fd051fac856a59ff0a2f3051b" +
"7512f55fcd6eea57262a5a24e141b2a9c105509b79976b952a4cfa0367535aa1db83290f18f62e2f604bfd5fee3fb6" +
"fa863ca5546e359e0348937e5b62e47f645e9552ebd2e7e516c13a192a6075c55351192dd545dd90c34fa28c695d66" +
"43a2449c0c7acc9d003b9bb4f9d249bc19beb8ffdc2d6115260499156461eea896361aac9a24ace3bf6c81db3e8c32" +
"fd6d74d876882382618c7ae920ce63b0c33a3ed6a59642acdcdccd68f2e84f6b1dfe8e4dd33fd78208c750f877a8ed" +
"dbf32b7f6cd28bc7f62a79e1281cad49b29ea1aeeb")),
bytes_to_long(bytes.fromhex(
"3d6ff33ae0ec1d029db4a6fb9ca3e41890f5cb5a53bfc0ab3cb2053d85243c7715a07ebfad719bea67c252a223ad0f" +
"e65074a5d26ea14ba63ff8d92e553e879b6ce51e065f05b23e5d27deed116ec751c9556ea0cec11e80f3bd206da9e9" +
"072fbe1695b19a8a9fcb576f00f7a268df8d6d262127ab3f3246941004f25534ac8d2f418815d15f4a5a663a2f1383" +
"115cb3e8bd263ebcd92c5bd1b92644497e15a1b41e77e648cac179182d83c496728fb52b9a1c600954ad0c3eac5d46" +
"33d519c88daf775fe090c2f2568c7c91a8938a2859245f100fce764033147d84d79075a81331ecdd170d2541832ab9" +
"161dc473cadc1dfbc17df2be89fa6d6c13d9db3611"))
),
# Alcatel/TCL MTK_S_2019
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"e4607e6cf78f5e4857bdaea441f8ddd35a7576f552b4ad2c8b4ee7f578c0590d747b049bb5014e06f8350dc6b78d5e" +
"0ddff1b4bb8af695e4a338a154596555738cccbe6b58eb43ae221df9babfe9dda6ca770c25ab42ff986f946756b46e" +
"c553daf7616f2843dcd6a48f48d9011c050e7ed11c99f61624f057695d622088f868bf6a3966f25bd8ad58db81623f" +
"d63f2b91f3ded1a5be0efb69a64bb40d8bbfc251d9c32fbf0a1bad516751e9e04439392c59ba6f856b5c0bebe0dcc6" +
"7d7d4f25da5342aba94680583ed76d94823c6f62e5e7484f7e2d2a467d167ad3f5647f958dbba3eb66f756c851a551" +
"38d1ce465333592969470fa8652df2e38bc380ff4f")),
bytes_to_long(bytes.fromhex(
"68d01875ee507057075dd8cf2e3007aebeaf767f350c130684911c483eb918a5e235ab71c2eaec62aa7bbeecdac518" +
"cb8962272e83a2943cb0e486b66da8e244fbf3e3d8e4a065198032fdb045f011784127cdfd63d285f7f20dcc37b0eb" +
"bdc8b49020b9a16333f196e8e3e8246835b1e76615985ba6e221241d096cc5bdd7336d8b22704dc1576ae0ac252fea" +
"8dab129756a609f347d60e25d8d085cf0c8775631d3c0e54e50fc67dff2c55148b4e78cf36987febb23e14ffc1da9c" +
"b0adfc139d509826aa98f6fe0e25ec6ab6442e5a7cebbe6454ff06b897467512cdd8f0460201125d0bc9cc2bae2598" +
"40722ae56d16b06f9e0515a2d128a23b5b0a1896e1"))
),
# Alcatel/TCL MTK_6577_SHENZHEN
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"a29274e3085c260de63f571646cd2c69737ba5a0bf604ad31cf6a86d6a9e08dc931ecdddb7404f4c9255c72b5debdb" +
"69114146bdd7edf6b38505b19c4d18eb0e71516d4faa871cbe1d2e24e15c1877b33587a8bdd1e7dfe1b17235d1ac43" +
"1c27cae07804014c287fbf2479e6b4b80665898f7cbaa7edcf23daa8dd95f63039fe7eb641ad7c05e221d29adc62cf" +
"84893ffc6acfd44a9d2cd60d5e0f94d1c29d317bbddb3f5a324648069c72857cfc708fc9bd8a3f7a98051fa9835af1" +
"f9c71d80236334ea51cbd52e57e5a7950beb394d9c97bcc32591d9700106b0abfe1dd2db9617fb7dd2eaa3885630c3" +
"ce1dfcf087c814b480f30c411f3071f12aedee4077")),
bytes_to_long(bytes.fromhex(
"6d209285b39ee78c7cfa17a34473855463c8a42d7b494ff0d6885c16d672aed0219193ef388b5aafb3ab10bef394d6" +
"fb7831b122ce47564abb084f68f3f7be113bcfc4e8ad3774fbc8eaa8a6fe030e96a56022cd0891f59eb2564ffa2700" +
"056e50a8cce72357d3f7ac7ef7b4fdaa69e0ceae1ab3d0f5b90e00414a3cd7bd17afc3b6463ef43bfd22788b68fcfc" +
"c2964421b1b622907d8c75e8d83193a579e50c26b0beb93e53e2888cfddafefa03c368c68e6d357087f1bf0800e1bb" +
"4f0fc97c092a7e7098cb60cad71e292b506c0cd1f428aff3192da6818351a780aa1b4cce0dccd15adad815b610f445" +
"a6571d3c65d2c44da9057b5c8970cded0dfc3072c1"))
),
# Alcatel/TCL MTK_S_2022
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"af823063550d6e5adcca01a1ae1fe357f73d7e5c60cfa25e4beac24304b70623654fd13547de869899be532f45f3c5" +
"ff26b50292dccd112dda1478721c05304445058499bd00f6b104e16fcf2d0af55781be147787227eff54a25dca42b9" +
"d6f1fc8f4b821c099f483c402addd178330167aa9b1021dae121bb2bdcb0127ac47ae866a1579f2399c70e69293ddd" +
"3b0bacec2df9dc518aa0c58c2d7561c5783ac32e57b91d16d6c57764755894963733b85f19f9a3bcbf624199cdd1b3" +
"1cbecc5448b132c3799e2d0e569f0ba61245796db5876820ef125f4a230039c5cd16b2414855bf3a3b565f81787a4e" +
"9b264c9bc855b4fe7ac17caca1bc5f070594a9c175")),
bytes_to_long(bytes.fromhex(
"3be4c4d89124e53d12cdc922c0c6571224e8925fba160186068855c5032de6655be49233899432008faef8ba5037f1" +
"a0b237e169f6f9f05be2694bf53d04b44507fceb1480007d2f49c8191ced7528e6b4fb06070851c85f2025ccb60271" +
"631def9f831822b351ed17ca9a165aae97516a6c3940971d17e927f3befb43432c1b689cc660a896237f090d7b311d" +
"9e39aa1eee5a4e3af00843c965c30ca9aa5dd7767809d27d4f66777661779d2a1fb90b014329a1973e67b8989de924" +
"e8ac98673667e4f734382f87f0dd0300d360142afa772d5beca2ef248e90a7bd32240c4a5b5f41aed3f4b63f90642f" +
"138186fe17afd713a3242eea7b2dd0f32b06b67681"))
),
# Alcatel/TCL MTK_B3G
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"cf8243d13128ed39fadad9ca97c15585d634f4d9b38dd59e4eec4b0b93e4eb2fd2d96c425855e69706d5c11021a8c2" +
"e08bff87b424bed2dc3efa9360bf1bcf80c96cd4ba9c39eb79bfa2bf9d4efc5a56798ccd9c6599ede595aea6440866" +
"05fbe55b2f7719fccbafe0c95956fcffb0ce77a9637c9ed66e067165cbe901eb041b")),
bytes_to_long(bytes.fromhex(
"12ff6a160cda225ddc898cc6ef7dd3c69d05dc24d23b7a0334568dc85191f3b63d278ab1c8449507dea8533496e04c" +
"77225a12a27b7abcf34d10c3cd67b1b41d7c19c44114e344a74396541d998d7b76ca06d0322bf3333684652528df22" +
"021c190bc38acdac2a3be6e2d0bce7f1e3c77a71750ff17895cff9c6225275a3ce81"))
),
# Alcatel/TCL MTK_E8
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"bdef438901dfa726cfc2cca59d12f009108b8e1fd7dd9b91a5cc71fa7b1e36c8783f9de5850050e6505fc715c50bdd" +
"d59a3064b05214c4365360cb98d080cc38658a94695184b564e8e8dcc28f70eb0122a4bb7662e3a1f34c057ea52381" +
"9ed02ed46bae0cd9530b0536cbe7a1ba3f33a45feb2f92ff5104dc32ebe94f249eed")),
bytes_to_long(bytes.fromhex(
"95b32d61a10e6c2a54fa4e5e020d590f6bf0f295fa87fa03b3d00dcdc4982dc997ad5c7ff872255141ec1b77f714c1" +
"4587ffb87c985531c937b245062ee03514aa796ad79698c40c49a8b3c54ec66fc20deb874a8bbce87239c414f54136" +
"7a350d525fa6bdea77e4cd3078cf7ddf22a8aefb0c595a6c76285d837008c0a77e29"))
),
# Alcatel/TCL MTK_C3G
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"c04e6a1be49c5a57accaebc837099b40890180fc046c3dca58745749d0979cadb63b8b4573fafc129c2f89ebb64c4ec" +
"81339e862f5638ae145e2c8bc291097e6b90434ff3f3a1e620fa77dcb6d963f53b79abaf4eefb8a5d4378cdf4ab3060" +
"a9901909fd455cf850ae5adbdf035cb3cbcf572ac4dce4bc1321562273a461ddf1")),
bytes_to_long(bytes.fromhex(
"4375be875664fad432cb6476f1c7aeecaea3166a51eadeaa32e96d0d79dd159b6287f4cd42685330fc15391eb4ee83d" +
"c6fd22a913c5fd5023d8fd6b71af8b530209b5355acf1cc6e6397aa6e5d2dc92b7d37635d391cd22a3aa337d8fc0a27" +
"4cdd7d6630395d13517e32c91daab2f5378ed7a1be86c81c2e775c249201f2c221"))
),
# Alcatel/TCL MTK_K6
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"a7e3089840bb7a9a7a972e8c88d7c464fe40dc4771a2df0da981079cc800f5d3cd45ed9eb34efac6bf7d2aa6dbc1266" +
"285f50d7e86e6e0e5dc6d062bc8fe871672139904e5ffe64c6ffb4ff00817ffc0ad4c18787a253ba5f7f7bd8412e5f4" +
"6e2c264cedf174ed5163943331a658b434c59ec9e11b269e829ab638c80c4ebe51")),
bytes_to_long(bytes.fromhex(
"4f65cda0c3ac66753c58d748db46bfb8cb8dbd1f849c7444afcf37dc6bb218904c5a2fe08808680d2a6e7587681256a" +
"6ed9751046fa42ce44874bf2061f40dca4953c345c2f156e8ee7e2f497ebc59b3ddccda98584dfc999d213d6782f2b0" +
"faff59a9671cee801defeb5a51178a7b95c487aa735b463e8b1321b6ebe58c7401"))
),
# Alcatel/TCL OPK_VLE5
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"cb676a5de86e2c7d75a17f10fb2e3f81a473e5d2d088833d8c1928ce78caf1000aaa607c83f55b57dc07fac7a9ecad1" +
"600df5d033986c02c003884620661a9674042a835b99cf8a024c27a10410eb379ac69e72d6f5a9cf72c185262331c98" +
"879cbc225de835d864983d2bd085f1df99341d3cbb0ba3b0a50491c8ee98d691b5")),
bytes_to_long(bytes.fromhex(
"4befe0eb0c424d83cd2dacb59740cddec599ab3c8833dee354717425993d12ba5441056297153bb3d2667c3e9c76caa" +
"bc349a07cfab60efa9e5e7b35e971fe7eedac090a1a5a7d8a2cd59de84762f09cacffecb65bf70ed504243721fd0e09" +
"4c3f216fbb85778ad82829658232a2f472919e992060394e79f2aada9e8a42ce21"))
),
# Alcatel/TCL OPK_U7_1
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"de15dc10818e30c363bd0a87d5f8d89b832329fa25b8388709d94e9b0ee4efdd3e24eed3d931f01ea1b0e2b76265d7d" +
"c270ea8012545bb7245c286761210bf46c6dd1fadefc257fabebba29bbbd86e8336460e5d21888a319156e8ba529e4b" +
"6a200136ae4aba447fb37a357028142d8b16d79a421d513ecd9b9ec0d908ba8217")),
bytes_to_long(bytes.fromhex(
"18e2fa361f4e7fc86574d9a93f2113a4d99d272710f303e29e07ebf71444335ce789dbf9816d472b27935ad49202379" +
"e44023071706bd0058e2bae45ace0938e75610579240ec87086d27fc0844ba25bba09214ae43037cb902801a58915ce" +
"58c6f805fb3ad6cf7996f25e0cf0a94c13e04eb4370ed6b93c39ba2136f8cfd101"))
),
# Alcatel/TCL MPK_U7_1
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"b6a33b825b0cf6abd3c9d39d1c8bdce50a41f9bd5ca2de52c4c447afa9943f5c1365d2e9cb7961ffd877fd38696b447" +
"9a8bb7eb8da15bd8d59a1cd7e5ee517d1a20f29bc66974f87796a11f7537529f8f46ac57861484808bfce9ee6cd6527" +
"f7fe3bfd57b4a7fd46f8dc047d6c8370de6507620c2b9a3bf864e8ee4c4d2abda1")),
bytes_to_long(bytes.fromhex(
"88a4477997b57337cb144d0656bd2d5f0ef59d6b574b631a79ac8015a4c20d454e1df85682ad25eccc7fb92be373259" +
"fffe58741b5a85e50caa68b9fe84f6e295d2176b96c20ff819e8bb889702c474effe1a77710ff3b93e896fa488f1717" +
"c75e46a1b0f5898fcacfa35943f1abf80ebb665ba7fde59c4baa61dd2f6c5ec001"))
),
# Alcatel/TCL MTK_S_AT_META
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"d1eee63f19d148c904076c507aa8d4f6c7e931a65476fe5231c06036fea2ecbcb8c811882c4f70e6e3523be73f5c7a8" +
"3570f3a40bd894399a5ee9f903e8e745ec4e4e034495175b167192535843f06241d6477e3ce1ad5270e590db9cb9054" +
"04c01aa407433fa2c2ca1f8366c1623fa45bd5ee68e3145a57f9af3e6e68fce41b8c682c0e07f3c48f4b377951b23b4" +
"67fea0d4ee0e67c0235d0e83ae27e40ad1c060063ceb966835a0ac1eb68066f8b55775ceb7b444ffaeec19548a42247" +
"ebe687f881a0c8e5277beec22241e2ddae1c21cec8046eb005302812b7ef42ac153cab317bbeaad73f7ccaced38c433" +
"530b7e0ad464150026025a9a3ff5d45e025db")),
bytes_to_long(bytes.fromhex(
"8294e45929b8f95a380c59fe715da5225fd518920a85fdc9a8b2ade6675b7680293c21539fa4466907cb3601b072d8a" +
"debb0481ecf069baaee00d0f5cb4396f4ffea11dfd41f3c62fdeb312ee9b4be2026bc40aacd9ff928130fa7af030522" +
"8dd5e47c551c2a701653dd6841b9566099de99e2731194ae617ca8d9df99a47c49d9f514620ea1e3742da8dc7dec675" +
"6403631a274dc226c6121863e4a571a120b63c38d134853df5b986fac1565e1f3bd8a02d239462967e9c71cedd9ae0c" +
"0eec330018ca553cc7cc2fbc73d6ba37be2fe360644ff69ab7c734264675c057417857df4ca206dfdac9a5621f9d8e4" +
"5dd2e58dc8b4198667de3efd1d5bd7ce007a1"))
),
# Alcatel/TCL MTK_B7
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"e3e3166f47177de4915e915a9d555d980afad96be22cbb8a02516ac8fe69657bd10bc6d072046dcd33e4476e24f128c" +
"b7ac613df140cefe71abf080a74d27c114635d3954c55299f6f81c2a0aa14c4c678307f4b3bbf0c64f0006051ea7573" +
"b5b0cc290201c76c4d272c981b1bb19bd0a0a0ac046e6e63b0f4cf88d2c98a5c91")),
bytes_to_long(bytes.fromhex(
"776b1deb8c3e943b3dae67cf2b597ba55c439dc1fa10e4e9ea530df96bd0815cc3ec3ef0267f89a699c5cb64bdb91e5" +
"e9ae4c7af03cbcfbfb4755cda55e3a31d510f96a102b5aed90731788a426e371f8ae24f660403377cc0836a06b2a8e1" +
"59bd177f4cf68e36d447e4b52ca63611cd8416c1efcac52143106c272f7474387d"))
),
# Alcatel/TCL MTK_BACHATA
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"94cc529bb1af0ab8043f09e3ca612d787cc19485d3769546e750f6edb844979ba8f1f9afb8b93b521330b74713831a7" +
"8a584f7b24780f92dd00e5d56ce8defa3cd39d01752e514a4c2ba7499f334729622049491b1aecee6c9e1c867e996c2" +
"94b10f5d62ea4504e333424b280162087296c300c01fdf75f47d874df40dbdb94f")),
bytes_to_long(bytes.fromhex(
"09fe029a23ff7e37c749386fcc9a640450546b95e5127489d364d380393c99f5c10da6d7cf0ed955f4a5f3d8d90d97c" +
"c7c49069d394206f9b59c11568ffe66163eae377447abb103cd5d4256885cf7984b28cff8a096dc479b9196d66cd534" +
"cbdfece7a61de04110bb14a3ba5e0f20ae0bb4d82e18fbff0335904dc09b829e91"))
),
# Alcatel/TCL MPK_VLE5
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"a62bf756a70657b6b560588e85e662e181b6a61ae466ac3d0d2e971f160e88216792cedfb1979b3d6b665068eee8a86" +
"99888cd74ec9482c61ae7eae3571e50beccdcb336477c26040d09b46dbd93efc0fece4adde2e00c1cbedafd6ad7c43b" +
"d621675a6a46425c5cf6182fc5602be443a372fb4ead4531e64285ce29be913285")),
bytes_to_long(bytes.fromhex(
"7005d1bf5be81db7b17c9b16b1d407b308b42e3490e75a93e9d00fd6c812d1d8db2f1041a342964808a037f315a448e" +
"caf0502a5215c58f0de709c5bd87e3a65e0291a1a23547c76cf437ef1d9b434b70dbb417049a31de9ee7becf218a5bb" +
"63b05fb84ff49d1e6aaa4b9b4376f47417435ecd85ccda63be9070e7892ecd4a41"))
),
# Alcatel/TCL MTK_C7
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"c1d6c392828f4620e455c138840ab448cfcd4aca821663335dba9c51dec9b8198301ca6b069adefcd1887f1cec31c15" +
"674ab264daeeb82398b419f08b4236904203c48a7db8724f1773d04a6b8c88cb38907a00bc53e86cdb2bbf479a68b82" +
"41382bdc5ac6105270efc2da4cb91a36459ccf6a2a87dd56ec4c331dd419ba5931")),
bytes_to_long(bytes.fromhex(
"31d28ed040a8ace0d56fc94b4a7d29dbb135d62c7905621818d657499fd6ff6fe7417592cececdd3f3d37ec0a361228d" +
"a34d3e7a2724b7832ced00008fb4ae500357fc3d285c64fbf7efd4bd1ee48ed40190296171acc3c2d0c69e89da5a8fde" +
"7e0ba7048aec6bef1bb19646f883fe9d77d8d263545e7c00e8604be38210d065"))
),
# Alcatel/TCL MTK_MARTELL
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"a800d061e4a42e4c3453a17cc8daa974e23bfaa403b4a60fad6d3516d8ec035c1ebabdcd60009d9b8c639954e616c6c" +
"b6cf821e31e58772ffc366e6ffb7314657567b12279a34dd69e46b8a4a628dc2dfabc68fa1d89388d2058a97d2e3152" +
"0b4fb04bc2f963e110e8541eefd22d90a03eca806b3c6a20c6bd1a7468e61ea1ab283ed1bc462dfae189eb5fb451f80" +
"2fb868cda9a7409aa52e42b18882e79f4f1c2377829fafd9760468bd1db823bd9080378cf46ef405d91636cafc03aca" +
"d9fada6b0446dbaf51e9d533887e4a3a8f62114063e0b8920684c28bfbe256aab26e98751166358c201347ba6c3b36d" +
"49aab6302fc248eea3c254e15a08429fd2149")),
bytes_to_long(bytes.fromhex(
"985e549fd42c0b4955d3db8c3ee601f65e10a3db08f957fab4016dbad0f60c7e09e8b7a782404cb0fc7c805dfd67fed" +
"814765ed58b7a146ed2c1d31b80e3f845a45b6ccda5a0344247be404c23debf027c7b5082373372b49bf78d9058caa6" +
"6c57d3be829088c3610034faf1ea9f24a21110bbb3865182747ca1779e83c6983c189b3f19f3df49e5f9cdfa57f4f69" +
"dfae53e19ee0b1ec30986d59ad11f52bdc022a9499dfa89f8546d266f6026aa307501ca5a619f5413a45ef38f139c3e" +
"a8b52f02fbc8983aa878052d9108668ecfc8605057a298355d2f680c34630e224c57dd4c4f2dc0d51766ef7070daddf" +
"a3c885a3f94d76c943c6c1054d338e2323b99"))
),
# Alcatel/TCL OPK_U7
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"9f94e8f1171fed4b427629c928e807b2220f109ac70a3d5b1b8cbd295bc3fa3226d3903298cd81319b9b08a6f8e77ef" +
"ad0b04139b686ee0d1586175913ad6f65d6cf21bbc7f769885381ba6d840414b26fe7b9b3e393acacb3453e3a0cb79c" +
"a21cb38a42685a03462244fdb2a5f1d8b9e20745fb3206e799655c47146310911b")),
bytes_to_long(bytes.fromhex(
"61ed86791440c26491b763730f483c18c32fcd77bdb6f9e9e3e11cdfb9716d22c392c68556219e2b6c1ada57649ce2d" +
"e559c239a9ff8f33252480421e4a2649df8e3ee0095c9bec361f25a5ec67d0b4d96c73404ff8a115fecf1173a656884" +
"5480fd4423b5dba2e5111335655f3bc2f3fec65510648571992e010ba0aaf243e1"))
),
# Alcatel/TCL MTK_S_2020
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"e4cc4967bec817bb348468024c3084b15fd4f7810c8a9d078a4f51cf9974d2e3bae8d5a19a85c0a73befd0675100e64" +
"2a3f425e3192dfb1de56928c37f45fc142adaa65798ada863b84d4b5f22c3f79b95cc201ac7c292c99475453a62b7b7" +
"e06e84833dfca7a0df931084932a80129e543c6d24a13c5f2cba6ef5ffed9efd4dbc20496f5194f0d1aad9d789f3257" +
"7f8846df9a14778504ccb5dd7507114c148c1937fb99da15f9596d4fa052cdaf1f66d7e5e0c0793628752bf9af3c4ac" +
"67e21c21d170ad448160761bddf586a4900fbb7dcc44467f1550d15db774d7cacfe3105b465321a5f95fec22c2011d6" +
"16a5c0e22f0535dd1f969202be56ec015f891")),
bytes_to_long(bytes.fromhex(
"b86887499d157d3b1feb1041b9d2e94065732b41d22feebce317676321d66d1babcc7a53544e35a714c207811e62d13" +
"4291d616417295e5b0c4aa3d65e40b41a352822263c22cbb4041a1883c76b97a8c925cb428a7b2300622ddaec62209d" +
"8dc0c60159f6c7ccfc26768bc469deec22bcd62f49f4c2ca1b2cf0be49d6e5ec563279cdee79c92800c6c965200d316" +
"c79285551a54359b37ec4173eadf4c0506d857ddca4831ade7ea8f13097b4e2b630a2d3eb9c57abcc65f84d693c55e3" +
"61763d8d37bb40cd6e2520684ae05edc62a36cda6747509600f4605b7ed924ee1ad49e66eca1176a20794600173dbb4" +
"2fced2f1fa0cccc0af3b56d58453bee420099"))
),
# Alcatel/TCL MTK_U82
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"ed2055a7b95db86f7e3101196ae6218015d70d03df6fd5787de150e82927443097a90485757743447e2f4641afcf510" +
"acf585f73e79c45b2908d5de8835221a76d93e48ca465ffbe0dd76cdaa98550ab2e7b84a6470d48595742fb54a20444" +
"2ce67bab989c69adf86457e313eb24c87d80aa7d635449fab0d97b6b08c5f7c86f")),
bytes_to_long(bytes.fromhex(
"3f5d99a61561d70c6c335a30d9a11fa8a3ad70fbecf46c9e233d57aa827cccbb137c060a47e693e234ba1b532851053" +
"e17446d5582b9fee205c0d12c7613378c8b8c8c0184cdba90d56a308014aac0458c5572699d599a15ba36146b6f2e23" +
"0034708cf67d31ab837b7bd8e5967fd9a7bf413b7d9314302b18e48962d01cf6f1"))
),
# Alcatel/TCL MTK_JADE
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"e8490dcbd3488278442f78ec5634ccdb8befee081ed0d19071480a10c299416ab8d0e9eb19e8975cac260606463c51b" +
"b62875ab24690d07905b9c48fe60086da12899bce3dbed91e0157cff76f27a1c09b37e837e7acb71da3c0e30564223a" +
"e20216fbcb3de5e93c2d7f98827d61441b988e57497c1ddacb87cec1e73139bf67")),
bytes_to_long(bytes.fromhex(
"69fd6b9e25ba604e204ec90e8e0769b28417e6b52dda7ac53deb712c549f398a48ea8ad20bf065a093ac85f336f92f1" +
"221d3413f3793bc8c7c6057a091828c04f6fb695f43747d0d22de100bccce70ac7a8f9d092afaa7d44fcda99b12454f" +
"8c887e383c69e7e21ad15203eaae51d803cf35da09c8d536139c658bebfddccf01"))
),
# Alcatel/TCL MTK_B82
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"b6a33b825b0cf6abd3c9d39d1c8bdce50a41f9bd5ca2de52c4c447afa9943f5c1365d2e9cb7961ffd877fd38696b447" +
"9a8bb7eb8da15bd8d59a1cd7e5ee517d1a20f29bc66974f87796a11f7537529f8f46ac57861484808bfce9ee6cd6527" +
"f7fe3bfd57b4a7fd46f8dc047d6c8370de6507620c2b9a3bf864e8ee4c4d2abda1")),
bytes_to_long(bytes.fromhex(
"88a4477997b57337cb144d0656bd2d5f0ef59d6b574b631a79ac8015a4c20d454e1df85682ad25eccc7fb92be373259" +
"fffe58741b5a85e50caa68b9fe84f6e295d2176b96c20ff819e8bb889702c474effe1a77710ff3b93e896fa488f1717" +
"c75e46a1b0f5898fcacfa35943f1abf80ebb665ba7fde59c4baa61dd2f6c5ec001"))
),
# Alcatel/TCL MTK_S_2021
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"df85f4c4ae8c98e78142d403d002276a5bf9edd17870caa848fc45720e8b4be94f6f9a47181417840a5b7d4fc365751" +
"29afd6a848a0de3f62fac5b5f687a2219cab8cdf2e7527d6af3c6be84eb99bf519b0b210960fc8f5223c9bc38e8f20d" +
"0267642153cf370312b955143e10490c6a207868ac7ac314bbe10f6063a1ba606e28d248a1ee3e7000d12e9c4ebd47a" +
"e483b625156b82026fcfdc36118198cac1463aeb56bdfe260efa38ac1d4123c13fe59e0fb0f2f895609c117f7a39fb9" +
"f27c356d4748cf7af41e15ea68c6c7c64c4d0a1acb4632965e0260d9b08de9fd81b82050c9929b79ee865f89272483b" +
"6fed8a409d6a1af2429d24fd358a4b4da4e77")),
bytes_to_long(bytes.fromhex(
"cf553c03ac3cf21fdb4097d4a97f35fc6c305a2e30dfbebb7667ba2adfdec99d3277bccd314281c592ade680b42849f" +
"de6122659a68cd7e525b764520d612c7c6c141bc4b2594bc88732d4ca0a97e464d7c1ecf4fc2788f1920cb030c1b2b3" +
"ea84e8d6191d5e53d56c5fc495051a1d0fdbea947d58a9d773a68152d157d4bf57f2b4fba8182f96ea4c9b798018361" +
"054f95b251089c786be542c7881c49b077ad52af25a359bb26257170706217f66533cf4b8379a1fb7a30c955c8ed4c1" +
"c6dca905ce6e7e5e92ec7e1bda1db44cd187a9e5137fe44a37cfdbee173a49654994926cb2fdd7857dfc8978d9de73e" +
"899e18f5dfe33a64e6414fc5d93738f8c5591"))
),
# Alcatel/TCL MTK_MINIQ2
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"ba1d10a245e60471e8d3138611615170f213cae5b895c8af35eb720e2671915f07dd6ccb5384d7580200d18f430c894" +
"05dcb0be6a5e91cff0fda970e292d5f0704720473bc61e19590539b1bb08ce2b306755db1f70cf1193933802ca44281" +
"fe01699f75e56fb7660fce0342ccc284d497a17ad7d3d15eaa20ad4c67bd92de61")),
bytes_to_long(bytes.fromhex(
"a475ba952a9f2f9e58d6ec91b41a03158354ea1e451656d83d15691c07eca3410e7a2401283462f66a0ebf1f91682a8" +
"0ae61168b2260f4368f93e197a9db65f4139523ef5449a6fa77568a9ffe90e0a34a37f99b7c1ec6ed1683a574d90459" +
"93679ef73299991cd43b96fdba6673ae4318f2f635a816f8559d325f9ebe428a01"))
),
# Alcatel/TCL MTK_HIGHWAY
(
bytes_to_long(bytes.fromhex("00010001")),
bytes_to_long(bytes.fromhex(
"beca753fd31ef104bbb01b0a7c560c7bc040d30ea18f216b64b7de416b695af2b3350ecc02fa5224b412793f876a7bd" +
"bd8cbe7fecd754aa8214a27bfe7ececd8caa16959df83bdaeed524880a820f8dfe601dc70f164ff1921baaa06efd8c5" +
"84c22269a109d16287356fd30e7eb02a1365ca93fcb8088278f119a2c7298306a9")),
bytes_to_long(bytes.fromhex(
"5407571c851f5b877a2255c6887c5d832369698b481c81db8ac07062dfabc7229d4b00f95956665743f7deeedbf54a1" +
"7c9a404c97433f46d983bd0c5f49fa4b013b9d86e5f1377f563d8299675c0ea2b81f51c33ad74a265184df9389eefb8" +
"e72d2f0585e4a41826b8846b0ee6da5ef8cce471536109fe4c658735247ebbc301"))
),
# Motorola G13
(
bytes_to_long(bytes.fromhex("00010001")),
# N
bytes_to_long(bytes.fromhex("DA61964924F441559A1F8B5264CEB01DACE8E417413BBA4657F4556811D07B85074FD69" +
"87F315A7492E003D03C57FC83D3B889F2D4F136D0989E515A08628A7B16A300217162DC" +
"35C340B1127046AA86649B763AF97F7C9871964483DE6695CDA2E8CCE82E1F6A0F701AF" +
"8BE767BB16927489524F8FC9A2C280F5692E850E4C4E2606436CF2E253147AFAB32E6B9" +
"2A19FA180C43CF480619B71B3D6A7863C7CC376C0A36BCF8BA3DA89CBF3E6DAA4691DCD" +
"769C0AE4535E502A9966AFF3F123C7A0EDA2DF04593B0E1FC60DC688F2BA7617DFE67D3" +
"1854443ED95D2645323728C594CA49DAA9351A572E3182D0A1B3146C92CEF87380CBD2D" +
"EFFEBC4E8F420D3")),
# D
bytes_to_long(bytes.fromhex("AEAC47CD11A5DD6C5EEEC43D8F2C536A2917CEF95AD02F5A7C978E88C35702B590F7A72" +
"A2AF28AEB9B5F5B2D8056D03F916595D189C9B6927AC0874980537178AACE8E1831DD65" +
"4E0B72FF2F44670196A57A43C340355CAF828B331A5715AED4E06D5D18896BCF25B201A" +
"0DC9760B0B2EF1CFB4EAB6940D7F8E2EBD86DC1E678AA69F6B0BBF55C688BF72C2123CF" +
"42E367F789E2592CE281C7C4752E14F6FD00D54610977DEF753E3890F12F704688537E8" +
"60D81142805750B805E7CAE3AACDE1CD7A272D227E9F8CCAADCB4D06489664627BAC46C" +
"AF5DA0F0740CEEDEBC7ED1C1D1EB1E37C6A8A9E6A0454F742B3248448B20C93D5FF6E5C" +
"789907A862C90A1")),
)
]
if isbrom:
# e, n, d
for key in rsakeys:
for key in brom_sla_keys:
if self.echo(self.Cmd.SLA.value):
status = self.rword()
if status == 0x7017:
@ -1175,12 +660,12 @@ class Preloader(metaclass=LogBase):
if status > 0xFF:
self.error(f"Send auth error:{self.eh.status(status)}")
return False
# e = key[0]
n = key[1]
d = key[2]
e = key.e
n = key.n
d = key.d
challenge_length = self.rdword()
challenge = self.rbyte(challenge_length)
response = generate_rsa_challenge(n, d, challenge)
response = generate_brom_sla_challenge(n, d, challenge)
resplen = len(response) # 0x80, 0x100, 0x180
self.usbwrite(int.to_bytes(resplen, 4, 'little'))
rlen = self.rdword()
@ -1198,14 +683,6 @@ class Preloader(metaclass=LogBase):
continue
return False
else: # not brom / da
"""
# N=B243F669.....
for key in rsakeys:
rsakey = RSA.construct((n, e, d))
encryptor = PKCS1_OAEP.new(rsakey)
encrypted = encryptor.encrypt(data)
print(encrypted.hex())
"""
return True
def get_brom_log(self):
@ -1351,10 +828,10 @@ class Preloader(metaclass=LogBase):
bytestowrite = len(data)
pos = 0
while bytestowrite > 0:
size = min(bytestowrite, 64)
self.usbwrite(data[pos:pos + size])
bytestowrite -= size
pos += size
_sz = min(bytestowrite, 64)
self.usbwrite(data[pos:pos + _sz])
bytestowrite -= _sz
pos += _sz
self.usbwrite(b"")
time.sleep(0.035)
try:
@ -1377,7 +854,6 @@ class Preloader(metaclass=LogBase):
except Exception as e:
self.error(f"upload_data resp error : {str(e)}")
return False
return True
def send_da(self, address, size, sig_len, dadata):
self.config.set_gui_status(self.config.tr("Sending DA."))
@ -1415,52 +891,3 @@ class Preloader(metaclass=LogBase):
self.error(f"DA_Send status error:{self.eh.status(status)}")
self.config.set_gui_status(self.config.tr("Error on DA_Send"))
return False
if __name__ == "__main__":
"""
e = bytes_to_long(bytes.fromhex("010001"))
n = bytes_to_long(bytes.fromhex(
"C43469A95B143CDC63CE318FE32BAD35B9554A136244FA74D13947425A32949EE6DC808CDEBF4121687A570B83C51E657303C925EC280B420C757E5A63AD3EC6980AAD5B6CA6D1BBDC50DB793D2FDDC0D0361C06163CFF9757C07F96559A2186322F7ABF1FFC7765F396673A48A4E8E3296427BC5510D0F97F54E5CA1BD7A93ADE3F6A625056426BDFE77B3B502C68A18F08B470DA23B0A2FAE13B8D4DB3746255371F43306582C74794D1491E97FDE504F0B1ECAC9DDEF282D674B817B7FFA8522672CF6281790910378FEBFA7DC6C2B0AF9DA03A58509D60AA1AD6F9BFDC84537CD0959B8735FE0BB9B471104B458A38DF846366926993097222F90628528F"))
d = bytes_to_long(bytes.fromhex(
"8E02CDB389BBC52D5383EBB5949C895B0850E633CF7DD3B5F7B5B8911B0DDF2A80387B46FAF67D22BC2748978A0183B5B420BA579B6D847082EA0BD14AB21B6CCCA175C66586FCE93756C2F426C85D7DF07629A47236265D1963B8354CB229AFA2E560B7B3641DDB8A0A839ED8F39BA8C7CDB94104650E8C7790305E2FF6D18206F49B7290B1ADB7B4C523E10EBF53630D438EF49C877402EA3C1BD6DD903892FD662FBDF1DFF5D7B095712E58E728BD7F6A8B5621175F4C08EBD6143CDACD65D9284DFFECAB64F70FD63182E4981551522727A2EE9873D0DB78180C26553AD0EE1CAAA21BCEBC5A8C0B331FE7FD8710F905A7456AF675A04AF1118CE71E36C9"))
data=bytearray([0xA,0xB,0xC,0xD,0xE,0xF,0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9])
msg = generate_rsa_challenge(n,d,data)
print(msg.hex())
"""
data = bytearray([0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9])
# from Cryptodome.PublicKey import RSA
from Cryptodome.Cipher import PKCS1_OAEP
# E_DA=bytes_to_long(bytes.fromhex("010001"))
# N_DA= bytes_to_long(bytes.fromhex("A243F6694336D527C5B3ED569DDD0386D309C6592841E4C033DCB461EEA7B6F8535FC49" +
# "39E403060646A970DD81DE367CF003848146F19D259F50A385015AF6309EAA71BFED6B098C7A24D4871B4B82AAD7DC6E2856C301BE" +
# "7CDB46DC10795C0D30A68DD8432B5EE5DA42BA22124796512FCA21D811D50B34C2F672E25BCC2594D9C012B34D473EE222D1E56B90" +
# "E7D697CEA97E8DD4CCC6BED5FDAECE1A43F96495335F322CCE32612DAB462B024281841F553FF7FF33E0103A7904037F8FE5D9BE29" +
# "3ACD7485CDB50957DB11CA6DB28AF6393C3E78D9FBCD4567DEBCA2601622F0F2EB19DA9192372F9EA3B28B1079409C0A09E3D51D64" +
# "A4C4CE026FAD24CD7"))
# D_DA= bytes_to_long(bytes.fromhex("707C8892D0DE8CE0CA116914C8BD277B821E784D298D00D3473EDE236399435F85410095" +
# "25C2786CB3ED3D7530D47C9163692B0D588209E7E0E8D06F4A69725498B979599DC576303B5D8D96F874687A310D32E8C86E965B84" +
# "4BC2ACE51DC5E06859EA087BD536C39DCB8E1262FDEAF6DA20035F14D3592AB2C1B58734C5C62AC86FE44F98C602BABAB60A6C8D09" +
# "A199D2170E373D9B9A5D9B6DE852E859DEB1BDF33034DCD91EC4EEBFDDBECA88E29724391BB928F40EFD945299DFFC4595BB8D45F4" +
# "26AC15EC8B1C68A19EB51BEB2CC6611072AE5637DF0ABA89ED1E9CB8C9AC1EB05B1F01734DB303C23BE1869C9013561B9F6EA65BD2" +
# "516DE950F08B2E81"))
e = bytes_to_long(bytes.fromhex("010001"))
n = bytes_to_long(bytes.fromhex(
"C43469A95B143CDC63CE318FE32BAD35B9554A136244FA74D13947425A32949EE6DC808CDEBF4121687A570B83C51E657303C925" +
"EC280B420C757E5A63AD3EC6980AAD5B6CA6D1BBDC50DB793D2FDDC0D0361C06163CFF9757C07F96559A2186322F7ABF1FFC7765" +
"F396673A48A4E8E3296427BC5510D0F97F54E5CA1BD7A93ADE3F6A625056426BDFE77B3B502C68A18F08B470DA23B0A2FAE13B8D" +
"4DB3746255371F43306582C74794D1491E97FDE504F0B1ECAC9DDEF282D674B817B7FFA8522672CF6281790910378FEBFA7DC6C2" +
"B0AF9DA03A58509D60AA1AD6F9BFDC84537CD0959B8735FE0BB9B471104B458A38DF846366926993097222F90628528F"))
d = bytes_to_long(bytes.fromhex(
"8E02CDB389BBC52D5383EBB5949C895B0850E633CF7DD3B5F7B5B8911B0DDF2A80387B46FAF67D22BC2748978A0183B5B420BA57" +
"9B6D847082EA0BD14AB21B6CCCA175C66586FCE93756C2F426C85D7DF07629A47236265D1963B8354CB229AFA2E560B7B3641DDB" +
"8A0A839ED8F39BA8C7CDB94104650E8C7790305E2FF6D18206F49B7290B1ADB7B4C523E10EBF53630D438EF49C877402EA3C1BD6" +
"DD903892FD662FBDF1DFF5D7B095712E58E728BD7F6A8B5621175F4C08EBD6143CDACD65D9284DFFECAB64F70FD63182E4981551" +
"522727A2EE9873D0DB78180C26553AD0EE1CAAA21BCEBC5A8C0B331FE7FD8710F905A7456AF675A04AF1118CE71E36C9"))
rsakey = RSA.construct((n, e, d))
encryptor = PKCS1_OAEP.new(rsakey)
encrypted = encryptor.encrypt(data)
decrypted = encryptor.decrypt(encrypted)
print(encrypted.hex())
print(decrypted.hex())

View file

@ -1,17 +1,18 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import logging
from mtkclient.Library.utils import LogBase, logsetup
from mtkclient.Library.gpt import gpt
from mtkclient.Library.pmt import pmt
from mtkclient.Library.gpt import GPT
from mtkclient.Library.pmt import PMT
class Partition(metaclass=LogBase):
def __init__(self, mtk, readflash, read_pmt, loglevel=logging.INFO):
self.mtk = mtk
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.config = self.mtk.config
self.readflash = readflash
self.read_pmt = read_pmt
@ -29,7 +30,7 @@ class Partition(metaclass=LogBase):
return b""
def get_pmt(self, backup: bool = False, parttype: str = "user") -> tuple:
pt = pmt()
pt = PMT()
blocksize = self.mtk.daloader.daconfig.pagesize
if not backup:
addr = self.mtk.daloader.daconfig.flashsize - (2 * blocksize)
@ -41,11 +42,11 @@ class Partition(metaclass=LogBase):
partdata = data[8:]
partitions = []
for partpos in range(128):
partinfo = pt.pt_resident(partdata[partpos * 96:(partpos * 96) + 96])
partinfo = pt.PtResident(partdata[partpos * 96:(partpos * 96) + 96])
if partinfo[:4] == b"\x00\x00\x00\x00":
break
class partf:
class Partf:
unique = b""
first_lba = 0
last_lba = 0
@ -55,7 +56,7 @@ class Partition(metaclass=LogBase):
type = b""
name = ""
pm = partf()
pm = Partf()
pm.name = partinfo.name.rstrip(b"\x00").decode('utf-8')
pm.sector = partinfo.offset // self.config.pagesize
pm.sectors = partinfo.size // self.config.pagesize
@ -68,7 +69,7 @@ class Partition(metaclass=LogBase):
def get_gpt(self, gpt_settings, parttype: str = "user") -> tuple:
data = self.readflash(addr=0, length=2 * self.config.pagesize, filename="", parttype=parttype, display=False)
if data[:4] == b"BPI\x00":
guid_gpt = gpt(
guid_gpt = GPT(
num_part_entries=gpt_settings.gpt_num_part_entries,
part_entry_size=gpt_settings.gpt_part_entry_size,
part_entry_start_lba=gpt_settings.gpt_part_entry_start_lba,
@ -93,7 +94,7 @@ class Partition(metaclass=LogBase):
return partdata, partentries
if data == b"":
return None, None
guid_gpt = gpt(
guid_gpt = GPT(
num_part_entries=gpt_settings.gpt_num_part_entries,
part_entry_size=gpt_settings.gpt_part_entry_size,
part_entry_start_lba=gpt_settings.gpt_part_entry_start_lba,
@ -120,7 +121,7 @@ class Partition(metaclass=LogBase):
data = self.readflash(addr=0, length=2 * self.config.pagesize, filename="", parttype=parttype, display=False)
if data == b"":
return data
guid_gpt = gpt(
guid_gpt = GPT(
num_part_entries=gpt_num_part_entries,
part_entry_size=gpt_part_entry_size,
part_entry_start_lba=gpt_part_entry_start_lba,

View file

@ -1,14 +1,14 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023 GPLv3 License
# (c) B.Kerler 2018-2024 GPLv3 License
import os
import logging
from binascii import hexlify
from mtkclient.Library.Exploit.amonet import Amonet
from mtkclient.Library.Exploit.hashimoto import Hashimoto
from mtkclient.config.payloads import pathconfig
from mtkclient.config.payloads import PathConfig
from mtkclient.Library.utils import LogBase, print_progress, logsetup
from mtkclient.Library.Hardware.hwcrypto import crypto_setup, hwcrypto
from mtkclient.Library.Hardware.hwcrypto import CryptoSetup, HwCrypto
from mtkclient.Library.Exploit.kamakiri import Kamakiri
from mtkclient.Library.Exploit.kamakiri2 import Kamakiri2
from mtkclient.Library.Port import Port
@ -16,7 +16,8 @@ from mtkclient.Library.Port import Port
class PLTools(metaclass=LogBase):
def __init__(self, mtk, loglevel=logging.INFO):
self.__logger = logsetup(self, self.__logger, loglevel, mtk.config.gui)
self.__logger, self.info, self.debug, self.warning, self.error = logsetup(self, self.__logger,
loglevel, mtk.config.gui)
self.mtk = mtk
self.chipconfig = self.mtk.config.chipconfig
self.config = self.mtk.config
@ -27,7 +28,7 @@ class PLTools(metaclass=LogBase):
self.hwcode = mtk.config.hwcode
# crypto types
setup = crypto_setup()
setup = CryptoSetup()
setup.hwcode = self.mtk.config.hwcode
setup.dxcc_base = self.mtk.config.chipconfig.dxcc_base
setup.read32 = self.mtk.preloader.read32
@ -41,7 +42,7 @@ class PLTools(metaclass=LogBase):
setup.ap_dma_mem = self.mtk.config.chipconfig.ap_dma_mem
setup.meid_addr = self.mtk.config.chipconfig.meid_addr
setup.prov_addr = self.mtk.config.chipconfig.prov_addr
self.hwcrypto = hwcrypto(setup, loglevel, self.mtk.config.gui)
self.hwcrypto = HwCrypto(setup, loglevel, self.mtk.config.gui)
# exploit types
if self.config.ptype == "kamakiri":
@ -55,7 +56,7 @@ class PLTools(metaclass=LogBase):
elif self.config.ptype == "carbonara":
assert "Carbonara is best served in your local restaurant :P"
self.pathconfig = pathconfig()
self.pathconfig = PathConfig()
if loglevel == logging.DEBUG:
logfilename = os.path.join("logs", "log.txt")
fh = logging.FileHandler(logfilename, encoding='utf-8')

View file

@ -1,26 +1,26 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023
# (c) B.Kerler 2018-2024
try:
from mtkclient.Library.utils import LogBase, structhelper
from mtkclient.Library.utils import LogBase, Structhelper
except Exception:
from utils import LogBase, structhelper
from utils import LogBase, Structhelper
class pmt(metaclass=LogBase):
class pt_resident:
class PMT(metaclass=LogBase):
class PtResident:
def __init__(self, data):
sh = structhelper(data)
sh = Structhelper(data)
self.name = sh.bytes(64)
self.size = sh.qword()
self.part_id = sh.qword()
self.offset = sh.qword()
self.mask_flags = sh.qword()
class pt_info:
class PtInfo:
def __init__(self, data):
sh = structhelper(data)
sh = Structhelper(data)
self.sequencenumber = sh.bytes(1)
self.tool_or_sd_update = sh.bytes(1)
tmp = sh.bytes(1)
@ -30,9 +30,9 @@ class pmt(metaclass=LogBase):
self.pt_changed = (tmp >> 4) & 0xF
self.pt_has_space = tmp & 0xF
class pmt_header:
class PmtHeader:
def __init__(self, data):
sh = structhelper(data)
sh = Structhelper(data)
self.signature = sh.bytes(8)
self.revision = sh.dword()
self.header_size = sh.dword()

View file

@ -3,7 +3,7 @@ import os.path
from binascii import hexlify
class hwparam:
class HwParam:
paramsetting = None
hwcode = None
appid = b""

View file

@ -1,6 +1,6 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# (c) B.Kerler 2018-2023
# (c) B.Kerler 2018-2024
import codecs
import copy
import datetime as dt
@ -31,7 +31,7 @@ sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding='utf-8')
sys.stderr = io.TextIOWrapper(sys.stderr.detach(), encoding='utf-8')
class mtktee:
class MTKTee:
magic = None
hdrlen = None
flag1 = None
@ -46,7 +46,7 @@ class mtktee:
data = None
def parse(self, data):
sh = structhelper_io(BytesIO(data))
sh = StructhelperIo(BytesIO(data))
self.magic = sh.qword()
self.hdrlen = sh.dword()
self.flag1 = sh.bytes()
@ -62,7 +62,7 @@ class mtktee:
self.data = bytearray(sh.bytes(self.datalen))
class structhelper_io:
class StructhelperIo:
pos = 0
def __init__(self, data: BytesIO = None, direction='little'):
@ -143,7 +143,7 @@ def find_binary(data, strf, pos=0):
return None
class progress:
class Progress:
def __init__(self, pagesize, guiprogress=None):
self.progtime = 0
self.prog = 0
@ -230,7 +230,7 @@ class progress:
self.progtime = t0
class structhelper:
class Structhelper:
pos = 0
def __init__(self, data, pos=0):
@ -475,7 +475,7 @@ def logsetup(self, logger, loglevel, signal=None):
else:
logger.setLevel(logging.INFO)
self.loglevel = loglevel
return logger
return logger, self.info, self.debug, self.warning, self.error
class LogBase(type):
@ -531,8 +531,8 @@ def rmrf(path):
shutil.rmtree(path, onerror=del_rw)
class elf:
class memorysegment:
class ELF:
class MemorySegment:
phy_addr = 0
virt_start_addr = 0
virt_end_addr = 0
@ -545,7 +545,7 @@ class elf:
self.header, self.pentry = self.parse()
self.memorylayout = []
for entry in self.pentry:
ms = self.memorysegment()
ms = self.MemorySegment()
ms.phy_addr = entry.phy_addr
ms.virt_start_addr = entry.virt_addr
ms.virt_end_addr = entry.virt_addr + entry.seg_mem_len
@ -571,7 +571,7 @@ class elf:
return memsegment.virt_start_addr
return None
class programentry:
class ProgramEntry:
p_type = 0
from_file = 0
virt_addr = 0
@ -582,7 +582,7 @@ class elf:
p_align = 0
def parse_programentry(self, dat):
pe = self.programentry()
pe = self.ProgramEntry()
if self.elfclass == 1:
(pe.p_type, pe.from_file, pe.virt_addr, pe.phy_addr, pe.seg_file_len, pe.seg_mem_len, pe.p_flags,
pe.p_align) = struct.unpack("<IIIIIIII", dat)
@ -613,7 +613,7 @@ class elf:
return [header, pentry]
class patchtools:
class Patchtools:
cstyle = False
bDebug = False
@ -697,7 +697,7 @@ class patchtools:
print(e)
print(e.stat_count)
print(code[e.stat_count:e.stat_count + 10])
exit(0)
"""
if self.bDebug:
# walk every line to find the (first) error
for idx, line in enumerate(code.splitlines()):
@ -709,6 +709,8 @@ class patchtools:
print("bummer: " + str(e))
else:
exit(0)
"""
exit(0)
else:
encoding, count = ks.asm(code)

View file

@ -41,16 +41,16 @@ def find_binary(data, strf, pos=0):
def ldr_lit(curpc, instr):
# LDR (literal), LDR R1, =SEC_REG
imm8 = instr & 0xFF
Rt = (instr >> 8) & 7
rt = (instr >> 8) & 7
pc = curpc // 4 * 4
return (pc + (imm8 * 4) + 4), Rt
return (pc + (imm8 * 4) + 4), rt
def ldr_imm(instr):
simm5 = (instr >> 6) & 0x1F
sRt = instr & 0x7
sRn = (instr >> 3) & 0x7
return simm5, sRt, sRn
s_rt = instr & 0x7
s_rn = (instr >> 3) & 0x7
return simm5, s_rt, s_rn
def main():
@ -80,7 +80,7 @@ def main():
usbdl_ptr = None
if usbdl_put_word:
mpos = (usbdl_put_word & 0xFFFFF) + 7
offset, Rn = ldr_lit(mpos,
offset, rn = ldr_lit(mpos,
unpack("<H", data[mpos:mpos + 2])[0])
usbdl_ptr = (base | offset)
@ -137,7 +137,7 @@ def main():
sec_sbc = None
if sla is not None:
if data[sla + 9] & 0xF0 == 0x60:
offset, Rn = ldr_lit(sla + 6,
offset, rn = ldr_lit(sla + 6,
unpack("<H", data[sla + 6:sla + 6 + 2])[0])
sec_sbc = unpack("<I", data[offset:offset + 4])[0]
if data[sla + 8] == 0x51:
@ -148,15 +148,15 @@ def main():
if mpos is not None:
mpos -= 1
sec_mode = 1
offset, Rn = ldr_lit(mpos,
offset, rn = ldr_lit(mpos,
unpack("<H", data[mpos:mpos + 2])[0])
rbase = unpack("<I", data[offset:offset + 4])[0]
simm5, sRt, sRn = ldr_imm(unpack("<H", data[mpos + 2:mpos + 4])[0])
simm5, s_rt, s_rn = ldr_imm(unpack("<H", data[mpos + 2:mpos + 4])[0])
sec_sbc = (rbase + (simm5 * 4))
instr = unpack("<H", data[sla + 0x12:sla + 0x12 + 2])[0]
offset, Rn = ldr_lit(sla + 0x12, instr)
offset, rn = ldr_lit(sla + 0x12, instr)
rbase = unpack("<I", data[offset:offset + 4])[0]
simm5, sRt, sRn = ldr_imm(unpack("<H", data[sla + 0x12 + 2:sla + 0x12 + 4])[0])
simm5, s_rt, s_rn = ldr_imm(unpack("<H", data[sla + 0x12 + 2:sla + 0x12 + 4])[0])
sec_sla = (rbase + (simm5 * 4))
func_wdt = None
@ -181,7 +181,7 @@ def main():
func_usb_buffer = pos - 1
for i in range(0, 0x100, 2):
if data[func_usb_buffer + i + 1] == 0x48:
offset, Rn = ldr_lit(func_usb_buffer + i,
offset, rn = ldr_lit(func_usb_buffer + i,
unpack("<H", data[func_usb_buffer + i:func_usb_buffer + i + 2])[0])
usb_buffer = unpack("<I", data[offset:offset + 4])[0]
break
@ -204,11 +204,11 @@ def main():
try:
for i in range(0, 0x100, 2):
if data[vuln_ctrl_handler + i + 1] == 0x49 or data[vuln_ctrl_handler + i + 1] == 0x4C:
offset, Rn = ldr_lit(vuln_ctrl_handler + i,
offset, rn = ldr_lit(vuln_ctrl_handler + i,
unpack("<H", data[vuln_ctrl_handler + i:vuln_ctrl_handler + i + 2])[0])
vulnaddr = unpack("<I", data[offset:offset + 4])[0]
if data[vuln_ctrl_handler + i + 1] == 0x6A and usb_buffer != 0:
simm5, sRt, sRn = ldr_imm(
simm5, s_rt, s_rn = ldr_imm(
unpack("<H", data[vuln_ctrl_handler + i:vuln_ctrl_handler + i + 2])[0])
vulnoff = (simm5 * 4)
var1 = (usb_buffer - vulnaddr - vulnoff) / 0x34
@ -253,7 +253,7 @@ def main():
if pos is not None:
pos -= 1
instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr)
offset, rn = ldr_lit(pos, instr)
wd = unpack("<I", data[offset:offset + 4])[0]
blacklist = None
@ -265,7 +265,7 @@ def main():
if pos is not None:
pos += 8
instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr)
offset, rn = ldr_lit(pos, instr)
blacklist_ptr = unpack("<I", data[offset:offset + 4])[0] & 0xFFFFF
blacklist = unpack("<I", data[blacklist_ptr - 4:blacklist_ptr - 4 + 4])[0]
else:
@ -275,7 +275,7 @@ def main():
if pos is not None and blacklist is None:
instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr)
offset, rn = ldr_lit(pos, instr)
blacklist = unpack("<I", data[offset:offset + 4])[0]
blacklistcount = None
@ -289,24 +289,24 @@ def main():
if pos is not None:
pos += 2
instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr)
offset, rn = ldr_lit(pos, instr)
bl2 = unpack("<I", data[offset:offset + 4])[0]
blacklist2 = bl2 + 0x90
pos = 0
memread = None
memread = 0
while pos is not None:
pos = find_binary(data, b"\x10\xB5", pos)
if pos is not None:
if data[pos + 3] == 0x20 and data[pos + 0x9] == 0x49:
pos += 8
instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr)
offset, rn = ldr_lit(pos, instr)
memread = unpack("<I", data[offset:offset + 4])[0]
break
pos += 1
payload_addr = None
payload_addr = 0
while pos is not None:
pos = find_binary(data, "C40811A9", pos)
if pos is not None:
@ -316,7 +316,7 @@ def main():
coffs = (usbdl_put_data & 0xFFFFF) + 1
try:
offset, Rn = ldr_lit(coffs,
offset, rn = ldr_lit(coffs,
unpack("<H", data[coffs:coffs + 2])[0])
except:
print("Err:" + sys.argv[1])
@ -333,7 +333,7 @@ def main():
if pos is not None:
pos += 0xA
instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr)
offset, rn = ldr_lit(pos, instr)
socid_addr = unpack("<I", data[offset:offset + 4])[0]
meid_addr = None
@ -341,7 +341,7 @@ def main():
if pos is not None:
pos += 0xA
instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr)
offset, rn = ldr_lit(pos, instr)
meid_addr = unpack("<I", data[offset:offset + 4])[0]
brom_register_access = None
@ -353,15 +353,15 @@ def main():
if pos is not None:
pos += 2
instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr)
offset, rn = ldr_lit(pos, instr)
brom_register_access_ptr = base | pos2
brom_register_access_ptr_offset = base | offset
else:
pos = find_binary(data, "194D1B49", pos2)
if pos is not None:
instr = unpack("<H", data[pos:pos + 2])[0]
offset, Rn = ldr_lit(pos, instr)
da_range = offset
offset, rn = ldr_lit(pos, instr)
# da_range = offset
print("Base: \t\t\t\t\t\t0x%08X" % base)
print("usbdl_put_data:\t\t\t\t0x%08X" % usbdl_put_data)
@ -421,7 +421,8 @@ def main():
print("*cmd_handler:\t\t\t\t0x%08X" % cmd_handler)
if brom_register_access_ptr:
print(
f"brom_register_access_ptr:\t\t\t\t\t({hex(brom_register_access_ptr)},{hex(brom_register_access_ptr_offset)}),")
f"brom_register_access_ptr:\t\t\t\t\t({hex(brom_register_access_ptr)}," +
f"{hex(brom_register_access_ptr_offset)}),")
if meid_addr:
print(f"meid_addr:\t\t\t\t\t{hex(meid_addr)}")
if socid_addr:

View file

@ -7,7 +7,7 @@ import inspect
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parent_dir = os.path.dirname(os.path.dirname(current_dir))
sys.path.insert(0, parent_dir)
from mtkclient.config.payloads import pathconfig
from mtkclient.config.payloads import PathConfig
from mtkclient.Library.utils import read_object
from mtkclient.Library.utils import find_binary
@ -39,8 +39,8 @@ efusedb = {}
def main():
da_setup = []
loaders = []
pc = pathconfig()
if len(sys.argv)>1:
pc = PathConfig()
if len(sys.argv) > 1:
loaders.append(sys.argv[1])
else:
for root, dirs, files in os.walk(pc.get_loader_path(), topdown=False):
@ -72,9 +72,9 @@ def main():
print("sw_version: 0x%04X" % da[0]["sw_version"])
print("Reserved1: 0x%04X" % da[0]["reserved1"])
print("Reserved3: 0x%04X" % da[0]["reserved3"])
for i in range(da[0]["entry_region_count"]):
entry = da[i + 1]
print(f"\t{i}: {hex(entry['m_start_addr'])}")
for x in range(da[0]["entry_region_count"]):
entry = da[x + 1]
print(f"\t{x}: {hex(entry['m_start_addr'])}")
mbuf = da[3]["m_buf"]
m_len = da[3]["m_len"]
startaddr = da[3]["m_start_addr"]
@ -104,7 +104,11 @@ def main():
if hashidx is not None:
print("Hash check 3 found.")
else:
print("HASH ERROR !!!!")
hashidx = find_binary(data, b"\x04\x50\x00\xE3\x07\x50\x4C\xE3")
if hashidx is not None:
print("Hash check 4 (V6) found.")
else:
print("HASH ERROR !!!!")
fname = os.path.join("loaders",
hex(da[0]["hw_code"])[2:] + "_" + hex(startaddr)[2:] + os.path.basename(
@ -116,7 +120,7 @@ def main():
bootldr.seek(da[2]["m_buf"])
tt = bootldr.read(da[2]["m_len"])
idx = tt.find(bytes.fromhex("70BB442D27D244A7"))
#idx = tt.find(bytes.fromhex("01279360D36013615361"))
# idx = tt.find(bytes.fromhex("01279360D36013615361"))
if idx != -1:
print("V3 Enabled")
bootldr.seek(da[3]["m_buf"])

View file

@ -167,6 +167,7 @@ def hook_code(uc, access, address, size):
def hook_mem_invalid(uc, access, address, size, value, user_data):
info = ""
pc = uc.reg_read(UC_ARM_REG_PC)
if access == UC_MEM_WRITE:
info = ("invalid WRITE of 0x%x at 0x%X, data size = %u, data value = 0x%x" % (address, pc, size, value))

View file

@ -1,4 +1,4 @@
from Crypto.Cipher import AES
from Cryptodome.Cipher import AES
from struct import unpack, pack
from binascii import hexlify

View file

@ -5,7 +5,7 @@ import os
import logging
from binascii import hexlify
from struct import pack, unpack
from mtkclient.Library.Connection.usblib import usb_class
from mtkclient.Library.Connection.usblib import UsbClass
from mtkclient.Library.utils import LogBase
from mtkclient.Library.utils import print_progress
from unicorn import (Uc, UC_MEM_WRITE, UC_MEM_READ, UC_MEM_FETCH, UC_MEM_READ_UNMAPPED,
@ -40,7 +40,7 @@ class Stage2(metaclass=LogBase):
else:
self.__logger.setLevel(logging.INFO)
portconfig = [[0x0E8D, 0x0003, -1], [0x0E8D, 0x2000, -1]]
self.cdc = usb_class(portconfig=portconfig, loglevel=loglevel, devclass=10)
self.cdc = UsbClass(portconfig=portconfig, loglevel=loglevel, devclass=10)
def connect(self):
self.cdc.connected = self.cdc.connect()

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# MTK Stage2 Client (c) B.Kerler 2018-2023.
# MTK Stage2 Client (c) B.Kerler 2018-2024.
# Licensed under GPLv3 License
import os
@ -10,16 +10,18 @@ import argparse
import hashlib
from binascii import hexlify
from struct import pack, unpack
from mtkclient.Library.Connection.usblib import usb_class
from mtkclient.Library.Connection.usblib import UsbClass
from mtkclient.Library.utils import LogBase
from mtkclient.Library.utils import progress
from mtkclient.Library.Hardware.hwcrypto import crypto_setup, hwcrypto
from mtkclient.config.mtk_config import Mtk_Config
from mtkclient.Library.utils import Progress
from mtkclient.Library.Hardware.hwcrypto import CryptoSetup, HwCrypto
from mtkclient.config.mtk_config import MtkConfig
from mtkclient.config.usb_ids import default_ids
class Stage2(metaclass=LogBase):
def __init__(self, args, loglevel=logging.INFO):
self.hwcrypto = None
self.config = None
self.__logger = self.__logger
self.args = args
self.loglevel = loglevel
@ -28,7 +30,7 @@ class Stage2(metaclass=LogBase):
self.warning = self.__logger.warning
self.emmc_inited = False
# Setup HW Crypto chip variables
self.setup = crypto_setup()
self.setup = CryptoSetup()
if loglevel == logging.DEBUG:
logfilename = os.path.join("logs", "log.txt")
@ -40,7 +42,7 @@ class Stage2(metaclass=LogBase):
else:
self.__logger.setLevel(logging.INFO)
self.cdc = usb_class(portconfig=default_ids, loglevel=loglevel, devclass=10)
self.cdc = UsbClass(portconfig=default_ids, loglevel=loglevel, devclass=10)
self.usbread = self.cdc.usbread
self.usbwrite = self.cdc.usbwrite
@ -50,7 +52,7 @@ class Stage2(metaclass=LogBase):
except:
print("Error reading hwcode...aborting.")
return False
self.config = Mtk_Config(self.loglevel)
self.config = MtkConfig(self.loglevel)
self.config.init_hwcode(hwcode)
self.setup.blacklist = self.config.chipconfig.blacklist
self.setup.gcpu_base = self.config.chipconfig.gcpu_base
@ -62,7 +64,7 @@ class Stage2(metaclass=LogBase):
self.setup.writemem = self.memwrite
self.setup.meid_addr = self.config.chipconfig.meid_addr
self.setup.socid_addr = self.config.chipconfig.socid_addr
self.hwcrypto = hwcrypto(self.setup, self.loglevel, self.config.gui)
self.hwcrypto = HwCrypto(self.setup, self.loglevel, self.config.gui)
return True
def init_emmc(self):
@ -133,7 +135,7 @@ class Stage2(metaclass=LogBase):
if not self.emmc_inited:
self.init_emmc()
wf = None
pg = progress(pagesize=0x200)
pg = Progress(pagesize=0x200)
buffer = bytearray()
if filename is not None:
wf = open(filename, "wb")
@ -253,6 +255,7 @@ class Stage2(metaclass=LogBase):
addr = start
data = b""
pos = 0
wf = None
if filename is not None:
wf = open(filename, "wb")
while bytestoread > 0:
@ -273,6 +276,7 @@ class Stage2(metaclass=LogBase):
return data
def memwrite(self, start, data, filename=None):
rf = None
if filename is not None:
rf = open(filename, "rb")
bytestowrite = os.stat(filename).st_size
@ -306,7 +310,7 @@ class Stage2(metaclass=LogBase):
return ack == b"\xD0\xD0\xD0\xD0"
def rpmb(self, start, length, filename, reverse=False):
pg = progress(pagesize=0x100)
pg = Progress(pagesize=0x100)
if not self.emmc_inited:
self.init_emmc()
if start == 0:
@ -333,7 +337,7 @@ class Stage2(metaclass=LogBase):
old = 0
bytestoread = sectors * 0x100
count = sectors
pg = progress(pagesize=0x200)
pg = Progress(pagesize=0x200)
if sectors > 0xFFFF:
count = 0xFFFF
with open(filename, "wb") as wf:
@ -582,7 +586,8 @@ def main():
parser_keys.add_argument('--otp', dest='otp', type=str,
help='OTP for keys (dxcc,sej,gcpu)')
parser_keys.add_argument('--mode', dest='mode', default=None, type=str,
help='keymode (dxcc,sej,gcpu,sej_aes_decrypt,sej_aes_decrypt,sej_sst_decrypt,sej_sst_encrypt')
help='keymode (dxcc,sej,gcpu,sej_aes_decrypt,sej_aes_decrypt,' +
'sej_sst_decrypt,sej_sst_encrypt')
parser_keys.add_argument('--data', dest='data', default=None, type=str,
help='data')
args = parser.parse_args()
@ -677,17 +682,17 @@ def main():
elif cmd == "reboot":
st2.reboot()
elif cmd == "seccfg":
critical_lock_state = 0
if args.flag not in ["unlock", "lock"]:
print("Valid flags are: unlock, lock")
sys.exit(1)
"""
LKS_DEFAULT = 0x01
LKS_MP_DEFAULT = 0x02
LKS_UNLOCK = 0x03
LKS_LOCK = 0x04
LKS_VERIFIED = 0x05
LKS_CUSTOM = 0x06
"""
LKS_DEFAULT = 0x01
LKS_MP_DEFAULT = 0x02
LKS_UNLOCK = 0x03
LKS_LOCK = 0x04
LKS_VERIFIED = 0x05
LKS_CUSTOM = 0x06
"""
"""
LKCS_UNLOCK = 0x01
LKCS_LOCK = 0x02
@ -696,6 +701,8 @@ def main():
SBOOT_RUNTIME_OFF = 0
SBOOT_RUNTIME_ON = 1
"""
sys.exit(1)
if args.flag == "unlock":
lock_state = 3
critical_lock_state = 1

View file

@ -46,7 +46,8 @@ def main():
if (flag & 0x16F) != 0:
info += "B"
print(
f"Offset {hex(checklist_generic[0] + (i * 3))} -> Flag {hex(flag)}+[{info}] Ptr {hex(ptr)} Count {hex(count)}")
f"Offset {hex(checklist_generic[0] + (i * 3))} -> Flag {hex(flag)}+" +
f"[{info}] Ptr {hex(ptr)} Count {hex(count)}")
print("----------------------------------------------------------------------------------------------")
for field in range(count):
start, end = dword(data, ptr + (field * 8), 2)

View file

@ -1,10 +1,10 @@
class damodes:
class DAmodes:
LEGACY = 3
XFLASH = 5
XML = 6
class efuse:
class Efuse:
def __init__(self, base, hwcode):
if hwcode in [0x6570, 0x6580, 0x321, 0x335]:
self.efuses = [base + 0x20, base + 0x30, base + 0x38, base + 0x40, base + 0x44,
@ -221,13 +221,13 @@ class efuse:
base + 0xA4, base + 0xA8, base + 0xAC]
class chipconfig:
class Chipconfig:
def __init__(self, var1=None, watchdog=None, uart=None, brom_payload_addr=None,
da_payload_addr=None, pl_payload_addr=None, cqdma_base=None, sej_base=None, dxcc_base=None,
gcpu_base=None, ap_dma_mem=None, name="", description="", dacode=None,
meid_addr=None, socid_addr=None, blacklist=(), blacklist_count=None,
send_ptr=None, ctrl_buffer=(), cmd_handler=None, brom_register_access=None,
damode=damodes.LEGACY, loader=None, prov_addr=None, misc_lock=None,
damode=DAmodes.LEGACY, loader=None, prov_addr=None, misc_lock=None,
efuse_addr=None):
self.var1 = var1
self.watchdog = watchdog
@ -319,7 +319,7 @@ class chipconfig:
"""
hwconfig = {
0x571: chipconfig( # var1
0x571: Chipconfig( # var1
watchdog=0x10007000,
# uart
# brom_payload_addr
@ -329,10 +329,10 @@ hwconfig = {
# cqdma_base
# ap_dma_mem
# blacklist
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x0571,
name="MT0571"),
0x598: chipconfig( # var1
0x598: Chipconfig( # var1
watchdog=0x10211000,
uart=0x11020000,
brom_payload_addr=0x100A00, # todo:check
@ -342,10 +342,10 @@ hwconfig = {
cqdma_base=0x10212c00,
ap_dma_mem=0x11000000 + 0x1A0,
# blacklist
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
dacode=0x0598,
name="ELBRUS/MT0598"),
0x992: chipconfig( # var1
0x992: Chipconfig( # var1
# watchdog
# uart
# brom_payload_addr
@ -355,10 +355,10 @@ hwconfig = {
# cqdma_base
# ap_dma_mem
# blacklist
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x0992,
name="MT0992"),
0x2601: chipconfig(
0x2601: Chipconfig(
var1=0xA, # Smartwatch, confirmed
watchdog=0x10007000,
uart=0x11005000,
@ -378,10 +378,10 @@ hwconfig = {
brom_register_access=(0x40bd48, 0x40befc),
meid_addr=0x11142C34,
dacode=0x2601,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
name="MT2601",
loader="mt2601_payload.bin"),
0x3967: chipconfig( # var1
0x3967: Chipconfig( # var1
# watchdog
# uart
brom_payload_addr=0x100A00,
@ -394,9 +394,9 @@ hwconfig = {
# ap_dma_mem
# blacklist
dacode=0x3967,
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
name="MT3967"),
0x6255: chipconfig( # var1
0x6255: Chipconfig( # var1
# watchdog
# uart
# brom_payload_addr
@ -407,10 +407,10 @@ hwconfig = {
# cqdma_base
# ap_dma_mem
# blacklist
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
# dacode
name="MT6255"),
0x6261: chipconfig(
0x6261: Chipconfig(
var1=0x28, # Smartwatch, confirmed
watchdog=0xA0030000,
uart=0xA0080000,
@ -425,12 +425,12 @@ hwconfig = {
send_ptr=(0x700044b0, 0x700058EC),
ctrl_buffer=0x700041A8,
cmd_handler=0x700061F6,
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
dacode=0x6261,
name="MT6261",
loader="mt6261_payload.bin"
),
0x6280: chipconfig( # var1
0x6280: Chipconfig( # var1
# watchdog
# uart
# brom_payload_addr
@ -441,10 +441,10 @@ hwconfig = {
# cqdma_base
# ap_dma_mem
# blacklist
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
name="MT6280"
),
0x6516: chipconfig( # var1
0x6516: Chipconfig( # var1
watchdog=0x10003000,
uart=0x10023000,
da_payload_addr=0x201000, # todo: check
@ -454,10 +454,10 @@ hwconfig = {
# cqdma_base
# ap_dma_mem
# blacklist
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
dacode=0x6516,
name="MT6516"),
0x633: chipconfig( # var1
0x633: Chipconfig( # var1
watchdog=0x10007000,
uart=0x11002000,
brom_payload_addr=0x100A00, # todo: check
@ -469,10 +469,10 @@ hwconfig = {
cqdma_base=0x1020ac00,
ap_dma_mem=0x11000000 + 0x1A0, # AP_P_DMA_I2C_RX_MEM_ADDR
efuse_addr=0x10009000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6570,
name="MT6570/MT8321"),
0x6571: chipconfig( # var1
0x6571: Chipconfig( # var1
watchdog=0x10007400,
# uart
da_payload_addr=0x2009000,
@ -484,10 +484,10 @@ hwconfig = {
# ap_dma_mem
# blacklist
misc_lock=0x1000141C,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x6571,
name="MT6571"),
0x6572: chipconfig(
0x6572: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11005000,
@ -508,11 +508,11 @@ hwconfig = {
meid_addr=0x11142C34,
misc_lock=0x1000141C,
efuse_addr=0x10009000,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x6572,
name="MT6572",
loader="mt6572_payload.bin"),
0x6573: chipconfig( # var1
0x6573: Chipconfig( # var1
watchdog=0x70025000,
# uart
da_payload_addr=0x90006000,
@ -523,10 +523,10 @@ hwconfig = {
# cqdma_base
# ap_dma_mem
# blacklist
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
dacode=0x6573,
name="MT6573/MT6260"),
0x6575: chipconfig( # var1
0x6575: Chipconfig( # var1
watchdog=0xC0000000,
uart=0xC1009000,
da_payload_addr=0xc2001000,
@ -537,10 +537,10 @@ hwconfig = {
# cqdma_base
ap_dma_mem=0xC100119C,
# blacklist
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
dacode=0x6572,
name="MT6575/77"),
0x6577: chipconfig( # var1
0x6577: Chipconfig( # var1
watchdog=0xC0000000,
uart=0xC1009000,
da_payload_addr=0xc2001000,
@ -551,10 +551,10 @@ hwconfig = {
# cqdma_base
ap_dma_mem=0xC100119C,
# blacklist
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
dacode=0x6577,
name="MT6577"),
0x6580: chipconfig(var1=0xAC,
0x6580: Chipconfig(var1=0xAC,
watchdog=0x10007000,
uart=0x11005000,
brom_payload_addr=0x100A00,
@ -574,11 +574,11 @@ hwconfig = {
efuse_addr=0x10206000,
misc_lock=0x10001838,
meid_addr=0x1030B4,
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
dacode=0x6580,
name="MT6580",
loader="mt6580_payload.bin"),
0x6582: chipconfig(
0x6582: Chipconfig(
var1=0xA, # confirmed
watchdog=0x10007000,
uart=0x11002000,
@ -599,11 +599,11 @@ hwconfig = {
efuse_addr=0x10206000,
meid_addr=0x1030CC,
misc_lock=0x10002050,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x6582,
name="MT6582/MT6574/MT8382",
loader="mt6582_payload.bin"),
0x6583: chipconfig( # var1
0x6583: Chipconfig( # var1
watchdog=0x10000000, # fixme
uart=0x11006000,
brom_payload_addr=0x100A00,
@ -616,10 +616,10 @@ hwconfig = {
cqdma_base=0x10212000, # This chip might not support cqdma
ap_dma_mem=0x11000000 + 0x320, # AP_DMA_I2C_0_RX_MEM_ADDR
misc_lock=0x10002050,
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
dacode=0x6589,
name="MT6583/6589"),
0x6592: chipconfig(
0x6592: Chipconfig(
var1=0xA, # confirmed
watchdog=0x10007000,
uart=0x11002000,
@ -641,10 +641,10 @@ hwconfig = {
misc_lock=0x10002050,
efuse_addr=0x10206000,
dacode=0x6592,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
name="MT6592/MT8392",
loader="mt6592_payload.bin"),
0x6595: chipconfig(var1=0xA,
0x6595: Chipconfig(var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
brom_payload_addr=0x100A00,
@ -663,11 +663,11 @@ hwconfig = {
meid_addr=0x1030A4,
efuse_addr=0x10206000,
dacode=0x6595,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
name="MT6595",
loader="mt6595_payload.bin"),
# 6725
0x321: chipconfig(
0x321: Chipconfig(
var1=0x28,
watchdog=0x10212000,
uart=0x11002000,
@ -688,11 +688,11 @@ hwconfig = {
meid_addr=0x1030B0,
misc_lock=0x10001838,
efuse_addr=0x11c50000,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x6735,
name="MT6735/T,MT8735A",
loader="mt6735_payload.bin"),
0x335: chipconfig(
0x335: Chipconfig(
var1=0x28, # confirmed
watchdog=0x10212000,
uart=0x11002000,
@ -712,12 +712,12 @@ hwconfig = {
brom_register_access=(0x98dc, 0x9aa4),
meid_addr=0x1030B0,
efuse_addr=0x10206000,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x6735,
name="MT6737M/MT6735G",
loader="mt6737_payload.bin"),
# MT6738
0x699: chipconfig(
0x699: Chipconfig(
var1=0xB4,
watchdog=0x10007000,
uart=0x11002000,
@ -740,11 +740,11 @@ hwconfig = {
prov_addr=0x10720C,
misc_lock=0x1001a100,
efuse_addr=0x11c00000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6739,
name="MT6739/MT6731/MT8765",
loader="mt6739_payload.bin"),
0x601: chipconfig(
0x601: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -758,10 +758,10 @@ hwconfig = {
# blacklist
efuse_addr=0x10206000,
misc_lock=0x10001838,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6755,
name="MT6750"),
0x6752: chipconfig(
0x6752: Chipconfig(
var1=0x28,
watchdog=0x10007000,
uart=0x11002000,
@ -782,12 +782,12 @@ hwconfig = {
efuse_addr=0x10206000,
meid_addr=0x1030B4,
# no socid
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
dacode=0x6752,
# misc_lock=0x10001838,
name="MT6752",
loader="mt6752_payload.bin"),
0x337: chipconfig(
0x337: Chipconfig(
var1=0x28, # confirmed
watchdog=0x10212000,
uart=0x11002000,
@ -806,12 +806,12 @@ hwconfig = {
cmd_handler=0x0000A1EF,
brom_register_access=(0x993c, 0x9b04),
meid_addr=0x1030B0,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x6735,
misc_lock=0x10001838,
name="MT6753",
loader="mt6753_payload.bin"),
0x326: chipconfig(
0x326: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -832,12 +832,12 @@ hwconfig = {
meid_addr=0x1030AC,
misc_lock=0x10001838,
efuse_addr=0x10206000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6755,
name="MT6755/MT6750/M/T/S",
description="Helio P10/P15/P18",
loader="mt6755_payload.bin"),
0x551: chipconfig(
0x551: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -858,12 +858,12 @@ hwconfig = {
meid_addr=0x1030B4,
misc_lock=0x10001838,
efuse_addr=0x10206000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6757,
name="MT6757/MT6757D",
description="Helio P20",
loader="mt6757_payload.bin"),
0x688: chipconfig(
0x688: Chipconfig(
var1=0xA,
watchdog=0x10211000, #
uart=0x11020000,
@ -884,13 +884,13 @@ hwconfig = {
meid_addr=0x102bf8,
socid_addr=0x102c08,
efuse_addr=0x10450000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6758,
name="MT6758",
description="Helio P30",
loader="mt6758_payload.bin"
),
0x507: chipconfig( # var1
0x507: Chipconfig( # var1
watchdog=0x10210000,
uart=0x11020000,
brom_payload_addr=0x100A00, # todo
@ -908,14 +908,14 @@ hwconfig = {
# cmd_handler
# brom_Register_access
# meid_addr
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
dacode=0x6758,
name="MT6759",
description="Helio P30"
# loader
),
0x717: chipconfig(
0x717: Chipconfig(
var1=0x25,
watchdog=0x10007000,
uart=0x11002000,
@ -938,12 +938,12 @@ hwconfig = {
prov_addr=0x1054F4,
misc_lock=0x1001a100,
efuse_addr=0x11c50000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6761,
name="MT6761/MT6762/MT3369/MT8766B",
description="Helio A20/P22/A22/A25/G25",
loader="mt6761_payload.bin"),
0x690: chipconfig(
0x690: Chipconfig(
var1=0x7F,
watchdog=0x10007000,
uart=0x11002000,
@ -966,12 +966,12 @@ hwconfig = {
prov_addr=0x106804,
misc_lock=0x1001a100,
efuse_addr=0x11f10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6763,
name="MT6763",
description="Helio P23",
loader="mt6763_payload.bin"),
0x766: chipconfig(
0x766: Chipconfig(
var1=0x25, # confirmed
watchdog=0x10007000,
uart=0x11002000,
@ -994,12 +994,12 @@ hwconfig = {
prov_addr=0x1054F4,
misc_lock=0x1001a100,
efuse_addr=0x11c50000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6765,
name="MT6765/MT8768t",
description="Helio P35/G35",
loader="mt6765_payload.bin"),
0x707: chipconfig(
0x707: Chipconfig(
var1=0x25,
watchdog=0x10007000,
uart=0x11002000,
@ -1022,12 +1022,12 @@ hwconfig = {
prov_addr=0x1054F4,
misc_lock=0x1001a100,
efuse_addr=0x11ce0000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6768,
name="MT6768/MT6769",
description="Helio P65/G85 k68v1",
loader="mt6768_payload.bin"),
0x788: chipconfig(
0x788: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -1050,7 +1050,7 @@ hwconfig = {
prov_addr=0x1065C0,
misc_lock=0x1001a100,
efuse_addr=0x11f10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6771,
name="MT6771/MT8385/MT8183/MT8666",
description="Helio P60/P70/G80",
@ -1066,7 +1066,7 @@ hwconfig = {
# (0x00200018, 0x00200000), # Memory region array pointer
# (0x0020001c, 0x00000001), # Memory region array length
# (0x00106A60, 0)], # Dynamic permission table entry count?
0x725: chipconfig(var1=0xA, # confirmed
0x725: Chipconfig(var1=0xA, # confirmed
watchdog=0x10007000,
uart=0x11002000,
brom_payload_addr=0x100A00,
@ -1088,12 +1088,12 @@ hwconfig = {
prov_addr=0x1065C0,
misc_lock=0x1001a100,
efuse_addr=0x11c10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6779,
name="MT6779",
description="Helio P90 k79v1",
loader="mt6779_payload.bin"),
0x1066: chipconfig(
0x1066: Chipconfig(
var1=0x73, # confirmed
watchdog=0x10007000,
uart=0x11002000,
@ -1114,13 +1114,13 @@ hwconfig = {
meid_addr=0x102B98,
socid_addr=0x102BA8,
efuse_addr=0x11cb0000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6781,
name="MT6781",
description="Helio G96",
loader="mt6781_payload.bin"
),
0x813: chipconfig(var1=0xA, # confirmed
0x813: Chipconfig(var1=0xA, # confirmed
watchdog=0x10007000,
uart=0x11002000,
brom_payload_addr=0x100A00,
@ -1142,12 +1142,12 @@ hwconfig = {
prov_addr=0x1065C0,
misc_lock=0x1001a100,
efuse_addr=0x11c10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6785,
name="MT6785",
description="Helio G90",
loader="mt6785_payload.bin"),
0x6795: chipconfig(
0x6795: Chipconfig(
var1=0xA, # confirmed
watchdog=0x10007000,
uart=0x11002000,
@ -1167,12 +1167,12 @@ hwconfig = {
brom_register_access=(0x9a60, 0x9c28),
meid_addr=0x1030A0,
efuse_addr=0x10206000,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x6795,
name="MT6795",
description="Helio X10",
loader="mt6795_payload.bin"),
0x279: chipconfig(
0x279: Chipconfig(
var1=0xA, # confirmed
watchdog=0x10007000,
uart=0x11002000,
@ -1193,12 +1193,12 @@ hwconfig = {
meid_addr=0x1030AC,
misc_lock=0x10002050,
efuse_addr=0x10206000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6797,
name="MT6797/MT6767",
description="Helio X23/X25/X27",
loader="mt6797_payload.bin"),
0x562: chipconfig(
0x562: Chipconfig(
var1=0xA, # confirmed
watchdog=0x10211000,
uart=0x11020000,
@ -1219,12 +1219,12 @@ hwconfig = {
meid_addr=0x1033B8,
socid_addr=0x1033C8,
efuse_addr=0x11F10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6799,
name="MT6799",
description="Helio X30/X35",
loader="mt6799_payload.bin"),
0x989: chipconfig(
0x989: Chipconfig(
var1=0x73,
watchdog=0x10007000,
uart=0x11002000,
@ -1246,12 +1246,12 @@ hwconfig = {
socid_addr=0x102ba8,
prov_addr=0x1066B4,
efuse_addr=0x11c10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6833,
name="MT6833",
description="Dimensity 700 5G k6833",
loader="mt6833_payload.bin"),
0x996: chipconfig(var1=0xA,
0x996: Chipconfig(var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
brom_payload_addr=0x100A00,
@ -1273,12 +1273,12 @@ hwconfig = {
prov_addr=0x1066C0,
misc_lock=0x1001A100,
efuse_addr=0x11c10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6853,
name="MT6853",
description="Dimensity 720 5G",
loader="mt6853_payload.bin"),
0x886: chipconfig(
0x886: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -1301,12 +1301,12 @@ hwconfig = {
prov_addr=0x1066C0,
misc_lock=0x1001A100,
efuse_addr=0x11c10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6873,
name="MT6873",
description="Dimensity 800/820 5G",
loader="mt6873_payload.bin"),
0x959: chipconfig(
0x959: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -1328,13 +1328,13 @@ hwconfig = {
socid_addr=0x102ba8,
prov_addr=0x1066C0,
efuse_addr=0x11f10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6877, # todo
name="MT6877/MT6877V",
description="Dimensity 900/1080",
loader="mt6877_payload.bin"
),
0x816: chipconfig(
0x816: Chipconfig(
var1=0xA, # confirmed
watchdog=0x10007000,
uart=0x11002000,
@ -1357,13 +1357,13 @@ hwconfig = {
prov_addr=0x1066C0,
misc_lock=0x1001A100,
efuse_addr=0x11c10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6885,
name="MT6885/MT6883/MT6889/MT6880/MT6890",
description="Dimensity 1000L/1000",
loader="mt6885_payload.bin"),
# Dimensity 1100 - MT6891 Realme Q3 Pro
0x950: chipconfig(
0x950: Chipconfig(
var1=0xA, # confirmed
watchdog=0x10007000,
uart=0x11002000,
@ -1385,13 +1385,13 @@ hwconfig = {
socid_addr=0x102BA8,
prov_addr=0x1066C0,
efuse_addr=0x11c10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x6893,
name="MT6893",
description="Dimensity 1200",
loader="mt6893_payload.bin"),
#
0x907: chipconfig(
0x907: Chipconfig(
var1=0xA,
watchdog=0x1c007000,
uart=0x11001000,
@ -1412,14 +1412,14 @@ hwconfig = {
meid_addr=0x1008EC,
socid_addr=0x100934,
# prov_addr=0x1066C0,
damode=damodes.XML,
damode=DAmodes.XML,
dacode=0x6983,
name="MT6983",
description="Dimensity 9000/9000+"
# loader="mt6983_payload.bin"
),
# Dimensity 1100 - MT6895 Dimensity 8200 - Vivo V27 Pro
0x1172: chipconfig(
0x1172: Chipconfig(
var1=0xA,
watchdog=0x1c007000,
uart=0x11001000,
@ -1440,14 +1440,14 @@ hwconfig = {
meid_addr=0x1008EC,
socid_addr=0x100934,
# prov_addr=0x1066C0,
damode=damodes.XML,
damode=DAmodes.XML,
dacode=0x6895,
name="MT6895",
description="Dimensity 8100"
# loader="mt6893_payload.bin"
),
# MT6789 Oppo Realme 10 / Gigaset GX4
0x1208: chipconfig(
0x1208: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -1469,13 +1469,13 @@ hwconfig = {
socid_addr=0x100934,
# prov_addr=0x1066C0,
efuse_addr=0x11C10000,
damode=damodes.XML,
damode=DAmodes.XML,
dacode=0x1208,
name="MT6789",
description="MTK Helio G99"
# loader="mt6789_payload.bin"
),
0x1229: chipconfig(
0x1229: Chipconfig(
var1=0xA,
watchdog=0x1c007000,
uart=0x11002000,
@ -1484,7 +1484,7 @@ hwconfig = {
pl_payload_addr=0x40200000,
# gcpu_base=0x10050000,
dxcc_base=0x10210000,
#sej_base=0x1000a000,
# sej_base=0x1000a000,
cqdma_base=0x10212000,
# ap_dma_mem=0x11300800 + 0x1a0,
# blacklist=[(0x102d5c, 0x0)],
@ -1493,17 +1493,17 @@ hwconfig = {
# ctrl_buffer=0x00103024,
# cmd_handler=0x000101E8,
# brom_register_access=(0xf99a, 0xfa0c),
#meid_addr=0x1008EC,
#socid_addr=0x100934,
# meid_addr=0x1008EC,
# socid_addr=0x100934,
# prov_addr=0x1066C0,
# efuse_addr=0x11C10000,
damode=damodes.XML,
damode=DAmodes.XML,
dacode=0x1229,
name="MT6886",
description="Dimensity 7200 Ultra"
# loader="mt7200_payload.bin"
),
0x1296: chipconfig(
0x1296: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -1525,13 +1525,13 @@ hwconfig = {
socid_addr=0x100934,
# prov_addr=0x1066C0,
# efuse_addr=0x11C10000,
damode=damodes.XML,
damode=DAmodes.XML,
dacode=0x1296,
name="MT6985",
description="Dimensity 9200/9200+"
# loader="mt6985_payload.bin"
),
0x8127: chipconfig(
0x8127: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -1550,11 +1550,11 @@ hwconfig = {
brom_register_access=(0xb58c, 0xb740),
meid_addr=0x1031CC,
misc_lock=0x10002050,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x8127,
name="MT8127/MT3367",
loader="mt8127_payload.bin"), # ford,austin,tank #mhmm wdt, nochmal checken
0x8135: chipconfig( # var1
0x8135: Chipconfig( # var1
watchdog=0x10000000,
uart=0x11002000,
# brom_payload_addr
@ -1572,13 +1572,13 @@ hwconfig = {
# brom_register_access
# meid_addr
# socid_addr
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x8135,
name="MT8135"
# description
# loader
),
0x8163: chipconfig(
0x8163: Chipconfig(
var1=0xB1,
watchdog=0x10007000,
uart=0x11002000,
@ -1599,11 +1599,11 @@ hwconfig = {
meid_addr=0x1031C0,
misc_lock=0x10002050,
efuse_addr=0x10206000,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x8163,
name="MT8163",
loader="mt8163_payload.bin"), # douglas, karnak
0x8167: chipconfig(var1=0xCC,
0x8167: Chipconfig(var1=0xCC,
watchdog=0x10007000,
uart=0x11005000,
brom_payload_addr=0x100A00,
@ -1623,12 +1623,12 @@ hwconfig = {
meid_addr=0x103478,
socid_addr=0x103488,
efuse_addr=0x10009000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x8167,
name="MT8167/MT8516/MT8362",
# description
loader="mt8167_payload.bin"),
0x8168: chipconfig(
0x8168: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -1648,12 +1648,12 @@ hwconfig = {
meid_addr=0x106438,
socid_addr=0x106448,
efuse_addr=0x10009000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x8168,
name="MT8168/MT6357",
# description, device is patched against kamakiri
loader="mt8168_payload.bin"),
0x8172: chipconfig(
0x8172: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -1673,12 +1673,12 @@ hwconfig = {
brom_register_access=(0xa3b8, 0xa580),
meid_addr=0x1230B0,
misc_lock=0x1202050,
damode=damodes.LEGACY, #
damode=DAmodes.LEGACY, #
dacode=0x8173,
name="MT8173",
# description
loader="mt8173_payload.bin"), # sloane, suez
0x8176: chipconfig(
0x8176: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -1701,11 +1701,11 @@ hwconfig = {
# socid_addr
efuse_addr=0x10206000,
dacode=0x8173,
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
# description
name="MT8176",
loader="mt8176_payload.bin"),
0x930: chipconfig(
0x930: Chipconfig(
# var1
watchdog=0x10007000,
uart=0x11001200,
@ -1727,12 +1727,12 @@ hwconfig = {
efuse_addr=0x11c10000,
misc_lock=0x1001A100,
dacode=0x8195,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
# description
name="MT8195 Chromebook"
# loader
),
0x8512: chipconfig(
0x8512: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
@ -1753,12 +1753,12 @@ hwconfig = {
socid_addr=0x104648,
efuse_addr=0x11c50000,
dacode=0x8512,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
# description
name="MT8512",
loader="mt8512_payload.bin"
),
0x8518: chipconfig( # var1
0x8518: Chipconfig( # var1
# watchdog
# uart
# brom_payload_addr
@ -1777,11 +1777,11 @@ hwconfig = {
# socid_addr
efuse_addr=0x10009000,
dacode=0x8518,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
name="MT8518 VoiceAssistant"
# loader
),
0x8590: chipconfig(
0x8590: Chipconfig(
var1=0xA, # confirmed, router
watchdog=0x10007000,
uart=0x11002000,
@ -1800,11 +1800,11 @@ hwconfig = {
brom_register_access=(0xbeb8, 0xc06c),
meid_addr=0x1031D8,
dacode=0x8590,
damode=damodes.LEGACY,
damode=DAmodes.LEGACY,
name="MT8590/MT7683/MT8521/MT7623",
# description=
loader="mt8590_payload.bin"),
0x8695: chipconfig(
0x8695: Chipconfig(
var1=0xA, # confirmed
watchdog=0x10007000,
uart=0x11002000,
@ -1823,12 +1823,12 @@ hwconfig = {
brom_register_access=(0xc298, 0xc3f8),
meid_addr=0x1032B8,
efuse_addr=0x10206000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x8695,
name="MT8695", # mantis
# description
loader="mt8695_payload.bin"),
0x908: chipconfig(
0x908: Chipconfig(
# var1
watchdog=0x10007000,
# uart
@ -1847,7 +1847,7 @@ hwconfig = {
# meid_addr
# socid_addr
efuse_addr=0x11c10000,
damode=damodes.XFLASH,
damode=DAmodes.XFLASH,
dacode=0x8696,
# description
name="MT8696"

View file

@ -3,8 +3,8 @@ import sys
import logging
from binascii import hexlify
from mtkclient.Library.utils import LogBase
from mtkclient.Library.settings import hwparam
from mtkclient.config.brom_config import chipconfig, damodes, hwconfig
from mtkclient.Library.settings import HwParam
from mtkclient.config.brom_config import Chipconfig, DAmodes, hwconfig
try:
from PySide6.QtCore import QObject
@ -15,10 +15,11 @@ except ImportError:
pass
class Mtk_Config(metaclass=LogBase):
class MtkConfig(metaclass=LogBase):
def __init__(self, loglevel=logging.INFO, gui=None, guiprogress=None, update_status_text=None):
self.peek = None
self.gui = gui
self.loglevel = loglevel
self.guiprogress = guiprogress
self.update_status_text = update_status_text
self.pid = -1
@ -64,7 +65,7 @@ class Mtk_Config(metaclass=LogBase):
self.meid = None
self.socid = None
self.target_config = None
self.chipconfig = chipconfig()
self.chipconfig = Chipconfig()
self.gpt_settings = None
self.hwparam = None
self.hwparam_path = "."
@ -113,7 +114,7 @@ class Mtk_Config(metaclass=LogBase):
self.hwparam.writesetting("hwcode", hex(hwcode))
def set_meid(self, meid):
self.hwparam = hwparam(self, meid, self.hwparam_path)
self.hwparam = HwParam(self, meid, self.hwparam_path)
self.meid = meid
self.hwparam.writesetting("meid", hexlify(meid).decode('utf-8'))
@ -180,7 +181,7 @@ class Mtk_Config(metaclass=LogBase):
if self.chipconfig.ap_dma_mem is None:
self.chipconfig.ap_dma_mem = 0x11000000 + 0x1A0
if self.chipconfig.damode is None:
self.chipconfig.damode = damodes.LEGACY
self.chipconfig.damode = DAmodes.LEGACY
if self.chipconfig.dxcc_base is None:
self.chipconfig.dxcc_base = None
if self.chipconfig.meid_addr is None:
@ -195,7 +196,7 @@ class Mtk_Config(metaclass=LogBase):
if hwcode in hwconfig:
self.chipconfig = hwconfig[hwcode]
else:
self.chipconfig = chipconfig()
self.chipconfig = Chipconfig()
self.default_values(hwcode)
def get_watchdog_addr(self):

View file

@ -2,7 +2,7 @@
import os
class pathconfig:
class PathConfig:
def __init__(self):
curscript = os.path.realpath(__file__)
self.scriptpath = os.path.dirname(curscript)

View file

@ -1,15 +1,27 @@
# -*- coding: utf-8 -*-
from PySide6.QtCore import (QCoreApplication, QMetaObject, QRect,
QSize, Qt)
from PySide6.QtGui import QAction, QPixmap
from PySide6.QtWidgets import (QAbstractScrollArea, QCheckBox, QFrame,
QGridLayout, QHBoxLayout, QLabel,
QLayout, QMenu, QMenuBar,
QPlainTextEdit, QProgressBar, QPushButton, QScrollArea,
QSizePolicy, QSpacerItem, QTabWidget, QTableWidget,
QTableWidgetItem, QVBoxLayout, QWidget)
################################################################################
## Form generated from reading UI file 'main_gui.ui'
##
## Created by: Qt User Interface Compiler version 6.6.3
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
QCursor, QFont, QFontDatabase, QGradient,
QIcon, QImage, QKeySequence, QLinearGradient,
QPainter, QPalette, QPixmap, QRadialGradient,
QTransform)
from PySide6.QtWidgets import (QAbstractScrollArea, QApplication, QCheckBox, QFrame,
QGridLayout, QHBoxLayout, QHeaderView, QLabel,
QLayout, QMainWindow, QMenu, QMenuBar,
QPlainTextEdit, QProgressBar, QPushButton, QScrollArea,
QSizePolicy, QSpacerItem, QTabWidget, QTableWidget,
QTableWidgetItem, QVBoxLayout, QWidget)
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
@ -17,7 +29,7 @@ class Ui_MainWindow(object):
MainWindow.setObjectName(u"MainWindow")
MainWindow.setWindowModality(Qt.NonModal)
MainWindow.resize(746, 720)
sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
sizePolicy = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
@ -79,33 +91,51 @@ class Ui_MainWindow(object):
self.tabWidget.setAutoFillBackground(False)
self.readtab = QWidget()
self.readtab.setObjectName(u"readtab")
self.gridLayout_7 = QGridLayout(self.readtab)
self.gridLayout_7.setObjectName(u"gridLayout_7")
self.gridLayout_5 = QGridLayout(self.readtab)
self.gridLayout_5.setObjectName(u"gridLayout_5")
self.verticalLayout_8 = QVBoxLayout()
self.verticalLayout_8.setObjectName(u"verticalLayout_8")
self.horizontalLayout_6 = QHBoxLayout()
self.horizontalLayout_6.setObjectName(u"horizontalLayout_6")
self.readselectallcheckbox = QCheckBox(self.readtab)
self.readselectallcheckbox.setObjectName(u"readselectallcheckbox")
self.horizontalLayout_6.addWidget(self.readselectallcheckbox)
self.readDumpGPTCheckbox = QCheckBox(self.readtab)
self.readDumpGPTCheckbox.setObjectName(u"readDumpGPTCheckbox")
sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.readDumpGPTCheckbox.sizePolicy().hasHeightForWidth())
self.readDumpGPTCheckbox.setSizePolicy(sizePolicy1)
self.gridLayout_7.addWidget(self.readDumpGPTCheckbox, 4, 1, 1, 1)
self.horizontalLayout_6.addWidget(self.readDumpGPTCheckbox)
self.horizontalSpacer_14 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_6.addItem(self.horizontalSpacer_14)
self.readtitle = QLabel(self.readtab)
self.readtitle.setObjectName(u"readtitle")
sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.readtitle.sizePolicy().hasHeightForWidth())
self.readtitle.setSizePolicy(sizePolicy1)
self.readtitle.setMinimumSize(QSize(0, 20))
self.readtitle.setAlignment(Qt.AlignLeading | Qt.AlignLeft | Qt.AlignTop)
self.gridLayout_7.addWidget(self.readtitle, 0, 0, 1, 1)
self.horizontalLayout_6.addWidget(self.readtitle)
self.horizontalSpacer_9 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_6.addItem(self.horizontalSpacer_9)
self.readpartitionsbtn = QPushButton(self.readtab)
self.readpartitionsbtn.setObjectName(u"readpartitionsbtn")
self.gridLayout_7.addWidget(self.readpartitionsbtn, 0, 1, 1, 1)
self.horizontalLayout_6.addWidget(self.readpartitionsbtn)
self.verticalLayout_8.addLayout(self.horizontalLayout_6)
self.readpartitionList = QScrollArea(self.readtab)
self.readpartitionList.setObjectName(u"readpartitionList")
sizePolicy2 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.MinimumExpanding)
sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.MinimumExpanding)
sizePolicy2.setHorizontalStretch(0)
sizePolicy2.setVerticalStretch(0)
sizePolicy2.setHeightForWidth(self.readpartitionList.sizePolicy().hasHeightForWidth())
@ -117,37 +147,63 @@ class Ui_MainWindow(object):
self.readpartitionList.setWidgetResizable(True)
self.scrollAreaWidgetContents = QWidget()
self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents")
self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 600, 278))
self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 700, 311))
self.readpartitionList.setWidget(self.scrollAreaWidgetContents)
self.gridLayout_7.addWidget(self.readpartitionList, 2, 0, 1, 1)
self.verticalLayout_8.addWidget(self.readpartitionList)
self.readselectallcheckbox = QCheckBox(self.readtab)
self.readselectallcheckbox.setObjectName(u"readselectallcheckbox")
self.gridLayout_7.addWidget(self.readselectallcheckbox, 1, 0, 1, 1)
self.gridLayout_5.addLayout(self.verticalLayout_8, 0, 0, 1, 1)
self.tabWidget.addTab(self.readtab, "")
self.writetab = QWidget()
self.writetab.setObjectName(u"writetab")
self.gridLayout_6 = QGridLayout(self.writetab)
self.gridLayout_6.setObjectName(u"gridLayout_6")
self.verticalLayout_9 = QVBoxLayout()
self.verticalLayout_9.setObjectName(u"verticalLayout_9")
self.horizontalLayout_8 = QHBoxLayout()
self.horizontalLayout_8.setObjectName(u"horizontalLayout_8")
self.writetitle = QLabel(self.writetab)
self.writetitle.setObjectName(u"writetitle")
sizePolicy1.setHeightForWidth(self.writetitle.sizePolicy().hasHeightForWidth())
self.writetitle.setSizePolicy(sizePolicy1)
sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed)
sizePolicy3.setHorizontalStretch(0)
sizePolicy3.setVerticalStretch(0)
sizePolicy3.setHeightForWidth(self.writetitle.sizePolicy().hasHeightForWidth())
self.writetitle.setSizePolicy(sizePolicy3)
self.writetitle.setMinimumSize(QSize(0, 20))
self.writetitle.setAlignment(Qt.AlignLeading | Qt.AlignLeft | Qt.AlignTop)
self.writetitle.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
self.gridLayout_6.addWidget(self.writetitle, 0, 0, 1, 1)
self.horizontalLayout_8.addWidget(self.writetitle)
self.horizontalSpacer_10 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_8.addItem(self.horizontalSpacer_10)
self.writeselectfromdir = QPushButton(self.writetab)
self.writeselectfromdir.setObjectName(u"writeselectfromdir")
self.horizontalLayout_8.addWidget(self.writeselectfromdir)
self.horizontalSpacer_11 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_8.addItem(self.horizontalSpacer_11)
self.writepartbtn = QPushButton(self.writetab)
self.writepartbtn.setObjectName(u"writepartbtn")
self.horizontalLayout_8.addWidget(self.writepartbtn)
self.verticalLayout_9.addLayout(self.horizontalLayout_8)
self.writepartitionList = QScrollArea(self.writetab)
self.writepartitionList.setObjectName(u"writepartitionList")
sizePolicy3 = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Expanding)
sizePolicy3.setHorizontalStretch(0)
sizePolicy3.setVerticalStretch(0)
sizePolicy3.setHeightForWidth(self.writepartitionList.sizePolicy().hasHeightForWidth())
self.writepartitionList.setSizePolicy(sizePolicy3)
sizePolicy4 = QSizePolicy(QSizePolicy.Policy.MinimumExpanding, QSizePolicy.Policy.Expanding)
sizePolicy4.setHorizontalStretch(0)
sizePolicy4.setVerticalStretch(0)
sizePolicy4.setHeightForWidth(self.writepartitionList.sizePolicy().hasHeightForWidth())
self.writepartitionList.setSizePolicy(sizePolicy4)
self.writepartitionList.setMinimumSize(QSize(0, 280))
self.writepartitionList.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.writepartitionList.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
@ -155,30 +211,57 @@ class Ui_MainWindow(object):
self.writepartitionList.setWidgetResizable(True)
self.scrollAreaWidgetContents_2 = QWidget()
self.scrollAreaWidgetContents_2.setObjectName(u"scrollAreaWidgetContents_2")
self.scrollAreaWidgetContents_2.setGeometry(QRect(0, 0, 577, 327))
self.scrollAreaWidgetContents_2.setGeometry(QRect(0, 0, 700, 311))
self.writepartitionList.setWidget(self.scrollAreaWidgetContents_2)
self.gridLayout_6.addWidget(self.writepartitionList, 1, 0, 2, 1)
self.verticalLayout_9.addWidget(self.writepartitionList)
self.writepartbtn = QPushButton(self.writetab)
self.writepartbtn.setObjectName(u"writepartbtn")
self.gridLayout_6.addWidget(self.writepartbtn, 0, 1, 1, 1)
self.writeselectfromdir = QPushButton(self.writetab)
self.writeselectfromdir.setObjectName(u"writeselectfromdir")
self.gridLayout_6.addWidget(self.writeselectfromdir, 2, 1, 1, 1)
self.gridLayout_6.addLayout(self.verticalLayout_9, 0, 0, 1, 1)
self.tabWidget.addTab(self.writetab, "")
self.erasetab = QWidget()
self.erasetab.setObjectName(u"erasetab")
self.gridLayout_5 = QGridLayout(self.erasetab)
self.gridLayout_5.setObjectName(u"gridLayout_5")
self.horizontalLayout_10 = QHBoxLayout(self.erasetab)
self.horizontalLayout_10.setObjectName(u"horizontalLayout_10")
self.verticalLayout_10 = QVBoxLayout()
self.verticalLayout_10.setObjectName(u"verticalLayout_10")
self.horizontalLayout_9 = QHBoxLayout()
self.horizontalLayout_9.setObjectName(u"horizontalLayout_9")
self.erasetitle = QLabel(self.erasetab)
self.erasetitle.setObjectName(u"erasetitle")
sizePolicy3.setHeightForWidth(self.erasetitle.sizePolicy().hasHeightForWidth())
self.erasetitle.setSizePolicy(sizePolicy3)
self.erasetitle.setMinimumSize(QSize(0, 20))
self.erasetitle.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
self.horizontalLayout_9.addWidget(self.erasetitle)
self.horizontalSpacer_13 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_9.addItem(self.horizontalSpacer_13)
self.eraseselectallpartitionscheckbox = QCheckBox(self.erasetab)
self.eraseselectallpartitionscheckbox.setObjectName(u"eraseselectallpartitionscheckbox")
self.horizontalLayout_9.addWidget(self.eraseselectallpartitionscheckbox)
self.horizontalSpacer_12 = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_9.addItem(self.horizontalSpacer_12)
self.erasepartitionsbtn = QPushButton(self.erasetab)
self.erasepartitionsbtn.setObjectName(u"erasepartitionsbtn")
self.horizontalLayout_9.addWidget(self.erasepartitionsbtn)
self.verticalLayout_10.addLayout(self.horizontalLayout_9)
self.erasepartitionList = QScrollArea(self.erasetab)
self.erasepartitionList.setObjectName(u"erasepartitionList")
sizePolicy3.setHeightForWidth(self.erasepartitionList.sizePolicy().hasHeightForWidth())
self.erasepartitionList.setSizePolicy(sizePolicy3)
sizePolicy4.setHeightForWidth(self.erasepartitionList.sizePolicy().hasHeightForWidth())
self.erasepartitionList.setSizePolicy(sizePolicy4)
self.erasepartitionList.setMinimumSize(QSize(0, 280))
self.erasepartitionList.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.erasepartitionList.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
@ -186,29 +269,13 @@ class Ui_MainWindow(object):
self.erasepartitionList.setWidgetResizable(True)
self.scrollAreaWidgetContents_3 = QWidget()
self.scrollAreaWidgetContents_3.setObjectName(u"scrollAreaWidgetContents_3")
self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 598, 298))
self.scrollAreaWidgetContents_3.setGeometry(QRect(0, 0, 700, 311))
self.erasepartitionList.setWidget(self.scrollAreaWidgetContents_3)
self.gridLayout_5.addWidget(self.erasepartitionList, 2, 0, 2, 1)
self.verticalLayout_10.addWidget(self.erasepartitionList)
self.erasetitle = QLabel(self.erasetab)
self.erasetitle.setObjectName(u"erasetitle")
sizePolicy1.setHeightForWidth(self.erasetitle.sizePolicy().hasHeightForWidth())
self.erasetitle.setSizePolicy(sizePolicy1)
self.erasetitle.setMinimumSize(QSize(0, 20))
self.erasetitle.setAlignment(Qt.AlignLeading | Qt.AlignLeft | Qt.AlignTop)
self.gridLayout_5.addWidget(self.erasetitle, 0, 0, 1, 1)
self.erasepartitionsbtn = QPushButton(self.erasetab)
self.erasepartitionsbtn.setObjectName(u"erasepartitionsbtn")
self.gridLayout_5.addWidget(self.erasepartitionsbtn, 0, 1, 1, 1)
self.eraseselectallpartitionscheckbox = QCheckBox(self.erasetab)
self.eraseselectallpartitionscheckbox.setObjectName(u"eraseselectallpartitionscheckbox")
self.gridLayout_5.addWidget(self.eraseselectallpartitionscheckbox, 1, 0, 1, 1)
self.horizontalLayout_10.addLayout(self.verticalLayout_10)
self.tabWidget.addTab(self.erasetab, "")
self.tab = QWidget()
@ -237,10 +304,11 @@ class Ui_MainWindow(object):
self.verticalLayout_2.addWidget(self.readrpmbbtn)
self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
self.verticalLayout_2.addItem(self.verticalSpacer)
self.gridLayout_4.addLayout(self.verticalLayout_2, 0, 0, 2, 1)
self.verticalLayout_3 = QVBoxLayout()
@ -265,10 +333,11 @@ class Ui_MainWindow(object):
self.verticalLayout_3.addWidget(self.writerpmbbtn)
self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
self.verticalLayout_3.addItem(self.verticalSpacer_2)
self.gridLayout_4.addLayout(self.verticalLayout_3, 0, 1, 2, 1)
self.verticalLayout_4 = QVBoxLayout()
@ -288,10 +357,11 @@ class Ui_MainWindow(object):
self.verticalLayout_4.addWidget(self.eraserpmbbtn)
self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.verticalSpacer_3 = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding)
self.verticalLayout_4.addItem(self.verticalSpacer_3)
self.gridLayout_4.addLayout(self.verticalLayout_4, 0, 2, 1, 1)
self.verticalLayout_5 = QVBoxLayout()
@ -306,6 +376,7 @@ class Ui_MainWindow(object):
self.verticalLayout_5.addWidget(self.unlockbutton)
self.gridLayout_4.addLayout(self.verticalLayout_5, 1, 2, 1, 1)
self.tabWidget.addTab(self.tab, "")
@ -314,13 +385,13 @@ class Ui_MainWindow(object):
self.gridLayout_2 = QGridLayout(self.keytab)
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.keytable = QTableWidget(self.keytab)
if self.keytable.columnCount() < 2:
if (self.keytable.columnCount() < 2):
self.keytable.setColumnCount(2)
__qtablewidgetitem = QTableWidgetItem()
self.keytable.setHorizontalHeaderItem(0, __qtablewidgetitem)
__qtablewidgetitem1 = QTableWidgetItem()
self.keytable.setHorizontalHeaderItem(1, __qtablewidgetitem1)
if self.keytable.rowCount() < 7:
if (self.keytable.rowCount() < 7):
self.keytable.setRowCount(7)
__qtablewidgetitem2 = QTableWidgetItem()
self.keytable.setVerticalHeaderItem(0, __qtablewidgetitem2)
@ -356,7 +427,7 @@ class Ui_MainWindow(object):
self.generatekeybtn = QPushButton(self.keytab)
self.generatekeybtn.setObjectName(u"generatekeybtn")
self.gridLayout_2.addWidget(self.generatekeybtn, 3, 0, 1, 1)
self.gridLayout_2.addWidget(self.generatekeybtn, 0, 0, 1, 1)
self.tabWidget.addTab(self.keytab, "")
self.debugtab = QWidget()
@ -372,11 +443,11 @@ class Ui_MainWindow(object):
self.logBox = QPlainTextEdit(self.debugtab)
self.logBox.setObjectName(u"logBox")
sizePolicy4 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
sizePolicy4.setHorizontalStretch(0)
sizePolicy4.setVerticalStretch(0)
sizePolicy4.setHeightForWidth(self.logBox.sizePolicy().hasHeightForWidth())
self.logBox.setSizePolicy(sizePolicy4)
sizePolicy5 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
sizePolicy5.setHorizontalStretch(0)
sizePolicy5.setVerticalStretch(0)
sizePolicy5.setHeightForWidth(self.logBox.sizePolicy().hasHeightForWidth())
self.logBox.setSizePolicy(sizePolicy5)
self.logBox.setMinimumSize(QSize(700, 0))
self.logBox.setStyleSheet(u"")
self.logBox.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
@ -385,6 +456,7 @@ class Ui_MainWindow(object):
self.gridLayout.addWidget(self.logBox, 0, 0, 1, 2)
self.gridLayout_3.addLayout(self.gridLayout, 0, 0, 1, 1)
self.tabWidget.addTab(self.debugtab, "")
@ -413,13 +485,14 @@ class Ui_MainWindow(object):
self.Main.addWidget(self.fullProgress)
self.gridLayout_8.addLayout(self.Main, 3, 0, 1, 1)
self.connectInfo = QWidget(self.centralwidget)
self.connectInfo.setObjectName(u"connectInfo")
self.connectInfo.setEnabled(True)
sizePolicy1.setHeightForWidth(self.connectInfo.sizePolicy().hasHeightForWidth())
self.connectInfo.setSizePolicy(sizePolicy1)
sizePolicy3.setHeightForWidth(self.connectInfo.sizePolicy().hasHeightForWidth())
self.connectInfo.setSizePolicy(sizePolicy3)
self.connectInfo.setMinimumSize(QSize(0, 0))
self.connectInfo.setMaximumSize(QSize(16777215, 0))
self.verticalLayout_6 = QVBoxLayout(self.connectInfo)
@ -430,11 +503,11 @@ class Ui_MainWindow(object):
self.horizontalLayout_4 = QHBoxLayout()
self.horizontalLayout_4.setSpacing(0)
self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
self.horizontalSpacer_2 = QSpacerItem(5, 20, QSizePolicy.Minimum, QSizePolicy.Minimum)
self.horizontalSpacer_2 = QSpacerItem(5, 20, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum)
self.horizontalLayout_4.addItem(self.horizontalSpacer_2)
self.horizontalSpacer_7 = QSpacerItem(9, 20, QSizePolicy.Fixed, QSizePolicy.Minimum)
self.horizontalSpacer_7 = QSpacerItem(9, 20, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
self.horizontalLayout_4.addItem(self.horizontalSpacer_7)
@ -445,81 +518,83 @@ class Ui_MainWindow(object):
self.initStepsImage.setFrameShape(QFrame.NoFrame)
self.initStepsImage.setPixmap(QPixmap(u"images/initsteps.png"))
self.initStepsImage.setScaledContents(True)
self.initStepsImage.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
self.initStepsImage.setAlignment(Qt.AlignHCenter|Qt.AlignTop)
self.initStepsImage.setWordWrap(False)
self.initStepsImage.setMargin(0)
self.horizontalLayout_4.addWidget(self.initStepsImage)
self.horizontalSpacer = QSpacerItem(5, 18, QSizePolicy.Minimum, QSizePolicy.Minimum)
self.horizontalSpacer = QSpacerItem(5, 18, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Minimum)
self.horizontalLayout_4.addItem(self.horizontalSpacer)
self.verticalLayout_6.addLayout(self.horizontalLayout_4)
self.horizontalLayout_3 = QHBoxLayout()
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
self.horizontalSpacer_6 = QSpacerItem(10, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalSpacer_6 = QSpacerItem(10, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_3.addItem(self.horizontalSpacer_6)
self.label_2 = QLabel(self.connectInfo)
self.label_2.setObjectName(u"label_2")
sizePolicy5 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
sizePolicy5.setHorizontalStretch(0)
sizePolicy5.setVerticalStretch(0)
sizePolicy5.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth())
self.label_2.setSizePolicy(sizePolicy5)
sizePolicy6 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Preferred)
sizePolicy6.setHorizontalStretch(0)
sizePolicy6.setVerticalStretch(0)
sizePolicy6.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth())
self.label_2.setSizePolicy(sizePolicy6)
self.label_2.setMinimumSize(QSize(195, 0))
self.label_2.setMaximumSize(QSize(195, 16777215))
self.label_2.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
self.label_2.setAlignment(Qt.AlignHCenter|Qt.AlignTop)
self.label_2.setWordWrap(True)
self.label_2.setMargin(5)
self.horizontalLayout_3.addWidget(self.label_2)
self.horizontalSpacer_3 = QSpacerItem(50, 0, QSizePolicy.Fixed, QSizePolicy.Minimum)
self.horizontalSpacer_3 = QSpacerItem(50, 0, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
self.horizontalLayout_3.addItem(self.horizontalSpacer_3)
self.label_3 = QLabel(self.connectInfo)
self.label_3.setObjectName(u"label_3")
sizePolicy5.setHeightForWidth(self.label_3.sizePolicy().hasHeightForWidth())
self.label_3.setSizePolicy(sizePolicy5)
sizePolicy6.setHeightForWidth(self.label_3.sizePolicy().hasHeightForWidth())
self.label_3.setSizePolicy(sizePolicy6)
self.label_3.setMinimumSize(QSize(195, 10))
self.label_3.setMaximumSize(QSize(195, 16777215))
self.label_3.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
self.label_3.setAlignment(Qt.AlignHCenter|Qt.AlignTop)
self.label_3.setWordWrap(True)
self.label_3.setMargin(5)
self.horizontalLayout_3.addWidget(self.label_3)
self.horizontalSpacer_4 = QSpacerItem(50, 0, QSizePolicy.Fixed, QSizePolicy.Minimum)
self.horizontalSpacer_4 = QSpacerItem(50, 0, QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Minimum)
self.horizontalLayout_3.addItem(self.horizontalSpacer_4)
self.label_4 = QLabel(self.connectInfo)
self.label_4.setObjectName(u"label_4")
sizePolicy5.setHeightForWidth(self.label_4.sizePolicy().hasHeightForWidth())
self.label_4.setSizePolicy(sizePolicy5)
sizePolicy6.setHeightForWidth(self.label_4.sizePolicy().hasHeightForWidth())
self.label_4.setSizePolicy(sizePolicy6)
self.label_4.setMinimumSize(QSize(195, 0))
self.label_4.setMaximumSize(QSize(195, 16777215))
self.label_4.setScaledContents(False)
self.label_4.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
self.label_4.setAlignment(Qt.AlignHCenter|Qt.AlignTop)
self.label_4.setWordWrap(True)
self.label_4.setMargin(5)
self.horizontalLayout_3.addWidget(self.label_4)
self.horizontalSpacer_5 = QSpacerItem(10, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalSpacer_5 = QSpacerItem(10, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_3.addItem(self.horizontalSpacer_5)
self.verticalLayout_6.addLayout(self.horizontalLayout_3)
self.horizontalLayout_5 = QHBoxLayout()
self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
self.horizontalSpacer_showdebug = QSpacerItem(50, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalSpacer_showdebug = QSpacerItem(50, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_5.addItem(self.horizontalSpacer_showdebug)
@ -528,8 +603,10 @@ class Ui_MainWindow(object):
self.horizontalLayout_5.addWidget(self.showdebugbtn)
self.verticalLayout_6.addLayout(self.horizontalLayout_5)
self.gridLayout_8.addWidget(self.connectInfo, 2, 0, 1, 1)
self.line_2 = QFrame(self.centralwidget)
@ -552,28 +629,30 @@ class Ui_MainWindow(object):
self.horizontalLayout.setContentsMargins(-1, -1, -1, 0)
self.logoPic = QLabel(self.centralwidget)
self.logoPic.setObjectName(u"logoPic")
sizePolicy6 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
sizePolicy6.setHorizontalStretch(0)
sizePolicy6.setVerticalStretch(0)
sizePolicy6.setHeightForWidth(self.logoPic.sizePolicy().hasHeightForWidth())
self.logoPic.setSizePolicy(sizePolicy6)
sizePolicy7 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
sizePolicy7.setHorizontalStretch(0)
sizePolicy7.setVerticalStretch(0)
sizePolicy7.setHeightForWidth(self.logoPic.sizePolicy().hasHeightForWidth())
self.logoPic.setSizePolicy(sizePolicy7)
self.logoPic.setMinimumSize(QSize(158, 158))
self.logoPic.setMaximumSize(QSize(158, 158))
self.logoPic.setPixmap(QPixmap(u"images/logo_256.png"))
self.logoPic.setScaledContents(True)
self.logoPic.setAlignment(Qt.AlignLeading | Qt.AlignLeft | Qt.AlignTop)
self.logoPic.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop)
self.horizontalLayout.addWidget(self.logoPic)
self.copyrightInfo = QLabel(self.centralwidget)
self.copyrightInfo.setObjectName(u"copyrightInfo")
sizePolicy6.setHeightForWidth(self.copyrightInfo.sizePolicy().hasHeightForWidth())
self.copyrightInfo.setSizePolicy(sizePolicy6)
sizePolicy7.setHeightForWidth(self.copyrightInfo.sizePolicy().hasHeightForWidth())
self.copyrightInfo.setSizePolicy(sizePolicy7)
self.horizontalLayout.addWidget(self.copyrightInfo)
self.verticalLayout.addLayout(self.horizontalLayout)
self.topInfo.addLayout(self.verticalLayout)
self.verticalLayout_7 = QVBoxLayout()
@ -581,19 +660,16 @@ class Ui_MainWindow(object):
self.verticalLayout_7.setObjectName(u"verticalLayout_7")
self.phoneInfoTextbox = QLabel(self.centralwidget)
self.phoneInfoTextbox.setObjectName(u"phoneInfoTextbox")
sizePolicy7 = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
sizePolicy7.setHorizontalStretch(0)
sizePolicy7.setVerticalStretch(0)
sizePolicy7.setHeightForWidth(self.phoneInfoTextbox.sizePolicy().hasHeightForWidth())
self.phoneInfoTextbox.setSizePolicy(sizePolicy7)
self.phoneInfoTextbox.setAlignment(Qt.AlignRight | Qt.AlignTop | Qt.AlignTrailing)
sizePolicy1.setHeightForWidth(self.phoneInfoTextbox.sizePolicy().hasHeightForWidth())
self.phoneInfoTextbox.setSizePolicy(sizePolicy1)
self.phoneInfoTextbox.setAlignment(Qt.AlignRight|Qt.AlignTop|Qt.AlignTrailing)
self.phoneInfoTextbox.setWordWrap(True)
self.verticalLayout_7.addWidget(self.phoneInfoTextbox)
self.phoneDebugInfoTextbox = QLabel(self.centralwidget)
self.phoneDebugInfoTextbox.setObjectName(u"phoneDebugInfoTextbox")
sizePolicy8 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
sizePolicy8 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
sizePolicy8.setHorizontalStretch(0)
sizePolicy8.setVerticalStretch(0)
sizePolicy8.setHeightForWidth(self.phoneDebugInfoTextbox.sizePolicy().hasHeightForWidth())
@ -602,7 +678,7 @@ class Ui_MainWindow(object):
self.phoneDebugInfoTextbox.setMaximumSize(QSize(16777215, 110))
self.phoneDebugInfoTextbox.setStyleSheet(u"color:#888;")
self.phoneDebugInfoTextbox.setTextFormat(Qt.PlainText)
self.phoneDebugInfoTextbox.setAlignment(Qt.AlignBottom | Qt.AlignRight | Qt.AlignTrailing)
self.phoneDebugInfoTextbox.setAlignment(Qt.AlignBottom|Qt.AlignRight|Qt.AlignTrailing)
self.verticalLayout_7.addWidget(self.phoneDebugInfoTextbox)
@ -611,36 +687,38 @@ class Ui_MainWindow(object):
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.horizontalLayout_2.setSizeConstraint(QLayout.SetDefaultConstraint)
self.horizontalLayout_2.setContentsMargins(-1, 0, -1, -1)
self.horizontalSpacer_8 = QSpacerItem(20, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalSpacer_8 = QSpacerItem(20, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum)
self.horizontalLayout_2.addItem(self.horizontalSpacer_8)
self.consettingsbtn = QPushButton(self.centralwidget)
self.consettingsbtn.setObjectName(u"consettingsbtn")
sizePolicy6.setHeightForWidth(self.consettingsbtn.sizePolicy().hasHeightForWidth())
self.consettingsbtn.setSizePolicy(sizePolicy6)
self.consettingsbtn.setMaximumSize(QSize(120, 16777215))
sizePolicy7.setHeightForWidth(self.consettingsbtn.sizePolicy().hasHeightForWidth())
self.consettingsbtn.setSizePolicy(sizePolicy7)
self.consettingsbtn.setMaximumSize(QSize(140, 16777215))
self.horizontalLayout_2.addWidget(self.consettingsbtn)
self.verticalLayout_7.addLayout(self.horizontalLayout_2)
self.verticalSpacer_5 = QSpacerItem(20, 2, QSizePolicy.Minimum, QSizePolicy.Maximum)
self.verticalSpacer_5 = QSpacerItem(20, 2, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Maximum)
self.verticalLayout_7.addItem(self.verticalSpacer_5)
self.topInfo.addLayout(self.verticalLayout_7)
self.widget_3 = QWidget(self.centralwidget)
self.widget_3.setObjectName(u"widget_3")
sizePolicy6.setHeightForWidth(self.widget_3.sizePolicy().hasHeightForWidth())
self.widget_3.setSizePolicy(sizePolicy6)
sizePolicy7.setHeightForWidth(self.widget_3.sizePolicy().hasHeightForWidth())
self.widget_3.setSizePolicy(sizePolicy7)
self.widget_3.setMinimumSize(QSize(90, 158))
self.pic = QLabel(self.widget_3)
self.pic.setObjectName(u"pic")
self.pic.setGeometry(QRect(0, 0, 90, 158))
sizePolicy6.setHeightForWidth(self.pic.sizePolicy().hasHeightForWidth())
self.pic.setSizePolicy(sizePolicy6)
sizePolicy7.setHeightForWidth(self.pic.sizePolicy().hasHeightForWidth())
self.pic.setSizePolicy(sizePolicy7)
self.pic.setMinimumSize(QSize(90, 158))
self.pic.setMaximumSize(QSize(90, 158))
self.pic.setPixmap(QPixmap(u"images/phone_notfound.png"))
@ -650,14 +728,15 @@ class Ui_MainWindow(object):
self.spinner_pic = QLabel(self.widget_3)
self.spinner_pic.setObjectName(u"spinner_pic")
self.spinner_pic.setGeometry(QRect(20, 55, 51, 51))
sizePolicy6.setHeightForWidth(self.spinner_pic.sizePolicy().hasHeightForWidth())
self.spinner_pic.setSizePolicy(sizePolicy6)
sizePolicy7.setHeightForWidth(self.spinner_pic.sizePolicy().hasHeightForWidth())
self.spinner_pic.setSizePolicy(sizePolicy7)
self.spinner_pic.setPixmap(QPixmap(u"images/phone_loading.png"))
self.spinner_pic.setScaledContents(True)
self.spinner_pic.setAlignment(Qt.AlignCenter)
self.topInfo.addWidget(self.widget_3)
self.gridLayout_8.addLayout(self.topInfo, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
@ -665,27 +744,27 @@ class Ui_MainWindow(object):
self.connectInfo.raise_()
self.menubar = QMenuBar(MainWindow)
self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 746, 22))
self.menubar.setGeometry(QRect(0, 0, 746, 24))
self.menuFile = QMenu(self.menubar)
self.menuFile.setObjectName(u"menuFile")
MainWindow.setMenuBar(self.menubar)
# if QT_CONFIG(shortcut)
#if QT_CONFIG(shortcut)
self.logoPic.setBuddy(self.logoPic)
# endif // QT_CONFIG(shortcut)
#endif // QT_CONFIG(shortcut)
self.menubar.addAction(self.menuFile.menuAction())
self.menuFile.addAction(self.action_Quit)
self.retranslateUi(MainWindow)
self.tabWidget.setCurrentIndex(5)
self.tabWidget.setCurrentIndex(0)
QMetaObject.connectSlotsByName(MainWindow)
# setupUi
def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MTKClient v2.0", None))
MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MTKClient v2.01", None))
self.actionRead_partition_s.setText(QCoreApplication.translate("MainWindow", u"Quit", None))
self.actionRead_full_flash.setText(QCoreApplication.translate("MainWindow", u"Read full flash", None))
self.actionRead_offset.setText(QCoreApplication.translate("MainWindow", u"Read at offset", None))
@ -704,23 +783,19 @@ class Ui_MainWindow(object):
self.actionUnlock_device.setText(QCoreApplication.translate("MainWindow", u"Unlock / Lock", None))
self.actionLock_device.setText(QCoreApplication.translate("MainWindow", u"Lock device", None))
self.action_Quit.setText(QCoreApplication.translate("MainWindow", u"&Quit", None))
self.readDumpGPTCheckbox.setText(QCoreApplication.translate("MainWindow", u"Dump GPT", None))
self.readtitle.setText(QCoreApplication.translate("MainWindow", u"Select partitions to read", None))
self.readpartitionsbtn.setText(QCoreApplication.translate("MainWindow", u"Read partition(s)", None))
self.readselectallcheckbox.setText(QCoreApplication.translate("MainWindow", u"Select all partitions", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.readtab),
QCoreApplication.translate("MainWindow", u"Read partition(s)", None))
self.readDumpGPTCheckbox.setText(QCoreApplication.translate("MainWindow", u"Dump GPT", None))
self.readtitle.setText("")
self.readpartitionsbtn.setText(QCoreApplication.translate("MainWindow", u"Read partition(s)", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.readtab), QCoreApplication.translate("MainWindow", u"Read partition(s)", None))
self.writetitle.setText(QCoreApplication.translate("MainWindow", u"Select partitions to write", None))
self.writepartbtn.setText(QCoreApplication.translate("MainWindow", u"Write partition(s)", None))
self.writeselectfromdir.setText(QCoreApplication.translate("MainWindow", u"Select from directory", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.writetab),
QCoreApplication.translate("MainWindow", u"Write partition(s)", None))
self.writepartbtn.setText(QCoreApplication.translate("MainWindow", u"Write partition(s)", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.writetab), QCoreApplication.translate("MainWindow", u"Write partition(s)", None))
self.erasetitle.setText(QCoreApplication.translate("MainWindow", u"Select partitions to erase", None))
self.eraseselectallpartitionscheckbox.setText(QCoreApplication.translate("MainWindow", u"Select all partitions", None))
self.erasepartitionsbtn.setText(QCoreApplication.translate("MainWindow", u"Erase partition(s)", None))
self.eraseselectallpartitionscheckbox.setText(
QCoreApplication.translate("MainWindow", u"Select all partitions", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.erasetab),
QCoreApplication.translate("MainWindow", u"Erase partition(s)", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.erasetab), QCoreApplication.translate("MainWindow", u"Erase partition(s)", None))
self.readflashbtn.setText(QCoreApplication.translate("MainWindow", u"Read flash", None))
self.readpreloaderbtn.setText(QCoreApplication.translate("MainWindow", u"Read preloader", None))
self.readboot2btn.setText(QCoreApplication.translate("MainWindow", u"Read boot2", None))
@ -734,49 +809,38 @@ class Ui_MainWindow(object):
self.eraserpmbbtn.setText(QCoreApplication.translate("MainWindow", u"Erase RPMB", None))
self.lockbutton.setText(QCoreApplication.translate("MainWindow", u"Lock bootloader", None))
self.unlockbutton.setText(QCoreApplication.translate("MainWindow", u"Unlock bootloader", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab),
QCoreApplication.translate("MainWindow", u"Flash Tools", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("MainWindow", u"Flash Tools", None))
___qtablewidgetitem = self.keytable.horizontalHeaderItem(0)
___qtablewidgetitem.setText(QCoreApplication.translate("MainWindow", u"Type", None))
___qtablewidgetitem.setText(QCoreApplication.translate("MainWindow", u"Type", None));
___qtablewidgetitem1 = self.keytable.horizontalHeaderItem(1)
___qtablewidgetitem1.setText(QCoreApplication.translate("MainWindow", u"Value", None))
___qtablewidgetitem1.setText(QCoreApplication.translate("MainWindow", u"Value", None));
___qtablewidgetitem2 = self.keytable.verticalHeaderItem(0)
___qtablewidgetitem2.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None))
___qtablewidgetitem2.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None));
___qtablewidgetitem3 = self.keytable.verticalHeaderItem(1)
___qtablewidgetitem3.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None))
___qtablewidgetitem3.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None));
___qtablewidgetitem4 = self.keytable.verticalHeaderItem(2)
___qtablewidgetitem4.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None))
___qtablewidgetitem4.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None));
___qtablewidgetitem5 = self.keytable.verticalHeaderItem(3)
___qtablewidgetitem5.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None))
___qtablewidgetitem5.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None));
___qtablewidgetitem6 = self.keytable.verticalHeaderItem(4)
___qtablewidgetitem6.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None))
___qtablewidgetitem6.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None));
___qtablewidgetitem7 = self.keytable.verticalHeaderItem(5)
___qtablewidgetitem7.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None))
___qtablewidgetitem7.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None));
___qtablewidgetitem8 = self.keytable.verticalHeaderItem(6)
___qtablewidgetitem8.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None))
___qtablewidgetitem8.setText(QCoreApplication.translate("MainWindow", u"Neue Zeile", None));
self.keystatuslabel.setText(QCoreApplication.translate("MainWindow", u"Ready.", None))
self.generatekeybtn.setText(QCoreApplication.translate("MainWindow", u"Generate Keys", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.keytab),
QCoreApplication.translate("MainWindow", u"Keys", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.debugtab),
QCoreApplication.translate("MainWindow", u"Debug Log", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.keytab), QCoreApplication.translate("MainWindow", u"Keys", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.debugtab), QCoreApplication.translate("MainWindow", u"Debug Log", None))
self.partProgressText.setText("")
self.fullProgressText.setText("")
self.initStepsImage.setText("")
self.label_2.setText(QCoreApplication.translate("MainWindow",
u"<html><head/><body><p><span style=\" font-weight:600;\">Step 1:</span></p><p>Power off the phone</p></body></html>",
None))
self.label_3.setText(QCoreApplication.translate("MainWindow",
u"<html><head/><body><p><span style=\" font-weight:600;\">Step 2:</span></p><p>Connect the USB cable, hold both volume buttons if needed</p></body></html>",
None))
self.label_4.setText(QCoreApplication.translate("MainWindow",
u"<html><head/><body><p>No connection? Try shorting the test point to ground</p></body></html>",
None))
self.label_2.setText(QCoreApplication.translate("MainWindow", u"<html><head/><body><p><span style=\" font-weight:600;\">Step 1:</span></p><p>Power off the phone</p></body></html>", None))
self.label_3.setText(QCoreApplication.translate("MainWindow", u"<html><head/><body><p><span style=\" font-weight:600;\">Step 2:</span></p><p>Connect the USB cable, hold both volume buttons if needed</p></body></html>", None))
self.label_4.setText(QCoreApplication.translate("MainWindow", u"<html><head/><body><p>No connection? Try shorting the test point to ground</p></body></html>", None))
self.showdebugbtn.setText(QCoreApplication.translate("MainWindow", u"Show Debug Log", None))
self.logoPic.setText("")
self.copyrightInfo.setText(QCoreApplication.translate("MainWindow",
u"<b>Made by:</b> Bjoern Kerler<br/><b>GUI by:</b> Geert-Jan Kreileman<br/><br/><b>Credits:</b><br/>kamakiri [xyzz]<br/>linecode exploit [chimera]<br/>Chaosmaster<br/>and all contributors</p>",
None))
self.copyrightInfo.setText(QCoreApplication.translate("MainWindow", u"<b>Made by:</b> Bjoern Kerler<br/><b>GUI by:</b> Geert-Jan Kreileman<br/><br/><b>Credits:</b><br/>kamakiri [xyzz]<br/>linecode exploit [chimera]<br/>Chaosmaster<br/>and all contributors</p>", None))
self.phoneInfoTextbox.setText(QCoreApplication.translate("MainWindow", u"No phone detected.", None))
self.phoneDebugInfoTextbox.setText("")
self.consettingsbtn.setText(QCoreApplication.translate("MainWindow", u"Connection settings", None))
@ -784,3 +848,4 @@ class Ui_MainWindow(object):
self.spinner_pic.setText("")
self.menuFile.setTitle(QCoreApplication.translate("MainWindow", u"&File", None))
# retranslateUi

555
mtkclient/gui/main_gui.ui Normal file → Executable file
View file

@ -29,7 +29,7 @@
<bool>false</bool>
</property>
<property name="windowTitle">
<string>MTKClient v2.0</string>
<string>MTKClient v2.01</string>
</property>
<property name="autoFillBackground">
<bool>false</bool>
@ -68,93 +68,118 @@
<bool>false</bool>
</property>
<property name="currentIndex">
<number>5</number>
<number>0</number>
</property>
<widget class="QWidget" name="readtab">
<attribute name="title">
<string>Read partition(s)</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="4" column="1">
<widget class="QCheckBox" name="readDumpGPTCheckbox">
<property name="text">
<string>Dump GPT</string>
</property>
</widget>
</item>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QLabel" name="readtitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Select partitions to read</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="readpartitionsbtn">
<property name="text">
<string>Read partition(s)</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QScrollArea" name="readpartitionList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>280</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>278</height>
</rect>
</property>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="readselectallcheckbox">
<property name="text">
<string>Select all partitions</string>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QCheckBox" name="readselectallcheckbox">
<property name="text">
<string>Select all partitions</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="readDumpGPTCheckbox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Dump GPT</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_14">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="readtitle">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="readpartitionsbtn">
<property name="text">
<string>Read partition(s)</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QScrollArea" name="readpartitionList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>280</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<height>311</height>
</rect>
</property>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
@ -164,78 +189,112 @@
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QLabel" name="writetitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Select partitions to write</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="1" column="0" rowspan="2">
<widget class="QScrollArea" name="writepartitionList">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>280</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>577</width>
<height>327</height>
</rect>
</property>
</widget>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="writepartbtn">
<property name="text">
<string>Write partition(s)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="writeselectfromdir">
<property name="text">
<string>Select from directory</string>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="writetitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Select partitions to write</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_10">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="writeselectfromdir">
<property name="text">
<string>Select from directory</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_11">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="writepartbtn">
<property name="text">
<string>Write partition(s)</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QScrollArea" name="writepartitionList">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>280</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<height>311</height>
</rect>
</property>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
@ -243,80 +302,114 @@
<attribute name="title">
<string>Erase partition(s)</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="2" column="0" rowspan="2">
<widget class="QScrollArea" name="erasepartitionList">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>280</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_3">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>598</width>
<height>298</height>
</rect>
</property>
</widget>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="erasetitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Select partitions to erase</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="erasepartitionsbtn">
<property name="text">
<string>Erase partition(s)</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="eraseselectallpartitionscheckbox">
<property name="text">
<string>Select all partitions</string>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<layout class="QVBoxLayout" name="verticalLayout_10">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="erasetitle">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Select partitions to erase</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_13">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="eraseselectallpartitionscheckbox">
<property name="text">
<string>Select all partitions</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_12">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="erasepartitionsbtn">
<property name="text">
<string>Erase partition(s)</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QScrollArea" name="erasepartitionList">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>280</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_3">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>700</width>
<height>311</height>
</rect>
</property>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
@ -558,7 +651,7 @@
</property>
</widget>
</item>
<item row="3" column="0">
<item row="0" column="0">
<widget class="QPushButton" name="generatekeybtn">
<property name="text">
<string>Generate Keys</string>
@ -1155,7 +1248,7 @@
</property>
<property name="maximumSize">
<size>
<width>120</width>
<width>140</width>
<height>16777215</height>
</size>
</property>
@ -1284,7 +1377,7 @@
<x>0</x>
<y>0</y>
<width>746</width>
<height>22</height>
<height>24</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">

View file

@ -6,7 +6,7 @@ import datetime as dt
from PySide6.QtCore import Signal, QThread, Slot, Property
from PySide6.QtWidgets import QFileDialog, QCheckBox
from traceback import print_exception
from mtkclient.config.payloads import pathconfig
from mtkclient.config.payloads import PathConfig
class TimeEstim:
@ -118,7 +118,7 @@ class asyncThread(QThread):
class FDialog:
def __init__(self, parent):
pc = pathconfig()
pc = PathConfig()
self.parent = parent
self.fdialog = QFileDialog(parent)
self.lastpath = os.path.dirname(os.path.dirname(pc.scriptpath))

View file

@ -1,7 +1,7 @@
from PySide6.QtCore import Slot, QObject, Signal
from PySide6.QtWidgets import QTableWidgetItem
from mtkclient.gui.toolkit import trap_exc_during_debug, asyncThread, FDialog
from mtkclient.Library.DA.mtk_da_handler import DA_handler
from mtkclient.Library.DA.mtk_da_handler import DaHandler
import os
import sys
import json
@ -13,7 +13,7 @@ class UnlockMenu(QObject):
enableButtonsSignal = Signal()
disableButtonsSignal = Signal()
def __init__(self, ui, parent, da_handler: DA_handler, sendToLog): # def __init__(self, *args, **kwargs):
def __init__(self, ui, parent, da_handler: DaHandler, sendToLog): # def __init__(self, *args, **kwargs):
super(UnlockMenu, self).__init__(parent)
self.parent = parent
self.ui = ui
@ -52,7 +52,7 @@ class generateKeysMenu(QObject):
enableButtonsSignal = Signal()
disableButtonsSignal = Signal()
def __init__(self, ui, parent, da_handler: DA_handler, sendToLog): # def __init__(self, *args, **kwargs):
def __init__(self, ui, parent, da_handler: DaHandler, sendToLog): # def __init__(self, *args, **kwargs):
super(generateKeysMenu, self).__init__(parent)
self.parent = parent
self.ui = ui

View file

@ -12,5 +12,6 @@ flake8
keystone-engine
capstone
unicorn
keystone
fusepy