-
-
Notifications
You must be signed in to change notification settings - Fork 493
Description
Some samsung loaders have an extra log that breaks edl writing.
EDL seems to assume no non-error logs will come after self.xmlsend has been ACK'd, but some loaders will actually send <log value="INFO: start_sector=26172, num_sectors=3" /> before starting to read our data. I don't know why, but edl seems to send all the data before the loader starts reading it, and by the time it does nothing is coming in, so it gets stuck in an infinite loop(?). EDL interprets this log as an error and writes firehose - [LIB]: Error:{}, all future calls to edl will hang.
I was able to work around this by adding self.wait_for_data() before writing.
This is obviously bad as it assumes no errors will come at this point, but as can bee seen in the decompiled code below(and in practice when writing some lun0 partitions) an error will be sent. Also it probably doesn't work on loaders without this log.
diff --git a/edlclient/Library/firehose.py b/edlclient/Library/firehose.py
index 93e7858..0083ac4 100755
--- a/edlclient/Library/firehose.py
+++ b/edlclient/Library/firehose.py
@@ -493,6 +493,9 @@ class firehose(metaclass=LogBase):
rsp = self.xmlsend(data, self.skipresponse)
progbar.show_progress(prefix="Write", pos=0, total=total, display=display)
if rsp.resp:
+ wd = self.wait_for_data()
+ print("Our broken log: ", wd)
+
while bytestowrite > 0:
wlen = min(bytestowrite, self.cfg.MaxPayloadSizeToTargetInBytes)
The affected loaders can be found by running grep -r "start_sector=%d, num_sectors=%d" in the Loaders repo, though I only tested 0000000000200000_666dc5b183834710_fhprg.bin(not merged).
Affected loaders
- Unmerged
samsung/0000000000200000_666dc5b183834710_fhprg.bin, the only one I actually tested. samsung/0000000000200000_18f91cb107db16e7_fhprg.binsamsung/0000000000200000_27fe520d8259d21a_fhprg.binsamsung/0000000000200000_320ecd66fba7f9b1_fhprg.binsamsung/0000000000200000_371ab117a61d3a6b_fhprg.binsamsung/0000000000200000_3dc5046245345178_fhprg.binsamsung/0000000000200000_4c0bf2437898c38e_fhprg.binsamsung/0000000000200000_57221a57066a14e0_fhprg.binsamsung/0000000000200000_585960a380533c2c_fhprg.binsamsung/0000000000200000_59cd3adfeeaf8f87_fhprg.binsamsung/0000000000200000_614c3cb6fe8bfee0_fhprg.binsamsung/0000000000200000_7e8ac4ee8d27363b_fhprg.binsamsung/0000000000200000_91c8c704d7fe059c_fhprg.binsamsung/0000000000200000_a0da75f4d371356f_fhprg.binsamsung/0000000000200000_adc06624e8eb216d_fhprg.binsamsung/0000000000200000_b64fa0e813ee4321_fhprg.binsamsung/0000000000200000_b6c0a48e991a5d86_fhprg.binsamsung/0000000000200000_bf7bae5174035818_fhprg.binsamsung/0000000000200000_c233729767656b6e_fhprg.binsamsung/0000000000200000_d6bd96b0682ee88a_fhprg.binsamsung/0000000000200000_ecdb07230e7294df_fhprg.binsamsung/0000000000200000_fbbe8b4ecf70b56c_fhprg.binsamsung/000950e100200000_27fe520d8259d21a_fhprg.binsamsung/000a50e100200000_0b5b6478293ddf9c_fhprg.binsamsung/000a50e100200000_3b0b67354f55dde5_fhprg.binsamsung/000a50e100200000_3b0b67354f55dde5_fhprg_2.binsamsung/000a50e100200000_3fd28b75e2557c5d_fhprg.binsamsung/000a50e100200000_45d5b07d5a34cd8c_fhprg.binsamsung/000a50e100200000_45d5b07d5a34cd8c_fhprg_2.binsamsung/000a50e100200000_ab28f20cfb2bd9fe_fhprg.binsamsung/000e60e100200000_94ec9a24b79bcc83_fhprg.binsamsung/001920E100200000_4A14C27B518909E1_fhprg.elf
Ghidra decompilation of the function with this log
undefined4 FUN_14838934(undefined8 param_1)
{
int *piVar1;
ulong uVar2;
int *piVar3;
long lVar4;
int iVar5;
int iVar6;
undefined4 uVar7;
long lVar8;
long lVar9;
long lVar10;
char *pcVar11;
undefined8 uVar12;
int *piVar13;
int *in_x4;
undefined8 in_x5;
undefined8 in_x6;
undefined8 in_x7;
long lVar14;
ulong uVar15;
int *piVar16;
long lVar17;
int *piVar18;
ulong local_b8;
int *local_b0;
int *local_a8;
long local_a0 [2];
int local_8c;
int local_88;
undefined4 uStack_84;
int local_80;
uint local_78 [2];
int *local_70;
ulong local_68;
local_8c = 0;
lVar8 = FUN_14840558(&local_a8);
if (((lVar8 == 0) || (local_a0[0] = lVar8, lVar9 = FUN_14840558(&local_b0), lVar9 == 0)) || (local_a8 != local_b0)) {
return 0xffffffff;
}
local_a0[1] = lVar9;
FUN_1483b02c(param_1,&local_88);
piVar13 = &local_8c;
lVar10 = FUN_1483b0c4(local_88,uStack_84,local_80);
if (lVar10 == 0) {
LAB_14838be0:
iVar5 = -1;
}
else {
iVar5 = FUN_1483b184(param_1,lVar10,local_78);
if ((iVar5 == 0) && (iVar5 = FUN_1483b24c(param_1,lVar10,local_68), iVar5 == 0)) {
piVar16 = (int *)(ulong)local_78[0];
iVar5 = FUN_1483b39c(lVar10,piVar16,local_88);
if (iVar5 == 0) {
piVar13 = (int *)0x1;
iVar5 = SEND_ACK_RESPONCE(lVar8,local_a8,1);
if (iVar5 == 0) {
piVar18 = (int *)((long)local_70 * (long)piVar16);
if (local_a8 <= piVar18 && (long)piVar18 - (long)local_a8 != 0) {
uVar15 = 0;
if (piVar16 != NULL) {
uVar15 = (ulong)local_a8 / (ulong)piVar16;
}
piVar18 = (int *)(uVar15 * (long)piVar16);
}
piVar13 = local_70;
/* This is the log that breaks */
SEND_EDL_LOG(INFO,"start_sector=%d, num_sectors=%d",local_68,local_70,in_x4,in_x5,in_x6,in_x7);
if (local_88 == 1) {
if ((local_68 < 0x108) && (((int *)0x108 < local_70 || (0x108 < (long)local_70 + local_68)))) {
LAB_14838bcc:
pcVar11 = "Not allowed to write into Protected area sectors for EDL Flash from Start Sector %lld";
}
else {
if (0x1fa9ff < local_68 - 0x108) goto LAB_14838acc;
pcVar11 = "Start sector %d not allowed through EDL Flash";
}
SEND_EDL_LOG(ERROR,pcVar11,local_68,piVar13,in_x4,in_x5,in_x6,in_x7);
goto LAB_14838be0;
}
if (local_80 == 0) {
if ((local_68 < 0x108) && (((int *)0x108 < local_70 || (0x108 < (long)local_70 + local_68)))) goto LAB_14838bcc;
if (local_68 - 0x108 < 0x1faa00) {
piVar13 = NULL;
SEND_EDL_LOG(ERROR,"Start sector %d not allowed for LUN %d through EDL Flash",local_68,0,in_x4,in_x5,in_x6,in_x7);
goto LAB_14838be0;
}
}
LAB_14838acc:
local_8c = FUN_1483f454(lVar8,piVar18);
lVar4 = 0;
uVar15 = local_68;
piVar18 = local_70;
lVar17 = 1;
while (lVar14 = lVar4, piVar18 != NULL) {
iVar5 = FUN_1483f77c(&local_b8);
if (iVar5 == 0) {
uVar2 = 0;
if (piVar16 != NULL) {
uVar2 = local_b8 / (ulong)piVar16;
}
if (local_b8 != uVar2 * (long)piVar16) {
local_8c = 0;
piVar13 = piVar16;
SEND_EDL_LOG(ERROR,"Read non multiple sector size value from USB %d sectsize%d",local_b8,piVar16,in_x4,in_x5,in_x6,in_x7);
}
}
piVar3 = NULL;
if (piVar16 != NULL) {
piVar3 = (int *)(local_b8 / (ulong)piVar16);
}
piVar18 = (int *)((long)piVar18 - (long)piVar3);
if (piVar18 != NULL) {
piVar13 = (int *)((long)piVar18 * (long)piVar16);
uVar2 = 0;
if (piVar16 != NULL) {
uVar2 = (ulong)local_a8 / (ulong)piVar16;
}
in_x4 = (int *)(uVar2 * (long)piVar16);
piVar1 = piVar13;
if (local_a8 <= piVar13 && (long)piVar13 - (long)local_a8 != 0) {
piVar1 = in_x4;
}
FUN_1483f454(local_a0[lVar17],piVar1);
}
if (local_8c == 0) {
piVar13 = piVar3;
local_8c = FUN_1483ca8c(lVar10,local_a0[lVar14],uVar15);
}
uVar15 = (long)piVar3 + uVar15;
lVar4 = lVar17;
lVar17 = lVar14;
}
iVar5 = 0;
}
}
}
}
iVar6 = FUN_1483b45c(lVar10);
if (iVar6 == 0) {
if (local_8c == 0 && iVar5 == 0) {
uVar12 = 1;
goto LAB_14838c18;
}
}
else {
SEND_EDL_LOG(ERROR,"Failed to close device%c",0x2e,piVar13,in_x4,in_x5,in_x6,in_x7);
}
uVar12 = 0;
LAB_14838c18:
uVar7 = SEND_ACK_RESPONCE(lVar8,local_a8,uVar12,0);
FUN_148405e0(lVar8);
FUN_148405e0(lVar9);
return uVar7;
}