summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2007-09-08 23:27:49 +0000
committerDave Chapman <dave@dchapman.com>2007-09-08 23:27:49 +0000
commit6e7971553e021a7fe72987490439bf9a5475fb44 (patch)
treeaaa6074b94e30cf4e37fed446b30ce059f36dbaa
parent6c24189d27f1bdd6f2e0458ada99a8d7e5896689 (diff)
downloadrockbox-6e7971553e021a7fe72987490439bf9a5475fb44.tar.gz
rockbox-6e7971553e021a7fe72987490439bf9a5475fb44.zip
Add functions to read and write the AUPD (flash update) image. "--read-aupd aupd.bin" will read (and decrypt) the AUPD image, and "--write-aupd aupd.bin" will write (and encrypt) an image. Also fix a bug in the "diskmove" function which corrupted the AUPD image when a bootloader was installed. So in order to manipulate the aupd image, you need to restore a clean firmware partition, and install the bootloader with this version of ipodpatcher. Decryption functions based on the description and sample code at http://ipodlinux.org/Flash_Decryption
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14644 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--rbutil/ipodpatcher/Makefile2
-rw-r--r--rbutil/ipodpatcher/arc4.c108
-rw-r--r--rbutil/ipodpatcher/arc4.h47
-rw-r--r--rbutil/ipodpatcher/ipodpatcher.c349
-rw-r--r--rbutil/ipodpatcher/ipodpatcher.h2
-rw-r--r--rbutil/ipodpatcher/main.c32
6 files changed, 537 insertions, 3 deletions
diff --git a/rbutil/ipodpatcher/Makefile b/rbutil/ipodpatcher/Makefile
index f65234a505..f76715b9f6 100644
--- a/rbutil/ipodpatcher/Makefile
+++ b/rbutil/ipodpatcher/Makefile
@@ -22,7 +22,7 @@ endif
22NATIVECC = gcc 22NATIVECC = gcc
23CC = $(CROSS)gcc 23CC = $(CROSS)gcc
24 24
25SRC = main.c ipodpatcher.c fat32format.c parttypes.h 25SRC = main.c ipodpatcher.c fat32format.c parttypes.h arc4.c
26 26
27all: $(OUTPUT) 27all: $(OUTPUT)
28 28
diff --git a/rbutil/ipodpatcher/arc4.c b/rbutil/ipodpatcher/arc4.c
new file mode 100644
index 0000000000..75b1862b89
--- /dev/null
+++ b/rbutil/ipodpatcher/arc4.c
@@ -0,0 +1,108 @@
1/*
2 * arc4.c
3 * Release $Name: MATRIXSSL_1_8_3_OPEN $
4 *
5 * ARC4 stream cipher implementation
6 */
7/*
8 * Copyright (c) PeerSec Networks, 2002-2007. All Rights Reserved.
9 * The latest version of this code is available at http://www.matrixssl.org
10 *
11 * This software is open source; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This General Public License does NOT permit incorporating this software
17 * into proprietary programs. If you are unable to comply with the GPL, a
18 * commercial license for this software may be purchased from PeerSec Networks
19 * at http://www.peersec.com
20 *
21 * This program is distributed in WITHOUT ANY WARRANTY; without even the
22 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 * See the GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * http://www.gnu.org/copyleft/gpl.html
29 */
30/******************************************************************************/
31
32#include "arc4.h"
33
34/*
35 Some accounts, such as O'Reilly's Secure Programming Cookbook say that no
36 more than 2^30 bytes should be processed without rekeying, so we
37 enforce that limit here. FYI, this is equal to 1GB of data transferred.
38*/
39#define ARC4_MAX_BYTES 0x40000000
40
41/******************************************************************************/
42/*
43 SSL_RSA_WITH_RC4_* cipher callbacks
44 */
45void matrixArc4Init(struct rc4_key_t *ctx, unsigned char *key, int32_t keylen)
46{
47 unsigned char index1, index2, tmp, *state;
48 int16_t counter;
49
50 ctx->byteCount = 0;
51 state = &ctx->state[0];
52
53 for (counter = 0; counter < 256; counter++) {
54 state[counter] = (unsigned char)counter;
55 }
56 ctx->x = 0;
57 ctx->y = 0;
58 index1 = 0;
59 index2 = 0;
60
61 for (counter = 0; counter < 256; counter++) {
62 index2 = (key[index1] + state[counter] + index2) & 0xff;
63
64 tmp = state[counter];
65 state[counter] = state[index2];
66 state[index2] = tmp;
67
68 index1 = (index1 + 1) % keylen;
69 }
70}
71
72int32_t matrixArc4(struct rc4_key_t *ctx, unsigned char *in,
73 unsigned char *out, int32_t len)
74{
75 unsigned char x, y, *state, xorIndex, tmp;
76 int counter; /* NOTE BY DAVE CHAPMAN: This was a short in
77 the original code, which caused a segfault
78 when attempting to process data > 32767
79 bytes. */
80
81 ctx->byteCount += len;
82 if (ctx->byteCount > ARC4_MAX_BYTES) {
83 return -1;
84 }
85
86 x = ctx->x;
87 y = ctx->y;
88 state = &ctx->state[0];
89 for (counter = 0; counter < len; counter++) {
90 x = (x + 1) & 0xff;
91 y = (state[x] + y) & 0xff;
92
93 tmp = state[x];
94 state[x] = state[y];
95 state[y] = tmp;
96
97 xorIndex = (state[x] + state[y]) & 0xff;
98
99 tmp = in[counter];
100 tmp ^= state[xorIndex];
101 out[counter] = tmp;
102 }
103 ctx->x = x;
104 ctx->y = y;
105 return len;
106}
107
108/*****************************************************************************/
diff --git a/rbutil/ipodpatcher/arc4.h b/rbutil/ipodpatcher/arc4.h
new file mode 100644
index 0000000000..8bff0e2dc1
--- /dev/null
+++ b/rbutil/ipodpatcher/arc4.h
@@ -0,0 +1,47 @@
1/*
2 arc4.h - based on matrixssl-1-8-3-open
3
4*/
5
6/*
7 * Copyright (c) PeerSec Networks, 2002-2007. All Rights Reserved.
8 * The latest version of this code is available at http://www.matrixssl.org
9 *
10 * This software is open source; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This General Public License does NOT permit incorporating this software
16 * into proprietary programs. If you are unable to comply with the GPL, a
17 * commercial license for this software may be purchased from PeerSec Networks
18 * at http://www.peersec.com
19 *
20 * This program is distributed in WITHOUT ANY WARRANTY; without even the
21 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 * See the GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * http://www.gnu.org/copyleft/gpl.html
28 */
29/*****************************************************************************/
30
31#ifndef _ARC4_H
32
33#include <stdint.h>
34
35struct rc4_key_t
36{
37 unsigned char state[256];
38 uint32_t byteCount;
39 unsigned char x;
40 unsigned char y;
41};
42
43void matrixArc4Init(struct rc4_key_t *ctx, unsigned char *key, int32_t keylen);
44int32_t matrixArc4(struct rc4_key_t *ctx, unsigned char *in,
45 unsigned char *out, int32_t len);
46
47#endif
diff --git a/rbutil/ipodpatcher/ipodpatcher.c b/rbutil/ipodpatcher/ipodpatcher.c
index 2655c57113..08ba9263d2 100644
--- a/rbutil/ipodpatcher/ipodpatcher.c
+++ b/rbutil/ipodpatcher/ipodpatcher.c
@@ -23,6 +23,7 @@
23#include <string.h> 23#include <string.h>
24#include <stdlib.h> 24#include <stdlib.h>
25#include <inttypes.h> 25#include <inttypes.h>
26#include <stdbool.h>
26#include <sys/types.h> 27#include <sys/types.h>
27#include <sys/stat.h> 28#include <sys/stat.h>
28 29
@@ -41,6 +42,10 @@
41#include "ipodvideo.h" 42#include "ipodvideo.h"
42#endif 43#endif
43 44
45#ifndef RBUTIL
46#include "arc4.h"
47#endif
48
44extern int verbose; 49extern int verbose;
45 50
46unsigned char* sectorbuf; 51unsigned char* sectorbuf;
@@ -392,7 +397,7 @@ int diskmove(struct ipod_t* ipod, int delta)
392 int chunksize; 397 int chunksize;
393 int n; 398 int n;
394 399
395 src_start = ipod->ipod_directory[1].devOffset + ipod->sector_size; 400 src_start = ipod->ipod_directory[1].devOffset;
396 src_end = (ipod->ipod_directory[ipod->nimages-1].devOffset + ipod->sector_size + 401 src_end = (ipod->ipod_directory[ipod->nimages-1].devOffset + ipod->sector_size +
397 ipod->ipod_directory[ipod->nimages-1].len + 402 ipod->ipod_directory[ipod->nimages-1].len +
398 (ipod->sector_size-1)) & ~(ipod->sector_size-1); 403 (ipod->sector_size-1)) & ~(ipod->sector_size-1);
@@ -575,7 +580,7 @@ int add_bootloader(struct ipod_t* ipod, char* filename, int type)
575 ipod->ipod_directory[1].devOffset) { 580 ipod->ipod_directory[1].devOffset) {
576 fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n"); 581 fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n");
577 delta = ipod->ipod_directory[0].devOffset + entryOffset+paddedlength 582 delta = ipod->ipod_directory[0].devOffset + entryOffset+paddedlength
578 - ipod->ipod_directory[1].devOffset; 583 - ipod->ipod_directory[1].devOffset + ipod->sector_size;
579 584
580 if (diskmove(ipod, delta) < 0) { 585 if (diskmove(ipod, delta) < 0) {
581 fprintf(stderr,"[ERR] Image movement failed.\n"); 586 fprintf(stderr,"[ERR] Image movement failed.\n");
@@ -1373,3 +1378,343 @@ int write_dos_partition_table(struct ipod_t* ipod)
1373 1378
1374 return 0; 1379 return 0;
1375} 1380}
1381
1382#ifndef RBUTIL
1383
1384static inline uint32_t getuint32le(unsigned char* buf)
1385{
1386 int32_t res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
1387
1388 return res;
1389}
1390
1391/* testMarker and GetSecurityBlockKey based on code from BadBlocks and
1392 Kingstone, posted at http://ipodlinux.org/Flash_Decryption
1393
1394*/
1395
1396static bool testMarker(int marker)
1397{
1398 int mask, decrypt, temp1, temp2;
1399
1400 mask = (marker&0xff)|((marker&0xff)<<8)|((marker&0xff)<<16)|((marker&0xff)<<24);
1401 decrypt = marker ^ mask;
1402 temp1=(int)((unsigned int)decrypt>>24);
1403 temp2=decrypt<<8;
1404
1405 if (temp1==0)
1406 return false;
1407
1408 temp2=(int)((unsigned int)temp2>>24);
1409 decrypt=decrypt<<16;
1410 decrypt=(int)((unsigned int)decrypt>>24);
1411
1412 if ((temp1 < temp2) && (temp2 < decrypt))
1413 {
1414 temp1 = temp1 & 0xf;
1415 temp2 = temp2 & 0xf;
1416 decrypt = decrypt & 0xf;
1417
1418 if ((temp1 > temp2) && (temp2 > decrypt) && (decrypt != 0))
1419 {
1420 return true;
1421 }
1422 }
1423 return false;
1424}
1425
1426static int GetSecurityBlockKey(unsigned char *data, unsigned char* this_key)
1427{
1428 int constant = 0x54c3a298;
1429 int key=0;
1430 int nkeys = 0;
1431 int aMarker=0;
1432 int pos=0;
1433 int c, count;
1434 int temp1;
1435 static const int offset[8]={0x5,0x25,0x6f,0x69,0x15,0x4d,0x40,0x34};
1436
1437 for (c = 0; c < 8; c++)
1438 {
1439 pos = offset[c]*4;
1440 aMarker = getuint32le(data + pos);
1441
1442 if (testMarker(aMarker))
1443 {
1444 if (c<7)
1445 pos =(offset[c+1]*4)+4;
1446 else
1447 pos =(offset[0]*4)+4;
1448
1449 key=0;
1450
1451 temp1=aMarker;
1452
1453 for (count=0;count<2;count++){
1454 int word = getuint32le(data + pos);
1455 temp1 = aMarker;
1456 temp1 = temp1^word;
1457 temp1 = temp1^constant;
1458 key = temp1;
1459 pos = pos+4;
1460 }
1461 int r1=0x6f;
1462 int r2=0;
1463 int r12;
1464 int r14;
1465 unsigned int r_tmp;
1466
1467 for (count=2;count<128;count=count+2){
1468 r2=getuint32le(data+count*4);
1469 r12=getuint32le(data+(count*4)+4);
1470 r_tmp=(unsigned int)r12>>16;
1471 r14=r2 | ((int)r_tmp);
1472 r2=r2&0xffff;
1473 r2=r2 | r12;
1474 r1=r1^r14;
1475 r1=r1+r2;
1476 }
1477 key=key^r1;
1478
1479 // Invert key, little endian
1480 this_key[0] = key & 0xff;
1481 this_key[1] = (key >> 8) & 0xff;
1482 this_key[2] = (key >> 16) & 0xff;
1483 this_key[3] = (key >> 24) & 0xff;
1484 nkeys++;
1485 }
1486 }
1487 return nkeys;
1488}
1489
1490static int find_key(struct ipod_t* ipod, int aupd, unsigned char* key)
1491{
1492 int n;
1493
1494 /* Firstly read the security block and find the RC4 key. This is
1495 in the sector preceeding the AUPD image. */
1496
1497 fprintf(stderr, "[INFO] Reading security block at offset 0x%08x\n",ipod->ipod_directory[aupd].devOffset-ipod->sector_size);
1498 if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[aupd].devOffset-ipod->sector_size) < 0) {
1499 return -1;
1500 }
1501
1502 if ((n = ipod_read(ipod, sectorbuf, 512)) < 0) {
1503 return -1;
1504 }
1505
1506 n = GetSecurityBlockKey(sectorbuf, key);
1507
1508 if (n != 1)
1509 {
1510 fprintf(stderr, "[ERR] %d keys found in security block, can not continue\n",n);
1511 return -1;
1512 }
1513
1514 return 0;
1515}
1516
1517int read_aupd(struct ipod_t* ipod, char* filename)
1518{
1519 int length;
1520 int i;
1521 int outfile;
1522 int n;
1523 int aupd;
1524 struct rc4_key_t rc4;
1525 unsigned char key[4];
1526 unsigned long chksum=0;
1527
1528 aupd = 0;
1529 while ((aupd < ipod->nimages) && (ipod->ipod_directory[aupd].ftype != FTYPE_AUPD))
1530 {
1531 aupd++;
1532 }
1533
1534 if (aupd == ipod->nimages)
1535 {
1536 fprintf(stderr,"[ERR] No AUPD image in firmware partition.\n");
1537 return -1;
1538 }
1539
1540 length = ipod->ipod_directory[aupd].len;
1541
1542 fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length);
1543
1544 if (find_key(ipod, aupd, key) < 0)
1545 {
1546 return -1;
1547 }
1548
1549 fprintf(stderr, "[INFO] Decrypting AUPD image with key %02x%02x%02x%02x\n",key[0],key[1],key[2],key[3]);
1550
1551 if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[aupd].devOffset) < 0) {
1552 return -1;
1553 }
1554
1555 i = (length+ipod->sector_size-1) & ~(ipod->sector_size-1);
1556
1557 if ((n = ipod_read(ipod,sectorbuf,i)) < 0) {
1558 return -1;
1559 }
1560
1561 if (n < i) {
1562 fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n",
1563 i,n);
1564 return -1;
1565 }
1566
1567 /* Perform the decryption - this is standard (A)RC4 */
1568 matrixArc4Init(&rc4, key, 4);
1569 matrixArc4(&rc4, sectorbuf, sectorbuf, length);
1570
1571 chksum = 0;
1572 for (i = 0; i < (int)length; i++) {
1573 /* add 8 unsigned bits but keep a 32 bit sum */
1574 chksum += sectorbuf[i];
1575 }
1576
1577 if (chksum != ipod->ipod_directory[aupd].chksum)
1578 {
1579 fprintf(stderr,"[ERR] Decryption failed - checksum error\n");
1580 return -1;
1581 }
1582 fprintf(stderr,"[INFO] Decrypted OK (checksum matches header)\n");
1583
1584 outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666);
1585 if (outfile < 0) {
1586 fprintf(stderr,"[ERR] Couldn't open file %s\n",filename);
1587 return -1;
1588 }
1589
1590 n = write(outfile,sectorbuf,length);
1591 if (n != length) {
1592 fprintf(stderr,"[ERR] Write error - %d\n",n);
1593 }
1594 close(outfile);
1595
1596 return 0;
1597}
1598
1599int write_aupd(struct ipod_t* ipod, char* filename)
1600{
1601 unsigned int length;
1602 int i;
1603 int x;
1604 int n;
1605 int infile;
1606 int newsize;
1607 int aupd;
1608 unsigned long chksum=0;
1609 struct rc4_key_t rc4;
1610 unsigned char key[4];
1611
1612 /* First check that the input file is the correct type for this ipod. */
1613 infile=open(filename,O_RDONLY);
1614 if (infile < 0) {
1615 fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename);
1616 return -1;
1617 }
1618
1619 length = filesize(infile);
1620 newsize=(length+ipod->sector_size-1)&~(ipod->sector_size-1);
1621
1622 fprintf(stderr,"[INFO] Padding input file from 0x%08x to 0x%08x bytes\n",
1623 length,newsize);
1624
1625 if (newsize > BUFFER_SIZE) {
1626 fprintf(stderr,"[ERR] Input file too big for buffer\n");
1627 if (infile >= 0) close(infile);
1628 return -1;
1629 }
1630
1631 /* Find aupd image number */
1632 aupd = 0;
1633 while ((aupd < ipod->nimages) && (ipod->ipod_directory[aupd].ftype != FTYPE_AUPD))
1634 {
1635 aupd++;
1636 }
1637
1638 if (aupd == ipod->nimages)
1639 {
1640 fprintf(stderr,"[ERR] No AUPD image in firmware partition.\n");
1641 return -1;
1642 }
1643
1644 if (length != ipod->ipod_directory[aupd].len)
1645 {
1646 fprintf(stderr,"[ERR] AUPD image (%d bytes) differs in size to %s (%d bytes).\n",
1647 ipod->ipod_directory[aupd].len, filename, length);
1648 return -1;
1649 }
1650
1651 if (find_key(ipod, aupd, key) < 0)
1652 {
1653 return -1;
1654 }
1655
1656 fprintf(stderr, "[INFO] Encrypting AUPD image with key %02x%02x%02x%02x\n",key[0],key[1],key[2],key[3]);
1657
1658 /* We now know we have enough space, so write it. */
1659
1660 fprintf(stderr,"[INFO] Reading input file...\n");
1661 n = read(infile,sectorbuf,length);
1662 if (n < 0) {
1663 fprintf(stderr,"[ERR] Couldn't read input file\n");
1664 close(infile);
1665 return -1;
1666 }
1667 close(infile);
1668
1669 /* Pad the data with zeros */
1670 memset(sectorbuf+length,0,newsize-length);
1671
1672 /* Calculate the new checksum (before we encrypt) */
1673 chksum = 0;
1674 for (i = 0; i < (int)length; i++) {
1675 /* add 8 unsigned bits but keep a 32 bit sum */
1676 chksum += sectorbuf[i];
1677 }
1678
1679 /* Perform the encryption - this is standard (A)RC4 */
1680 matrixArc4Init(&rc4, key, 4);
1681 matrixArc4(&rc4, sectorbuf, sectorbuf, length);
1682
1683 if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[aupd].devOffset) < 0) {
1684 fprintf(stderr,"[ERR] Seek failed\n");
1685 return -1;
1686 }
1687
1688 if ((n = ipod_write(ipod,sectorbuf,newsize)) < 0) {
1689 perror("[ERR] Write failed\n");
1690 return -1;
1691 }
1692
1693 if (n < newsize) {
1694 fprintf(stderr,"[ERR] Short write - requested %d bytes, received %d\n"
1695 ,newsize,n);
1696 return -1;
1697 }
1698 fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",n);
1699
1700 x = ipod->diroffset % ipod->sector_size;
1701
1702 /* Read directory */
1703 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; }
1704
1705 n=ipod_read(ipod, sectorbuf, ipod->sector_size);
1706 if (n < 0) { return -1; }
1707
1708 /* Update checksum */
1709 fprintf(stderr,"[INFO] Updating checksum to 0x%08x (was 0x%08x)\n",(unsigned int)chksum,le2int(sectorbuf + x + aupd*40 + 28));
1710 int2le(chksum,sectorbuf+x+aupd*40+28);
1711
1712 /* Write directory */
1713 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; }
1714 n=ipod_write(ipod, sectorbuf, ipod->sector_size);
1715 if (n < 0) { return -1; }
1716
1717 return 0;
1718}
1719
1720#endif
diff --git a/rbutil/ipodpatcher/ipodpatcher.h b/rbutil/ipodpatcher/ipodpatcher.h
index d816c68724..0d9222268f 100644
--- a/rbutil/ipodpatcher/ipodpatcher.h
+++ b/rbutil/ipodpatcher/ipodpatcher.h
@@ -47,6 +47,8 @@ int list_images(struct ipod_t* ipod);
47int getmodel(struct ipod_t* ipod, int ipod_version); 47int getmodel(struct ipod_t* ipod, int ipod_version);
48int ipod_scan(struct ipod_t* ipod); 48int ipod_scan(struct ipod_t* ipod);
49int write_dos_partition_table(struct ipod_t* ipod); 49int write_dos_partition_table(struct ipod_t* ipod);
50int read_aupd(struct ipod_t* ipod, char* filename);
51int write_aupd(struct ipod_t* ipod, char* filename);
50off_t filesize(int fd); 52off_t filesize(int fd);
51 53
52#endif 54#endif
diff --git a/rbutil/ipodpatcher/main.c b/rbutil/ipodpatcher/main.c
index c47063cba8..f113c8aff4 100644
--- a/rbutil/ipodpatcher/main.c
+++ b/rbutil/ipodpatcher/main.c
@@ -45,6 +45,8 @@ enum {
45 ADD_BOOTLOADER, 45 ADD_BOOTLOADER,
46 READ_FIRMWARE, 46 READ_FIRMWARE,
47 WRITE_FIRMWARE, 47 WRITE_FIRMWARE,
48 READ_AUPD,
49 WRITE_AUPD,
48 READ_PARTITION, 50 READ_PARTITION,
49 WRITE_PARTITION, 51 WRITE_PARTITION,
50 FORMAT_PARTITION, 52 FORMAT_PARTITION,
@@ -89,6 +91,8 @@ void print_usage(void)
89 fprintf(stderr," -d, --delete-bootloader\n"); 91 fprintf(stderr," -d, --delete-bootloader\n");
90 fprintf(stderr," -f, --format\n"); 92 fprintf(stderr," -f, --format\n");
91 fprintf(stderr," -c, --convert\n"); 93 fprintf(stderr," -c, --convert\n");
94 fprintf(stderr," --read-aupd filename.bin\n");
95 fprintf(stderr," --write-aupd filename.bin\n");
92 fprintf(stderr,"\n"); 96 fprintf(stderr,"\n");
93 97
94#ifdef __WIN32__ 98#ifdef __WIN32__
@@ -299,6 +303,18 @@ int main(int argc, char* argv[])
299 (strcmp(argv[i],"--format")==0)) { 303 (strcmp(argv[i],"--format")==0)) {
300 action = FORMAT_PARTITION; 304 action = FORMAT_PARTITION;
301 i++; 305 i++;
306 } else if (strcmp(argv[i],"--read-aupd")==0) {
307 action = READ_AUPD;
308 i++;
309 if (i == argc) { print_usage(); return 1; }
310 filename=argv[i];
311 i++;
312 } else if (strcmp(argv[i],"--write-aupd")==0) {
313 action = WRITE_AUPD;
314 i++;
315 if (i == argc) { print_usage(); return 1; }
316 filename=argv[i];
317 i++;
302 } else if ((strcmp(argv[i],"-c")==0) || 318 } else if ((strcmp(argv[i],"-c")==0) ||
303 (strcmp(argv[i],"--convert")==0)) { 319 (strcmp(argv[i],"--convert")==0)) {
304 action = CONVERT_TO_FAT32; 320 action = CONVERT_TO_FAT32;
@@ -444,6 +460,22 @@ int main(int argc, char* argv[])
444 } else { 460 } else {
445 fprintf(stderr,"[ERR] --read-firmware failed.\n"); 461 fprintf(stderr,"[ERR] --read-firmware failed.\n");
446 } 462 }
463 } else if (action==READ_AUPD) {
464 if (read_aupd(&ipod, filename)==0) {
465 fprintf(stderr,"[INFO] AUPD image read to file %s.\n",filename);
466 } else {
467 fprintf(stderr,"[ERR] --read-aupd failed.\n");
468 }
469 } else if (action==WRITE_AUPD) {
470 if (ipod_reopen_rw(&ipod) < 0) {
471 return 5;
472 }
473
474 if (write_aupd(&ipod, filename)==0) {
475 fprintf(stderr,"[INFO] AUPD image %s written to device.\n",filename);
476 } else {
477 fprintf(stderr,"[ERR] --write-aupd failed.\n");
478 }
447 } else if (action==READ_PARTITION) { 479 } else if (action==READ_PARTITION) {
448 outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IREAD|S_IWRITE); 480 outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IREAD|S_IWRITE);
449 if (outfile < 0) { 481 if (outfile < 0) {