Index: rbutil/ipodpatcher/ipodpatcher.c =================================================================== --- rbutil/ipodpatcher/ipodpatcher.c (revision 22698) +++ rbutil/ipodpatcher/ipodpatcher.c (working copy) @@ -774,7 +774,9 @@ int bytesavailable; unsigned long chksum=0; unsigned long filechksum=0; + unsigned long offset; unsigned char header[8]; /* Header for .ipod file */ + unsigned char* p; #ifdef WITH_BOOTOBJS if (type == FILETYPE_INTERNAL) { @@ -876,7 +878,23 @@ } } - if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { + + offset = ipod->fwoffset+ipod->ipod_directory[ipod->ososimage].devOffset; + + if (ipod->modelnum==62) { + + /* 2nd Gen Nano has encrypted firmware, and the sector + preceeding the firmware contains hashes that need to be + preserved. Nano 2G images include these extra 2048 (0x800) + bytes + */ + + offset -= 0x800; + + /* TODO: The above checks need to take into account this 0x800 bytes */ + } + + if (ipod_seek(ipod, offset) < 0) { fprintf(stderr,"[ERR] Seek failed\n"); return -1; } @@ -893,7 +911,14 @@ } fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",n); - /* Now we need to update the "len", "entryOffset" and "chksum" fields */ + /* Now we need to update the "len", "entryOffset" and "chksum" fields + + NOTE: On the Nano 2G, the checksum is the checksum of the + unencrypted firmware. But this isn't checked by the NOR + bootloader (there are cryptographic hashes in the + firmware itself), so it doesn't matter that this is + wrong. + */ chksum = 0; for (i = 0; i < length; i++) { /* add 8 unsigned bits but keep a 32 bit sum */ @@ -908,10 +933,11 @@ n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size); if (n < 0) { return -1; } - /* Update entries for image 0 */ - int2le(length,ipod_sectorbuf+x+16); - int2le(0,ipod_sectorbuf+x+24); - int2le(chksum,ipod_sectorbuf+x+28); + /* Update entries for image */ + p = ipod_sectorbuf + x + (ipod->ososimage * 40); + int2le(length - (ipod->modelnum==62 ? 0x800: 0), p + 16); + int2le(0, p + 24); + int2le(chksum, p + 28); /* Write directory */ if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; } @@ -927,26 +953,36 @@ int i; int outfile; int n; + unsigned long offset; unsigned long chksum=0; /* 32 bit checksum - Rockbox .ipod style*/ unsigned char header[8]; /* Header for .ipod file */ - if (ipod->ipod_directory[0].entryOffset != 0) { + if (ipod->ipod_directory[ipod->ososimage].entryOffset != 0) { /* We have a bootloader... */ - length = ipod->ipod_directory[0].entryOffset; + length = ipod->ipod_directory[ipod->ososimage].entryOffset; } else { - length = ipod->ipod_directory[0].len; + length = ipod->ipod_directory[ipod->ososimage].len; } fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length); - if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { - return -1; - } - + offset = ipod->fwoffset + ipod->ipod_directory[ipod->ososimage].devOffset; i = (length+ipod->sector_size-1) & ~(ipod->sector_size-1); fprintf(stderr,"[INFO] Padding read from 0x%08x to 0x%08x bytes\n", length,i); + if (ipod->modelnum==62) { + /* 2nd Gen Nano has encrypted firmware, and we need to dump the + sector preceeding the image - it contains hashes */ + offset -= 0x800; + length += 0x800; + i += 0x800; + } + + if (ipod_seek(ipod, offset)) { + return -1; + } + if ((n = ipod_read(ipod,ipod_sectorbuf,i)) < 0) { return -1; } @@ -1049,6 +1085,9 @@ /* A hack to detect 2nd gen Nanos - maybe there is a better way? */ if (p[0] == 0) { + /* Adjust diroffset */ + ipod->diroffset += ipod->sector_size - x; + n=ipod_read(ipod, ipod_sectorbuf, ipod->sector_size); if (n < 0) { fprintf(stderr,"[ERR] Read of directory failed.\n"); @@ -1057,11 +1096,13 @@ p = ipod_sectorbuf; } + ipod->ososimage = -1; while ((ipod->nimages < MAX_IMAGES) && (p < (ipod_sectorbuf + x + 400)) && ((memcmp(p,"!ATA",4)==0) || (memcmp(p,"DNAN",4)==0))) { p+=4; if (memcmp(p,"soso",4)==0) { ipod->ipod_directory[ipod->nimages].ftype=FTYPE_OSOS; + ipod->ososimage = ipod->nimages; } else if (memcmp(p,"crsr",4)==0) { ipod->ipod_directory[ipod->nimages].ftype=FTYPE_RSRC; } else if (memcmp(p,"dpua",4)==0) { @@ -1092,12 +1133,17 @@ ipod->nimages++; } + if (ipod->ososimage < 0) { + fprintf(stderr,"[ERR] No OSOS image found.\n"); + return -1; + } + if ((ipod->nimages > 1) && (version==2)) { /* The 3g firmware image doesn't appear to have a version, so let's make one up... Note that this is never written back to the ipod, so it's OK to do. */ - if (ipod->ipod_directory[0].vers == 0) { ipod->ipod_directory[0].vers = 3; } + if (ipod->ipod_directory[ipod->ososimage].vers == 0) { ipod->ipod_directory[ipod->ososimage].vers = 3; } ipod->fwoffset = ipod->start; } else { @@ -1242,11 +1288,12 @@ break; case 0x100: ipod->modelstr="2nd Generation Nano"; - ipod->modelnum = 0; - ipod->targetname = NULL; + ipod->modelnum = 62; + ipod->modelname = "nn2g"; + ipod->targetname = "ipodnano2g"; #ifdef WITH_BOOTOBJS - ipod->bootloader = NULL; - ipod->bootloader_len = 0; + ipod->bootloader = ipodnano2g; + ipod->bootloader_len = LEN_ipodnano2g; #endif break; default: @@ -1311,7 +1358,7 @@ continue; } - ipod_version=(ipod->ipod_directory[0].vers>>8); + ipod_version=(ipod->ipod_directory[ipod->ososimage].vers>>8); if (getmodel(ipod,ipod_version) < 0) { ipod_close(ipod); continue; Index: rbutil/ipodpatcher/ipodio-posix.c =================================================================== --- rbutil/ipodpatcher/ipodio-posix.c (revision 22698) +++ rbutil/ipodpatcher/ipodio-posix.c (working copy) @@ -177,7 +177,7 @@ /* Read information about the disk */ if(ioctl(ipod->dh,IPOD_SECTORSIZE_IOCTL,&ipod->sector_size) < 0) { - ipod->sector_size=512; + ipod->sector_size=2048; if (!silent) { fprintf(stderr,"[ERR] ioctl() call to get sector size failed, defaulting to %d\n" ,ipod->sector_size); Index: rbutil/ipodpatcher/main.c =================================================================== --- rbutil/ipodpatcher/main.c (revision 22698) +++ rbutil/ipodpatcher/main.c (working copy) @@ -364,9 +364,9 @@ return 1; } - if (getmodel(&ipod,(ipod.ipod_directory[0].vers>>8)) < 0) { + if (getmodel(&ipod,(ipod.ipod_directory[ipod.ososimage].vers>>8)) < 0) { fprintf(stderr,"[ERR] Unknown version number in firmware (%08x)\n", - ipod.ipod_directory[0].vers); + ipod.ipod_directory[ipod.ososimage].vers); return -1; } @@ -391,7 +391,7 @@ if (ipod.ramsize > 0) { printf("(%dMB RAM) ",ipod.ramsize); } printf("(\"%s\")\n",ipod.macpod ? "macpod" : "winpod"); - if (ipod.ipod_directory[0].vers == 0x10000) { + if (ipod.ipod_directory[ipod.ososimage].vers == 0x10000) { fprintf(stderr,"[ERR] *** ipodpatcher does not support the 2nd Generation Nano! ***\n"); #ifdef WITH_BOOTOBJS printf("Press ENTER to exit ipodpatcher :"); Index: rbutil/ipodpatcher/ipodio.h =================================================================== --- rbutil/ipodpatcher/ipodio.h (revision 22698) +++ rbutil/ipodpatcher/ipodio.h (working copy) @@ -71,6 +71,7 @@ int num_heads; struct ipod_directory_t ipod_directory[MAX_IMAGES]; int nimages; + int ososimage; off_t diroffset; off_t start; /* Offset in bytes of firmware partition from start of disk */ off_t fwoffset; /* Offset in bytes of start of firmware images from start of disk */