Compare commits

...

5 commits

Author SHA1 Message Date
hopez13
ee6c8b0ca8
Merge e3cd58a837 into 501a23a7fa 2024-10-20 17:07:47 +06:00
Bjoern Kerler
501a23a7fa
Add slot detection, minor v6 fixes
Some checks failed
Python application / Test (push) Has been cancelled
2024-10-19 16:09:04 +02:00
hopez13
e3cd58a837
Fix Preloader Handshake In Debug Mode 2024-09-16 21:06:29 +05:30
hopez13
35c5803ae0
Update Port.py 2024-09-15 01:52:34 +05:30
hopez13
2e65679cc8
Fix preloader handshake 2024-09-15 01:30:13 +05:30
12 changed files with 244 additions and 108 deletions

Binary file not shown.

View file

@ -309,7 +309,7 @@ class UsbClass(DeviceClass):
break
if self.device is None:
self.debug("Couldn't detect the device. Is it connected ?")
# self.debug("Couldn't detect the device. Is it connected ?")
return False
try:

View file

@ -96,15 +96,29 @@ class EntryRegion:
class DA:
def __init__(self, data):
v6=False
loader=None
magic=0
hw_code=0
hw_sub_code=0
hw_version=0
sw_version=0
pagesize=512
entry_region_index=1
entry_region_count=0
region = []
def __init__(self, data, old_ldr:bool=False, v6:bool=False):
self.loader = None
self.v6 = v6
sh = Structhelper(data)
self.magic = sh.short()
self.hw_code = sh.short()
self.hw_sub_code = sh.short()
self.hw_version = sh.short()
self.sw_version = sh.short()
self.reserved1 = sh.short()
if not old_ldr:
self.sw_version = sh.short()
self.reserved1 = sh.short()
self.pagesize = sh.short()
self.reserved3 = sh.short()
self.entry_region_index = sh.short()
@ -113,6 +127,7 @@ class DA:
for _ in range(self.entry_region_count):
entry_tmp = EntryRegion(sh.bytes(20))
self.region.append(entry_tmp)
self.old_ldr = old_ldr
def setfilename(self, loaderfilename: str):
self.loader = loaderfilename
@ -222,11 +237,17 @@ class DAconfig(metaclass=LogBase):
hdr = bootldr.read(0x68)
count_da = unpack("<I", bootldr.read(4))[0]
v6 = b"MTK_DA_v6" in hdr
old_ldr = False
bootldr.seek(0x6C+0xD8)
if bootldr.read(2) == b"\xDA\xDA":
offset=0xD8
old_ldr = True
else:
offset=0xDC
for i in range(0, count_da):
bootldr.seek(0x6C + (i * 0xDC))
da = DA(bootldr.read(0xDC))
bootldr.seek(0x6C + (i * offset))
da = DA(bootldr.read(offset),old_ldr, v6)
da.setfilename(loader)
da.v6 = v6
# if da.hw_code == 0x8127 and "5.1824" not in loader:
# continue
if da.hw_code not in dasetup:

View file

@ -290,6 +290,12 @@ class DALegacy(metaclass=LogBase):
return False
errorcode = int.from_bytes(buffer, 'big')
if errorcode == 0x0:
if hwcode == 0x6592:
tmp1=self.usbread(4)
tmp2=self.usbread(4)
tmp3=self.usbread(4)
tmp4 = self.usbread(4)
tmp5 = self.usbread(4)
return True
if errorcode != 0xBC3:
self.error(self.eh.status(errorcode))

View file

@ -1,3 +1,4 @@
import json
import os
import time
import sys
@ -184,27 +185,28 @@ class DaHandler(metaclass=LogBase):
def da_vbmeta(self, vbmode:int=3):
gpttable = self.mtk.daloader.get_partition_data(parttype="user")
for partition in ["vbmeta","vbmeta_a"]:
rpartition = None
for gptentry in gpttable:
if gptentry.name.lower() == partition.lower():
rpartition = gptentry
break
if rpartition is not None:
self.info(f'Dumping partition "{rpartition.name}"')
vbmeta=self.mtk.daloader.readflash(addr=rpartition.sector * self.config.pagesize,
length=rpartition.sectors * self.config.pagesize,
filename="", parttype="user")
if vbmeta!=b"":
self.info(f'Patching vbmeta"')
patched_vbmeta = self.patch_vbmeta(vbmeta,vbmode)
self.info(f'Writing partition "{rpartition.name}"')
if self.mtk.daloader.writeflash(addr=rpartition.sector * self.config.pagesize,
length=rpartition.sectors * self.config.pagesize,
wdata=patched_vbmeta, parttype="user"):
self.info("Successfully patched vbmeta :)")
else:
self.error("Error on patching vbmeta :(")
slot = self.get_current_slot()
partition="vbmeta"+slot
rpartition = None
for gptentry in gpttable:
if gptentry.name.lower() == partition.lower():
rpartition = gptentry
break
if rpartition is not None:
self.info(f'Dumping partition "{rpartition.name}"')
vbmeta=self.mtk.daloader.readflash(addr=rpartition.sector * self.config.pagesize,
length=rpartition.sectors * self.config.pagesize,
filename="", parttype="user")
if vbmeta!=b"":
self.info(f'Patching {partition}"')
patched_vbmeta = self.patch_vbmeta(vbmeta,vbmode)
self.info(f'Writing partition "{rpartition.name}"')
if self.mtk.daloader.writeflash(addr=rpartition.sector * self.config.pagesize,
length=rpartition.sectors * self.config.pagesize,
wdata=patched_vbmeta, parttype="user"):
self.info("Successfully patched vbmeta :)")
else:
self.error("Error on patching vbmeta :(")
def da_gpt(self, directory: str):
if directory is None:
@ -225,6 +227,36 @@ class DaHandler(metaclass=LogBase):
wf.write(data[self.mtk.daloader.daconfig.pagesize:])
print(f"Dumped Backup GPT to {sfilename}")
def da_read_partition(self, partitionname, parttype="user"):
rpartition = None
gpttable = self.mtk.daloader.get_partition_data(parttype=parttype)
for gptentry in gpttable:
if gptentry.name.lower() == partitionname.lower():
rpartition = gptentry
break
if rpartition is not None:
self.info(f'Dumping partition "{rpartition.name}"')
data=self.mtk.daloader.readflash(addr=rpartition.sector * self.config.pagesize,
length=rpartition.sectors * self.config.pagesize,
filename="", parttype=parttype)
return data
return None
def da_write_partition(self, partitionname, data:bytes=None, parttype="user"):
rpartition = None
gpttable = self.mtk.daloader.get_partition_data(parttype=parttype)
for gptentry in gpttable:
if gptentry.name.lower() == partitionname.lower():
rpartition = gptentry
break
if rpartition is not None:
self.info(f'Writing partition "{rpartition.name}"')
res=self.mtk.daloader.writeflash(addr=rpartition.sector * self.config.pagesize,
length=rpartition.sectors * self.config.pagesize,
filename="", parttype=parttype, wdata=data)
return res
return None
def da_read(self, partitionname, parttype, filename):
filenames = filename.split(",")
partitions = partitionname.split(",")
@ -639,6 +671,16 @@ class DaHandler(metaclass=LogBase):
data = bytearray(self.mtk.daloader.peek(addr=addr, length=4))
self.info(f"EFuse Idx {hex(idx)}: {data.hex()}")
def get_current_slot(self):
tmp = self.da_read_partition("misc")
if tmp == b"":
tmp = self.da_read_partition("para")
if tmp != b"":
slot = tmp[0x800:0x802].decode('utf-8')
else:
slot = ""
return slot
def da_brom(self, filename: str):
return self.mtk.daloader.dump_brom(filename)

View file

@ -572,7 +572,7 @@ class XFlashExt(metaclass=LogBase):
towrite -= sz
if display:
progressbar.show_progress("RPMB written", sectors * 0x100, sectors * 0x100, display)
self.info(f"Done reading writing {filename} to rpmb")
self.info(f"Done writing {filename} to rpmb")
return True
return False
@ -868,7 +868,7 @@ class XFlashExt(metaclass=LogBase):
else:
self.info("SEJ Mode: No meid found. Are you in brom mode ?")
if self.config.chipconfig.gcpu_base is not None:
if self.config.hwcode in [0x335, 0x8167, 0x8163, 0x8176]:
if self.config.hwcode in [0x335, 0x8167, 0x8168, 0x8163, 0x8176]:
self.info("Generating gcpu mtee2 key...")
mtee2 = hwc.aes_hwcrypt(btype="gcpu", mode="mtee")
if mtee2 is not None:

View file

@ -278,6 +278,11 @@ class XmlFlashExt(metaclass=LogBase):
da2patched[idx2:idx2 + 8] = b"\x00\x00\xA0\xE3\x1E\xFF\x2F\xE1"
self.info("Patched Vivo Remote SLA authentification.")
else:
idx=da2patched.find(b"DA.SLA\x00ENABLED")
if idx!=-1:
patch = b"DA.SLA\x00DISABLE"
da2patched[idx:idx+len(patch)] = patch
"""
n = "9BB734774443D77557A76E24B10733787750D90D09C869CD606D54F28978EA6220DC9948B3C9E89284F8551D6166F3754B6A3B890AC9CDA9E37DFAA0C1317E351CE5107C4273795949C6CCE638314AB1A345385D7642CB8D055A1F410C7D7E24A6F0A2AAB8184E773D21B3754A947541680F2C1A8D6BA5BEFD3B6E1FC28EC0B61D55B1454383F2C3E8BD27170A25978608F6788B90A2FC34F0CE35056BF7520795C8C60232CBBC0B0399367AF937869CA45CF737A8A066127893E93166C433298DD6FD009E6790E743B3392ACA8EA99F61DFC77BD99416DDA4B8A9D7E4DA24217427F3584119A4932016F1735CC63B12650FDDDA73C8FCFBC79E058F36219D3D"
pubkey = bytes.fromhex(n)
# Generic SLA patch, just replace the public key with a known one
@ -291,7 +296,7 @@ class XmlFlashExt(metaclass=LogBase):
if idx2 is not None:
da2patched[idx2 - 0x100:idx2] = pubkey
self.warning("SLA authentification not patched.")
"""
# open("da.patched.bin",
# "wb").write(da2patched)
return da2patched
@ -341,12 +346,11 @@ class XmlFlashExt(metaclass=LogBase):
if len(data) % 0x100 != 0:
self.error("Incorrect rpmb frame length. Aborting")
return False
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMRPMBW")
if self.xflash.emmc is not None:
ufs = False
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMRPMBW")
else:
ufs = True
if ufs:
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMURPMBW")
if self.xsend(xmlcmd):
result = self.xflash.get_response()
@ -405,14 +409,20 @@ class XmlFlashExt(metaclass=LogBase):
ufs = False
if self.xflash.emmc is None:
ufs = True
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMMMCINIT")
if ufs:
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMUFSINIT")
else:
xmlcmd = self.xflash.Cmd.create_cmd("CUSTOMMMCINIT")
if self.xsend(xmlcmd):
result = self.xflash.get_response()
if result == "OK":
derivedrpmb = self.xflash.get_response(raw=True)
if int.from_bytes(derivedrpmb[:4], 'little') != 0xff:
# rpmb frame
result = self.xflash.get_response(raw=True)
self.xflash.ack()
# hash
result = self.xflash.get_response(raw=True)
self.xflash.ack()
# CMD:END
result = self.xflash.get_response()
self.xflash.ack()
@ -450,7 +460,7 @@ class XmlFlashExt(metaclass=LogBase):
else:
ufs = True
if sectors == 0:
if not ufs:
if self.xflash.emmc is not None:
sectors = self.xflash.emmc.rpmb_size // 0x100
elif self.xflash.ufs.lu1_size != 0:
sectors = (512 * 256)
@ -507,7 +517,7 @@ class XmlFlashExt(metaclass=LogBase):
towrite -= 0x1
if display:
progressbar.show_progress("RPMB written", sectors * 0x100, sectors * 0x100, display)
self.info(f"Done reading writing {filename} to rpmb")
self.info(f"Done writing {filename} to rpmb")
return True
return False

View file

@ -288,7 +288,7 @@ class DAXML(metaclass=LogBase):
da2sig_len = self.daconfig.da_loader.region[2].m_sig_len
bootldr.seek(da2offset)
da2 = bootldr.read(self.daconfig.da_loader.region[2].m_len)
if self.patch or not self.config.target_config["sbc"]:
if self.patch or not self.config.target_config["sbc"] and not self.config.stock:
da1, da2 = self.patch_da(da1, da2)
self.patch = True
self.daconfig.da2 = da2
@ -453,9 +453,10 @@ class DAXML(metaclass=LogBase):
if display:
self.mtk.daloader.progress.clear()
resp = self.get_response()
byteswritten = 0
pos = 0
bytestowrite=length
if resp == "OK":
for pos in range(0, length, packet_length):
while bytestowrite>0:
self.ack_value(0)
resp = self.get_response()
if "OK" not in resp:
@ -470,9 +471,10 @@ class DAXML(metaclass=LogBase):
if "OK" not in resp:
self.error(f"Error on writing stage2 at pos {hex(pos)}")
return False
byteswritten += tmplen
pos += tmplen
if display:
self.mtk.daloader.progress.show_progress("Written", byteswritten, length, display)
self.mtk.daloader.progress.show_progress("Written", pos, length, display)
bytestowrite-=packet_length
if raw:
self.ack()
cmd, result = self.get_command_result()
@ -597,8 +599,8 @@ class DAXML(metaclass=LogBase):
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:
if self.carbonara is not None:
if not self.mtk.daloader.patch and not self.mtk.config.stock:
if self.carbonara is not None and self.mtk.config.target_config["sbc"]:
loaded = self.boot_to(da2offset, da2)
if loaded:
self.patch = True
@ -798,8 +800,9 @@ class DAXML(metaclass=LogBase):
return None
def change_usb_speed(self):
return self.send_command(self.Cmd.cmd_can_higher_usb_speed())
resp = self.send_command(self.Cmd.cmd_can_higher_usb_speed())
if not resp:
return False
def read_partition_table(self) -> tuple:
self.send_command(self.Cmd.cmd_read_partition_table(), noack=True)

View file

@ -125,63 +125,51 @@ class Port(metaclass=LogBase):
pass
return False
def run_handshake(self):
ep_out = self.cdc.EP_OUT.write
ep_in = self.cdc.EP_IN.read
maxinsize = self.cdc.EP_IN.wMaxPacketSize
i = 0
startcmd = b"\xa0\x0a\x50\x05"
length = len(startcmd)
# On preloader, send 0xa0 first
if self.cdc.pid!=0x3:
ep_out(startcmd[0:1])
try:
while i < length:
if ep_out(startcmd[i:i+1]):
if ep_in(maxinsize)[-1] == ~(startcmd[i]) & 0xFF:
i += 1
else:
i = 0
self.info("Device detected :)")
return True
except Exception as serr:
self.debug(str(serr))
time.sleep(0.005)
return False
# def run_handshake(self):
def handshake(self, maxtries=None, loop=0):
counter = 0
while not self.cdc.connected:
try:
if maxtries is not None and counter == maxtries:
break
counter += 1
if self.cdc.connect() and self.run_handshake():
return True
else:
if loop == 5:
sys.stdout.write('\n')
self.info("Hint:\n\nPower off the phone before connecting.\n" +
"For brom mode, press and hold vol up, vol dwn, or all hw buttons and " +
"connect usb.\n" +
"For preloader mode, don't press any hw button and connect usb.\n"
"If it is already connected and on, hold power for 10 seconds to reset.\n")
sys.stdout.write('\n')
if loop >= 10:
sys.stdout.write('.')
if loop >= 20:
sys.stdout.write('\n')
loop = 0
loop += 1
time.sleep(0.3)
sys.stdout.flush()
self.cdc.connect()
ep_out = self.cdc.EP_OUT.write
ep_in = self.cdc.EP_IN.read
maxinsize = self.cdc.EP_IN.wMaxPacketSize
i = 0
startcmd = b"\xa0\x0a\x50\x05"
length = len(startcmd)
# On preloader, send 0xa0 first
if self.cdc.pid!=0x3:
ep_out(startcmd[0:1])
try:
while i < length:
if ep_out(startcmd[i:i+1]):
if ep_in(maxinsize)[-1] == ~(startcmd[i]) & 0xFF:
i += 1
else:
i = 0
self.info("Device detected :)")
return True
except Exception as serr:
self.debug(str(serr))
time.sleep(0.005)
return False
except Exception as serr:
if "access denied" in str(serr):
self.warning(str(serr))
self.debug(str(serr))
# self.debug(str(serr))
pass
return False

View file

@ -160,9 +160,6 @@ class Preloader(metaclass=LogBase):
else:
res = self.mtk.port.handshake(maxtries=maxtries)
if not res:
if display:
self.error("Status: Handshake failed, retrying...")
self.config.set_gui_status(self.config.tr("Status: Handshake failed, retrying..."))
self.mtk.port.close()
tries += 1
if tries == 1000:

View file

@ -275,6 +275,8 @@ class Structhelper:
def bytes(self, rlen=1):
dat = self.data[self.pos:self.pos + rlen]
if dat==b"":
return b""
self.pos += rlen
if rlen == 1:
return dat[0]

View file

@ -5,6 +5,10 @@ class DAmodes:
class Efuse:
efuses = []
internal_fuses = []
external_fuses = []
def __init__(self, base, hwcode):
if hwcode in [0x6570, 0x6580, 0x321, 0x335]:
self.efuses = [base + 0x20, base + 0x30, base + 0x38, base + 0x40, base + 0x44,
@ -222,13 +226,43 @@ class Efuse:
class Chipconfig:
var1 = None
watchdog = None
uart = None
brom_payload_addr = None
da_payload_addr = None
pl_payload_addr = None
cqdma_base = None
ap_dma_mem = None
sej_base = None
dxcc_base = None
name = ""
description = ""
dacode = 0
blacklist = None
blacklist_count = None
send_ptr = None
ctrl_buffer = None
cmd_handler = None
brom_register_access = None
meid_addr = None
socid_addr = None
prov_addr = None
gcpu_base = None
dacode = None
damode = None
loader = None
misc_lock = None
efuse_addr = None
has64bit = False
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,
efuse_addr=None):
efuse_addr=None, has64bit=False):
self.var1 = var1
self.watchdog = watchdog
self.uart = uart
@ -257,6 +291,7 @@ class Chipconfig:
self.loader = loader
self.misc_lock = misc_lock
self.efuse_addr = efuse_addr
self.has64bit = has64bit
# Credits to cyrozap and Chaosmaster for some values
"""
@ -539,8 +574,8 @@ hwconfig = {
ap_dma_mem=0xC100119C,
# blacklist
damode=DAmodes.LEGACY,
dacode=0x6572,
name="MT6575/77"),
dacode=0x6575,
name="MT6575/MT6577/MT8317"),
0x6577: Chipconfig( # var1
watchdog=0xC0000000,
uart=0xC1009000,
@ -1412,10 +1447,12 @@ hwconfig = {
# brom_register_access=(0xeba4, 0xec5c),
meid_addr=0x1008EC,
socid_addr=0x100934,
efuse_addr=0x11EE0000,
# prov_addr=0x1066C0,
damode=DAmodes.XML,
dacode=0x907,
name="MT6983",
has64bit=True,
description="Dimensity 9000/9000+"
# loader="mt6983_payload.bin"
),
@ -1468,6 +1505,7 @@ hwconfig = {
# brom_register_access=(0xeba4, 0xec5c),
meid_addr=0x1008EC,
socid_addr=0x100934,
efuse_addr=0x11F10000,
# prov_addr=0x1066C0,
damode=DAmodes.XML,
dacode=0x1172,
@ -1475,6 +1513,33 @@ hwconfig = {
description="Dimensity 8200"
# loader="mt6893_payload.bin"
),
0x1203: Chipconfig(
var1=0xA,
watchdog=0x1c007000,
uart=0x11002000,
brom_payload_addr=0x100A00,
da_payload_addr=0x201000,
pl_payload_addr=0x40200000,
gcpu_base=0x1000D000,
dxcc_base=0x10403000,
sej_base=0x1040E000,
# cqdma_base=0x10212000,
# ap_dma_mem=0x11300800 + 0x1a0,
# blacklist=[(0x102848, 0x0), (0x00106B60, 0x0)],
# blacklist_count=0x0000000A,
# send_ptr=(0x102888, 0xE79C),
# ctrl_buffer=0x00102A9C,
# cmd_handler=0x0000F569,
# brom_register_access=(0xeba4, 0xec5c),
# meid_addr=0x1008EC,
socid_addr=0x20E7090,
# prov_addr=0x1066C0,
damode=DAmodes.XML,
dacode=0x1203,
name="MT6897",
description="Dimensity 8300 Ultra"
# loader="mt6897_payload.bin"
),
# MT6789 Oppo Realme 10 / Gigaset GX4
0x1208: Chipconfig(
var1=0xA,
@ -1500,7 +1565,7 @@ hwconfig = {
efuse_addr=0x11C10000,
damode=DAmodes.XML,
dacode=0x1208,
name="MT6789",
name="MT6789/MT8781V",
description="MTK Helio G99"
# loader="mt6789_payload.bin"
),
@ -1511,10 +1576,10 @@ hwconfig = {
brom_payload_addr=0x100A00,
da_payload_addr=0x2001000,
pl_payload_addr=0x40200000,
# gcpu_base=0x10050000,
dxcc_base=0x10210000,
# sej_base=0x1000a000,
cqdma_base=0x10212000,
gcpu_base=0x1000D000,
dxcc_base=0x1C807000,
sej_base=0x1C009000,
# cqdma_base=0x10212000,
# ap_dma_mem=0x11300800 + 0x1a0,
# blacklist=[(0x102d5c, 0x0)],
# blacklist_count=0x0000000A,
@ -1525,23 +1590,24 @@ hwconfig = {
# meid_addr=0x1008EC,
# socid_addr=0x100934,
# prov_addr=0x1066C0,
# efuse_addr=0x11C10000,
efuse_addr=0x11E30000,
damode=DAmodes.XML,
dacode=0x1229,
has64bit=True,
name="MT6886",
description="Dimensity 7200 Ultra"
# loader="mt7200_payload.bin"
),
0x1296: Chipconfig(
var1=0xA,
watchdog=0x10007000,
uart=0x11002000,
watchdog=0x1C007000,
uart=0x1C011000,
brom_payload_addr=0x100A00,
da_payload_addr=0x201000,
pl_payload_addr=0x40200000,
# gcpu_base=0x10050000,
dxcc_base=0x10210000,
sej_base=0x1000a000,
dxcc_base=0x1C807000,
sej_base=0x1C009000,
# cqdma_base=0x10212000,
# ap_dma_mem=0x11300800 + 0x1a0,
# blacklist=[(0x102d5c, 0x0)],
@ -1553,9 +1619,10 @@ hwconfig = {
meid_addr=0x1008EC,
socid_addr=0x100934,
# prov_addr=0x1066C0,
# efuse_addr=0x11C10000,
efuse_addr=0x11E80000,
damode=DAmodes.XML,
dacode=0x1296,
has64bit=True,
name="MT6985",
description="Dimensity 9200/9200+"
# loader="mt6985_payload.bin"