summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2017-07-30 14:22:39 +0200
committerAmaury Pouly <amaury.pouly@gmail.com>2017-07-30 14:32:12 +0200
commitd1ca2e45e9ebab9f9e254317e625c0a40f377315 (patch)
treeae21739bd91fbd5eecba4c23b0b65f4f3b397c86
parent51984098ef2f60e0a1e4a870fc8842a8f7577413 (diff)
downloadrockbox-d1ca2e45e9ebab9f9e254317e625c0a40f377315.tar.gz
rockbox-d1ca2e45e9ebab9f9e254317e625c0a40f377315.zip
atjboottool: cleanup and add support for atj2127
Several people asked me recently how to decrypt atj2127 firmware. Someone posted on github (https://github.com/nfd/atj2127decrypt) a decrypt utility clearly reverse engineered from some unknown source. The code is an absolute horror but I concluded that ATJ changed very little between ATJ213x and ATJ2127 so I added support for the ATJ2127, credit to this github code that I stole and rewrite (code was under MIT licence). At the same time do some small code cleanups. Note that there is not 100% sure way that I know to distinguish between the two firmware types, so the code tries to do an educated guess to detect ATJ2127. If this does not work, use --atj21217 option. Also note that contrary to the github tool that decrypts and unpack in one go, this tool only does one step at once. So first decrypt: HEX -> AFI, then unpack AFI -> files. I also added for a different version of AFI. Based on AFI files I have, there are, I think, two versions: the "old" ones (pre-ATJ213x) and "new" ones. The tool only supported the new one but for some reason the ATJ2127 uses the old ones without a mostly empty header. Strangely, even this mostly empty header does not seem to follow the old layout as reverse engineered by the s1mp3 project (https://sourceforge.net/p/s1mp3/code/HEAD/tree/trunk/s1fwx/heads.h), so in fact there might be three versions. In any case, only the header is different, the rest of the file is identical so at the moment I just don't print any header info for "old" files. Change-Id: I1de61e64f433f6cacd239cd3c1ba469b9bb12442
-rw-r--r--utils/atj2137/atjboottool/atjboottool.c258
1 files changed, 203 insertions, 55 deletions
diff --git a/utils/atj2137/atjboottool/atjboottool.c b/utils/atj2137/atjboottool/atjboottool.c
index 44bf875309..5f4d8afd40 100644
--- a/utils/atj2137/atjboottool/atjboottool.c
+++ b/utils/atj2137/atjboottool/atjboottool.c
@@ -763,8 +763,8 @@ static int process_block_B(uint8_t block[512])
763 return 0; 763 return 0;
764} 764}
765 765
766static int do_fwu_v3(int size, uint8_t *buf, uint8_t *blockA, uint8_t *blockB, 766static int get_key_fwu_v3(int size, uint8_t *buf, uint8_t *blockA, uint8_t *blockB,
767 uint8_t *unk, uint8_t *unk2, uint8_t *blo) 767 uint8_t *keybuf, uint8_t *blo)
768{ 768{
769 (void) size; 769 (void) size;
770 uint8_t smallblock[512]; 770 uint8_t smallblock[512];
@@ -777,7 +777,7 @@ static int do_fwu_v3(int size, uint8_t *buf, uint8_t *blockA, uint8_t *blockB,
777 uint8_t bb = buf[0x1fe] & 0xf; 777 uint8_t bb = buf[0x1fe] & 0xf;
778 778
779 cprintf_field(" Block A: ", "%d\n", ba + 2); 779 cprintf_field(" Block A: ", "%d\n", ba + 2);
780 cprintf(" Block B: ", "%d\n", ba + bb + 5); 780 cprintf_field(" Block B: ", "%d\n", ba + bb + 5);
781 781
782 *blockA = buf[494] & 0xf; 782 *blockA = buf[494] & 0xf;
783 *blockB = buf[510] & 0xf; 783 *blockB = buf[510] & 0xf;
@@ -814,10 +814,10 @@ static int do_fwu_v3(int size, uint8_t *buf, uint8_t *blockA, uint8_t *blockB,
814 cprintf(GREEN, " Crypto 4: "); 814 cprintf(GREEN, " Crypto 4: ");
815 check_field(ret, 0, "Pass\n", "Fail\n"); 815 check_field(ret, 0, "Pass\n", "Fail\n");
816 816
817 memcpy(unk2, &smallbuf[17], 32); 817 memcpy(keybuf, &smallbuf[17], 32);
818 int offset = g_decode_A_info.nr_words + 91; 818 int offset = g_decode_A_info.nr_words + 91;
819 819
820 decode_block_with_swap(unk2, 0, &buf[offset], 512 - offset, g_perm_B); 820 decode_block_with_swap(keybuf, 0, &buf[offset], 512 - offset, g_perm_B);
821 821
822 int pos = *(uint16_t *)&buf[offset]; 822 int pos = *(uint16_t *)&buf[offset];
823 cprintf_field(" Word: ", "%d ", pos); 823 cprintf_field(" Word: ", "%d ", pos);
@@ -854,12 +854,6 @@ static int do_fwu_v3(int size, uint8_t *buf, uint8_t *blockA, uint8_t *blockB,
854 cprintf(GREEN, " Compare: "); 854 cprintf(GREEN, " Compare: ");
855 check_field(ret, 0, "Pass\n", "Fail\n"); 855 check_field(ret, 0, "Pass\n", "Fail\n");
856 856
857 uint8_t zero[16];
858 memset(zero, 0, sizeof(zero));
859 ret = memcmp(unk, zero, sizeof(zero));
860 cprintf(GREEN, " Sanity: ");
861 check_field(ret, 0, "Pass\n", "Fail\n");
862
863 /* 857 /*
864 ret = memcmp(midbuf + 25, zero, sizeof(zero)); 858 ret = memcmp(midbuf + 25, zero, sizeof(zero));
865 cprintf(GREEN, " Sanity: "); 859 cprintf(GREEN, " Sanity: ");
@@ -869,15 +863,81 @@ static int do_fwu_v3(int size, uint8_t *buf, uint8_t *blockA, uint8_t *blockB,
869 return 0; 863 return 0;
870} 864}
871 865
872static int do_sthg_fwu_v3(uint8_t *buf, int *size, uint8_t *unk, uint8_t *block) 866/* stolen from https://github.com/nfd/atj2127decrypt, I have no idea from where
867 * he got this sequence of code. This code is really weird, I copy verbatim
868 * his authors comment below. */
869uint32_t atj2127_key[] =
870{
871 0x42146ea2, 0x892c8e85, 0x9f9f6d27, 0x545fedc3,
872 0x09e5c0ca, 0x2dfa7e61, 0x4e5322e6, 0xb19185b9
873};
874
875/* decrypt a 512-byte sector */
876static void atj2127_decrypt_sector(void *inbuf, size_t size,
877 uint32_t session_key[8], int rounds_to_perform)
878{
879 uint32_t key[8];
880 for(int i = 0; i < 8; i++)
881 key[i] = atj2127_key[i] ^ session_key[i];
882 uint32_t *buf = inbuf;
883 if(size % 32)
884 cprintf(GREY, "Size is not a multiple of 32!!!\n");
885 while(rounds_to_perform > 0)
886 {
887 uint32_t rollover = buf[7] ^ session_key[7];
888
889 buf[0] ^= key[1];
890 buf[1] ^= key[2];
891 buf[2] ^= key[3];
892 buf[3] ^= key[4];
893 buf[4] ^= key[5];
894 buf[5] ^= key[6];
895 buf[6] ^= key[7];
896 buf[7] ^= key[1] ^ key[4];
897
898 key[1] = key[2];
899 key[2] = key[3];
900 key[3] = key[4];
901 key[4] = key[5];
902 key[5] = key[6];
903 key[6] = key[7];
904 key[7] = rollover;
905
906 buf += 8;
907 rounds_to_perform -= 1;
908 }
909}
910
911static void atj2127_decrypt(uint8_t *dst, const uint8_t *src, size_t size,
912 uint8_t keybuf[32], int rounds_to_perform)
913{
914 cprintf(BLUE, "ATJ2127:\n");
915 cprintf_field(" Rounds: ", "%d\n", rounds_to_perform);
916 while(size > 0)
917 {
918 int sec_sz = MIN(size, 512);
919 memcpy(dst, src, sec_sz);
920 atj2127_decrypt_sector(dst, sec_sz, (uint32_t *)keybuf, rounds_to_perform);
921 src += sec_sz;
922 dst += sec_sz;
923 size -= sec_sz;
924 }
925}
926
927static bool check_afi(uint8_t *buf, int size);
928
929static int decrypt_fwu_v3(uint8_t *buf, int *size, uint8_t block[512], bool force_atj2127)
873{ 930{
874 uint8_t blockA; 931 uint8_t blockA;
875 uint8_t blockB; 932 uint8_t blockB;
876 uint8_t unk2[32]; 933 uint8_t keybuf[32];
877 memset(unk2, 0, sizeof(unk2)); 934 memset(keybuf, 0, sizeof(keybuf));
878 int ret = do_fwu_v3(*size, buf, &blockA, &blockB, unk, unk2, block); 935 int ret = get_key_fwu_v3(*size, buf, &blockA, &blockB, keybuf, block);
879 continue_the_force(ret); 936 continue_the_force(ret);
880 937
938 int file_size = *size;
939 /* the input buffer is reorganized based on two offsets (blockA and blockB),
940 * skip 2048 bytes of data used for crypto init */
881 *size -= 2048; 941 *size -= 2048;
882 uint8_t *tmpbuf = malloc(*size); 942 uint8_t *tmpbuf = malloc(*size);
883 memset(tmpbuf, 0, *size); 943 memset(tmpbuf, 0, *size);
@@ -887,9 +947,54 @@ static int do_sthg_fwu_v3(uint8_t *buf, int *size, uint8_t *unk, uint8_t *block)
887 memcpy(tmpbuf + offsetA, buf + offsetA + 1536, offsetB); 947 memcpy(tmpbuf + offsetA, buf + offsetA + 1536, offsetB);
888 memcpy(tmpbuf + offsetA + offsetB, 948 memcpy(tmpbuf + offsetA + offsetB,
889 buf + offsetA + 1536 + offsetB + 512, *size - offsetA - offsetB); 949 buf + offsetA + 1536 + offsetB + 512, *size - offsetA - offsetB);
890 compute_perm(unk2, 32, g_perm_B); 950 /* stolen from https://github.com/nfd/atj2127decrypt, I have no idea from where
891 decode_perm(tmpbuf, *size, g_perm_B); 951 * he got this sequence of code. This code is really weird, I copy verbatim
892 memcpy(buf, tmpbuf, *size); 952 * his authors comment below.
953 *
954 * This is really weird. This is passed to the decrypt-sector function and
955 * determines how much of each 512-byte sector to decrypt, where for every
956 * 32MB of size above the first 32MB, one 32 byte chunk of each sector
957 * (starting from the end) will remain unencrypted, up to a maximum of 480
958 * bytes of plaintext. Was this a speed-related thing? It just seems
959 * completely bizarre. */
960
961 /* NOTE: the original code uses the file length to determine how much
962 * to encrypt and not the size reported in the header. Since
963 * the file size can be different from the size reported in the header
964 * (the infamous 512 bytes described above), this might be wrong. */
965 int rounds_to_perform = 16 - (file_size >> 0x19);
966 if(rounds_to_perform <= 0)
967 rounds_to_perform = 1;
968 /* the ATJ213x and ATJ2127 do not use the same encryption at this point, and I
969 * don't see any obvious way to tell which encryption is used (since they
970 * use the same version above). The only difference is that ATJ2127 images
971 * I have seen have an extra 512 bytes at the end file (ie the actual file
972 * is 512 bytes larger than indicated by the header) but I don't know if this
973 * is the case for all files. Thus, unless the user force encryption mode,
974 * try both and see if one looks like an AFI file. To guess which one to use,
975 * decrypt the first sector and see if it looks like an AFI file */
976 bool is_atj2127 = false;
977 if(force_atj2127)
978 is_atj2127 = true;
979 else
980 {
981 uint8_t hdr_buf[512];
982 atj2127_decrypt(hdr_buf, tmpbuf, sizeof(hdr_buf), keybuf, rounds_to_perform);
983 is_atj2127 = check_afi(hdr_buf, sizeof(hdr_buf));
984 if(is_atj2127)
985 cprintf(BLUE, "File looks like an ATJ2127 firmware\n");
986 else
987 cprintf(BLUE, "File does not looks like an ATJ2127 firmware\n");
988 }
989
990 if(is_atj2127)
991 atj2127_decrypt(buf, tmpbuf, *size, keybuf, rounds_to_perform);
992 else
993 {
994 compute_perm(keybuf, 32, g_perm_B);
995 decode_perm(tmpbuf, *size, g_perm_B);
996 memcpy(buf, tmpbuf, *size);
997 }
893 998
894 return 0; 999 return 0;
895} 1000}
@@ -925,7 +1030,7 @@ static void build_out_prefix(char *add, char *replace, bool slash)
925 } 1030 }
926} 1031}
927 1032
928static int do_fwu(uint8_t *buf, int size) 1033static int do_fwu(uint8_t *buf, int size, bool force_atj2127)
929{ 1034{
930 struct fwu_hdr_t *hdr = (void *)buf; 1035 struct fwu_hdr_t *hdr = (void *)buf;
931 1036
@@ -988,11 +1093,9 @@ static int do_fwu(uint8_t *buf, int size)
988 1093
989 if(g_version[ver].version == 3) 1094 if(g_version[ver].version == 3)
990 { 1095 {
991 uint8_t unk[32];
992 memset(unk, 0, sizeof(unk));
993 uint8_t block[512]; 1096 uint8_t block[512];
994 memset(block, 0, sizeof(block)); 1097 memset(block, 0, sizeof(block));
995 int ret = do_sthg_fwu_v3(buf, &size, unk, block); 1098 int ret = decrypt_fwu_v3(buf, &size, block, force_atj2127);
996 continue_the_force(ret); 1099 continue_the_force(ret);
997 1100
998 cprintf(GREY, "Descrambling to %s... ", g_out_prefix); 1101 cprintf(GREY, "Descrambling to %s... ", g_out_prefix);
@@ -1198,7 +1301,7 @@ static int do_afi(uint8_t *buf, int size)
1198 return 0; 1301 return 0;
1199} 1302}
1200 1303
1201static bool check_afi(uint8_t *buf, int size) 1304bool check_afi(uint8_t *buf, int size)
1202{ 1305{
1203 struct afi_hdr_t *hdr = (void *)buf; 1306 struct afi_hdr_t *hdr = (void *)buf;
1204 1307
@@ -1257,11 +1360,28 @@ struct fw_hdr_t
1257 struct fw_entry_t entry[FW_ENTRIES]; 1360 struct fw_entry_t entry[FW_ENTRIES];
1258} __attribute__((packed)); 1361} __attribute__((packed));
1259 1362
1260const uint8_t g_fw_signature[FW_SIG_SIZE] = 1363/* the s1fwx source code has a layout but it does not make any sense for firmwares
1364 * found in ATJ2127 for example. In doubt just don't do anything */
1365struct fw_hdr_f0_t
1366{
1367 uint8_t sig[FW_SIG_SIZE];
1368 uint8_t res[12];
1369 uint32_t checksum;
1370 uint8_t res2[492];
1371
1372 struct fw_entry_t entry[FW_ENTRIES];
1373} __attribute__((packed));
1374
1375const uint8_t g_fw_signature_f2[FW_SIG_SIZE] =
1261{ 1376{
1262 0x55, 0xaa, 0xf2, 0x0f 1377 0x55, 0xaa, 0xf2, 0x0f
1263}; 1378};
1264 1379
1380const uint8_t g_fw_signature_f0[FW_SIG_SIZE] =
1381{
1382 0x55, 0xaa, 0xf0, 0x0f
1383};
1384
1265static void build_filename_fw(char buf[16], struct fw_entry_t *ent) 1385static void build_filename_fw(char buf[16], struct fw_entry_t *ent)
1266{ 1386{
1267 int pos = 0; 1387 int pos = 0;
@@ -1286,42 +1406,60 @@ static int do_fw(uint8_t *buf, int size)
1286 cprintf(GREEN, " Signature:"); 1406 cprintf(GREEN, " Signature:");
1287 for(int i = 0; i < FW_SIG_SIZE; i++) 1407 for(int i = 0; i < FW_SIG_SIZE; i++)
1288 cprintf(YELLOW, " %02x", hdr->sig[i]); 1408 cprintf(YELLOW, " %02x", hdr->sig[i]);
1289 if(memcmp(hdr->sig, g_fw_signature, FW_SIG_SIZE) == 0) 1409 int variant = 0;
1290 cprintf(RED, " Ok\n"); 1410 if(memcmp(hdr->sig, g_fw_signature_f2, FW_SIG_SIZE) == 0)
1411 {
1412 variant = 0xf2;
1413 cprintf(RED, " Ok (f2 variant)\n");
1414 }
1415 else if(memcmp(hdr->sig, g_fw_signature_f0, FW_SIG_SIZE) == 0)
1416 {
1417 variant = 0xf0;
1418 cprintf(RED, " Ok (f0 variant)\n");
1419 }
1291 else 1420 else
1292 { 1421 {
1293 cprintf(RED, " Mismatch\n"); 1422 cprintf(RED, " Mismatch\n");
1294 let_the_force_flow(__LINE__); 1423 let_the_force_flow(__LINE__);
1295 } 1424 }
1296 1425
1297 cprintf_field(" USB VID: ", "0x%x\n", hdr->usb_vid); 1426 /* both variants have the same header size, only the fields differ */
1298 cprintf_field(" USB PID: ", "0x%x\n", hdr->usb_pid); 1427 if(variant == 0xf2)
1299 cprintf_field(" Date: ", "%x/%x/%x%x\n", hdr->day, hdr->month, hdr->year[0], hdr->year[1]); 1428 {
1300 cprintf_field(" Checksum: ", "%x\n", hdr->checksum); 1429 cprintf_field(" USB VID: ", "0x%x\n", hdr->usb_vid);
1301 cprintf_field(" Productor: ", "%.16s\n", hdr->productor); 1430 cprintf_field(" USB PID: ", "0x%x\n", hdr->usb_pid);
1302 cprintf_field(" String 2: ", "%.16s\n", hdr->str2); 1431 cprintf_field(" Date: ", "%x/%x/%02x%02x\n", hdr->day, hdr->month, hdr->year[0], hdr->year[1]);
1303 cprintf_field(" String 3: ", "%.32s\n", hdr->str3); 1432 cprintf_field(" Checksum: ", "%x\n", hdr->checksum);
1304 cprintf_field(" Device Name: ", "%.32s\n", hdr->dev_name); 1433 cprintf_field(" Productor: ", "%.16s\n", hdr->productor);
1305 cprintf(GREEN, " Unknown:\n"); 1434 cprintf_field(" String 2: ", "%.16s\n", hdr->str2);
1306 for(int i = 0; i < 8; i++) 1435 cprintf_field(" String 3: ", "%.32s\n", hdr->str3);
1436 cprintf_field(" Device Name: ", "%.32s\n", hdr->dev_name);
1437 cprintf(GREEN, " Unknown:\n");
1438 for(int i = 0; i < 8; i++)
1439 {
1440 cprintf(YELLOW, " ");
1441 for(int j = 0; j < 16; j++)
1442 cprintf(YELLOW, "%02x ", hdr->res2[i * 16 + j]);
1443 cprintf(YELLOW, "\n");
1444 }
1445 cprintf_field(" USB Name 1: ", "%.8s\n", hdr->usb_name1);
1446 cprintf_field(" USB Name 2: ", "%.8s\n", hdr->usb_name2);
1447 cprintf_field(" MTP Name 1: ", "%.32s\n", hdr->mtp_name1);
1448 cprintf_field(" MTP Name 2: ", "%.32s\n", hdr->mtp_name2);
1449 cprintf_field(" MTP Version: ", "%.32s\n", hdr->mtp_ver);
1450
1451 cprintf_field(" MTP VID: ", "0x%x\n", hdr->mtp_vid);
1452 cprintf_field(" MTP PID: ", "0x%x\n", hdr->mtp_pid);
1453 cprintf_field(" FW Version: ", "%.64s\n", hdr->fw_ver);
1454 }
1455 else
1307 { 1456 {
1308 cprintf(YELLOW, " "); 1457 struct fw_hdr_f0_t *hdr_f0 = (void *)hdr;
1309 for(int j = 0; j < 16; j++) 1458 cprintf(GREEN, " Header not dumped because format is unclear.\n");
1310 cprintf(YELLOW, "%02x ", hdr->res2[i * 16 + j]);
1311 cprintf(YELLOW, "\n");
1312 } 1459 }
1313 cprintf_field(" USB Name 1: ", "%.8s\n", hdr->usb_name1);
1314 cprintf_field(" USB Name 2: ", "%.8s\n", hdr->usb_name2);
1315 cprintf_field(" MTP Name 1: ", "%.32s\n", hdr->mtp_name1);
1316 cprintf_field(" MTP Name 2: ", "%.32s\n", hdr->mtp_name2);
1317 cprintf_field(" MTP Version: ", "%.32s\n", hdr->mtp_ver);
1318
1319 cprintf_field(" MTP VID: ", "0x%x\n", hdr->mtp_vid);
1320 cprintf_field(" MTP PID: ", "0x%x\n", hdr->mtp_pid);
1321 cprintf_field(" FW Version: ", "%.64s\n", hdr->fw_ver);
1322 1460
1323 build_out_prefix(".unpack", "", true); 1461 build_out_prefix(".unpack", "", true);
1324 1462
1325 cprintf(BLUE, "Entries\n"); 1463 cprintf(BLUE, "Entries\n");
1326 for(int i = 0; i < AFI_ENTRIES; i++) 1464 for(int i = 0; i < AFI_ENTRIES; i++)
1327 { 1465 {
@@ -1365,7 +1503,11 @@ static bool check_fw(uint8_t *buf, int size)
1365 1503
1366 if(size < (int)sizeof(struct fw_hdr_t)) 1504 if(size < (int)sizeof(struct fw_hdr_t))
1367 return false; 1505 return false;
1368 return memcmp(hdr->sig, g_fw_signature, FW_SIG_SIZE) == 0; 1506 if(memcmp(hdr->sig, g_fw_signature_f2, FW_SIG_SIZE) == 0)
1507 return true;
1508 if(memcmp(hdr->sig, g_fw_signature_f0, FW_SIG_SIZE) == 0)
1509 return true;
1510 return false;
1369} 1511}
1370 1512
1371static void usage(void) 1513static void usage(void)
@@ -1380,6 +1522,7 @@ static void usage(void)
1380 printf(" --fwu\tUnpack a FWU firmware file\n"); 1522 printf(" --fwu\tUnpack a FWU firmware file\n");
1381 printf(" --afi\tUnpack a AFI archive file\n"); 1523 printf(" --afi\tUnpack a AFI archive file\n");
1382 printf(" --fw\tUnpack a FW archive file\n"); 1524 printf(" --fw\tUnpack a FW archive file\n");
1525 printf(" --atj2127\tForce ATJ2127 decryption mode\n");
1383 printf("The default is to try to guess the format.\n"); 1526 printf("The default is to try to guess the format.\n");
1384 printf("If several formats are specified, all are tried.\n"); 1527 printf("If several formats are specified, all are tried.\n");
1385 printf("If no output prefix is specified, a default one is picked.\n"); 1528 printf("If no output prefix is specified, a default one is picked.\n");
@@ -1391,7 +1534,8 @@ int main(int argc, char **argv)
1391 bool try_fwu = false; 1534 bool try_fwu = false;
1392 bool try_afi = false; 1535 bool try_afi = false;
1393 bool try_fw = false; 1536 bool try_fw = false;
1394 1537 bool force_atj2127 = false;
1538
1395 while(1) 1539 while(1)
1396 { 1540 {
1397 static struct option long_options[] = 1541 static struct option long_options[] =
@@ -1403,6 +1547,7 @@ int main(int argc, char **argv)
1403 {"fwu", no_argument, 0, 'u'}, 1547 {"fwu", no_argument, 0, 'u'},
1404 {"afi", no_argument, 0, 'a'}, 1548 {"afi", no_argument, 0, 'a'},
1405 {"fw", no_argument, 0, 'w'}, 1549 {"fw", no_argument, 0, 'w'},
1550 {"atj2127", no_argument, 0, '2'},
1406 {0, 0, 0, 0} 1551 {0, 0, 0, 0}
1407 }; 1552 };
1408 1553
@@ -1437,6 +1582,9 @@ int main(int argc, char **argv)
1437 case 'w': 1582 case 'w':
1438 try_fw = true; 1583 try_fw = true;
1439 break; 1584 break;
1585 case '2':
1586 force_atj2127 = true;
1587 break;
1440 default: 1588 default:
1441 abort(); 1589 abort();
1442 } 1590 }
@@ -1471,12 +1619,12 @@ int main(int argc, char **argv)
1471 perror("Cannot read file"); 1619 perror("Cannot read file");
1472 return 1; 1620 return 1;
1473 } 1621 }
1474 1622
1475 fclose(fin); 1623 fclose(fin);
1476 1624
1477 int ret = -99; 1625 int ret = -99;
1478 if(try_fwu || check_fwu(buf, size)) 1626 if(try_fwu || check_fwu(buf, size))
1479 ret = do_fwu(buf, size); 1627 ret = do_fwu(buf, size, force_atj2127);
1480 else if(try_afi || check_afi(buf, size)) 1628 else if(try_afi || check_afi(buf, size))
1481 ret = do_afi(buf, size); 1629 ret = do_afi(buf, size);
1482 else if(try_fw || check_fw(buf, size)) 1630 else if(try_fw || check_fw(buf, size))
@@ -1486,7 +1634,7 @@ int main(int argc, char **argv)
1486 cprintf(GREY, "No valid format found\n"); 1634 cprintf(GREY, "No valid format found\n");
1487 ret = 1; 1635 ret = 1;
1488 } 1636 }
1489 1637
1490 if(ret != 0) 1638 if(ret != 0)
1491 { 1639 {
1492 cprintf(GREY, "Error: %d", ret); 1640 cprintf(GREY, "Error: %d", ret);