summaryrefslogtreecommitdiff
path: root/rbutil/ipodpatcher/ipodpatcher.c
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2009-10-13 08:02:59 +0000
committerDave Chapman <dave@dchapman.com>2009-10-13 08:02:59 +0000
commit8e95cc432935df1225a7bcc8e87e04f9f16bb643 (patch)
treecff528d4f69aed098f178236eee1ee26c759bf5e /rbutil/ipodpatcher/ipodpatcher.c
parente486241c0143580ef81c79dbc75b69b0abbc5b2c (diff)
downloadrockbox-8e95cc432935df1225a7bcc8e87e04f9f16bb643.tar.gz
rockbox-8e95cc432935df1225a7bcc8e87e04f9f16bb643.zip
ipodpatcher and rbutil support for the Nano2G - FS#10609 with a few further changes.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23142 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'rbutil/ipodpatcher/ipodpatcher.c')
-rw-r--r--rbutil/ipodpatcher/ipodpatcher.c503
1 files changed, 483 insertions, 20 deletions
diff --git a/rbutil/ipodpatcher/ipodpatcher.c b/rbutil/ipodpatcher/ipodpatcher.c
index 79357fde06..7116056350 100644
--- a/rbutil/ipodpatcher/ipodpatcher.c
+++ b/rbutil/ipodpatcher/ipodpatcher.c
@@ -42,6 +42,7 @@
42#include "ipodcolor.h" 42#include "ipodcolor.h"
43#include "ipodnano.h" 43#include "ipodnano.h"
44#include "ipodvideo.h" 44#include "ipodvideo.h"
45#include "ipodnano2g.h"
45#endif 46#endif
46 47
47#ifndef RBUTIL 48#ifndef RBUTIL
@@ -389,7 +390,7 @@ int write_partition(struct ipod_t* ipod, int infile)
389 return 0; 390 return 0;
390} 391}
391 392
392char* ftypename[] = { "OSOS", "RSRC", "AUPD", "HIBE" }; 393char* ftypename[] = { "OSOS", "RSRC", "AUPD", "HIBE", "OSBK" };
393 394
394int diskmove(struct ipod_t* ipod, int delta) 395int diskmove(struct ipod_t* ipod, int delta)
395{ 396{
@@ -470,6 +471,409 @@ int diskmove(struct ipod_t* ipod, int delta)
470 return 0; 471 return 0;
471} 472}
472 473
474static int rename_image(struct ipod_t* ipod, char* from, char* to)
475{
476 int n;
477 int x;
478 int found;
479 int i;
480 unsigned char* p;
481
482 /* diroffset may not be sector-aligned */
483 x = ipod->diroffset % ipod->sector_size;
484
485 /* Read directory */
486 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) {
487 fprintf(stderr,"[ERR] Seek to diroffset (%08x) failed.\n",(unsigned)ipod->diroffset);
488 return -1;
489 }
490
491 n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size);
492 if (n < 0) {
493 fprintf(stderr,"[ERR] Read of directory failed.\n");
494 return -1;
495 }
496
497 p = ipod_sectorbuf + x;
498
499 /* A hack to detect 2nd gen Nanos - maybe there is a better way? */
500 if (p[0] == 0)
501 {
502 /* Adjust diroffset */
503 ipod->diroffset += ipod->sector_size - x;
504
505 n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size);
506 if (n < 0) {
507 fprintf(stderr,"[ERR] Read of directory failed.\n");
508 return -1;
509 }
510 p = ipod_sectorbuf;
511 }
512
513 found = 0;
514 for (i=0 ; !found && i < MAX_IMAGES; i++) {
515 if (memcmp(p + 4, from, 4) == 0) {
516 memcpy(p + 4, to, 4);
517
518 found = 1;
519 }
520 p += 40;
521 }
522
523 if (!found) {
524 fprintf(stderr,"[ERR] Unexpected error - no \"%s\" image!\n", from);
525 return -1;
526 }
527
528 /* Write directory back to disk */
529 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) {
530 fprintf(stderr,"[ERR] Seek to diroffset (%08x) failed.\n",(unsigned)ipod->diroffset);
531 return -1;
532 }
533
534 n=ipod_write(ipod, ipod_sectorbuf, ipod->sector_size);
535 if (n < 0) {
536 fprintf(stderr,"[ERR] Write of directory failed in rename_image.\n");
537 return -1;
538 }
539
540 return 0;
541}
542
543static int delete_image(struct ipod_t* ipod, char* name)
544{
545 int n;
546 int x;
547 int found;
548 int i;
549 unsigned char* p;
550
551 /* diroffset may not be sector-aligned */
552 x = ipod->diroffset % ipod->sector_size;
553
554 /* Read directory */
555 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) {
556 fprintf(stderr,"[ERR] Seek to diroffset (%08x) failed.\n",(unsigned)ipod->diroffset);
557 return -1;
558 }
559
560 n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size);
561 if (n < 0) {
562 fprintf(stderr,"[ERR] Read of directory failed.\n");
563 return -1;
564 }
565
566 p = ipod_sectorbuf + x;
567
568 /* A hack to detect 2nd gen Nanos - maybe there is a better way? */
569 if (p[0] == 0)
570 {
571 /* Adjust diroffset */
572 ipod->diroffset += ipod->sector_size - x;
573
574 n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size);
575 if (n < 0) {
576 fprintf(stderr,"[ERR] Read of directory failed.\n");
577 return -1;
578 }
579 p = ipod_sectorbuf;
580 }
581
582 found = 0;
583 for (i=0 ; !found && i < MAX_IMAGES; i++) {
584 if (memcmp(p + 4, name, 4) == 0) {
585 memset(p, 0, 40); /* Delete directory entry */
586 found = 1;
587 }
588 p += 40;
589 }
590
591 if (!found) {
592 fprintf(stderr,"[ERR] Unexpected error - no \"%s\" image!\n", name);
593 return -1;
594 }
595
596 /* Write directory back to disk */
597 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) {
598 fprintf(stderr,"[ERR] Seek to diroffset (%08x) failed.\n",(unsigned)ipod->diroffset);
599 return -1;
600 }
601
602 n=ipod_write(ipod, ipod_sectorbuf, ipod->sector_size);
603 if (n < 0) {
604 fprintf(stderr,"[ERR] Write of directory failed in delete_image.\n");
605 return -1;
606 }
607
608 return 0;
609}
610
611int add_new_image(struct ipod_t* ipod, char* imagename, char* filename, int type)
612{
613 int length;
614 int found;
615 int i;
616 int x;
617 int n;
618 int infile;
619 int newsize;
620 unsigned long chksum=0;
621 unsigned long filechksum=0;
622 unsigned long offset;
623 unsigned char header[8]; /* Header for .ipod file */
624 unsigned char* p;
625
626#ifdef WITH_BOOTOBJS
627 if (type == FILETYPE_INTERNAL) {
628 fprintf(stderr,"[INFO] Using internal bootloader - %d bytes\n",ipod->bootloader_len);
629 length = ipod->bootloader_len;
630 infile = -1;
631 }
632 else
633#endif
634 {
635 /* First check that the input file is the correct type for this ipod. */
636 infile=open(filename,O_RDONLY);
637 if (infile < 0) {
638 fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename);
639 return -1;
640 }
641
642 if (type==FILETYPE_DOT_IPOD) {
643 n = read(infile,header,8);
644 if (n < 8) {
645 fprintf(stderr,"[ERR] Failed to read header from %s\n",filename);
646 close(infile);
647 return -1;
648 }
649
650 if (memcmp(header+4, ipod->modelname,4)!=0) {
651 fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n",
652 header[4],header[5],header[6],header[7], ipod->modelname);
653 close(infile);
654 return -1;
655 }
656
657 filechksum = be2int(header);
658
659 length = filesize(infile)-8;
660 } else {
661 length = filesize(infile);
662 }
663 }
664
665 newsize=(length+ipod->sector_size-1)&~(ipod->sector_size-1);
666
667 fprintf(stderr,"[INFO] Padding input file from 0x%08x to 0x%08x bytes\n",
668 length,newsize);
669
670 if (newsize > BUFFER_SIZE) {
671 fprintf(stderr,"[ERR] Input file too big for buffer\n");
672 if (infile >= 0) close(infile);
673 return -1;
674 }
675
676 /* TODO: Check if we have enough space in the partition for the new image */
677
678#ifdef WITH_BOOTOBJS
679 if (type == FILETYPE_INTERNAL) {
680 memcpy(ipod_sectorbuf,ipod->bootloader,ipod->bootloader_len);
681 }
682 else
683#endif
684 {
685 fprintf(stderr,"[INFO] Reading input file...\n");
686
687 n = read(infile,ipod_sectorbuf,length);
688 if (n < 0) {
689 fprintf(stderr,"[ERR] Couldn't read input file\n");
690 close(infile);
691 return -1;
692 }
693 close(infile);
694 }
695
696 /* Pad the data with zeros */
697 memset(ipod_sectorbuf+length,0,newsize-length);
698
699 if (type==FILETYPE_DOT_IPOD) {
700 chksum = ipod->modelnum;
701 for (i = 0; i < length; i++) {
702 /* add 8 unsigned bits but keep a 32 bit sum */
703 chksum += ipod_sectorbuf[i];
704 }
705
706 if (chksum == filechksum) {
707 fprintf(stderr,"[INFO] Checksum OK in %s\n",filename);
708 } else {
709 fprintf(stderr,"[ERR] Checksum in %s failed check\n",filename);
710 return -1;
711 }
712 }
713
714
715 offset = ipod->fwoffset + ipod->ipod_directory[ipod->nimages - 1].devOffset +
716 ipod->ipod_directory[ipod->nimages - 1].len + ipod->sector_size;
717
718 /* 2nd Gen Nano has encrypted firmware, and the sector
719 preceeding the firmware contains hashes that need to be
720 preserved. Nano 2G images include these extra 2048 (0x800)
721 bytes
722 */
723 if (ipod_seek(ipod, offset - (ipod->modelnum == 62 ? 0x800 : 0)) < 0) {
724 fprintf(stderr,"[ERR] Seek failed\n");
725 return -1;
726 }
727
728 if ((n = ipod_write(ipod,ipod_sectorbuf,newsize)) < 0) {
729 perror("[ERR] Write failed\n");
730 return -1;
731 }
732
733 if (n < newsize) {
734 fprintf(stderr,"[ERR] Short write - requested %d bytes, received %d\n"
735 ,newsize,n);
736 return -1;
737 }
738 fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",n);
739
740 /* Now we need to create a new directory entry
741
742 NOTE: On the Nano 2G, the checksum is the checksum of the
743 unencrypted firmware. But this isn't checked by the NOR
744 bootloader (there are cryptographic hashes in the
745 firmware itself), so it doesn't matter that this is
746 wrong.
747 */
748 chksum = 0;
749 for (i = 0; i < length; i++) {
750 /* add 8 unsigned bits but keep a 32 bit sum */
751 chksum += ipod_sectorbuf[i];
752 }
753
754 x = ipod->diroffset % ipod->sector_size;
755
756 /* Read directory */
757 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; }
758
759 n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size);
760 if (n < 0) { return -1; }
761
762 /* Create a new directory entry */
763
764 /* Copy OSOS or OSBK details - we assume one of them exists */
765 p = ipod_sectorbuf + x;
766 found = 0;
767 for (i = 0; !found && i < ipod->nimages; i++) {
768 if ((memcmp(p + 4, "soso", 4)==0) || (memcmp(p + 4, "kbso", 4)==0)) {
769 found = 1;
770 } else {
771 p += 40;
772 }
773 }
774
775 if (!found) {
776 fprintf(stderr,"[ERR] No OSOS or OSBK image to copy directory from\n");
777 return -1;
778 }
779
780 /* Copy directory image */
781 memcpy(ipod_sectorbuf + x + (ipod->nimages * 40), p, 40);
782 p = ipod_sectorbuf + x + (ipod->nimages * 40);
783
784 /* Modify directory. */
785 memcpy(p + 4, imagename, 4);
786 int2le(offset - ipod->fwoffset, p + 12); /* devOffset */
787 int2le(length - (ipod->modelnum==62 ? 0x800: 0), p + 16); /* len */
788 int2le(chksum, p + 28); /* checksum */
789
790 /* Write directory */
791 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; }
792 n=ipod_write(ipod, ipod_sectorbuf, ipod->sector_size);
793 if (n < 0) { return -1; }
794
795 return 0;
796}
797
798
799/*
800 Bootloader installation on the Nano2G consists of renaming the
801 OSOS image to OSBK and then writing the Rockbox bootloader as a
802 new OSOS image.
803
804 Maybe this approach can/should be adapted for other ipods, as it
805 prevents the Apple bootloader loading the original firmware into
806 RAM along with the Rockbox bootloader (and hence will give a
807 faster boot when the user just wants to start Rockbox).
808
809*/
810
811static int add_bootloader_nano2g(struct ipod_t* ipod, char* filename, int type)
812{
813 int i;
814 int has_osbk = 0;
815
816 /* Check if we already have an OSBK image */
817 for (i = 0; i < ipod->nimages; i++) {
818 if (ipod->ipod_directory[i].ftype==FTYPE_OSBK) {
819 has_osbk = 1;
820 }
821 }
822
823 if (has_osbk == 0) {
824 /* First-time install - rename OSOS to OSBK and create new OSOS for bootloader */
825 fprintf(stderr,"[INFO] Creating OSBK backup image of original firmware\n");
826
827 if (rename_image(ipod, "soso", "kbso") < 0) {
828 fprintf(stderr,"[ERR] Could not rename OSOS image\n");
829 return -1;
830 }
831
832 /* Add our bootloader as a brand new image */
833 return add_new_image(ipod, "soso", filename, type);
834 } else {
835 /* This is an update, just replace OSOS with our bootloader */
836
837 return write_firmware(ipod, filename, type);
838 }
839}
840
841
842static int delete_bootloader_nano2g(struct ipod_t* ipod)
843{
844 int i;
845 int has_osbk = 0;
846
847 /* Check if we have an OSBK image */
848 for (i = 0; i < ipod->nimages; i++) {
849 if (ipod->ipod_directory[i].ftype==FTYPE_OSBK) {
850 has_osbk = 1;
851 }
852 }
853
854 if (has_osbk == 0) {
855 fprintf(stderr,"[ERR] No OSBK image found - nothing to uninstall\n");
856 return -1;
857 } else {
858 /* Delete our bootloader image */
859 if (delete_image(ipod, "soso") < 0) {
860 fprintf(stderr,"[WARN] Could not delete OSOS image\n");
861 } else {
862 fprintf(stderr,"[INFO] OSOS image deleted\n");
863 }
864
865 if (rename_image(ipod, "kbso", "soso") < 0) {
866 fprintf(stderr,"[ERR] Could not rename OSBK image\n");
867 return -1;
868 }
869
870
871 fprintf(stderr,"[INFO] OSBK image renamed to OSOS - bootloader uninstalled.\n");
872 return 0;
873 }
874}
875
876
473int add_bootloader(struct ipod_t* ipod, char* filename, int type) 877int add_bootloader(struct ipod_t* ipod, char* filename, int type)
474{ 878{
475 int length; 879 int length;
@@ -485,6 +889,11 @@ int add_bootloader(struct ipod_t* ipod, char* filename, int type)
485 unsigned char header[8]; /* Header for .ipod file */ 889 unsigned char header[8]; /* Header for .ipod file */
486 unsigned char* bootloader_buf; 890 unsigned char* bootloader_buf;
487 891
892 /* The 2nd gen Nano is installed differently */
893 if (ipod->modelnum == 62) {
894 return add_bootloader_nano2g(ipod, filename, type);
895 }
896
488 /* Calculate the position in the OSOS image where our bootloader will go. */ 897 /* Calculate the position in the OSOS image where our bootloader will go. */
489 if (ipod->ipod_directory[0].entryOffset>0) { 898 if (ipod->ipod_directory[0].entryOffset>0) {
490 /* Keep the same entryOffset */ 899 /* Keep the same entryOffset */
@@ -698,6 +1107,11 @@ int delete_bootloader(struct ipod_t* ipod)
698 int n; 1107 int n;
699 unsigned long chksum=0; /* 32 bit checksum - Rockbox .ipod style*/ 1108 unsigned long chksum=0; /* 32 bit checksum - Rockbox .ipod style*/
700 1109
1110 /* The 2nd gen Nano is installed differently */
1111 if (ipod->modelnum == 62) {
1112 return delete_bootloader_nano2g(ipod);
1113 }
1114
701 /* Removing the bootloader involves adjusting the "length", 1115 /* Removing the bootloader involves adjusting the "length",
702 "chksum" and "entryOffset" values in the osos image's directory 1116 "chksum" and "entryOffset" values in the osos image's directory
703 entry. */ 1117 entry. */
@@ -774,7 +1188,9 @@ int write_firmware(struct ipod_t* ipod, char* filename, int type)
774 int bytesavailable; 1188 int bytesavailable;
775 unsigned long chksum=0; 1189 unsigned long chksum=0;
776 unsigned long filechksum=0; 1190 unsigned long filechksum=0;
1191 unsigned long offset;
777 unsigned char header[8]; /* Header for .ipod file */ 1192 unsigned char header[8]; /* Header for .ipod file */
1193 unsigned char* p;
778 1194
779#ifdef WITH_BOOTOBJS 1195#ifdef WITH_BOOTOBJS
780 if (type == FILETYPE_INTERNAL) { 1196 if (type == FILETYPE_INTERNAL) {
@@ -876,7 +1292,23 @@ int write_firmware(struct ipod_t* ipod, char* filename, int type)
876 } 1292 }
877 } 1293 }
878 1294
879 if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { 1295
1296 offset = ipod->fwoffset+ipod->ipod_directory[ipod->ososimage].devOffset;
1297
1298 if (ipod->modelnum==62) {
1299
1300 /* 2nd Gen Nano has encrypted firmware, and the sector
1301 preceeding the firmware contains hashes that need to be
1302 preserved. Nano 2G images include these extra 2048 (0x800)
1303 bytes
1304 */
1305
1306 offset -= 0x800;
1307
1308 /* TODO: The above checks need to take into account this 0x800 bytes */
1309 }
1310
1311 if (ipod_seek(ipod, offset) < 0) {
880 fprintf(stderr,"[ERR] Seek failed\n"); 1312 fprintf(stderr,"[ERR] Seek failed\n");
881 return -1; 1313 return -1;
882 } 1314 }
@@ -893,7 +1325,14 @@ int write_firmware(struct ipod_t* ipod, char* filename, int type)
893 } 1325 }
894 fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",n); 1326 fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",n);
895 1327
896 /* Now we need to update the "len", "entryOffset" and "chksum" fields */ 1328 /* Now we need to update the "len", "entryOffset" and "chksum" fields
1329
1330 NOTE: On the Nano 2G, the checksum is the checksum of the
1331 unencrypted firmware. But this isn't checked by the NOR
1332 bootloader (there are cryptographic hashes in the
1333 firmware itself), so it doesn't matter that this is
1334 wrong.
1335 */
897 chksum = 0; 1336 chksum = 0;
898 for (i = 0; i < length; i++) { 1337 for (i = 0; i < length; i++) {
899 /* add 8 unsigned bits but keep a 32 bit sum */ 1338 /* add 8 unsigned bits but keep a 32 bit sum */
@@ -908,10 +1347,11 @@ int write_firmware(struct ipod_t* ipod, char* filename, int type)
908 n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size); 1347 n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size);
909 if (n < 0) { return -1; } 1348 if (n < 0) { return -1; }
910 1349
911 /* Update entries for image 0 */ 1350 /* Update entries for image */
912 int2le(length,ipod_sectorbuf+x+16); 1351 p = ipod_sectorbuf + x + (ipod->ososimage * 40);
913 int2le(0,ipod_sectorbuf+x+24); 1352 int2le(length - (ipod->modelnum==62 ? 0x800: 0), p + 16);
914 int2le(chksum,ipod_sectorbuf+x+28); 1353 int2le(0, p + 24);
1354 int2le(chksum, p + 28);
915 1355
916 /* Write directory */ 1356 /* Write directory */
917 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; } 1357 if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; }
@@ -927,26 +1367,36 @@ int read_firmware(struct ipod_t* ipod, char* filename, int type)
927 int i; 1367 int i;
928 int outfile; 1368 int outfile;
929 int n; 1369 int n;
1370 unsigned long offset;
930 unsigned long chksum=0; /* 32 bit checksum - Rockbox .ipod style*/ 1371 unsigned long chksum=0; /* 32 bit checksum - Rockbox .ipod style*/
931 unsigned char header[8]; /* Header for .ipod file */ 1372 unsigned char header[8]; /* Header for .ipod file */
932 1373
933 if (ipod->ipod_directory[0].entryOffset != 0) { 1374 if (ipod->ipod_directory[ipod->ososimage].entryOffset != 0) {
934 /* We have a bootloader... */ 1375 /* We have a bootloader... */
935 length = ipod->ipod_directory[0].entryOffset; 1376 length = ipod->ipod_directory[ipod->ososimage].entryOffset;
936 } else { 1377 } else {
937 length = ipod->ipod_directory[0].len; 1378 length = ipod->ipod_directory[ipod->ososimage].len;
938 } 1379 }
939 1380
940 fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length); 1381 fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length);
941 1382
942 if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { 1383 offset = ipod->fwoffset + ipod->ipod_directory[ipod->ososimage].devOffset;
943 return -1;
944 }
945
946 i = (length+ipod->sector_size-1) & ~(ipod->sector_size-1); 1384 i = (length+ipod->sector_size-1) & ~(ipod->sector_size-1);
947 fprintf(stderr,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n", 1385 fprintf(stderr,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n",
948 length,i); 1386 length,i);
949 1387
1388 if (ipod->modelnum==62) {
1389 /* 2nd Gen Nano has encrypted firmware, and we need to dump the
1390 sector preceeding the image - it contains hashes */
1391 offset -= 0x800;
1392 length += 0x800;
1393 i += 0x800;
1394 }
1395
1396 if (ipod_seek(ipod, offset)) {
1397 return -1;
1398 }
1399
950 if ((n = ipod_read(ipod,ipod_sectorbuf,i)) < 0) { 1400 if ((n = ipod_read(ipod,ipod_sectorbuf,i)) < 0) {
951 return -1; 1401 return -1;
952 } 1402 }
@@ -1049,6 +1499,9 @@ int read_directory(struct ipod_t* ipod)
1049 /* A hack to detect 2nd gen Nanos - maybe there is a better way? */ 1499 /* A hack to detect 2nd gen Nanos - maybe there is a better way? */
1050 if (p[0] == 0) 1500 if (p[0] == 0)
1051 { 1501 {
1502 /* Adjust diroffset */
1503 ipod->diroffset += ipod->sector_size - x;
1504
1052 n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size); 1505 n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size);
1053 if (n < 0) { 1506 if (n < 0) {
1054 fprintf(stderr,"[ERR] Read of directory failed.\n"); 1507 fprintf(stderr,"[ERR] Read of directory failed.\n");
@@ -1057,15 +1510,19 @@ int read_directory(struct ipod_t* ipod)
1057 p = ipod_sectorbuf; 1510 p = ipod_sectorbuf;
1058 } 1511 }
1059 1512
1513 ipod->ososimage = -1;
1060 while ((ipod->nimages < MAX_IMAGES) && (p < (ipod_sectorbuf + x + 400)) && 1514 while ((ipod->nimages < MAX_IMAGES) && (p < (ipod_sectorbuf + x + 400)) &&
1061 ((memcmp(p,"!ATA",4)==0) || (memcmp(p,"DNAN",4)==0))) { 1515 ((memcmp(p,"!ATA",4)==0) || (memcmp(p,"DNAN",4)==0))) {
1062 p+=4; 1516 p+=4;
1063 if (memcmp(p,"soso",4)==0) { 1517 if (memcmp(p,"soso",4)==0) {
1064 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_OSOS; 1518 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_OSOS;
1519 ipod->ososimage = ipod->nimages;
1065 } else if (memcmp(p,"crsr",4)==0) { 1520 } else if (memcmp(p,"crsr",4)==0) {
1066 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_RSRC; 1521 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_RSRC;
1067 } else if (memcmp(p,"dpua",4)==0) { 1522 } else if (memcmp(p,"dpua",4)==0) {
1068 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_AUPD; 1523 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_AUPD;
1524 } else if (memcmp(p,"kbso",4)==0) {
1525 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_OSBK;
1069 } else if (memcmp(p,"ebih",4)==0) { 1526 } else if (memcmp(p,"ebih",4)==0) {
1070 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_HIBE; 1527 ipod->ipod_directory[ipod->nimages].ftype=FTYPE_HIBE;
1071 } else { 1528 } else {
@@ -1092,12 +1549,17 @@ int read_directory(struct ipod_t* ipod)
1092 ipod->nimages++; 1549 ipod->nimages++;
1093 } 1550 }
1094 1551
1552 if (ipod->ososimage < 0) {
1553 fprintf(stderr,"[ERR] No OSOS image found.\n");
1554 return -1;
1555 }
1556
1095 if ((ipod->nimages > 1) && (version==2)) { 1557 if ((ipod->nimages > 1) && (version==2)) {
1096 /* The 3g firmware image doesn't appear to have a version, so 1558 /* The 3g firmware image doesn't appear to have a version, so
1097 let's make one up... Note that this is never written back to the 1559 let's make one up... Note that this is never written back to the
1098 ipod, so it's OK to do. */ 1560 ipod, so it's OK to do. */
1099 1561
1100 if (ipod->ipod_directory[0].vers == 0) { ipod->ipod_directory[0].vers = 3; } 1562 if (ipod->ipod_directory[ipod->ososimage].vers == 0) { ipod->ipod_directory[ipod->ososimage].vers = 3; }
1101 1563
1102 ipod->fwoffset = ipod->start; 1564 ipod->fwoffset = ipod->start;
1103 } else { 1565 } else {
@@ -1247,11 +1709,12 @@ int getmodel(struct ipod_t* ipod, int ipod_version)
1247 break; 1709 break;
1248 case 0x100: 1710 case 0x100:
1249 ipod->modelstr="2nd Generation Nano"; 1711 ipod->modelstr="2nd Generation Nano";
1250 ipod->modelnum = 0; 1712 ipod->modelnum = 62;
1251 ipod->targetname = NULL; 1713 ipod->modelname = "nn2x";
1714 ipod->targetname = "ipodnano2g";
1252#ifdef WITH_BOOTOBJS 1715#ifdef WITH_BOOTOBJS
1253 ipod->bootloader = NULL; 1716 ipod->bootloader = ipodnano2g;
1254 ipod->bootloader_len = 0; 1717 ipod->bootloader_len = LEN_ipodnano2g;
1255#endif 1718#endif
1256 break; 1719 break;
1257 default: 1720 default:
@@ -1316,7 +1779,7 @@ int ipod_scan(struct ipod_t* ipod)
1316 continue; 1779 continue;
1317 } 1780 }
1318 1781
1319 ipod_version=(ipod->ipod_directory[0].vers>>8); 1782 ipod_version=(ipod->ipod_directory[ipod->ososimage].vers>>8);
1320 /* Windows requires the ipod in R/W mode for SCSI Inquiry */ 1783 /* Windows requires the ipod in R/W mode for SCSI Inquiry */
1321 ipod->ramsize = 0; 1784 ipod->ramsize = 0;
1322 ipod_reopen_rw(ipod); 1785 ipod_reopen_rw(ipod);