Skip to content

Commit

Permalink
Add slot detection, minor v6 fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
bkerler committed Oct 19, 2024
1 parent 127c353 commit 501a23a
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 59 deletions.
Binary file removed examples/vbmeta.img.empty
Binary file not shown.
33 changes: 27 additions & 6 deletions mtkclient/Library/DA/daconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,15 +96,29 @@ def __repr__(self):


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()
Expand All @@ -113,6 +127,7 @@ def __init__(self, data):
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
Expand Down Expand Up @@ -222,11 +237,17 @@ def parse_da_loader(self, loader: str, dasetup: dict):
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:
Expand Down
6 changes: 6 additions & 0 deletions mtkclient/Library/DA/legacy/dalegacy_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,12 @@ def set_stage2_config(self, hwcode):
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))
Expand Down
84 changes: 63 additions & 21 deletions mtkclient/Library/DA/mtk_da_handler.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
import os
import time
import sys
Expand Down Expand Up @@ -184,27 +185,28 @@ def patch_vbmeta(self, vbmeta:bytes, vbmode:int):

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:
Expand All @@ -225,6 +227,36 @@ def da_gpt(self, directory: str):
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(",")
Expand Down Expand Up @@ -639,6 +671,16 @@ def da_efuse(self):
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)

Expand Down
4 changes: 2 additions & 2 deletions mtkclient/Library/DA/xflash/extension/xflash.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ def write_rpmb(self, filename=None, sector: int = None, sectors: int = None, dis
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

Expand Down Expand Up @@ -868,7 +868,7 @@ def generate_keys(self):
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:
Expand Down
24 changes: 17 additions & 7 deletions mtkclient/Library/DA/xml/extension/v6.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,11 @@ def patch_da2(self, _da2):
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
Expand All @@ -291,7 +296,7 @@ def patch_da2(self, _da2):
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
Expand Down Expand Up @@ -341,12 +346,11 @@ def custom_rpmb_write(self, sector, data: bytes):
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()
Expand Down Expand Up @@ -405,14 +409,20 @@ def custom_rpmb_init(self):
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()
Expand Down Expand Up @@ -450,7 +460,7 @@ def read_rpmb(self, filename=None, sector: int = None, sectors: int = None, disp
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)
Expand Down Expand Up @@ -507,7 +517,7 @@ def write_rpmb(self, filename=None, sector: int = None, sectors: int = None, dis
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

Expand Down
21 changes: 12 additions & 9 deletions mtkclient/Library/DA/xml/xml_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ def upload_da1(self):
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
Expand Down Expand Up @@ -453,9 +453,10 @@ def upload(self, result: DwnFile, data, display=True, raw=False):
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:
Expand All @@ -470,9 +471,10 @@ def upload(self, result: DwnFile, data, display=True, raw=False):
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()
Expand Down Expand Up @@ -597,8 +599,8 @@ def upload_da(self):
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
Expand Down Expand Up @@ -798,8 +800,9 @@ def get_sys_property(self, key: str = "DA.SLA", length: int = 0x200000):
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)
Expand Down
2 changes: 2 additions & 0 deletions mtkclient/Library/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ def shorts(self, shorts, big=False):

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]
Expand Down
Loading

0 comments on commit 501a23a

Please sign in to comment.