mirror of
https://github.com/bkerler/mtkclient.git
synced 2024-11-14 03:04:54 -05:00
MT6781 fixes, read speed improvements, dxcc improvements, minor bug fixes
This commit is contained in:
parent
c5bc57d2b2
commit
1ffb152766
22 changed files with 397 additions and 173 deletions
122
README.md
122
README.md
|
@ -171,12 +171,17 @@ sudo reboot
|
|||
### Using MTKTools via the graphical user interface:
|
||||
For the 'basics' you can use the GUI interface. This supports dumping partitions or the full flash for now. Run the following command:
|
||||
```
|
||||
python mtk_gui
|
||||
python mtk_gui.py
|
||||
```
|
||||
|
||||
### Using stock mtk functionality without exploits :
|
||||
```
|
||||
python mtk.py --stock
|
||||
```
|
||||
|
||||
### Run multiple commands
|
||||
```bash
|
||||
python mtk script run.example
|
||||
python mtk.py script run.example
|
||||
```
|
||||
See the file "[run.example](https://github.com/bkerler/mtkclient/blob/main/run.example)" on how to structure the script file
|
||||
|
||||
|
@ -184,12 +189,12 @@ See the file "[run.example](https://github.com/bkerler/mtkclient/blob/main/run.e
|
|||
|
||||
1. Dump boot and vbmeta
|
||||
```
|
||||
python mtk r boot,vbmeta boot.img,vbmeta.img
|
||||
python mtk.py r boot,vbmeta boot.img,vbmeta.img
|
||||
```
|
||||
|
||||
2. Reboot the phone
|
||||
```
|
||||
python mtk reset
|
||||
python mtk.py reset
|
||||
```
|
||||
|
||||
3. Download patched magisk for mtk:
|
||||
|
@ -219,12 +224,12 @@ mv [displayed magisk patched boot filename here] boot.patched
|
|||
|
||||
8. Flash magisk-patched boot and empty vbmeta
|
||||
```
|
||||
python mtk w boot,vbmeta boot.patched,vbmeta.img.empty
|
||||
python mtk.py w boot,vbmeta boot.patched,vbmeta.img.empty
|
||||
```
|
||||
|
||||
9. Reboot the phone
|
||||
```
|
||||
python mtk reset
|
||||
python mtk.py reset
|
||||
```
|
||||
|
||||
10. Disconnect usb cable and enjoy your rooted phone :)
|
||||
|
@ -235,7 +240,7 @@ python mtk reset
|
|||
Example:
|
||||
|
||||
```
|
||||
python mtk payload --metamode FASTBOOT
|
||||
python mtk.py payload --metamode FASTBOOT
|
||||
```
|
||||
|
||||
### Read efuses
|
||||
|
@ -243,28 +248,28 @@ python mtk payload --metamode FASTBOOT
|
|||
Example:
|
||||
|
||||
```
|
||||
python mtk da efuse
|
||||
python mtk.py da efuse
|
||||
```
|
||||
|
||||
### Unlock bootloader
|
||||
|
||||
1. Erase metadata and userdata (and md_udc if existing):
|
||||
```
|
||||
python mtk e metadata,userdata,md_udc
|
||||
python mtk.py e metadata,userdata,md_udc
|
||||
```
|
||||
|
||||
2. Unlock bootloader:
|
||||
```
|
||||
python mtk da seccfg unlock
|
||||
python mtk.py da seccfg unlock
|
||||
```
|
||||
for relocking use:
|
||||
```
|
||||
python mtk da seccfg lock
|
||||
python mtk.py da seccfg lock
|
||||
```
|
||||
|
||||
3. Reboot the phone:
|
||||
```
|
||||
python mtk reset
|
||||
python mtk.py reset
|
||||
```
|
||||
|
||||
and disconnect usb cable to let the phone reboot.
|
||||
|
@ -279,57 +284,57 @@ then the device should boot within 5 seconds.
|
|||
Dump boot partition to filename boot.bin via preloader
|
||||
|
||||
```
|
||||
python mtk r boot boot.bin
|
||||
python mtk.py r boot boot.bin
|
||||
```
|
||||
|
||||
Dump boot partition to filename boot.bin via bootrom
|
||||
|
||||
```
|
||||
python mtk r boot boot.bin [--preloader=Loader/Preloader/your_device_preloader.bin]
|
||||
python mtk.py r boot boot.bin [--preloader=Loader/Preloader/your_device_preloader.bin]
|
||||
```
|
||||
|
||||
|
||||
Dump preloader partition to filename preloader.bin via bootrom
|
||||
|
||||
```
|
||||
python mtk r preloader preloader.bin --parttype=boot1 [--preloader=Loader/Preloader/your_device_preloader.bin]
|
||||
python mtk.py r preloader preloader.bin --parttype=boot1 [--preloader=Loader/Preloader/your_device_preloader.bin]
|
||||
```
|
||||
|
||||
Read full flash to filename flash.bin (use --preloader for brom)
|
||||
|
||||
```
|
||||
python mtk rf flash.bin
|
||||
python mtk.py rf flash.bin
|
||||
```
|
||||
|
||||
Read full flash to filename flash.bin (use --preloader for brom) for IoT devices (MT6261/MT2301):
|
||||
|
||||
```
|
||||
python mtk rf flash.bin --iot
|
||||
python mtk.py rf flash.bin --iot
|
||||
```
|
||||
|
||||
Read flash offset 0x128000 with length 0x200000 to filename flash.bin (use --preloader for brom)
|
||||
|
||||
```
|
||||
python mtk ro 0x128000 0x200000 flash.bin
|
||||
python mtk.py ro 0x128000 0x200000 flash.bin
|
||||
```
|
||||
|
||||
Dump all partitions to directory "out". (use --preloader for brom)
|
||||
|
||||
```
|
||||
python mtk rl out
|
||||
python mtk.py rl out
|
||||
```
|
||||
|
||||
Show gpt (use --preloader for brom)
|
||||
|
||||
```
|
||||
python mtk printgpt
|
||||
python mtk.py printgpt
|
||||
```
|
||||
|
||||
|
||||
Mount the flash as a filesystem
|
||||
|
||||
```
|
||||
python mtk fs /mnt/mtk
|
||||
python mtk.py fs /mnt/mtk
|
||||
```
|
||||
|
||||
### Write flash
|
||||
|
@ -338,83 +343,83 @@ python mtk fs /mnt/mtk
|
|||
Write filename boot.bin to boot partition
|
||||
|
||||
```
|
||||
python mtk w boot boot.bin
|
||||
python mtk.py w boot boot.bin
|
||||
```
|
||||
|
||||
Write filename flash.bin as full flash (currently only works in da mode)
|
||||
|
||||
```
|
||||
python mtk wf flash.bin
|
||||
python mtk.py wf flash.bin
|
||||
```
|
||||
|
||||
Write all files in directory "out" to the flash partitions
|
||||
|
||||
```
|
||||
python mtk wl out
|
||||
python mtk.py wl out
|
||||
```
|
||||
|
||||
write file flash.bin to flash offset 0x128000 with length 0x200000 (use --preloader for brom)
|
||||
|
||||
```
|
||||
python mtk wo 0x128000 0x200000 flash.bin
|
||||
python mtk.py wo 0x128000 0x200000 flash.bin
|
||||
```
|
||||
|
||||
### Erase flash
|
||||
|
||||
Erase boot partition
|
||||
```
|
||||
python mtk e boot
|
||||
python mtk.py e boot
|
||||
```
|
||||
|
||||
Erase boot sectors
|
||||
```
|
||||
python mtk es boot [sector count]
|
||||
python mtk.py es boot [sector count]
|
||||
```
|
||||
|
||||
### DA commands:
|
||||
|
||||
Peek memory
|
||||
```
|
||||
python mtk da peek [addr in hex] [length in hex] [optional: -filename filename.bin for reading to file]
|
||||
python mtk.py da peek [addr in hex] [length in hex] [optional: -filename filename.bin for reading to file]
|
||||
```
|
||||
|
||||
Poke memory
|
||||
```
|
||||
python mtk da poke [addr in hex] [data as hexstring or -filename for reading from file]
|
||||
python mtk.py da poke [addr in hex] [data as hexstring or -filename for reading from file]
|
||||
```
|
||||
|
||||
Read rpmb (Only xflash for now)
|
||||
```
|
||||
python mtk da rpmb r [will read to rpmb.bin]
|
||||
python mtk.py da rpmb r [will read to rpmb.bin]
|
||||
```
|
||||
|
||||
Write rpmb [Currently broken, xflash only]
|
||||
```
|
||||
python mtk da rpmb w filename
|
||||
python mtk.py da rpmb w filename
|
||||
```
|
||||
|
||||
Generate and display rpmb1-3 key
|
||||
```
|
||||
python mtk da generatekeys
|
||||
python mtk.py da generatekeys
|
||||
```
|
||||
|
||||
Unlock / Lock bootloader
|
||||
```
|
||||
python mtk da seccfg [lock or unlock]
|
||||
python mtk.py da seccfg [lock or unlock]
|
||||
```
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------
|
||||
|
||||
### Bypass SLA, DAA and SBC (using generic_patcher_payload)
|
||||
``
|
||||
python mtk payload
|
||||
python mtk.py payload
|
||||
``
|
||||
If you want to use SP Flash tool afterwards, make sure you select "UART" in the settings, not "USB".
|
||||
|
||||
### Dump preloader
|
||||
- Device has to be in bootrom mode and preloader has to be intact on the device
|
||||
```
|
||||
python mtk dumppreloader [--ptype=["amonet","kamakiri","kamakiri2","hashimoto"]] [--filename=preloader.bin]
|
||||
python mtk.py dumppreloader [--ptype=["amonet","kamakiri","kamakiri2","hashimoto"]] [--filename=preloader.bin]
|
||||
```
|
||||
|
||||
### Dump brom
|
||||
|
@ -425,12 +430,12 @@ python mtk dumppreloader [--ptype=["amonet","kamakiri","kamakiri2","hashimoto"]]
|
|||
and "hashimoto" (via cqdma)
|
||||
|
||||
```
|
||||
python mtk dumpbrom --ptype=["amonet","kamakiri","hashimoto"] [--filename=brom.bin]
|
||||
python mtk.py dumpbrom --ptype=["amonet","kamakiri","hashimoto"] [--filename=brom.bin]
|
||||
```
|
||||
|
||||
For to dump unknown bootroms, use brute option :
|
||||
```
|
||||
python mtk brute
|
||||
python mtk.py brute
|
||||
```
|
||||
If it's successful, please add an issue over here and append the bootrom in order to add full support.
|
||||
|
||||
|
@ -439,39 +444,39 @@ If it's successful, please add an issue over here and append the bootrom in orde
|
|||
### Crash da in order to enter brom
|
||||
|
||||
```
|
||||
python mtk crash [--vid=vid] [--pid=pid] [--interface=interface]
|
||||
python mtk.py crash [--vid=vid] [--pid=pid] [--interface=interface]
|
||||
```
|
||||
|
||||
### Read memory using patched preloader
|
||||
- Boot in Brom or crash to Brom
|
||||
```
|
||||
python mtk peek [addr] [length] --preloader=patched_preloader.bin
|
||||
python mtk.py peek [addr] [length] --preloader=patched_preloader.bin
|
||||
```
|
||||
|
||||
### Run custom payload
|
||||
|
||||
```
|
||||
python mtk payload --payload=payload.bin [--var1=var1] [--wdt=wdt] [--uartaddr=addr] [--da_addr=addr] [--brom_addr=addr]
|
||||
python mtk.py payload --payload=payload.bin [--var1=var1] [--wdt=wdt] [--uartaddr=addr] [--da_addr=addr] [--brom_addr=addr]
|
||||
```
|
||||
|
||||
---------------------------------------------------------------------------------------------------------------
|
||||
## Stage2 usage
|
||||
### Run python mtk stage (brom) or mtk plstage (preloader)
|
||||
### Run python mtk.py stage (brom) or mtk plstage (preloader)
|
||||
|
||||
#### Run stage2 in bootrom
|
||||
``
|
||||
python mtk stage
|
||||
python mtk.py stage
|
||||
``
|
||||
|
||||
#### Run stage2 in preloader
|
||||
``
|
||||
python mtk plstage
|
||||
python mtk.py plstage
|
||||
``
|
||||
|
||||
#### Run stage2 plstage in bootrom
|
||||
- Boot in Brom or crash to Brom
|
||||
```
|
||||
python mtk plstage --preloader=preloader.bin
|
||||
python mtk.py plstage --preloader=preloader.bin
|
||||
```
|
||||
|
||||
### Use stage2 tool
|
||||
|
@ -479,42 +484,42 @@ python mtk plstage --preloader=preloader.bin
|
|||
|
||||
### Leave stage2 and reboot
|
||||
``
|
||||
python stage2 reboot
|
||||
python stage2.py reboot
|
||||
``
|
||||
|
||||
### Read rpmb in stage2 mode
|
||||
``
|
||||
python stage2 rpmb
|
||||
python stage2.py rpmb
|
||||
``
|
||||
|
||||
### Read preloader in stage2 mode
|
||||
``
|
||||
python stage2 preloader
|
||||
python stage2.py preloader
|
||||
``
|
||||
|
||||
### Read memory as hex data in stage2 mode
|
||||
``
|
||||
python stage2 memread [start addr] [length]
|
||||
python stage2.py memread [start addr] [length]
|
||||
``
|
||||
|
||||
### Read memory to file in stage2 mode
|
||||
``
|
||||
python stage2 memread [start addr] [length] --filename filename.bin
|
||||
python stage2.py memread [start addr] [length] --filename filename.bin
|
||||
``
|
||||
|
||||
### Write hex data to memory in stage2 mode
|
||||
``
|
||||
python stage2 memwrite [start addr] --data [data as hexstring]
|
||||
python stage2.py memwrite [start addr] --data [data as hexstring]
|
||||
``
|
||||
|
||||
### Write memory from file in stage2 mode
|
||||
``
|
||||
python stage2 memwrite [start addr] --filename filename.bin
|
||||
python stage2.py memwrite [start addr] --filename filename.bin
|
||||
``
|
||||
|
||||
### Extract keys
|
||||
``
|
||||
python stage2 keys --mode [sej, dxcc]
|
||||
python stage2.py keys --mode [sej, dxcc]
|
||||
``
|
||||
For dxcc, you need to use plstage instead of stage
|
||||
|
||||
|
@ -529,16 +534,3 @@ For dxcc, you need to use plstage instead of stage
|
|||
### Chip details / configs
|
||||
- Go to config/brom_config.py
|
||||
- Unknown usb vid/pids for autodetection go to config/usb_ids.py
|
||||
|
||||
## Learning Resources
|
||||
[MTK Preloader](https://o0xmuhe.github.io/2022/03/05/MTK-Preloader-踩坑/)
|
||||
|
||||
[MOSEC-2022](https://o0xmuhe.github.io/2022/11/23/议题解读-MOSEC2022-MediAttack-break-the-boot-chain-of-MediaTek-SoC/)
|
||||
|
||||
[Dissecting MTK BROM Exploit](https://tinyhack.com/2021/01/31/dissecting-a-mediatek-bootrom-exploit/)
|
||||
|
||||
[Dumping Exynos BROM](https://fredericb.info/2020/06/exynos8890-bootrom-dump-dump-exynos-8890-bootrom-from-samsung-galaxy-s7.html)
|
||||
|
||||
[Rev Exynos BROM USB STACK ](https://fredericb.info/2020/06/reverse-engineer-usb-stack-of-exynos-bootrom.html#reverse-engineer-usb-stack-of-exynos-bootrom)
|
||||
|
||||
[Buffer Overflow In Huawei BROM USB STACK](https://labs.taszk.io/blog/post/bootrom_usb/)
|
||||
|
|
|
@ -92,9 +92,15 @@ def main():
|
|||
with open(loader, "rb") as rf:
|
||||
rf.seek(mbuf)
|
||||
data = rf.read(m_len)
|
||||
test = data.find(b"\x01\x01\x54\xE3\x01\x14\xA0\xE3")
|
||||
if test != -1:
|
||||
print("V6 Device is patched against carbonara :(")
|
||||
test=data.find(b"\x08\x00\xa8\x52\xff\x02\x08\xeb")
|
||||
if test != -1:
|
||||
print("Device is patched against carbonara :(")
|
||||
print("V6 Device is patched against carbonara :(")
|
||||
test2=data.find(b"\x06\x9B\x4F\xF0\x80\x40\x02\xA9")
|
||||
if test2 != -1:
|
||||
print("V5 Device is patched against carbonara :(")
|
||||
hashidx = data.find(int.to_bytes(0xC0070004, 4, 'little'))
|
||||
if hashidx != -1:
|
||||
print("Hash check found.")
|
||||
|
@ -111,7 +117,11 @@ def main():
|
|||
if hashidx is not None:
|
||||
print("Hash check 4 (V6) found.")
|
||||
else:
|
||||
print("HASH ERROR !!!!")
|
||||
hashidx = find_binary(data,b"\x01\x10\x81\xE2\x00\x00\x51\xE1")
|
||||
if hashidx is not None:
|
||||
print("Hash check 5 (V6) found.")
|
||||
else:
|
||||
print("HASH ERROR !!!!")
|
||||
|
||||
fname = os.path.join("loaders",
|
||||
hex(da[0]["hw_code"])[2:] + "_" + hex(startaddr)[2:] + os.path.basename(
|
||||
|
|
13
learning_resources.md
Normal file
13
learning_resources.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
## Learning Resources
|
||||
[MTK Preloader](https://o0xmuhe.github.io/2022/03/05/MTK-Preloader-踩坑/)
|
||||
|
||||
[MOSEC-2022](https://o0xmuhe.github.io/2022/11/23/议题解读-MOSEC2022-MediAttack-break-the-boot-chain-of-MediaTek-SoC/)
|
||||
|
||||
[Dissecting MTK BROM Exploit](https://tinyhack.com/2021/01/31/dissecting-a-mediatek-bootrom-exploit/)
|
||||
|
||||
[Dumping Exynos BROM](https://fredericb.info/2020/06/exynos8890-bootrom-dump-dump-exynos-8890-bootrom-from-samsung-galaxy-s7.html)
|
||||
|
||||
[Rev Exynos BROM USB STACK ](https://fredericb.info/2020/06/reverse-engineer-usb-stack-of-exynos-bootrom.html#reverse-engineer-usb-stack-of-exynos-bootrom)
|
||||
|
||||
[Buffer Overflow In Huawei BROM USB STACK](https://labs.taszk.io/blog/post/bootrom_usb/)
|
||||
|
20
mtk.py
20
mtk.py
|
@ -942,6 +942,26 @@ if __name__ == '__main__':
|
|||
da_dump.add_argument('--noreconnect', action="store_true", help='Disable reconnect')
|
||||
da_rpmb.add_argument('--noreconnect', action="store_true", help='Disable reconnect')
|
||||
|
||||
parser_script.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_printgpt.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_footer.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_e.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_es.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_wl.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_wf.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_w.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_rs.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_rf.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_rl.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_gpt.add_argument('--stock', action="store_true", help='use stock da')
|
||||
parser_r.add_argument('--stock', action="store_true", help='use stock da')
|
||||
da_keys.add_argument('--stock', action="store_true", help='use stock da')
|
||||
da_unlock.add_argument('--stock', action="store_true", help='use stock da')
|
||||
da_peek.add_argument('--stock', action="store_true", help='use stock da')
|
||||
da_poke.add_argument('--stock', action="store_true", help='use stock da')
|
||||
da_dump.add_argument('--stock', action="store_true", help='use stock da')
|
||||
da_rpmb.add_argument('--stock', action="store_true", help='use stock da')
|
||||
|
||||
parser_script.add_argument('--uartloglevel', help='Set uart log level (0=Trace, 2=Normal)')
|
||||
parser_printgpt.add_argument('--uartloglevel', help='Set uart log level (0=Trace, 2=Normal)')
|
||||
parser_footer.add_argument('--uartloglevel', help='Set uart log level (0=Trace, 2=Normal)')
|
||||
|
|
|
@ -33,6 +33,12 @@ class SlaKey:
|
|||
|
||||
|
||||
da_sla_keys = [
|
||||
SlaKey(vendor="Tecno/Infinix",
|
||||
da_codes=[0x1208, 0x0907],
|
||||
name="",
|
||||
d="499890AEF768030B56AD8BF7355262A57643A8C3DF318647B72E0B72416D91D25882D0077FEBE9E8275E9F42C3F89FFF5E99E0163487461B7CC3E97C1CC4F4E2D587AB7D8DB80335AA8E3254F318AAC42136FF1043649918685A0F5CF5548318090C26D951A2B93F79FB0D9B5E1DB1C928091E1908A5DA7D3B9194A22B18B78C6EF88932EFB3D88DB8BA7117257063DE165FA8534D50C6B35F6F7C0AF5F4A96BB89756BB7AC94110E8D1B5868A5DAADF815FE8FA38960A039D681F319C7B7ED7A55649C2F2F75B26C27807AFED8BC4EF57619FF9DA152E337FE379E1B1B0020C1EF2ABDCE4A66AAF3802EE8AB105ACA6F3388EA4C20184E572778C8EB3D30B51",
|
||||
n="BA4C5178EE5477B7A30FC99F9FE78E7C011E58B5DC05832591AADEE0D26A2667738FFE851782016CAE7DB8DC1958C627BC60E3A96D46E225536DCC76CBFADFE6CA2CBE4BE982AB46CBB0F1C5CB2CB13D7BBAC96E467D76AF819DCA28FB90A03AF92DDC05B34506E24F02A049D73B8143A1CF4B081372D49F4BCA21DA9EE8A19679669C71C836FC5B8180BD98256BA2AE82B702DDC61EDFD9C47871D027297D6C72A984046081953D141656F0DC4BC4E2D4006147BE096D7E855AA7057460EAC7C57660F1F28BE278C38700BAC5EBADB39F6508CF2F1E4044421664A856623FFB2002C1204CED786D576E3DDAA7C185FD698B1185A98A03B875F0A93831270557",
|
||||
e="010001"),
|
||||
# lk/files/pbp/keys/toolauth/da_prvk.pem
|
||||
SlaKey(vendor="KaiOS",
|
||||
da_codes=[],
|
||||
|
@ -47,14 +53,6 @@ da_sla_keys = [
|
|||
d="09976537029b4362591c5b13873f223de5525d55df52dde283e52afa67f6c9dbf1408d2fb586a624efc93426f5f3be981f80e861ddd975a1e5e662db84f5164804a3ae717605d7f15866df9ed1497c38fdd6197243163ef22f958d7b822c57317203e9a1e7d18dad01f15054facdbddb9261a1272638da661fe4f9f0714ecf00e6541cc435afb1fd75a27d34b17ad400e9474ba850dafce266799caff32a058ff71e4c2daacaf8ba709e9ca4dc87584a7ffe8aa9a0a160ed069c3970b7dae3987ded71bd0bc824356987bd74363d46682c71913c3edbdb2a911f701f23aee3f8dd98180b5a138fd5ad74743682d2d2d1bb3d92786710248f316dd8391178ea81",
|
||||
n="D16403466C530EF9BB53C1E8A96A61A4E332E17DC0F55BB46D207AC305BAE9354EAAC2CB3077B33740D275036B822DB268200DE17DA3DB7266B27686B8970B85737050F084F8D576904E74CD6C53B31F0BB0CD60686BF67C60DA0EC20F563EEA715CEBDBF76D1C5C10E982AB2955D833DE553C9CDAFD7EA2388C02823CFE7DD9AC83FA2A8EB0685ABDAB56A92DF1A7805E8AC0BD10C0F3DCB1770A9E6BBC3418C5F84A48B7CB2316B2C8F64972F391B116A58C9395A9CE9E743569A367086D7771D39FEC8EBBBA3DD2B519785A76A9F589D36D637AF884543FD65BAC75BE823C0C50AA16D58187B97223625C54C66B5A5E4DBAEAB7BE89A4E340A2E241B09B2F",
|
||||
e="010001"),
|
||||
"""
|
||||
SlaKey(vendor="Generic",
|
||||
da_codes=[],
|
||||
name="VERIFIED_BOOT_IMG_AUTH_KEY.ini",
|
||||
d=0xDACD8B5FDA8A766FB7BCAA43F0B16915CE7B47714F1395FDEBCF12A2D41155B0FB587A51FECCCB4DDA1C8E5EB9EB69B86DAF2C620F6C2735215A5F22C0B6CE377AA0D07EB38ED340B5629FC2890494B078A63D6D07FDEACDBE3E7F27FDE4B143F49DB4971437E6D00D9E18B56F02DABEB0000B6E79516D0C8074B5A42569FD0D9196655D2A4030D42DFE05E9F64883E6D5F79A5BFA3E7014C9A62853DC1F21D5D626F4D0846DB16452187DD776E8886B48C210C9E208059E7CAFC997FD2CA210775C1A5D9AA261252FB975268D970C62733871D57814098A453DF92BC6CA19025CD9D430F02EE46F80DE6C63EA802BEF90673AAC4C6667F2883FB4501FA77455,
|
||||
n=0x8BC9B1F7A559BCDD1717F3F7BFF8B858743892A6338D21D0BE2CE78D1BCB8F61A8D31822F694C476929897E4B10753DDBE45A2276C0EFEE594CF75E47016DA9CDB3D8EB6C3E4C5D69B8BCCE1AE443CF299C22B905300C85875E8DBB8231F4E9949D8CF9D8E0F40E93F29F843420F22CD9D080A45A4407F58F3609D03A7DB950D3D847B8B4E7D50DB6359D37A2DD730D3CE77F8FB2A33C095B0A6CF3E08593E4F70254DCDF671790F530EC07C3CD1E80199CB42F24ACA92DB5996F2119003F502E16D88EB4E4A8DEAE4036558D2A52F5C9960B0FBBC6F6FA75EFF6F5A173CE1A82539A35973D568B8918ED12F7610748BEB0239A5006257E19574C77F4133A269,
|
||||
e="010001"),
|
||||
""",
|
||||
SlaKey(vendor="Generic",
|
||||
da_codes=[],
|
||||
name="CodeSigKey",
|
||||
|
@ -69,6 +67,23 @@ da_sla_keys = [
|
|||
e="010001"),
|
||||
]
|
||||
|
||||
"""
|
||||
SlaKey(vendor="Generic",
|
||||
da_codes=[],
|
||||
name="VERIFIED_BOOT_IMG_AUTH_KEY.ini",
|
||||
d=0xDACD8B5FDA8A766FB7BCAA43F0B16915CE7B47714F1395FDEBCF12A2D41155B0FB587A51FECCCB4DDA1C8E5EB9EB69B86DAF2C620F6C2735215A5F22C0B6CE377AA0D07EB38ED340B5629FC2890494B078A63D6D07FDEACDBE3E7F27FDE4B143F49DB4971437E6D00D9E18B56F02DABEB0000B6E79516D0C8074B5A42569FD0D9196655D2A4030D42DFE05E9F64883E6D5F79A5BFA3E7014C9A62853DC1F21D5D626F4D0846DB16452187DD776E8886B48C210C9E208059E7CAFC997FD2CA210775C1A5D9AA261252FB975268D970C62733871D57814098A453DF92BC6CA19025CD9D430F02EE46F80DE6C63EA802BEF90673AAC4C6667F2883FB4501FA77455,
|
||||
n=0x8BC9B1F7A559BCDD1717F3F7BFF8B858743892A6338D21D0BE2CE78D1BCB8F61A8D31822F694C476929897E4B10753DDBE45A2276C0EFEE594CF75E47016DA9CDB3D8EB6C3E4C5D69B8BCCE1AE443CF299C22B905300C85875E8DBB8231F4E9949D8CF9D8E0F40E93F29F843420F22CD9D080A45A4407F58F3609D03A7DB950D3D847B8B4E7D50DB6359D37A2DD730D3CE77F8FB2A33C095B0A6CF3E08593E4F70254DCDF671790F530EC07C3CD1E80199CB42F24ACA92DB5996F2119003F502E16D88EB4E4A8DEAE4036558D2A52F5C9960B0FBBC6F6FA75EFF6F5A173CE1A82539A35973D568B8918ED12F7610748BEB0239A5006257E19574C77F4133A269,
|
||||
e="010001"),
|
||||
""",
|
||||
|
||||
"""SlaKey(vendor="Generic",
|
||||
da_codes=[],
|
||||
name="AuthGen_SV5.ini",
|
||||
d="9a3c3d4da0650cef38ed96ef833904c9c13835199367c7b9cb03a55e7aa482016a820dfe597cd54dd1f81fd879cf070ec0c25899ac5a49822db09675a92acf6a01e0f8f538bbe66de48ca9bdca313b616470d9ec2914356d03c95f7d9236549e5a21457e4dd5fcaf09046c47ca7436f06cd7b82cb6d2a936fca88b707f6ce28f33110fea1ec363e8482419db901cb0d38e574fe0c02ad117166b40ec78f59aaa7f3eafa425010a95614e046651273a6cb1371380c4e6ce81bdb892db6ff4892cc4d8c613a8fb3fec1e72c279052896872fc23da07fba63783374f3be8e16a15e0a04a139108dd6ac239f191135f4a895e27c670de065d2248e3f9c7e920fd001",
|
||||
n="008C8BF38EB2FC7FC06D567DBF70E9C34BE4281C4239ED9C58A6B598C3AE7821815D94D0B463463EEBBD69FF6AF990AE0499B6C3B3CADCD91D54499CD66E5314DB610FC0C6CAEEB1F16B6F2D451E3F2B2D515008917FCEC50ADA4CE0699BCF247D5AE2A1DDD34C48624A657CCB11CE5F8C6CE92CAB6038EFC2A89E42E029488C02C3CF21947C86D51BBA8EF540A2A7CE85356F431891261D860B518E89DD73B2D240461ACB66BCC213403145DE83F6963147E65274EA1E45DB2D231E0774ECC86E4F2328F8A90835C4FDEF1088DDBA1D8F7CA0CA732A64BDA6816162C0F88F02CF97634D85530968CBF8B7CE6A8B67D53BBFB4910843EA413135D56FB5074445",
|
||||
e="010001"),
|
||||
"""
|
||||
|
||||
brom_sla_keys = [
|
||||
SlaKey(vendor="Generic",
|
||||
da_codes=[],
|
||||
|
@ -76,13 +91,6 @@ brom_sla_keys = [
|
|||
d="4BD992E9A2230CD2ABEF49E4F6A7E11D7E2ADD24847787B320239829C560D5EAB94B8304317C938E9358E94758AE60D9B13F2913DD1A749A9941FACAFAB574D70EBBFBCC0133A4BE2134CBA3CE7EE18A6D3CC98D33DAB06AEEE512F405A3248EA316ABC31A2758D4C5A7B9DFCC02C2508A492EF3760A0D4CDA827CFFCADD11ED",
|
||||
n="5FFF0B70D5DE3FC5BF41CB824B4BFD14820571CE57EDD3E7C668CC570E718DB07DCC7A6CACD0E80DADC38AA33DB37816839D97980DF3E577A6E0B1169D708071E17DD259CFE538DBDA804A2FC07D795841F2F59DEE023A9919360D0A3F4647FDF5657D9FC5944C8BFA2802336BA23AFDCDE8D546E8806EB532AA7F95A01D8DD1",
|
||||
e="010001"),
|
||||
"""SlaKey(vendor="Generic",
|
||||
da_codes=[],
|
||||
name="AuthGen_SV5.ini",
|
||||
d="9a3c3d4da0650cef38ed96ef833904c9c13835199367c7b9cb03a55e7aa482016a820dfe597cd54dd1f81fd879cf070ec0c25899ac5a49822db09675a92acf6a01e0f8f538bbe66de48ca9bdca313b616470d9ec2914356d03c95f7d9236549e5a21457e4dd5fcaf09046c47ca7436f06cd7b82cb6d2a936fca88b707f6ce28f33110fea1ec363e8482419db901cb0d38e574fe0c02ad117166b40ec78f59aaa7f3eafa425010a95614e046651273a6cb1371380c4e6ce81bdb892db6ff4892cc4d8c613a8fb3fec1e72c279052896872fc23da07fba63783374f3be8e16a15e0a04a139108dd6ac239f191135f4a895e27c670de065d2248e3f9c7e920fd001",
|
||||
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",
|
||||
|
|
|
@ -81,7 +81,7 @@ class DeviceClass(metaclass=LogBase):
|
|||
def usbwrite(self, data, pktsize=None):
|
||||
raise NotImplementedError()
|
||||
|
||||
def usbread(self, resplen=None, timeout=0):
|
||||
def usbread(self, resplen=None, timeout=0, w_max_packet_size=None):
|
||||
raise NotImplementedError()
|
||||
|
||||
def usbxmlread(self, maxtimeout=100):
|
||||
|
|
|
@ -4,11 +4,14 @@
|
|||
import time
|
||||
import sys
|
||||
import logging
|
||||
from queue import Queue
|
||||
|
||||
from mtkclient.Library.DA.xml.xml_param import max_xml_data_length
|
||||
import serial
|
||||
import serial.tools.list_ports
|
||||
import inspect
|
||||
from mtkclient.Library.Connection.devicehandler import DeviceClass
|
||||
|
||||
if sys.platform != "win32":
|
||||
import termios
|
||||
|
||||
|
@ -28,6 +31,7 @@ class SerialClass(DeviceClass):
|
|||
super().__init__(loglevel, portconfig, devclass)
|
||||
self.is_serial = True
|
||||
self.device = None
|
||||
self.queue = Queue()
|
||||
|
||||
def connect(self, ep_in=-1, ep_out=-1):
|
||||
if self.connected:
|
||||
|
@ -193,7 +197,7 @@ class SerialClass(DeviceClass):
|
|||
self.device.flushOutput()
|
||||
return self.device.flush()
|
||||
|
||||
def usbread(self, resplen=None, maxtimeout=0, timeout=0):
|
||||
def usbread(self, resplen=None, maxtimeout=0, timeout=0, w_max_packet_size=None):
|
||||
# print("Reading {} bytes".format(resplen))
|
||||
if timeout == 0 and maxtimeout != 0:
|
||||
timeout = maxtimeout / 1000 # Some code calls this with ms delays, some with seconds.
|
||||
|
@ -209,14 +213,26 @@ class SerialClass(DeviceClass):
|
|||
return b""
|
||||
self.device.timeout = timeout
|
||||
epr = self.device.read
|
||||
q = self.queue
|
||||
extend = res.extend
|
||||
bytestoread = resplen
|
||||
while len(res) < bytestoread:
|
||||
while bytestoread:
|
||||
bytestoread = resplen - len(res) if len(res) < resplen else 0
|
||||
if not q.empty():
|
||||
data = q.get(bytestoread)
|
||||
extend(data)
|
||||
if bytestoread <= 0:
|
||||
break
|
||||
try:
|
||||
val = epr(bytestoread)
|
||||
if len(val) == 0:
|
||||
break
|
||||
extend(val)
|
||||
if len(val) > bytestoread:
|
||||
self.warning("Buffer overflow")
|
||||
q.put(val[bytestoread:])
|
||||
extend(val[:bytestoread])
|
||||
else:
|
||||
extend(val)
|
||||
except Exception as e:
|
||||
error = str(e)
|
||||
if "timed out" in error:
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import logging
|
||||
import os
|
||||
import sys
|
||||
from queue import Queue
|
||||
import usb.core # pyusb
|
||||
import usb.util
|
||||
import time
|
||||
|
@ -127,6 +128,7 @@ class UsbClass(DeviceClass):
|
|||
self.EP_IN = None
|
||||
self.EP_OUT = None
|
||||
self.is_serial = False
|
||||
self.queue = Queue()
|
||||
if sys.platform.startswith('freebsd') or sys.platform.startswith('linux') or sys.platform.startswith('darwin'):
|
||||
self.backend = usb.backend.libusb1.get_backend(find_library=lambda x: "libusb-1.0.so")
|
||||
elif sys.platform.startswith('win32'):
|
||||
|
@ -376,8 +378,8 @@ class UsbClass(DeviceClass):
|
|||
self.EP_IN = usb.util.find_descriptor(itf,
|
||||
# match the first OUT endpoint
|
||||
custom_match=lambda xe: \
|
||||
usb.util.endpoint_direction(xe.bEndpointAddress) ==
|
||||
usb.util.ENDPOINT_IN)
|
||||
usb.util.endpoint_direction(xe.bEndpointAddress) ==
|
||||
usb.util.ENDPOINT_IN)
|
||||
self.connected = True
|
||||
return True
|
||||
print("Couldn't find CDC interface. Aborting.")
|
||||
|
@ -456,7 +458,7 @@ class UsbClass(DeviceClass):
|
|||
def get_write_packetsize(self):
|
||||
return self.EP_OUT.wMaxPacketSize
|
||||
|
||||
def usbread(self, resplen=None, maxtimeout=100):
|
||||
def usbread(self, resplen=None, maxtimeout=100, w_max_packet_size=None):
|
||||
if resplen is None:
|
||||
resplen = self.maxsize
|
||||
if resplen <= 0:
|
||||
|
@ -465,19 +467,38 @@ class UsbClass(DeviceClass):
|
|||
timeout = 0
|
||||
loglevel = self.loglevel
|
||||
epr = self.EP_IN.read
|
||||
w_max_packet_size = self.EP_IN.wMaxPacketSize
|
||||
q = self.queue
|
||||
b = self.buffer
|
||||
if w_max_packet_size is None:
|
||||
w_max_packet_size = self.EP_IN.wMaxPacketSize
|
||||
extend = res.extend
|
||||
fast = self.fast
|
||||
buffer = None
|
||||
buflen = min(resplen, w_max_packet_size)
|
||||
if self.fast:
|
||||
buffer = self.buffer[:buflen]
|
||||
while len(res) < resplen:
|
||||
buffer = b[:buflen]
|
||||
bytestoread = resplen
|
||||
while bytestoread > 0:
|
||||
bytestoread = resplen - len(res) if len(res) < resplen else 0
|
||||
if not q.empty():
|
||||
extend(q.get(bytestoread))
|
||||
if bytestoread <= 0:
|
||||
break
|
||||
sz = min(buflen, bytestoread)
|
||||
try:
|
||||
if self.fast:
|
||||
if fast:
|
||||
rlen = epr(buffer, timeout)
|
||||
if rlen > sz:
|
||||
self.warning("Buffer overflow")
|
||||
q.put(buffer[rlen:])
|
||||
if self.loglevel == logging.DEBUG:
|
||||
self.warning(traceback.format_exc())
|
||||
self.warning(f"{rlen} vs {sz}")
|
||||
self.warning(buffer[sz:].hex())
|
||||
sys.stdout.flush()
|
||||
extend(buffer[:rlen])
|
||||
else:
|
||||
extend(epr(buflen))
|
||||
extend(epr(sz))
|
||||
except usb.core.USBError as e:
|
||||
error = str(e.strerror)
|
||||
if "timed out" in error:
|
||||
|
@ -489,6 +510,9 @@ class UsbClass(DeviceClass):
|
|||
elif "Overflow" in error:
|
||||
self.error("USB Overflow")
|
||||
return b""
|
||||
elif "No such device" in error:
|
||||
self.error("Device disconnected")
|
||||
sys.exit(1)
|
||||
else:
|
||||
self.info(repr(e))
|
||||
return b""
|
||||
|
|
|
@ -256,6 +256,8 @@ class DAconfig(metaclass=LogBase):
|
|||
if loader.hw_version <= self.config.hwver:
|
||||
if loader.sw_version <= self.config.swver:
|
||||
if self.da_loader is None:
|
||||
if loader.v6:
|
||||
self.config.chipconfig.damode = DAmodes.XML
|
||||
self.da_loader = loader
|
||||
self.loader = loader.loader
|
||||
if self.da_loader is None and dacode != 0x6261:
|
||||
|
|
|
@ -809,6 +809,8 @@ class DALegacy(metaclass=LogBase):
|
|||
res = self.usbread(1)
|
||||
if res == self.Rsp.ACK:
|
||||
speed = self.usbread(1)
|
||||
if speed[0] > 0:
|
||||
self.mtk.port.cdc.set_fast_mode(True)
|
||||
return speed
|
||||
return None
|
||||
|
||||
|
@ -1099,7 +1101,7 @@ class DALegacy(metaclass=LogBase):
|
|||
size = bytestoread
|
||||
if bytestoread > packetsize:
|
||||
size = packetsize
|
||||
tmp = self.usbread(size)
|
||||
tmp = self.usbread(size, w_max_packet_size=size)
|
||||
rq.put(tmp[:size])
|
||||
bytestoread -= size
|
||||
curpos += size
|
||||
|
@ -1124,8 +1126,8 @@ class DALegacy(metaclass=LogBase):
|
|||
size = bytestoread
|
||||
if bytestoread > packetsize:
|
||||
size = packetsize
|
||||
buffer.extend(self.usbread(size))
|
||||
bytestoread -= size
|
||||
buffer.extend(self.usbread(size, w_max_packet_size=size))
|
||||
bytestoread = len(buffer)-length
|
||||
checksum = unpack(">H", self.usbread(2))[0]
|
||||
self.debug("Checksum: %04X" % checksum)
|
||||
self.usbwrite(self.Rsp.ACK)
|
||||
|
|
|
@ -832,22 +832,28 @@ class DAXFlash(metaclass=LogBase):
|
|||
worker.start()
|
||||
while bytestoread > 0:
|
||||
status = self.usbread(4 + 4 + 4)
|
||||
magic, datatype, slength = unpack("<III", status)
|
||||
if magic == 0xFEEEEEEF:
|
||||
resdata = self.usbread(slength)
|
||||
if slength > 4:
|
||||
rq.put(resdata)
|
||||
stmp = pack("<III", self.Cmd.MAGIC, self.DataType.DT_PROTOCOL_FLOW, 4)
|
||||
data = pack("<I", 0)
|
||||
self.usbwrite(stmp)
|
||||
self.usbwrite(data)
|
||||
bytestoread -= len(resdata)
|
||||
bytesread += len(resdata)
|
||||
if display:
|
||||
self.mtk.daloader.progress.show_progress("Read", bytesread, total, display)
|
||||
elif slength == 4:
|
||||
if unpack("<I", resdata)[0] != 0:
|
||||
break
|
||||
try:
|
||||
magic, datatype, slength = unpack("<III", status)
|
||||
if magic == 0xFEEEEEEF:
|
||||
resdata = self.usbread(slength, w_max_packet_size=slength)
|
||||
if slength > 4:
|
||||
rq.put(resdata)
|
||||
stmp = pack("<III", self.Cmd.MAGIC, self.DataType.DT_PROTOCOL_FLOW, 4)
|
||||
data = pack("<I", 0)
|
||||
self.usbwrite(stmp)
|
||||
self.usbwrite(data)
|
||||
bytestoread -= len(resdata)
|
||||
bytesread += len(resdata)
|
||||
if display:
|
||||
self.mtk.daloader.progress.show_progress("Read", bytesread, total, display)
|
||||
elif slength == 4:
|
||||
if unpack("<I", resdata)[0] != 0:
|
||||
break
|
||||
else:
|
||||
print("Error: Invalid slength")
|
||||
except:
|
||||
print("Error: Timeout")
|
||||
|
||||
status = self.usbread(4 + 4 + 4)
|
||||
magic, datatype, slength = unpack("<III", status)
|
||||
if magic == 0xFEEEEEEF:
|
||||
|
@ -1054,7 +1060,7 @@ class DAXFlash(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)
|
||||
else:
|
||||
self.patch = False
|
||||
|
@ -1141,11 +1147,13 @@ class DAXFlash(metaclass=LogBase):
|
|||
for key in da_sla_keys:
|
||||
if da2.find(bytes.fromhex(key.n)) != -1:
|
||||
sla_signature = generate_da_sla_signature(data=data, key=key.key)
|
||||
found = not self.set_remote_sec_policy(data=sla_signature)
|
||||
found = self.set_remote_sec_policy(data=sla_signature)
|
||||
if found:
|
||||
break
|
||||
if not found:
|
||||
print("No valid sla key found, using dummy auth ....")
|
||||
sla_signature = b"\x00" * 0x100
|
||||
found = not self.set_remote_sec_policy(data=sla_signature)
|
||||
found = self.set_remote_sec_policy(data=sla_signature)
|
||||
if found:
|
||||
print("SLA Signature was accepted.")
|
||||
return found
|
||||
|
@ -1210,12 +1218,10 @@ class DAXFlash(metaclass=LogBase):
|
|||
if stage == 1:
|
||||
self.info("Uploading stage 2...")
|
||||
stage = stage + 1
|
||||
if not self.mtk.daloader.patch:
|
||||
#if self.carbonara is not None:
|
||||
# loaded = self.carbonara.patchda1_and_upload_da2()
|
||||
#else:
|
||||
loaded = False
|
||||
if not self.mtk.daloader.patch and not self.mtk.config.stock and connagent == b"preloader":
|
||||
loaded = self.boot_to(self.daconfig.da_loader.region[stage].m_start_addr, self.daconfig.da2)
|
||||
else:
|
||||
if not loaded:
|
||||
loaded = self.boot_to(self.daconfig.da_loader.region[stage].m_start_addr, self.daconfig.da2)
|
||||
if loaded:
|
||||
self.info("Successfully uploaded stage 2")
|
||||
|
@ -1224,7 +1230,6 @@ class DAXFlash(metaclass=LogBase):
|
|||
self.info("DA SLA is enabled")
|
||||
if not self.handle_sla(self.daconfig.da2):
|
||||
self.error("Can't bypass DA SLA")
|
||||
sys.exit(1)
|
||||
else:
|
||||
self.info("DA SLA is disabled")
|
||||
self.reinit(True)
|
||||
|
|
|
@ -635,12 +635,14 @@ class XmlFlashExt(metaclass=LogBase):
|
|||
if rpartition.name == "seccfg":
|
||||
partition = rpartition
|
||||
seccfg_data = self.xflash.readflash(
|
||||
addr=partition.sector * self.mtk.daloader.daconfig.pagesize,
|
||||
length=partition.sectors * self.mtk.daloader.daconfig.pagesize,
|
||||
addr=partition.sector * guid_gpt.sectorsize,
|
||||
length=partition.sectors * guid_gpt.sectorsize,
|
||||
filename="", parttype="user", display=False)
|
||||
break
|
||||
if seccfg_data is None:
|
||||
return False, "Couldn't detect existing seccfg partition. Aborting unlock."
|
||||
if seccfg_data.find(b"\x4D\x4D\x4D\x4D") == -1:
|
||||
return False, "SecCfg is empty. Aborting unlock."
|
||||
if seccfg_data[:4] != pack("<I", 0x4D4D4D4D):
|
||||
return False, "Unknown seccfg partition header. Aborting unlock."
|
||||
hwc = self.cryptosetup()
|
||||
|
@ -766,6 +768,8 @@ class XmlFlashExt(metaclass=LogBase):
|
|||
self.info(f"CID : {cid}")
|
||||
retval["cid"] = cid
|
||||
if self.config.chipconfig.dxcc_base is not None:
|
||||
# self.info("Generating provision key...")
|
||||
# platkey, provkey = hwc.aes_hwcrypt(btype="dxcc", mode="prov")
|
||||
self.info("Generating dxcc rpmbkey...")
|
||||
rpmbkey = hwc.aes_hwcrypt(btype="dxcc", mode="rpmb")
|
||||
self.info("Generating dxcc mirpmbkey...")
|
||||
|
|
|
@ -6,7 +6,11 @@ import os
|
|||
from struct import pack, unpack
|
||||
from queue import Queue
|
||||
from threading import Thread
|
||||
from Cryptodome.Util.number import size
|
||||
|
||||
from Cryptodome.Cipher import PKCS1_OAEP
|
||||
from Cryptodome.Hash import SHA256
|
||||
from Cryptodome.PublicKey import RSA
|
||||
from Cryptodome.Util.number import size, bytes_to_long
|
||||
from mtkclient.Library.DA.xml.xml_param import DataType, FtSystemOSE, LogLevel
|
||||
from mtkclient.Library.utils import logsetup, LogBase
|
||||
from mtkclient.Library.error import ErrorHandler
|
||||
|
@ -228,7 +232,7 @@ class DAXML(metaclass=LogBase):
|
|||
bytestoread = length
|
||||
while bytestoread > 0:
|
||||
sz = min(usbepsz, bytestoread)
|
||||
data.extend(self.usbread(sz))
|
||||
data.extend(self.usbread(sz,w_max_packet_size=sz))
|
||||
bytestoread -= sz
|
||||
if len(data) == length:
|
||||
return data
|
||||
|
|
|
@ -61,7 +61,7 @@ class HwCrypto(metaclass=LogBase):
|
|||
return self.sej.hw_aes128_cbc_encrypt(buf=data, encrypt=True)
|
||||
elif mode == "sst":
|
||||
self.sej.sej_base = 0xC0016000
|
||||
data2 = self.sej.generate_hw_meta(encrypt=True, data=data)
|
||||
data2 = self.sej.generate_hw_meta(encrypt=True, data=data, legacy=False)
|
||||
data3 = self.sej.sst_secure_algo_with_level(buf=data, encrypt=True)
|
||||
print(data2.hex())
|
||||
print(data3.hex())
|
||||
|
|
|
@ -12,6 +12,14 @@ from Cryptodome.Cipher import AES
|
|||
from Cryptodome.Util import Counter
|
||||
from mtkclient.Library.utils import LogBase, logsetup
|
||||
|
||||
Lcs = 0xA
|
||||
KceSet = 0xB
|
||||
Kce = 0xC # CodeEncryptionKey
|
||||
SASI_SB_HASH_BOOT_KEY_256B = 2 # 0x10
|
||||
SASI_SB_HASH_BOOT_KEY_1_128B = 1 # 0x14
|
||||
SASI_SW_VERSION_COUNTER1 = 1 # 0x18
|
||||
SASI_SW_VERSION_COUNTER2 = 2 # 0x19
|
||||
|
||||
oem_pubk = "DACD8B5FDA8A766FB7BCAA43F0B16915" + \
|
||||
"CE7B47714F1395FDEBCF12A2D41155B0" + \
|
||||
"FB587A51FECCCB4DDA1C8E5EB9EB69B8" + \
|
||||
|
@ -1114,6 +1122,18 @@ class Dxcc(metaclass=LogBase):
|
|||
self.tzcc_clk(0)
|
||||
return rpmbkey
|
||||
|
||||
def sasi_bsv_socid_compute(self):
|
||||
key = bytes.fromhex("49")
|
||||
salt = b"\x00"*32
|
||||
keylength = 0x10
|
||||
self.tzcc_clk(1)
|
||||
dstaddr = self.da_payload_addr - 0x300
|
||||
pubkey = self.sasi_bsv_pubkey_hash_get(SASI_SB_HASH_BOOT_KEY_256B)
|
||||
derivedkey = self.sbrom_key_derivation(1, key, salt, keylength, dstaddr)
|
||||
hash = hashlib.sha256(pubkey+derivedkey).digest()
|
||||
self.tzcc_clk(0)
|
||||
return hash
|
||||
|
||||
def generate_rpmb_mitee(self):
|
||||
rpmb_ikey = bytes.fromhex("AD1AC6B4BDF4EDB7")
|
||||
rpmb_salt = bytes.fromhex("69EF6584")
|
||||
|
@ -1124,37 +1144,120 @@ class Dxcc(metaclass=LogBase):
|
|||
self.tzcc_clk(0)
|
||||
return rpmbkey
|
||||
|
||||
def salt_func(self, value):
|
||||
def sasi_bsv_otp_word_read(self, otpAddress):
|
||||
if otpAddress>0x24:
|
||||
return None
|
||||
while True:
|
||||
val = self.read32(self.dxcc_base + (0x2AF * 4)) & 1
|
||||
if val != 0:
|
||||
break
|
||||
self.write32(self.dxcc_base + (0x2A9 * 4), (4 * value) | 0x10000)
|
||||
self.write32(self.dxcc_base + (0x2A9 * 4), (4 * otpAddress) | 0x10000)
|
||||
while True:
|
||||
val = self.read32(self.dxcc_base + (0x2AD * 4)) << 31
|
||||
val = self.read32(self.dxcc_base + (0x2AD * 4)) & 1
|
||||
if val != 0:
|
||||
break
|
||||
res = self.read32(self.dxcc_base + (0x2AB * 4))
|
||||
return res
|
||||
|
||||
def sasi_bsv_lcs_get(self):
|
||||
while True:
|
||||
val = self.read32(self.dxcc_base + (0x2AF * 4)) & 1
|
||||
if val != 0:
|
||||
break
|
||||
lcs = self.read32(self.dxcc_base + (0x2B5 * 4))
|
||||
if lcs != 1:
|
||||
if lcs != 5:
|
||||
return 0
|
||||
if self.read32(self.dxcc_base + (0x2B5 * 4)) & 0x100 != 0:
|
||||
return 0xB000002
|
||||
otp_word = self.sasi_bsv_otp_word_read(0xA)
|
||||
if self.read32(self.dxcc_base + (0x2B5 * 4)) & 0x100 != 0:
|
||||
if otp_word & 0xF0000 != 0x30000:
|
||||
return 0xB000080
|
||||
if self.read32(self.dxcc_base + (0x2B5 * 4)) & 0x200 == 0:
|
||||
return 0
|
||||
return 0xB000003
|
||||
|
||||
def sasi_bsv_pub_key_hash_get(self, keyindex=SASI_SB_HASH_BOOT_KEY_256B):
|
||||
if keyindex == SASI_SB_HASH_BOOT_KEY_256B:
|
||||
start = 0x10
|
||||
length = 0x8
|
||||
elif keyindex == SASI_SB_HASH_BOOT_KEY_1_128B:
|
||||
start = 0x14
|
||||
length = 0x4
|
||||
else:
|
||||
return None
|
||||
hashval = bytearray()
|
||||
for idx in range(start,start+length,0x1):
|
||||
hashval.extend(int.to_bytes(self.sasi_bsv_otp_word_read(idx),4,'little'))
|
||||
return hashval
|
||||
|
||||
def sbrom_decrypt_kcst(self):
|
||||
pdesc = hw_desc_init()
|
||||
pdesc[0] = 0
|
||||
pdesc[1] = 0x3FFC000
|
||||
pdesc[2] = 0
|
||||
pdesc[3] = 0
|
||||
pdesc[4] = 0
|
||||
pdesc[5] = 0
|
||||
self.sasi_sb_adddescsequence(pdesc)
|
||||
self.sb_hal_wait_desc_completion()
|
||||
|
||||
def sbrom_aeslockenginekey(self):
|
||||
pdesc = hw_desc_init()
|
||||
pdesc[0] = 0
|
||||
pdesc[1] = 0x8000081
|
||||
pdesc[2] = 0
|
||||
pdesc[3] = 0
|
||||
pdesc[4] = 0x4801C20
|
||||
pdesc[5] = 0
|
||||
self.sasi_sb_adddescsequence(pdesc)
|
||||
self.sb_hal_wait_desc_completion()
|
||||
|
||||
def sasi_bsv_customer_key_decrypt(self):
|
||||
plat_key = b"KEY PLAT"
|
||||
dstaddr = self.da_payload_addr - 0x300
|
||||
salt = self.sasi_bsv_pub_key_hash_get(keyindex=SASI_SB_HASH_BOOT_KEY_256B)
|
||||
platkey = self.sbrom_key_derivation(HwCryptoKey.PLATFORM_KEY, plat_key, salt, 0x10, dstaddr)
|
||||
while True:
|
||||
val = self.read32(self.dxcc_base + 0xAF4) & 1
|
||||
if val != 0:
|
||||
break
|
||||
self.sbrom_decrypt_kcst()
|
||||
while True:
|
||||
val = self.read32(self.dxcc_base + 0xAF0) & 1
|
||||
if val != 0:
|
||||
break
|
||||
self.write32(self.dxcc_base + 0xAC0, 0)
|
||||
self.write32(self.dxcc_base + 0xAC4, 0)
|
||||
self.write32(self.dxcc_base + 0xAC8, 0)
|
||||
self.write32(self.dxcc_base + 0xACC, 0)
|
||||
self.sbrom_aeslockenginekey()
|
||||
|
||||
def sasi_bsv_security_disable(self):
|
||||
lcs = self.sasi_bsv_lcs_get()
|
||||
if lcs == 7:
|
||||
return
|
||||
self.write32(self.dxcc_base + 0xAC0, 0)
|
||||
self.write32(self.dxcc_base + 0xAC4, 0)
|
||||
self.write32(self.dxcc_base + 0xAC8, 0)
|
||||
self.write32(self.dxcc_base + 0xACC, 0)
|
||||
self.write32(self.dxcc_base + 0xAD8, 1)
|
||||
|
||||
def generate_provision_key(self):
|
||||
plat_key = b"KEY PLAT"
|
||||
prov_key = b"PROVISION KEY"
|
||||
self.tzcc_clk(1)
|
||||
dstaddr = self.da_payload_addr - 0x300
|
||||
|
||||
salt = hashlib.sha256(bytes.fromhex(oem_pubk)).digest()
|
||||
"""
|
||||
salt = bytearray(b"\x00"*0x20)
|
||||
for i in range(8):
|
||||
salt[i*4]=self.salt_func(0x10+i)
|
||||
"""
|
||||
provkey = self.sbrom_key_derivation(HwCryptoKey.PROVISIONING_KEY, plat_key, salt, 0x10, dstaddr)
|
||||
lcs = self.sasi_bsv_lcs_get()
|
||||
#salt = hashlib.sha256(bytes.fromhex(oem_pubk)).digest()
|
||||
salt = self.sasi_bsv_pub_key_hash_get(keyindex=SASI_SB_HASH_BOOT_KEY_256B)
|
||||
platkey = self.sbrom_key_derivation(HwCryptoKey.PLATFORM_KEY, plat_key, salt, 0x10, dstaddr)
|
||||
while True:
|
||||
val = self.read32(self.dxcc_base + 0xAF4) & 1
|
||||
if val != 0:
|
||||
break
|
||||
platkey = self.sbrom_key_derivation(HwCryptoKey.PLATFORM_KEY, prov_key, salt, 0x10, dstaddr)
|
||||
provkey = self.sbrom_key_derivation(HwCryptoKey.PROVISIONING_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)
|
||||
|
@ -1183,7 +1286,7 @@ class Dxcc(metaclass=LogBase):
|
|||
|
||||
def sbrom_key_derivation(self, aeskeytype, label, salt, requestedlen, destaddr):
|
||||
result = bytearray()
|
||||
if aeskeytype - 1 > 4 or (1 << (aeskeytype - 1) & 0x17) == 0:
|
||||
if aeskeytype <= HwCryptoKey.PLATFORM_KEY or (1 << (aeskeytype - 1) & 0x17) == 0:
|
||||
return 0xF2000002
|
||||
if requestedlen > 0xFF or (requestedlen << 28) & 0xFFFFFFFF:
|
||||
return 0xF2000003
|
||||
|
|
|
@ -468,7 +468,7 @@ 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, legacyxor=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)]
|
||||
|
@ -502,11 +502,11 @@ class Sej(metaclass=LogBase):
|
|||
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, legacy=legacyxor)
|
||||
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)
|
||||
buf2 = self.sej_aes_hw_internal(buf, encrypt=encrypt, attr=attr, sej_param=sej_param, legacy=legacyxor)
|
||||
return buf2
|
||||
|
||||
def sej_terminate(self):
|
||||
|
@ -557,7 +557,7 @@ class Sej(metaclass=LogBase):
|
|||
if legacy:
|
||||
self.reg.HACC_UNK |= 2
|
||||
# clear HACC_ASRC/HACC_ACFG/HACC_AOUT
|
||||
self.reg.HACC_ACON2 = 0x40000000 | self.HACC_AES_CLR
|
||||
self.reg.HACC_ACON2 |= 0x40000000
|
||||
i = 0
|
||||
while i < 20:
|
||||
if self.reg.HACC_ACON2 > 0x80000000:
|
||||
|
@ -598,12 +598,12 @@ class Sej(metaclass=LogBase):
|
|||
self.reg.HACC_ACONK = 0
|
||||
return acon_setting
|
||||
|
||||
def hw_aes128_cbc_encrypt(self, buf, encrypt=True, iv=None):
|
||||
def hw_aes128_cbc_encrypt(self, buf, encrypt=True, iv=None, legacy=False):
|
||||
if iv is None:
|
||||
iv = self.g_HACC_CFG_1
|
||||
self.tz_pre_init()
|
||||
self.info("HACC init")
|
||||
self.SEJ_V3_Init(ben=encrypt, iv=iv)
|
||||
self.SEJ_V3_Init(ben=encrypt, iv=iv, legacy=legacy)
|
||||
self.info("HACC run")
|
||||
buf2 = self.sej_run(buf)
|
||||
self.info("HACC terminate")
|
||||
|
@ -693,8 +693,8 @@ class Sej(metaclass=LogBase):
|
|||
break
|
||||
return data
|
||||
|
||||
def sej_sec_cfg_hw(self, data, encrypt=True):
|
||||
if encrypt:
|
||||
def sej_sec_cfg_hw(self, data, encrypt=True, noxor=False):
|
||||
if encrypt and not noxor:
|
||||
data = self.xor_data(bytearray(data))
|
||||
self.info("HACC init")
|
||||
self.SEJ_V3_Init(ben=encrypt, iv=self.g_HACC_CFG_1, legacy=True)
|
||||
|
@ -702,12 +702,12 @@ class Sej(metaclass=LogBase):
|
|||
dec = self.sej_run(data)
|
||||
self.info("HACC terminate")
|
||||
self.sej_terminate()
|
||||
if not encrypt:
|
||||
if not encrypt and not noxor:
|
||||
dec = self.xor_data(dec)
|
||||
return dec
|
||||
|
||||
def sej_sec_cfg_hw_V3(self, data, encrypt=True):
|
||||
return self.hw_aes128_cbc_encrypt(buf=data, encrypt=encrypt)
|
||||
def sej_sec_cfg_hw_V3(self, data, encrypt=True, legacy=False):
|
||||
return self.hw_aes128_cbc_encrypt(buf=data, encrypt=encrypt, legacy=legacy)
|
||||
|
||||
# seclib_get_msg_auth_key
|
||||
def generate_rpmb(self, meid, otp, derivedlen=32):
|
||||
|
@ -782,7 +782,7 @@ class Sej(metaclass=LogBase):
|
|||
self.sej_terminate()
|
||||
return dec
|
||||
|
||||
def generate_hw_meta(self, otp=None, encrypt=False, data=b""):
|
||||
def generate_hw_meta(self, otp=None, encrypt=False, data=b"", legacy=False):
|
||||
"""
|
||||
WR8 mt65
|
||||
LR9 CRC RC4 AES128-CBC SBC=OFF
|
||||
|
@ -800,7 +800,7 @@ class Sej(metaclass=LogBase):
|
|||
iv = [seed, (~seed) & 0xFFFFFFFF, (((seed >> 16) | (seed << 16)) & 0xFFFFFFFF),
|
||||
(~((seed >> 16) | (seed << 16)) & 0xFFFFFFFF)]
|
||||
self.info("HACC init")
|
||||
self.SEJ_V3_Init(ben=encrypt, iv=iv)
|
||||
self.SEJ_V3_Init(ben=encrypt, iv=iv, legacy=legacy)
|
||||
self.info("HACC run")
|
||||
dec = self.sej_run(data)
|
||||
self.info("HACC terminate")
|
||||
|
|
|
@ -60,7 +60,12 @@ class SecCfgV4(metaclass=LogBase):
|
|||
if _hash == dec_hash:
|
||||
self.hwtype = "V3"
|
||||
else:
|
||||
return False
|
||||
dec_hash = self.hwc.sej.sej_sec_cfg_hw_V3(self.hash, False, legacy=True)
|
||||
if _hash == dec_hash:
|
||||
self.hwtype = "V4"
|
||||
else:
|
||||
return False
|
||||
|
||||
"""
|
||||
LKS_DEFAULT = 0x01
|
||||
LKS_MP_DEFAULT = 0x02
|
||||
|
@ -91,11 +96,13 @@ class SecCfgV4(metaclass=LogBase):
|
|||
dec_hash = hashlib.sha256(seccfg_data).digest()
|
||||
enc_hash = b""
|
||||
if self.hwtype == "SW":
|
||||
enc_hash = self.hwc.sej.sej_sec_cfg_sw(dec_hash, True)
|
||||
enc_hash = self.hwc.sej.sej_sec_cfg_sw(dec_hash, encrypt=True)
|
||||
elif self.hwtype == "V2":
|
||||
enc_hash = self.hwc.sej.sej_sec_cfg_hw(dec_hash, True)
|
||||
enc_hash = self.hwc.sej.sej_sec_cfg_hw(dec_hash, encrypt=True)
|
||||
elif self.hwtype == "V3":
|
||||
enc_hash = self.hwc.sej.sej_sec_cfg_hw_V3(dec_hash, True)
|
||||
enc_hash = self.hwc.sej.sej_sec_cfg_hw_V3(dec_hash, encrypt=True)
|
||||
elif self.hwtype == "V4":
|
||||
enc_hash = self.hwc.sej.sej_sec_cfg_hw_V3(dec_hash, encrypt=True, legacy=True)
|
||||
indata = seccfg_data + enc_hash
|
||||
while len(indata) % 0x200 != 0:
|
||||
indata += b"\x00"
|
||||
|
@ -199,14 +206,18 @@ class SecCfgV3(metaclass=LogBase):
|
|||
if self.magic != 0x4D4D4D4D or self.endflag != 0x45454545:
|
||||
self.error("Unknown V3 seccfg structure !")
|
||||
return False
|
||||
err = self.hwc.sej.sej_sec_cfg_sw(self.data, False)
|
||||
err = self.hwc.sej.sej_sec_cfg_sw(self.data, encrypt=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)
|
||||
err = self.hwc.sej.sej_sec_cfg_hw_V3(self.data, encrypt=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)
|
||||
err = self.hwc.sej.sej_sec_cfg_hw(self.data, encrypt=False)
|
||||
if err[:4] not in [b"IIII", b"CCCC", b"\x00\x00\x00\x00"]:
|
||||
self.error("Unknown V3 seccfg encryption !")
|
||||
return False
|
||||
err = self.hwc.sej.sej_sec_cfg_hw_V3(self.data, encrypt=False, legacy=True)
|
||||
if err[:4] not in [b"IIII", b"CCCC", b"\x00\x00\x00\x00"]:
|
||||
self.error("Unknown V3 seccfg encryption !")
|
||||
return False
|
||||
else:
|
||||
self.hwtype = "V4"
|
||||
else:
|
||||
self.hwtype = "V3"
|
||||
else:
|
||||
|
@ -267,11 +278,13 @@ class SecCfgV3(metaclass=LogBase):
|
|||
ed.write(self.seccfg_ext)
|
||||
indata = ed.getbuffer()
|
||||
if self.hwtype == "SW":
|
||||
indata = self.hwc.sej.sej_sec_cfg_sw(indata, True)
|
||||
indata = self.hwc.sej.sej_sec_cfg_sw(indata, encrypt=True)
|
||||
elif self.hwtype == "V2":
|
||||
indata = self.hwc.sej.sej_sec_cfg_hw(indata, True)
|
||||
indata = self.hwc.sej.sej_sec_cfg_hw(indata, encrypt=True)
|
||||
elif self.hwtype == "V3":
|
||||
indata = self.hwc.sej.sej_sec_cfg_hw_V3(indata, True)
|
||||
indata = self.hwc.sej.sej_sec_cfg_hw_V3(indata, encrypt=True)
|
||||
elif self.hwtype == "V4":
|
||||
indata = self.hwc.sej.sej_sec_cfg_hw_V3(indata, encrypt=True, legacy=True)
|
||||
else:
|
||||
return False, "Unknown error"
|
||||
wf.write(indata)
|
||||
|
@ -297,7 +310,7 @@ if __name__ == "__main__":
|
|||
sej_base = None
|
||||
|
||||
|
||||
v3 = SecCfgV3(hwc, MTK)
|
||||
v3.parse(data)
|
||||
ret, newdata = v3.create("lock")
|
||||
v4 = SecCfgV4(hwc, MTK)
|
||||
v4.parse(data)
|
||||
ret, newdata = v4.create("lock")
|
||||
print(newdata.hex())
|
||||
|
|
|
@ -42,6 +42,13 @@ class ArgHandler(metaclass=LogBase):
|
|||
config.pid = getint(args.pid)
|
||||
except AttributeError:
|
||||
pass
|
||||
config.stock = True
|
||||
try:
|
||||
if args.stock is not None:
|
||||
config.stock = args.stock
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
config.reconnect = True
|
||||
try:
|
||||
if args.noreconnect is not None:
|
||||
|
|
|
@ -82,8 +82,8 @@ class PLTools(metaclass=LogBase):
|
|||
return True
|
||||
elif response_ack == b"\xc1\xc2\xc3\xc4":
|
||||
if "preloader" in rf.name:
|
||||
ack = self.mtk.port.usbread(4)
|
||||
if ack == b"\xC0\xC0\xC0\xC0":
|
||||
rack = self.mtk.port.usbread(4)
|
||||
if rack == b"\xC0\xC0\xC0\xC0":
|
||||
with open("preloader.bin", 'wb') as wf:
|
||||
print_progress(0, 100, prefix='Progress:', suffix='Complete', bar_length=50)
|
||||
for pos in range(0, 0x40000, 64):
|
||||
|
|
|
@ -1115,7 +1115,7 @@ hwconfig = {
|
|||
socid_addr=0x102BA8,
|
||||
efuse_addr=0x11cb0000,
|
||||
damode=DAmodes.XFLASH,
|
||||
dacode=0x1066,
|
||||
dacode=0x6781,
|
||||
name="MT6781",
|
||||
description="Helio G96",
|
||||
loader="mt6781_payload.bin"
|
||||
|
@ -1471,7 +1471,7 @@ hwconfig = {
|
|||
damode=DAmodes.XML,
|
||||
dacode=0x1172,
|
||||
name="MT6895",
|
||||
description="Dimensity 8100"
|
||||
description="Dimensity 8200"
|
||||
# loader="mt6893_payload.bin"
|
||||
),
|
||||
# MT6789 Oppo Realme 10 / Gigaset GX4
|
||||
|
|
|
@ -69,6 +69,7 @@ class MtkConfig(metaclass=LogBase):
|
|||
self.sram = None
|
||||
self.dram = None
|
||||
self.otp = None
|
||||
self.stock = False
|
||||
if loglevel == logging.DEBUG:
|
||||
logfilename = os.path.join("logs", "log.txt")
|
||||
fh = logging.FileHandler(logfilename)
|
||||
|
|
|
@ -13,7 +13,7 @@ maintainers = [
|
|||
]
|
||||
readme = "README.md"
|
||||
license = {file = "LICENSE"}
|
||||
version = "2.0.1"
|
||||
version = "2.0.2"
|
||||
requires-python = ">= 3.8"
|
||||
dependencies = [
|
||||
"pyusb",
|
||||
|
|
Loading…
Reference in a new issue