From 955afed1b74793a3f06f98f3c259ec98f26a0b82 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Sat, 10 Feb 2007 19:49:43 +0000 Subject: Move ipodpatcher into rbutil directory git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12263 a1c6a512-1295-4272-9138-f99709370657 --- rbutil/ipodpatcher/Makefile | 61 ++ rbutil/ipodpatcher/ipod2c.c | 139 ++++ rbutil/ipodpatcher/ipodio-posix.c | 115 ++++ rbutil/ipodpatcher/ipodio-win32.c | 190 ++++++ rbutil/ipodpatcher/ipodio.h | 89 +++ rbutil/ipodpatcher/ipodpatcher.c | 1261 +++++++++++++++++++++++++++++++++++++ rbutil/ipodpatcher/ipodpatcher.h | 51 ++ rbutil/ipodpatcher/main.c | 429 +++++++++++++ rbutil/ipodpatcher/parttypes.h | 109 ++++ tools/ipodpatcher/Makefile | 61 -- tools/ipodpatcher/ipod2c.c | 139 ---- tools/ipodpatcher/ipodio-posix.c | 115 ---- tools/ipodpatcher/ipodio-win32.c | 190 ------ tools/ipodpatcher/ipodio.h | 89 --- tools/ipodpatcher/ipodpatcher.c | 1261 ------------------------------------- tools/ipodpatcher/ipodpatcher.h | 51 -- tools/ipodpatcher/main.c | 429 ------------- tools/ipodpatcher/parttypes.h | 109 ---- 18 files changed, 2444 insertions(+), 2444 deletions(-) create mode 100644 rbutil/ipodpatcher/Makefile create mode 100644 rbutil/ipodpatcher/ipod2c.c create mode 100644 rbutil/ipodpatcher/ipodio-posix.c create mode 100644 rbutil/ipodpatcher/ipodio-win32.c create mode 100644 rbutil/ipodpatcher/ipodio.h create mode 100644 rbutil/ipodpatcher/ipodpatcher.c create mode 100644 rbutil/ipodpatcher/ipodpatcher.h create mode 100644 rbutil/ipodpatcher/main.c create mode 100644 rbutil/ipodpatcher/parttypes.h delete mode 100644 tools/ipodpatcher/Makefile delete mode 100644 tools/ipodpatcher/ipod2c.c delete mode 100644 tools/ipodpatcher/ipodio-posix.c delete mode 100644 tools/ipodpatcher/ipodio-win32.c delete mode 100644 tools/ipodpatcher/ipodio.h delete mode 100644 tools/ipodpatcher/ipodpatcher.c delete mode 100644 tools/ipodpatcher/ipodpatcher.h delete mode 100644 tools/ipodpatcher/main.c delete mode 100644 tools/ipodpatcher/parttypes.h diff --git a/rbutil/ipodpatcher/Makefile b/rbutil/ipodpatcher/Makefile new file mode 100644 index 0000000000..f5a4d7cfb3 --- /dev/null +++ b/rbutil/ipodpatcher/Makefile @@ -0,0 +1,61 @@ +CFLAGS=-Wall + +BOOT_H = ipod3g.h ipod4g.h ipodcolor.h ipodmini.h ipodmini2g.h ipodnano.h ipodvideo.h + +# Uncomment the next two lines to build with embedded bootloaders and the +# --install option and interactive mode. You need the full set of Rockbox +# bootloaders in this directory - download them from +# http://download.rockbox.org/bootloader/ipod/bootloaders.zip + +#BOOTSRC = ipod3g.c ipod4g.c ipodcolor.c ipodmini.c ipodmini2g.c ipodnano.c ipodvideo.c +#CFLAGS += -DWITH_BOOTOBJS + +ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN) +OUTPUT=ipodpatcher.exe +CROSS= +CFLAGS+=-mno-cygwin +else +OUTPUT=ipodpatcher +CROSS=i586-mingw32msvc- +endif + +NATIVECC = gcc +CC = $(CROSS)gcc + +all: $(OUTPUT) + +ipodpatcher: main.c ipodpatcher.c ipodio-posix.c parttypes.h $(BOOTSRC) + gcc $(CFLAGS) -o ipodpatcher main.c ipodpatcher.c ipodio-posix.c $(BOOTSRC) + strip ipodpatcher + +ipodpatcher.exe: main.c ipodpatcher.c ipodio-win32.c parttypes.h $(BOOTSRC) + $(CC) $(CFLAGS) -o ipodpatcher.exe main.c ipodpatcher.c ipodio-win32.c $(BOOTSRC) + $(CROSS)strip ipodpatcher.exe + +ipod2c: ipod2c.c + $(NATIVECC) $(CFLAGS) -o ipod2c ipod2c.c + +ipod3g.c: bootloader-ipod3g.ipod ipod2c + ./ipod2c bootloader-ipod3g.ipod ipod3g + +ipod4g.c: bootloader-ipod4g.ipod ipod2c + ./ipod2c bootloader-ipod4g.ipod ipod4g + +ipodcolor.c: bootloader-ipodcolor.ipod ipod2c + ./ipod2c bootloader-ipodcolor.ipod ipodcolor + +ipodmini.c: bootloader-ipodmini.ipod ipod2c + ./ipod2c bootloader-ipodmini.ipod ipodmini + +ipodmini2g.c: bootloader-ipodmini2g.ipod ipod2c + ./ipod2c bootloader-ipodmini2g.ipod ipodmini2g + +ipodnano.c: bootloader-ipodnano.ipod ipod2c + ./ipod2c bootloader-ipodnano.ipod ipodnano + +ipodvideo.c: bootloader-ipodvideo.ipod ipod2c + ./ipod2c bootloader-ipodvideo.ipod ipodvideo + + +clean: + rm -f ipodpatcher.exe ipodpatcher ipod2c *~ $(BOOTSRC) $(BOOT_H) diff --git a/rbutil/ipodpatcher/ipod2c.c b/rbutil/ipodpatcher/ipod2c.c new file mode 100644 index 0000000000..af2e25dd09 --- /dev/null +++ b/rbutil/ipodpatcher/ipod2c.c @@ -0,0 +1,139 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: ipodio-win32.c 12205 2007-02-05 01:20:20Z dave $ + * + * Copyright (C) 2007 Dave Chapman + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +static off_t filesize(int fd) +{ + struct stat buf; + + fstat(fd,&buf); + return buf.st_size; +} + +static int write_cfile(unsigned char* buf, off_t len, char* cname) +{ + char filename[256]; + FILE* fp; + int i; + + snprintf(filename,256,"%s.c",cname); + + fp = fopen(filename,"w+"); + if (fp == NULL) { + fprintf(stderr,"Couldn't open %s\n",filename); + return -1; + } + + fprintf(fp,"/* Generated by ipod2c */\n\n"); + fprintf(fp,"unsigned char %s[] = {",cname); + + for (i=0;i ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006-2007 Dave Chapman + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(linux) || defined (__linux) +#include +#define IPOD_SECTORSIZE_IOCTL BLKSSZGET +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ + || defined(__bsdi__) || defined(__DragonFly__) +#include +#define IPOD_SECTORSIZE_IOCTL DIOCGSECTORSIZE +#elif defined(__APPLE__) && defined(__MACH__) +#include +#define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE +#else + #error No sector-size detection implemented for this platform +#endif + +#include "ipodio.h" + +void print_error(char* msg) +{ + perror(msg); +} + +int ipod_open(struct ipod_t* ipod, int silent) +{ + ipod->dh=open(ipod->diskname,O_RDONLY); + if (ipod->dh < 0) { + if (!silent) perror(ipod->diskname); + return -1; + } + + if(ioctl(ipod->dh,IPOD_SECTORSIZE_IOCTL,&ipod->sector_size) < 0) { + ipod->sector_size=512; + if (!silent) { + fprintf(stderr,"[ERR] ioctl() call to get sector size failed, defaulting to %d\n" + ,ipod->sector_size); + } + } + return 0; +} + + +int ipod_reopen_rw(struct ipod_t* ipod) +{ + close(ipod->dh); + ipod->dh=open(ipod->diskname,O_RDWR); + if (ipod->dh < 0) { + perror(ipod->diskname); + return -1; + } + return 0; +} + +int ipod_close(struct ipod_t* ipod) +{ + close(ipod->dh); + return 0; +} + +int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize) +{ + *sectorbuf=malloc(bufsize); + if (*sectorbuf == NULL) { + return -1; + } + return 0; +} + +int ipod_seek(struct ipod_t* ipod, unsigned long pos) +{ + off_t res; + + res = lseek(ipod->dh, pos, SEEK_SET); + + if (res == -1) { + return -1; + } + return 0; +} + +int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes) +{ + return read(ipod->dh, buf, nbytes); +} + +int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes) +{ + return write(ipod->dh, buf, nbytes); +} diff --git a/rbutil/ipodpatcher/ipodio-win32.c b/rbutil/ipodpatcher/ipodio-win32.c new file mode 100644 index 0000000000..83f00b8cd9 --- /dev/null +++ b/rbutil/ipodpatcher/ipodio-win32.c @@ -0,0 +1,190 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006-2007 Dave Chapman + * + * error(), lock_volume() and unlock_volume() functions and inspiration taken + * from: + * RawDisk - Direct Disk Read/Write Access for NT/2000/XP + * Copyright (c) 2003 Jan Kiszka + * http://www.stud.uni-hannover.de/user/73174/RawDisk/ + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __WIN32__ +#include +#include +#endif + +#include "ipodio.h" + +static int lock_volume(HANDLE hDisk) +{ + DWORD dummy; + + return DeviceIoControl(hDisk, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, + &dummy, NULL); +} + +static int unlock_volume(HANDLE hDisk) +{ + DWORD dummy; + + return DeviceIoControl(hDisk, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, + &dummy, NULL); +} + +void print_error(char* msg) +{ + char* pMsgBuf; + + printf(msg); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&pMsgBuf, + 0, NULL); + printf(pMsgBuf); + LocalFree(pMsgBuf); +} + +int ipod_open(struct ipod_t* ipod, int silent) +{ + DISK_GEOMETRY_EX diskgeometry_ex; + DISK_GEOMETRY diskgeometry; + unsigned long n; + + ipod->dh = CreateFile(ipod->diskname, GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); + + if (ipod->dh == INVALID_HANDLE_VALUE) { + if (!silent) print_error(" Error opening disk: "); + return -1; + } + + if (!lock_volume(ipod->dh)) { + if (!silent) print_error(" Error locking disk: "); + return -1; + } + + if (!DeviceIoControl(ipod->dh, + IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, + NULL, + 0, + &diskgeometry_ex, + sizeof(diskgeometry_ex), + &n, + NULL)) { + if (!DeviceIoControl(ipod->dh, + IOCTL_DISK_GET_DRIVE_GEOMETRY, + NULL, + 0, + &diskgeometry, + sizeof(diskgeometry), + &n, + NULL)) { + if (!silent) print_error(" Error reading disk geometry: "); + return -1; + } else { + ipod->sector_size=diskgeometry.BytesPerSector; + } + } else { + ipod->sector_size=diskgeometry_ex.Geometry.BytesPerSector; + } + + return 0; +} + +int ipod_reopen_rw(struct ipod_t* ipod) +{ + /* Close existing file and re-open for writing */ + unlock_volume(ipod->dh); + CloseHandle(ipod->dh); + + ipod->dh = CreateFile(ipod->diskname, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); + + if (ipod->dh == INVALID_HANDLE_VALUE) { + print_error(" Error opening disk: "); + return -1; + } + + if (!lock_volume(ipod->dh)) { + print_error(" Error locking disk: "); + return -1; + } + + return 0; +} + +int ipod_close(struct ipod_t* ipod) +{ + unlock_volume(ipod->dh); + CloseHandle(ipod->dh); + return 0; +} + +int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize) +{ + /* The ReadFile function requires a memory buffer aligned to a multiple of + the disk sector size. */ + *sectorbuf = (unsigned char*)VirtualAlloc(NULL, bufsize, MEM_COMMIT, PAGE_READWRITE); + if (*sectorbuf == NULL) { + print_error(" Error allocating a buffer: "); + return -1; + } + return 0; +} + +int ipod_seek(struct ipod_t* ipod, unsigned long pos) +{ + if (SetFilePointer(ipod->dh, pos, NULL, FILE_BEGIN)==0xffffffff) { + print_error(" Seek error "); + return -1; + } + return 0; +} + +int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes) +{ + unsigned long count; + + if (!ReadFile(ipod->dh, buf, nbytes, &count, NULL)) { + print_error(" Error reading from disk: "); + return -1; + } + + return count; +} + +int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes) +{ + unsigned long count; + + if (!WriteFile(ipod->dh, buf, nbytes, &count, NULL)) { + print_error(" Error writing to disk: "); + return -1; + } + + return count; +} diff --git a/rbutil/ipodpatcher/ipodio.h b/rbutil/ipodpatcher/ipodio.h new file mode 100644 index 0000000000..d0641faa2b --- /dev/null +++ b/rbutil/ipodpatcher/ipodio.h @@ -0,0 +1,89 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006-2007 Dave Chapman + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef __IPODIO_H +#define __IPODIO_H + +#include + +#ifdef __WIN32__ +#include +#else +#define HANDLE int +#define O_BINARY 0 +#endif + +/* The maximum number of images in a firmware partition - a guess... */ +#define MAX_IMAGES 10 + +enum firmwaretype_t { + FTYPE_OSOS = 0, + FTYPE_RSRC, + FTYPE_AUPD, + FTYPE_HIBE +}; + +struct ipod_directory_t { + enum firmwaretype_t ftype; + int id; + uint32_t devOffset; /* Offset of image relative to one sector into bootpart*/ + uint32_t len; + uint32_t addr; + uint32_t entryOffset; + uint32_t chksum; + uint32_t vers; + uint32_t loadAddr; +}; + +struct partinfo_t { + unsigned long start; /* first sector (LBA) */ + unsigned long size; /* number of sectors */ + int type; +}; + +struct ipod_t { + HANDLE dh; + char diskname[4096]; + int sector_size; + struct ipod_directory_t ipod_directory[MAX_IMAGES]; + int nimages; + 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 */ + struct partinfo_t pinfo[4]; + int modelnum; + char* modelname; + char* modelstr; + int macpod; +#ifdef WITH_BOOTOBJS + unsigned char* bootloader; + int bootloader_len; +#endif +}; + +void print_error(char* msg); +int ipod_open(struct ipod_t* ipod, int silent); +int ipod_reopen_rw(struct ipod_t* ipod); +int ipod_close(struct ipod_t* ipod); +int ipod_seek(struct ipod_t* ipod, unsigned long pos); +int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes); +int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes); +int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize); + +#endif diff --git a/rbutil/ipodpatcher/ipodpatcher.c b/rbutil/ipodpatcher/ipodpatcher.c new file mode 100644 index 0000000000..6c60bae38d --- /dev/null +++ b/rbutil/ipodpatcher/ipodpatcher.c @@ -0,0 +1,1261 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2006-2007 Dave Chapman + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "parttypes.h" +#include "ipodio.h" +#include "ipodpatcher.h" + +#ifdef WITH_BOOTOBJS +#include "ipod3g.h" +#include "ipod4g.h" +#include "ipodmini.h" +#include "ipodmini2g.h" +#include "ipodcolor.h" +#include "ipodnano.h" +#include "ipodvideo.h" +#endif + +extern int verbose; + +unsigned char* sectorbuf; + +/* The following string appears at the start of the firmware partition */ +static const char *apple_stop_sign = "{{~~ /-----\\ "\ + "{{~~ / \\ "\ + "{{~~| | "\ + "{{~~| S T O P | "\ + "{{~~| | "\ + "{{~~ \\ / "\ + "{{~~ \\-----/ "\ + "Copyright(C) 200"\ + "1 Apple Computer"\ + ", Inc.----------"\ + "----------------"\ + "----------------"\ + "----------------"\ + "----------------"\ + "----------------"\ + "---------------"; + +/* Windows requires the buffer for disk I/O to be aligned in memory on a + multiple of the disk volume size - so we use a single global variable + and initialise it with ipod_alloc_buf() +*/ + +char* get_parttype(int pt) +{ + int i; + static char unknown[]="Unknown"; + + if (pt == -1) { + return "HFS/HFS+"; + } + + i=0; + while (parttypes[i].name != NULL) { + if (parttypes[i].type == pt) { + return (parttypes[i].name); + } + i++; + } + + return unknown; +} + +off_t filesize(int fd) { + struct stat buf; + + if (fstat(fd,&buf) < 0) { + perror("[ERR] Checking filesize of input file"); + return -1; + } else { + return(buf.st_size); + } +} + +/* Partition table parsing code taken from Rockbox */ + +#define MAX_SECTOR_SIZE 2048 +#define SECTOR_SIZE 512 + +unsigned short static inline le2ushort(unsigned char* buf) +{ + unsigned short res = (buf[1] << 8) | buf[0]; + + return res; +} + +int static inline le2int(unsigned char* buf) +{ + int32_t res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; + + return res; +} + +int static inline be2int(unsigned char* buf) +{ + int32_t res = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; + + return res; +} + +int static inline getint16le(char* buf) +{ + int16_t res = (buf[1] << 8) | buf[0]; + + return res; +} + +void static inline short2le(unsigned short val, unsigned char* addr) +{ + addr[0] = val & 0xFF; + addr[1] = (val >> 8) & 0xff; +} + +void static inline int2le(unsigned int val, unsigned char* addr) +{ + addr[0] = val & 0xFF; + addr[1] = (val >> 8) & 0xff; + addr[2] = (val >> 16) & 0xff; + addr[3] = (val >> 24) & 0xff; +} + +void int2be(unsigned int val, unsigned char* addr) +{ + addr[0] = (val >> 24) & 0xff; + addr[1] = (val >> 16) & 0xff; + addr[2] = (val >> 8) & 0xff; + addr[3] = val & 0xFF; +} + + +#define BYTES2INT32(array,pos)\ + ((long)array[pos] | ((long)array[pos+1] << 8 ) |\ + ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 )) + +void display_partinfo(struct ipod_t* ipod) +{ + int i; + double sectors_per_MB = (1024.0*1024.0)/ipod->sector_size; + + printf("[INFO] Part Start Sector End Sector Size (MB) Type\n"); + for ( i = 0; i < 4; i++ ) { + if (ipod->pinfo[i].start != 0) { + printf("[INFO] %d %10ld %10ld %10.1f %s (0x%02x)\n", + i, + ipod->pinfo[i].start, + ipod->pinfo[i].start+ipod->pinfo[i].size-1, + ipod->pinfo[i].size/sectors_per_MB, + get_parttype(ipod->pinfo[i].type), + ipod->pinfo[i].type); + } + } +} + +int read_partinfo(struct ipod_t* ipod, int silent) +{ + int i; + unsigned long count; + + count = ipod_read(ipod,sectorbuf, ipod->sector_size); + + if (count <= 0) { + print_error(" Error reading from disk: "); + return -1; + } + + if ((sectorbuf[510] == 0x55) && (sectorbuf[511] == 0xaa)) { + /* DOS partition table */ + if ((memcmp(§orbuf[71],"iPod",4) != 0) && + (memcmp(§orbuf[0x40],"This is your Apple iPod. You probably do not want to boot from it!",66) != 0) ) { + if (!silent) fprintf(stderr,"[ERR] Drive is not an iPod, aborting\n"); + return -1; + } + + ipod->macpod = 0; + /* parse partitions */ + for ( i = 0; i < 4; i++ ) { + unsigned char* ptr = sectorbuf + 0x1be + 16*i; + ipod->pinfo[i].type = ptr[4]; + ipod->pinfo[i].start = BYTES2INT32(ptr, 8); + ipod->pinfo[i].size = BYTES2INT32(ptr, 12); + + /* extended? */ + if ( ipod->pinfo[i].type == 5 ) { + /* not handled yet */ + } + } + } else if ((sectorbuf[0] == 'E') && (sectorbuf[1] == 'R')) { + /* Apple Partition Map */ + + /* APM parsing code based on the check_mac_partitions() function in + ipodloader2 - written by Thomas Tempelmann and released + under the GPL. */ + + int blkNo = 1; + int partBlkCount = 1; + int partBlkSizMul = sectorbuf[2] / 2; + + int pmMapBlkCnt; /* # of blks in partition map */ + int pmPyPartStart; /* physical start blk of partition */ + int pmPartBlkCnt; /* # of blks in this partition */ + int i = 0; + + ipod->macpod = 1; + + memset(ipod->pinfo,0,sizeof(ipod->pinfo)); + + while (blkNo <= partBlkCount) { + if (ipod_seek(ipod, blkNo * partBlkSizMul * 512) < 0) { + fprintf(stderr,"[ERR] Seek failed whilst reading APM\n"); + return -1; + } + + count = ipod_read(ipod, sectorbuf, ipod->sector_size); + + if (count <= 0) { + print_error(" Error reading from disk: "); + return -1; + } + + /* see if it's a partition entry */ + if ((sectorbuf[0] != 'P') || (sectorbuf[1] != 'M')) { + /* end of partition table -> leave the loop */ + break; + } + + /* Extract the interesting entries */ + pmMapBlkCnt = be2int(sectorbuf + 4); + pmPyPartStart = be2int(sectorbuf + 8); + pmPartBlkCnt = be2int(sectorbuf + 12); + + /* update the number of part map blocks */ + partBlkCount = pmMapBlkCnt; + + if (strncmp((char*)(sectorbuf + 48), "Apple_MDFW", 32)==0) { + /* A Firmware partition */ + ipod->pinfo[i].start = pmPyPartStart; + ipod->pinfo[i].size = pmPartBlkCnt; + ipod->pinfo[i].type = 0; + i++; + } else if (strncmp((char*)(sectorbuf + 48), "Apple_HFS", 32)==0) { + /* A HFS partition */ + ipod->pinfo[i].start = pmPyPartStart; + ipod->pinfo[i].size = pmPartBlkCnt; + ipod->pinfo[i].type = -1; + i++; + } + + blkNo++; /* read next partition map entry */ + } + } else { + if (!silent) fprintf(stderr,"[ERR] Bad boot sector signature\n"); + return -1; + } + + ipod->start = ipod->pinfo[0].start*ipod->sector_size; + return 0; +} + +int read_partition(struct ipod_t* ipod, int outfile) +{ + int res; + unsigned long n; + int bytesleft; + int chunksize; + int count = ipod->pinfo[0].size; + + if (ipod_seek(ipod, ipod->start) < 0) { + return -1; + } + + fprintf(stderr,"[INFO] Writing %d sectors to output file\n",count); + + bytesleft = count * ipod->sector_size; + while (bytesleft > 0) { + if (bytesleft > BUFFER_SIZE) { + chunksize = BUFFER_SIZE; + } else { + chunksize = bytesleft; + } + + n = ipod_read(ipod, sectorbuf, chunksize); + + if (n < 0) { + return -1; + } + + if (n < chunksize) { + fprintf(stderr, + "[ERR] Short read in disk_read() - requested %d, got %lu\n", + chunksize,n); + return -1; + } + + bytesleft -= n; + + res = write(outfile,sectorbuf,n); + + if (res < 0) { + perror("[ERR] write in disk_read"); + return -1; + } + + if (res != n) { + fprintf(stderr, + "Short write - requested %lu, received %d - aborting.\n",n,res); + return -1; + } + } + + fprintf(stderr,"[INFO] Done.\n"); + return 0; +} + +int write_partition(struct ipod_t* ipod, int infile) +{ + unsigned long res; + int n; + int bytesread; + int byteswritten = 0; + int eof; + int padding = 0; + + if (ipod_seek(ipod, ipod->start) < 0) { + return -1; + } + + fprintf(stderr,"[INFO] Writing input file to device\n"); + bytesread = 0; + eof = 0; + while (!eof) { + n = read(infile,sectorbuf,BUFFER_SIZE); + + if (n < 0) { + perror("[ERR] read in disk_write"); + return -1; + } + + if (n < BUFFER_SIZE) { + eof = 1; + /* We need to pad the last write to a multiple of SECTOR_SIZE */ + if ((n % ipod->sector_size) != 0) { + padding = (ipod->sector_size-(n % ipod->sector_size)); + n += padding; + } + } + + bytesread += n; + + res = ipod_write(ipod, sectorbuf, n); + + if (res < 0) { + print_error(" Error writing to disk: "); + fprintf(stderr,"Bytes written: %d\n",byteswritten); + return -1; + } + + if (res != n) { + fprintf(stderr,"[ERR] Short write - requested %d, received %lu - aborting.\n",n,res); + return -1; + } + + byteswritten += res; + } + + fprintf(stderr,"[INFO] Wrote %d bytes plus %d bytes padding.\n", + byteswritten-padding,padding); + return 0; +} + +char* ftypename[] = { "OSOS", "RSRC", "AUPD", "HIBE" }; + +int diskmove(struct ipod_t* ipod, int delta) +{ + int src_start; + int src_end; + int bytesleft; + int chunksize; + int i; + int n; + + src_start = ipod->ipod_directory[1].devOffset + ipod->sector_size; + src_end = (ipod->ipod_directory[ipod->nimages-1].devOffset + ipod->sector_size + + ipod->ipod_directory[ipod->nimages-1].len + + (ipod->sector_size-1)) & ~(ipod->sector_size-1); + bytesleft = src_end - src_start; + + if (verbose) { + fprintf(stderr,"[INFO] Need to move images 2-%d forward %08x bytes\n", ipod->nimages,delta); + fprintf(stderr,"[VERB] src_start = %08x\n",src_start); + fprintf(stderr,"[VERB] src_end = %08x\n",src_end); + fprintf(stderr,"[VERB] dest_start = %08x\n",src_start+delta); + fprintf(stderr,"[VERB] dest_end = %08x\n",src_end+delta); + fprintf(stderr,"[VERB] bytes to copy = %08x\n",bytesleft); + } + + while (bytesleft > 0) { + if (bytesleft <= BUFFER_SIZE) { + chunksize = bytesleft; + } else { + chunksize = BUFFER_SIZE; + } + + if (verbose) { + fprintf(stderr,"[VERB] Copying %08x bytes from %08x to %08x (absolute %08x to %08x)\n", + chunksize, + src_end-chunksize, + src_end-chunksize+delta, + (unsigned int)(ipod->start+src_end-chunksize), + (unsigned int)(ipod->start+src_end-chunksize+delta)); + } + + + if (ipod_seek(ipod, ipod->start+src_end-chunksize) < 0) { + fprintf(stderr,"[ERR] Seek failed\n"); + return -1; + } + + if ((n = ipod_read(ipod,sectorbuf,chunksize)) < 0) { + perror("[ERR] Write failed\n"); + return -1; + } + + if (n < chunksize) { + fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n", + i,n); + return -1; + } + + if (ipod_seek(ipod, ipod->start+src_end-chunksize+delta) < 0) { + fprintf(stderr,"[ERR] Seek failed\n"); + return -1; + } + + if ((n = ipod_write(ipod,sectorbuf,chunksize)) < 0) { + perror("[ERR] Write failed\n"); + return -1; + } + + if (n < chunksize) { + fprintf(stderr,"[ERR] Short write - requested %d bytes, received %d\n" + ,i,n); + return -1; + } + + src_end -= chunksize; + bytesleft -= chunksize; + } + + return 0; +} + +int add_bootloader(struct ipod_t* ipod, char* filename, int type) +{ + int length; + int i; + int x; + int n; + int infile; + int paddedlength; + int entryOffset; + int delta = 0; + unsigned long chksum=0; + unsigned long filechksum=0; + unsigned char header[8]; /* Header for .ipod file */ + unsigned char* bootloader_buf; + + /* Calculate the position in the OSOS image where our bootloader will go. */ + if (ipod->ipod_directory[0].entryOffset>0) { + /* Keep the same entryOffset */ + entryOffset = ipod->ipod_directory[0].entryOffset; + } else { + entryOffset = (ipod->ipod_directory[0].len+ipod->sector_size-1)&~(ipod->sector_size-1); + } + +#ifdef WITH_BOOTOBJS + if (type == FILETYPE_INTERNAL) { + fprintf(stderr,"[INFO] Using internal bootloader - %d bytes\n",ipod->bootloader_len); + memcpy(sectorbuf+entryOffset,ipod->bootloader,ipod->bootloader_len); + length = ipod->bootloader_len; + paddedlength=(ipod->bootloader_len+ipod->sector_size-1)&~(ipod->sector_size-1); + } + else +#endif + { + infile=open(filename,O_RDONLY); + if (infile < 0) { + fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); + return -1; + } + + if (type==FILETYPE_DOT_IPOD) { + /* First check that the input file is the correct type for this ipod. */ + n = read(infile,header,8); + if (n < 8) { + fprintf(stderr,"[ERR] Failed to read header from %s\n",filename); + close(infile); + return -1; + } + + if (memcmp(header+4, ipod->modelname,4)!=0) { + fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n", + header[4],header[5],header[6],header[7], ipod->modelname); + close(infile); + return -1; + } + + filechksum = be2int(header); + + length=filesize(infile)-8; + } else { + length=filesize(infile); + } + paddedlength=(length+ipod->sector_size-1)&~(ipod->sector_size-1); + + bootloader_buf = malloc(length); + if (bootloader_buf == NULL) { + fprintf(stderr,"[ERR] Can not allocate memory for bootlaoder\n"); + } + /* Now read our bootloader - we need to check it before modifying the partition*/ + n = read(infile,bootloader_buf,length); + close(infile); + + if (n < 0) { + fprintf(stderr,"[ERR] Couldn't read input file\n"); + return -1; + } + + if (type==FILETYPE_DOT_IPOD) { + /* Calculate and confirm bootloader checksum */ + chksum = ipod->modelnum; + for (i = 0; i < length; i++) { + /* add 8 unsigned bits but keep a 32 bit sum */ + chksum += bootloader_buf[i]; + } + + if (chksum == filechksum) { + fprintf(stderr,"[INFO] Checksum OK in %s\n",filename); + } else { + fprintf(stderr,"[ERR] Checksum in %s failed check\n",filename); + return -1; + } + } + } + + if (entryOffset+paddedlength > BUFFER_SIZE) { + fprintf(stderr,"[ERR] Input file too big for buffer\n"); + return -1; + } + + if (verbose) { + fprintf(stderr,"[VERB] Original firmware begins at 0x%08x\n", ipod->ipod_directory[0].devOffset + ipod->sector_size); + fprintf(stderr,"[VERB] New entryOffset will be 0x%08x\n",entryOffset); + fprintf(stderr,"[VERB] End of bootloader will be at 0x%08x\n",entryOffset+paddedlength); + } + + /* Check if we have enough space */ + /* TODO: Check the size of the partition. */ + if (ipod->nimages > 1) { + if ((ipod->ipod_directory[0].devOffset+entryOffset+paddedlength) > + ipod->ipod_directory[1].devOffset) { + fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n"); + delta = ipod->ipod_directory[0].devOffset + entryOffset+paddedlength + - ipod->ipod_directory[1].devOffset; + + if (diskmove(ipod, delta) < 0) { + fprintf(stderr,"[ERR] Image movement failed.\n"); + return -1; + } + } + } + + + /* We have moved the partitions, now we can write our bootloader */ + + /* Firstly read the original firmware into sectorbuf */ + fprintf(stderr,"[INFO] Reading original firmware...\n"); + if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { + fprintf(stderr,"[ERR] Seek failed\n"); + return -1; + } + + if ((n = ipod_read(ipod,sectorbuf,entryOffset)) < 0) { + perror("[ERR] Read failed\n"); + return -1; + } + + if (n < entryOffset) { + fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n" + ,i,n); + return -1; + } + +#ifdef WITH_BOOTOBJS + if (type == FILETYPE_INTERNAL) { + memcpy(sectorbuf+entryOffset,ipod->bootloader,ipod->bootloader_len); + } + else +#endif + { + memcpy(sectorbuf+entryOffset,bootloader_buf,length); + free(bootloader_buf); + } + + /* Calculate new checksum for combined image */ + chksum = 0; + for (i=0;ifwoffset+ipod->ipod_directory[0].devOffset) < 0) { + fprintf(stderr,"[ERR] Seek failed\n"); + return -1; + } + + if ((n = ipod_write(ipod,sectorbuf,entryOffset+paddedlength)) < 0) { + perror("[ERR] Write failed\n"); + return -1; + } + + if (n < (entryOffset+paddedlength)) { + fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n" + ,i,n); + return -1; + } + + fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",entryOffset+paddedlength); + + x = ipod->diroffset % ipod->sector_size; + + /* Read directory */ + if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { + fprintf(stderr,"[ERR] Seek failed\n"); + return -1; + } + + n=ipod_read(ipod, sectorbuf, ipod->sector_size); + if (n < 0) { + fprintf(stderr,"[ERR] Directory read failed\n"); + return -1; + } + + /* Update entries for image 0 */ + int2le(entryOffset+length,sectorbuf+x+16); + int2le(entryOffset,sectorbuf+x+24); + int2le(chksum,sectorbuf+x+28); + int2le(0xffffffff,sectorbuf+x+36); /* loadAddr */ + + /* Update devOffset entries for other images, if we have moved them */ + if (delta > 0) { + for (i=1;inimages;i++) { + int2le(le2int(sectorbuf+x+i*40+12)+delta,sectorbuf+x+i*40+12); + } + } + + /* Write directory */ + if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { + fprintf(stderr,"[ERR] Seek to %d failed\n", (int)(ipod->start+ipod->diroffset-x)); + return -1; + } + n=ipod_write(ipod, sectorbuf, ipod->sector_size); + if (n < 0) { + fprintf(stderr,"[ERR] Directory write failed\n"); + return -1; + } + + return 0; +} + +int delete_bootloader(struct ipod_t* ipod) +{ + int length; + int i; + int x; + int n; + unsigned long chksum=0; /* 32 bit checksum - Rockbox .ipod style*/ + + /* Removing the bootloader involves adjusting the "length", + "chksum" and "entryOffset" values in the osos image's directory + entry. */ + + /* Firstly check we have a bootloader... */ + + if (ipod->ipod_directory[0].entryOffset == 0) { + fprintf(stderr,"[ERR] No bootloader found.\n"); + return -1; + } + + length = ipod->ipod_directory[0].entryOffset; + + /* Read the firmware so we can calculate the checksum */ + fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length); + + if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { + return -1; + } + + 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 ((n = ipod_read(ipod,sectorbuf,i)) < 0) { + return -1; + } + + if (n < i) { + fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n", + i,n); + return -1; + } + + chksum = 0; + for (i = 0; i < length; i++) { + /* add 8 unsigned bits but keep a 32 bit sum */ + chksum += sectorbuf[i]; + } + + /* Now write back the updated directory entry */ + + fprintf(stderr,"[INFO] Updating firmware checksum\n"); + + x = ipod->diroffset % ipod->sector_size; + + /* Read directory */ + if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; } + + n=ipod_read(ipod, sectorbuf, ipod->sector_size); + if (n < 0) { return -1; } + + /* Update entries for image 0 */ + int2le(length,sectorbuf+x+16); + int2le(0,sectorbuf+x+24); + int2le(chksum,sectorbuf+x+28); + + /* Write directory */ + if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; } + n=ipod_write(ipod, sectorbuf, ipod->sector_size); + if (n < 0) { return -1; } + + return 0; +} + +int write_firmware(struct ipod_t* ipod, char* filename, int type) +{ + int length; + int i; + int x; + int n; + int infile; + int newsize; + int bytesavailable; + unsigned long chksum=0; + unsigned long filechksum=0; + unsigned char header[8]; /* Header for .ipod file */ + + /* First check that the input file is the correct type for this ipod. */ + infile=open(filename,O_RDONLY); + if (infile < 0) { + fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); + return -1; + } + + if (type==FILETYPE_DOT_IPOD) { + n = read(infile,header,8); + if (n < 8) { + fprintf(stderr,"[ERR] Failed to read header from %s\n",filename); + close(infile); + return -1; + } + + if (memcmp(header+4, ipod->modelname,4)!=0) { + fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n", + header[4],header[5],header[6],header[7], ipod->modelname); + close(infile); + return -1; + } + + filechksum = be2int(header); + + length = filesize(infile)-8; + } else { + length = filesize(infile); + } + newsize=(length+ipod->sector_size-1)&~(ipod->sector_size-1); + + fprintf(stderr,"[INFO] Padding input file from 0x%08x to 0x%08x bytes\n", + length,newsize); + + if (newsize > BUFFER_SIZE) { + fprintf(stderr,"[ERR] Input file too big for buffer\n"); + close(infile); + return -1; + } + + /* Check if we have enough space */ + /* TODO: Check the size of the partition. */ + if (ipod->nimages > 1) { + bytesavailable=ipod->ipod_directory[1].devOffset-ipod->ipod_directory[0].devOffset; + if (bytesavailable < newsize) { + fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n"); + + /* TODO: Implement image movement */ + fprintf(stderr,"[ERR] Image movement not yet implemented.\n"); + close(infile); + return -1; + } + } + + fprintf(stderr,"[INFO] Reading input file...\n"); + /* We now know we have enough space, so write it. */ + memset(sectorbuf+length,0,newsize-length); + n = read(infile,sectorbuf,length); + if (n < 0) { + fprintf(stderr,"[ERR] Couldn't read input file\n"); + close(infile); + return -1; + } + close(infile); + + if (type==FILETYPE_DOT_IPOD) { + chksum = ipod->modelnum; + for (i = 0; i < length; i++) { + /* add 8 unsigned bits but keep a 32 bit sum */ + chksum += sectorbuf[i]; + } + + if (chksum == filechksum) { + fprintf(stderr,"[INFO] Checksum OK in %s\n",filename); + } else { + fprintf(stderr,"[ERR] Checksum in %s failed check\n",filename); + return -1; + } + } + + if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { + fprintf(stderr,"[ERR] Seek failed\n"); + return -1; + } + + if ((n = ipod_write(ipod,sectorbuf,newsize)) < 0) { + perror("[ERR] Write failed\n"); + return -1; + } + + if (n < newsize) { + fprintf(stderr,"[ERR] Short write - requested %d bytes, received %d\n" + ,i,n); + return -1; + } + fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",n); + + /* Now we need to update the "len", "entryOffset" and "chksum" fields */ + chksum = 0; + for (i = 0; i < length; i++) { + /* add 8 unsigned bits but keep a 32 bit sum */ + chksum += sectorbuf[i]; + } + + x = ipod->diroffset % ipod->sector_size; + + /* Read directory */ + if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; } + + n=ipod_read(ipod, sectorbuf, ipod->sector_size); + if (n < 0) { return -1; } + + /* Update entries for image 0 */ + int2le(length,sectorbuf+x+16); + int2le(0,sectorbuf+x+24); + int2le(chksum,sectorbuf+x+28); + + /* Write directory */ + if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; } + n=ipod_write(ipod, sectorbuf, ipod->sector_size); + if (n < 0) { return -1; } + + return 0; +} + +int read_firmware(struct ipod_t* ipod, char* filename) +{ + int length; + int i; + int outfile; + int n; + 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) { + /* We have a bootloader... */ + length = ipod->ipod_directory[0].entryOffset; + } else { + length = ipod->ipod_directory[0].len; + } + + fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length); + + if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { + return -1; + } + + 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 ((n = ipod_read(ipod,sectorbuf,i)) < 0) { + return -1; + } + + if (n < i) { + fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n", + i,n); + return -1; + } + + chksum = ipod->modelnum; + for (i = 0; i < length; i++) { + /* add 8 unsigned bits but keep a 32 bit sum */ + chksum += sectorbuf[i]; + } + + int2be(chksum,header); + memcpy(header+4, ipod->modelname,4); + + outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666); + if (outfile < 0) { + fprintf(stderr,"[ERR] Couldn't open file %s\n",filename); + return -1; + } + + write(outfile,header,8); + write(outfile,sectorbuf,length); + close(outfile); + + return 0; +} + +int read_directory(struct ipod_t* ipod) +{ + int n; + int x; + unsigned char* p; + unsigned short version; + + ipod->nimages=0; + + /* Read firmware partition header (first 512 bytes of disk - but + let's read a whole sector) */ + + if (ipod_seek(ipod, ipod->start) < 0) { + fprintf(stderr,"[ERR] Seek to 0x%08x in read_directory() failed.\n", + (unsigned int)(ipod->start)); + return -1; + } + + n=ipod_read(ipod, sectorbuf, ipod->sector_size); + if (n < 0) { + fprintf(stderr,"[ERR] ipod_read(ipod,buf,0x%08x) failed in read_directory()\n", ipod->sector_size); + return -1; + } + + if (memcmp(sectorbuf,apple_stop_sign,sizeof(apple_stop_sign))!=0) { + fprintf(stderr,"[ERR] Firmware partition doesn't contain Apple copyright, aborting.\n"); + return -1; + } + + if (memcmp(sectorbuf+0x100,"]ih[",4)!=0) { + fprintf(stderr,"[ERR] Bad firmware directory\n"); + return -1; + } + + version = le2ushort(sectorbuf+0x10a); + if ((version != 2) && (version != 3)) { + fprintf(stderr,"[ERR] Unknown firmware format version %04x\n", + version); + } + ipod->diroffset=le2int(sectorbuf+0x104) + 0x200; + + /* diroffset may not be sector-aligned */ + x = ipod->diroffset % ipod->sector_size; + + /* Read directory */ + if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { + fprintf(stderr,"[ERR] Seek to diroffset (%08x) failed.\n",(unsigned)ipod->diroffset); + return -1; + } + + n=ipod_read(ipod, sectorbuf, ipod->sector_size); + if (n < 0) { + fprintf(stderr,"[ERR] Read of directory failed.\n"); + return -1; + } + + p = sectorbuf + x; + + while ((ipod->nimages < MAX_IMAGES) && (p < (sectorbuf + x + 400)) && + (memcmp(p,"!ATA",4)==0)) { + p+=4; + if (memcmp(p,"soso",4)==0) { + ipod->ipod_directory[ipod->nimages].ftype=FTYPE_OSOS; + } else if (memcmp(p,"crsr",4)==0) { + ipod->ipod_directory[ipod->nimages].ftype=FTYPE_RSRC; + } else if (memcmp(p,"dpua",4)==0) { + ipod->ipod_directory[ipod->nimages].ftype=FTYPE_AUPD; + } else if (memcmp(p,"ebih",4)==0) { + ipod->ipod_directory[ipod->nimages].ftype=FTYPE_HIBE; + } else { + fprintf(stderr,"[ERR] Unknown image type %c%c%c%c\n", + p[0],p[1],p[2],p[3]); + } + p+=4; + ipod->ipod_directory[ipod->nimages].id=le2int(p); + p+=4; + ipod->ipod_directory[ipod->nimages].devOffset=le2int(p); + p+=4; + ipod->ipod_directory[ipod->nimages].len=le2int(p); + p+=4; + ipod->ipod_directory[ipod->nimages].addr=le2int(p); + p+=4; + ipod->ipod_directory[ipod->nimages].entryOffset=le2int(p); + p+=4; + ipod->ipod_directory[ipod->nimages].chksum=le2int(p); + p+=4; + ipod->ipod_directory[ipod->nimages].vers=le2int(p); + p+=4; + ipod->ipod_directory[ipod->nimages].loadAddr=le2int(p); + p+=4; + ipod->nimages++; + } + + 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; } + + ipod->fwoffset = ipod->start; + } else { + ipod->fwoffset = ipod->start + ipod->sector_size; + } + + return 0; +} + +int list_images(struct ipod_t* ipod) +{ + int i; + + if (verbose) { + printf(" Type id devOffset len addr entryOffset chksum vers loadAddr devOffset+len\n"); + for (i = 0 ; i < ipod->nimages; i++) { + printf("%d - %s 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",i, + ftypename[ipod->ipod_directory[i].ftype], + ipod->ipod_directory[i].id, + ipod->ipod_directory[i].devOffset, + ipod->ipod_directory[i].len, + ipod->ipod_directory[i].addr, + ipod->ipod_directory[i].entryOffset, + ipod->ipod_directory[i].chksum, + ipod->ipod_directory[i].vers, + ipod->ipod_directory[i].loadAddr, + ipod->ipod_directory[i].devOffset+((ipod->ipod_directory[i].len+ipod->sector_size-1)&~(ipod->sector_size-1))); + } + } + + printf("\n"); + printf("Listing firmware partition contents:\n"); + printf("\n"); + + for (i = 0 ; i < ipod->nimages; i++) { + printf("Image %d:\n",i+1); + switch(ipod->ipod_directory[i].ftype) { + case FTYPE_OSOS: + if (ipod->ipod_directory[i].entryOffset==0) { + printf(" Main firmware - %d bytes\n", + ipod->ipod_directory[i].len); + } else { + printf(" Main firmware - %d bytes\n", + ipod->ipod_directory[i].entryOffset); + printf(" Third-party bootloader - %d bytes\n", + ipod->ipod_directory[i].len-ipod->ipod_directory[i].entryOffset); + } + break; + default: + printf(" %s - %d bytes\n", + ftypename[ipod->ipod_directory[i].ftype], + ipod->ipod_directory[i].len); + } + } + printf("\n"); + + return 0; +} + +int getmodel(struct ipod_t* ipod, int ipod_version) +{ + switch (ipod_version) { + case 0x02: + ipod->modelstr="3rd Generation"; + ipod->modelnum = 7; + ipod->modelname = "ip3g"; +#ifdef WITH_BOOTOBJS + ipod->bootloader = ipod3g; + ipod->bootloader_len = LEN_ipod3g; +#endif + break; + case 0x40: + ipod->modelstr="1st Generation Mini"; + ipod->modelnum = 9; + ipod->modelname = "mini"; +#ifdef WITH_BOOTOBJS + ipod->bootloader = ipodmini; + ipod->bootloader_len = LEN_ipodmini; +#endif + break; + case 0x50: + ipod->modelstr="4th Generation"; + ipod->modelnum = 8; + ipod->modelname = "ip4g"; +#ifdef WITH_BOOTOBJS + ipod->bootloader = ipod4g; + ipod->bootloader_len = LEN_ipod4g; +#endif + break; + case 0x60: + ipod->modelstr="Photo/Color"; + ipod->modelnum = 3; + ipod->modelname = "ipco"; +#ifdef WITH_BOOTOBJS + ipod->bootloader = ipodcolor; + ipod->bootloader_len = LEN_ipodcolor; +#endif + break; + case 0x70: + ipod->modelstr="2nd Generation Mini"; + ipod->modelnum = 11; + ipod->modelname = "mn2g"; +#ifdef WITH_BOOTOBJS + ipod->bootloader = ipodmini2g; + ipod->bootloader_len = LEN_ipodmini2g; +#endif + break; + case 0xc0: + ipod->modelstr="1st Generation Nano"; + ipod->modelnum = 4; + ipod->modelname = "nano"; +#ifdef WITH_BOOTOBJS + ipod->bootloader = ipodnano; + ipod->bootloader_len = LEN_ipodnano; +#endif + break; + case 0xb0: + ipod->modelstr="Video (aka 5th Generation)"; + ipod->modelnum = 5; + ipod->modelname = "ipvd"; +#ifdef WITH_BOOTOBJS + ipod->bootloader = ipodvideo; + ipod->bootloader_len = LEN_ipodvideo; +#endif + break; + default: + ipod->modelname = NULL; + ipod->modelnum = 0; +#ifdef WITH_BOOTOBJS + ipod->bootloader = NULL; + ipod->bootloader_len = 0; +#endif + return -1; + } + return 0; +} + +int ipod_scan(struct ipod_t* ipod) +{ + int i; + int n = 0; + int ipod_version; + char last_ipod[4096]; + + printf("[INFO] Scanning disk devices...\n"); + + for (i = 0; i <= 25 ; i++) { +#ifdef __WIN32__ + sprintf(ipod->diskname,"\\\\.\\PhysicalDrive%d",i); +#elif defined(linux) || defined (__linux) + sprintf(ipod->diskname,"/dev/sd%c",'a'+i); +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ + || defined(__bsdi__) || defined(__DragonFly__) + sprintf(ipod->diskname,"/dev/da%d",i); +#elif defined(__APPLE__) && defined(__MACH__) + sprintf(ipod->diskname,"/dev/disk%d",i); +#else + #error No disk paths defined for this platform +#endif + if (ipod_open(ipod, 1) < 0) { + continue; + } + + if (read_partinfo(ipod,1) < 0) { + continue; + } + + if ((ipod->pinfo[0].start==0) || (ipod->pinfo[0].type != 0)) { + continue; + } + + if (read_directory(ipod) < 0) { + continue; + } + + ipod_version=(ipod->ipod_directory[0].vers>>8); + if (getmodel(ipod,ipod_version) < 0) { + continue; + } + +#ifdef __WIN32__ + printf("[INFO] Ipod found - %s (\"%s\") - disk device %d\n", + ipod->modelstr,ipod->macpod ? "macpod" : "winpod",i); +#else + printf("[INFO] Ipod found - %s (\"%s\") - %s\n", + ipod->modelstr,ipod->macpod ? "macpod" : "winpod",ipod->diskname); +#endif + n++; + strcpy(last_ipod,ipod->diskname); + ipod_close(ipod); + } + + if (n==1) { + /* Remember the disk name */ + strcpy(ipod->diskname,last_ipod); + } + return n; +} diff --git a/rbutil/ipodpatcher/ipodpatcher.h b/rbutil/ipodpatcher/ipodpatcher.h new file mode 100644 index 0000000000..c533f4c2dc --- /dev/null +++ b/rbutil/ipodpatcher/ipodpatcher.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: ipodpatcher.c 12237 2007-02-08 21:31:38Z dave $ + * + * Copyright (C) 2006-2007 Dave Chapman + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _IPODPATCHER_H +#define _IPODPATCHER_H + +#include "ipodio.h" + +/* Size of buffer for disk I/O - 8MB is large enough for any version + of the Apple firmware, but not the Nano's RSRC image. */ +#define BUFFER_SIZE 8*1024*1024 +extern unsigned char* sectorbuf; + +#define FILETYPE_DOT_IPOD 0 +#define FILETYPE_DOT_BIN 1 +#ifdef WITH_BOOTOBJS + #define FILETYPE_INTERNAL 2 +#endif + +void display_partinfo(struct ipod_t* ipod); +int read_partinfo(struct ipod_t* ipod, int silent); +int read_partition(struct ipod_t* ipod, int outfile); +int write_partition(struct ipod_t* ipod, int infile); +int diskmove(struct ipod_t* ipod, int delta); +int add_bootloader(struct ipod_t* ipod, char* filename, int type); +int delete_bootloader(struct ipod_t* ipod); +int write_firmware(struct ipod_t* ipod, char* filename, int type); +int read_firmware(struct ipod_t* ipod, char* filename); +int read_directory(struct ipod_t* ipod); +int list_images(struct ipod_t* ipod); +int getmodel(struct ipod_t* ipod, int ipod_version); +int ipod_scan(struct ipod_t* ipod); +off_t filesize(int fd); + +#endif diff --git a/rbutil/ipodpatcher/main.c b/rbutil/ipodpatcher/main.c new file mode 100644 index 0000000000..d183b9bc52 --- /dev/null +++ b/rbutil/ipodpatcher/main.c @@ -0,0 +1,429 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: ipodpatcher.c 12237 2007-02-08 21:31:38Z dave $ + * + * Copyright (C) 2006-2007 Dave Chapman + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ipodpatcher.h" +#include "ipodio.h" + +#define VERSION "0.8 with r12194-070204 bootloaders" + +int verbose = 0; + +enum { + NONE, +#ifdef WITH_BOOTOBJS + INSTALL, +#endif + INTERACTIVE, + SHOW_INFO, + LIST_IMAGES, + DELETE_BOOTLOADER, + ADD_BOOTLOADER, + READ_FIRMWARE, + WRITE_FIRMWARE, + READ_PARTITION, + WRITE_PARTITION +}; + +void print_macpod_warning(void) +{ + printf("[INFO] ************************************************************************\n"); + printf("[INFO] *** WARNING FOR ROCKBOX USERS\n"); + printf("[INFO] *** You must convert this ipod to FAT32 format (aka a \"winpod\")\n"); + printf("[INFO] *** if you want to run Rockbox. Rockbox WILL NOT work on this ipod.\n"); + printf("[INFO] *** See http://www.rockbox.org/twiki/bin/view/Main/IpodConversionToFAT32\n"); + printf("[INFO] ************************************************************************\n"); +} + +void print_usage(void) +{ + fprintf(stderr,"Usage: ipodpatcher --scan\n"); +#ifdef __WIN32__ + fprintf(stderr," or ipodpatcher [DISKNO] [action]\n"); +#else + fprintf(stderr," or ipodpatcher [device] [action]\n"); +#endif + fprintf(stderr,"\n"); + fprintf(stderr,"Where [action] is one of the following options:\n"); +#ifdef WITH_BOOTOBJS + fprintf(stderr," --install\n"); +#endif + fprintf(stderr," -l, --list\n"); + fprintf(stderr," -r, --read-partition bootpartition.bin\n"); + fprintf(stderr," -w, --write-partition bootpartition.bin\n"); + fprintf(stderr," -rf, --read-firmware filename.ipod\n"); + fprintf(stderr," -wf, --write-firmware filename.ipod\n"); + fprintf(stderr," -wfb, --write-firmware-bin filename.bin\n"); + fprintf(stderr," -a, --add-bootloader filename.ipod\n"); + fprintf(stderr," -ab, --add-bootloader-bin filename.bin\n"); + fprintf(stderr," -d, --delete-bootloader\n"); + fprintf(stderr,"\n"); + +#ifdef __WIN32__ + fprintf(stderr,"DISKNO is the number (e.g. 2) Windows has assigned to your ipod's hard disk.\n"); + fprintf(stderr,"The first hard disk in your computer (i.e. C:\\) will be disk 0, the next disk\n"); + fprintf(stderr,"will be disk 1 etc. ipodpatcher will refuse to access a disk unless it\n"); + fprintf(stderr,"can identify it as being an ipod.\n"); + fprintf(stderr,"\n"); +#else +#if defined(linux) || defined (__linux) + fprintf(stderr,"\"device\" is the device node (e.g. /dev/sda) assigned to your ipod.\n"); +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + fprintf(stderr,"\"device\" is the device node (e.g. /dev/da1) assigned to your ipod.\n"); +#elif defined(__APPLE__) && defined(__MACH__) + fprintf(stderr,"\"device\" is the device node (e.g. /dev/disk1) assigned to your ipod.\n"); +#endif + fprintf(stderr,"ipodpatcher will refuse to access a disk unless it can identify it as being\n"); + fprintf(stderr,"an ipod.\n"); +#endif +} + +int main(int argc, char* argv[]) +{ +#ifdef WITH_BOOTOBJS + char yesno[4]; +#endif + int i; + int n; + int infile, outfile; + unsigned int inputsize; + char* filename; + int action = SHOW_INFO; + int type; + struct ipod_t ipod; + + fprintf(stderr,"ipodpatcher v" VERSION " - (C) Dave Chapman 2006-2007\n"); + fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n"); + fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); + + if ((argc > 1) && ((strcmp(argv[1],"-h")==0) || (strcmp(argv[1],"--help")==0))) { + print_usage(); + return 1; + } + + if (ipod_alloc_buffer(§orbuf,BUFFER_SIZE) < 0) { + fprintf(stderr,"Failed to allocate memory buffer\n"); + } + + if ((argc > 1) && (strcmp(argv[1],"--scan")==0)) { + if (ipod_scan(&ipod) == 0) + fprintf(stderr,"[ERR] No ipods found.\n"); + return 0; + } + + /* If the first parameter doesn't start with -, then we interpret it as a device */ + if ((argc > 1) && (argv[1][0] != '-')) { + ipod.diskname[0]=0; +#ifdef __WIN32__ + snprintf(ipod.diskname,sizeof(ipod.diskname),"\\\\.\\PhysicalDrive%s",argv[1]); +#else + strncpy(ipod.diskname,argv[1],sizeof(ipod.diskname)); +#endif + i = 2; + } else { + /* Autoscan for ipods */ + n = ipod_scan(&ipod); + if (n==0) { + fprintf(stderr,"[ERR] No ipods found, aborting\n"); + fprintf(stderr,"[ERR] Please connect your ipod and ensure it is in disk mode\n"); +#if defined(__APPLE__) && defined(__MACH__) + fprintf(stderr,"[ERR] Also ensure that itunes is closed, and that your ipod is not mounted.\n"); +#elif !defined(__WIN32__) + if (geteuid()!=0) { + fprintf(stderr,"[ERR] You may also need to run ipodpatcher as root.\n"); + } +#endif + fprintf(stderr,"[ERR] Please refer to the Rockbox manual if you continue to have problems.\n"); + } else if (n > 1) { + fprintf(stderr,"[ERR] %d ipods found, aborting\n",n); + fprintf(stderr,"[ERR] Please connect only one ipod and re-run ipodpatcher.\n"); + } + + if (n != 1) { +#ifdef WITH_BOOTOBJS + if (argc==1) { + printf("\nPress ENTER to exit ipodpatcher :"); + fgets(yesno,4,stdin); + } +#endif + return 0; + } + + i = 1; + } + +#ifdef WITH_BOOTOBJS + action = INTERACTIVE; +#else + action = NONE; +#endif + + while (i < argc) { + if ((strcmp(argv[i],"-l")==0) || (strcmp(argv[i],"--list")==0)) { + action = LIST_IMAGES; + i++; +#ifdef WITH_BOOTOBJS + } else if (strcmp(argv[i],"--install")==0) { + action = INSTALL; + i++; +#endif + } else if ((strcmp(argv[i],"-d")==0) || + (strcmp(argv[i],"--delete-bootloader")==0)) { + action = DELETE_BOOTLOADER; + i++; + } else if ((strcmp(argv[i],"-a")==0) || + (strcmp(argv[i],"--add-bootloader")==0)) { + action = ADD_BOOTLOADER; + type = FILETYPE_DOT_IPOD; + i++; + if (i == argc) { print_usage(); return 1; } + filename=argv[i]; + i++; + } else if ((strcmp(argv[i],"-ab")==0) || + (strcmp(argv[i],"--add-bootloader-bin")==0)) { + action = ADD_BOOTLOADER; + type = FILETYPE_DOT_BIN; + i++; + if (i == argc) { print_usage(); return 1; } + filename=argv[i]; + i++; + } else if ((strcmp(argv[i],"-rf")==0) || + (strcmp(argv[i],"--read-firmware")==0)) { + action = READ_FIRMWARE; + i++; + if (i == argc) { print_usage(); return 1; } + filename=argv[i]; + i++; + } else if ((strcmp(argv[i],"-wf")==0) || + (strcmp(argv[i],"--write-firmware")==0)) { + action = WRITE_FIRMWARE; + type = FILETYPE_DOT_IPOD; + i++; + if (i == argc) { print_usage(); return 1; } + filename=argv[i]; + i++; + } else if ((strcmp(argv[i],"-wfb")==0) || + (strcmp(argv[i],"--write-firmware-bin")==0)) { + action = WRITE_FIRMWARE; + type = FILETYPE_DOT_BIN; + i++; + if (i == argc) { print_usage(); return 1; } + filename=argv[i]; + i++; + } else if ((strcmp(argv[i],"-r")==0) || + (strcmp(argv[i],"--read-partition")==0)) { + action = READ_PARTITION; + i++; + if (i == argc) { print_usage(); return 1; } + filename=argv[i]; + i++; + } else if ((strcmp(argv[i],"-w")==0) || + (strcmp(argv[i],"--write-partition")==0)) { + action = WRITE_PARTITION; + i++; + if (i == argc) { print_usage(); return 1; } + filename=argv[i]; + i++; + } else if ((strcmp(argv[i],"-v")==0) || + (strcmp(argv[i],"--verbose")==0)) { + verbose++; + i++; + } else { + print_usage(); return 1; + } + } + + if (ipod.diskname[0]==0) { + print_usage(); + return 1; + } + + if (ipod_open(&ipod, 0) < 0) { + return 1; + } + + fprintf(stderr,"[INFO] Reading partition table from %s\n",ipod.diskname); + fprintf(stderr,"[INFO] Sector size is %d bytes\n",ipod.sector_size); + + if (read_partinfo(&ipod,0) < 0) { + return 2; + } + + display_partinfo(&ipod); + + if (ipod.pinfo[0].start==0) { + fprintf(stderr,"[ERR] No partition 0 on disk:\n"); + display_partinfo(&ipod); + return 3; + } + + read_directory(&ipod); + + if (ipod.nimages <= 0) { + fprintf(stderr,"[ERR] Failed to read firmware directory - nimages=%d\n",ipod.nimages); + return 1; + } + + if (getmodel(&ipod,(ipod.ipod_directory[0].vers>>8)) < 0) { + fprintf(stderr,"[ERR] Unknown version number in firmware (%08x)\n", + ipod.ipod_directory[0].vers); + return -1; + } + + printf("[INFO] Ipod model: %s (\"%s\")\n",ipod.modelstr, + ipod.macpod ? "macpod" : "winpod"); + + if (ipod.macpod) { + print_macpod_warning(); + } + + if (action==LIST_IMAGES) { + list_images(&ipod); +#ifdef WITH_BOOTOBJS + } else if (action==INTERACTIVE) { + + printf("Do you wish to install the rockbox bootloader? (y/n) :"); + if (fgets(yesno,4,stdin)) { + if (yesno[0]=='y') { + if (ipod_reopen_rw(&ipod) < 0) { + return 5; + } + + if (add_bootloader(&ipod, NULL, FILETYPE_INTERNAL)==0) { + fprintf(stderr,"[INFO] Bootloader installed successfully.\n"); + } else { + fprintf(stderr,"[ERR] --install failed.\n"); + } + } + } +#endif + } else if (action==DELETE_BOOTLOADER) { + if (ipod_reopen_rw(&ipod) < 0) { + return 5; + } + + if (ipod.ipod_directory[0].entryOffset==0) { + fprintf(stderr,"[ERR] No bootloader detected.\n"); + } else { + if (delete_bootloader(&ipod)==0) { + fprintf(stderr,"[INFO] Bootloader removed.\n"); + } else { + fprintf(stderr,"[ERR] --delete-bootloader failed.\n"); + } + } + } else if (action==ADD_BOOTLOADER) { + if (ipod_reopen_rw(&ipod) < 0) { + return 5; + } + + if (add_bootloader(&ipod, filename, type)==0) { + fprintf(stderr,"[INFO] Bootloader %s written to device.\n",filename); + } else { + fprintf(stderr,"[ERR] --add-bootloader failed.\n"); + } +#ifdef WITH_BOOTOBJS + } else if (action==INSTALL) { + if (ipod_reopen_rw(&ipod) < 0) { + return 5; + } + + if (add_bootloader(&ipod, NULL, FILETYPE_INTERNAL)==0) { + fprintf(stderr,"[INFO] Bootloader installed successfully.\n"); + } else { + fprintf(stderr,"[ERR] --install failed.\n"); + } +#endif + } else if (action==WRITE_FIRMWARE) { + if (ipod_reopen_rw(&ipod) < 0) { + return 5; + } + + if (write_firmware(&ipod, filename,type)==0) { + fprintf(stderr,"[INFO] Firmware %s written to device.\n",filename); + } else { + fprintf(stderr,"[ERR] --write-firmware failed.\n"); + } + } else if (action==READ_FIRMWARE) { + if (read_firmware(&ipod, filename)==0) { + fprintf(stderr,"[INFO] Firmware read to file %s.\n",filename); + } else { + fprintf(stderr,"[ERR] --read-firmware failed.\n"); + } + } else if (action==READ_PARTITION) { + outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IREAD|S_IWRITE); + if (outfile < 0) { + perror(filename); + return 4; + } + + if (read_partition(&ipod, outfile) < 0) { + fprintf(stderr,"[ERR] --read-partition failed.\n"); + } else { + fprintf(stderr,"[INFO] Partition extracted to %s.\n",filename); + } + close(outfile); + } else if (action==WRITE_PARTITION) { + if (ipod_reopen_rw(&ipod) < 0) { + return 5; + } + + infile = open(filename,O_RDONLY|O_BINARY); + if (infile < 0) { + perror(filename); + return 2; + } + + /* Check filesize is <= partition size */ + inputsize=filesize(infile); + if (inputsize > 0) { + if (inputsize <= (ipod.pinfo[0].size*ipod.sector_size)) { + fprintf(stderr,"[INFO] Input file is %u bytes\n",inputsize); + if (write_partition(&ipod,infile) < 0) { + fprintf(stderr,"[ERR] --write-partition failed.\n"); + } else { + fprintf(stderr,"[INFO] %s restored to partition\n",filename); + } + } else { + fprintf(stderr,"[ERR] File is too large for firmware partition, aborting.\n"); + } + } + + close(infile); + } + + ipod_close(&ipod); + +#ifdef WITH_BOOTOBJS + if (action==INTERACTIVE) { + printf("Press ENTER to exit ipodpatcher :"); + fgets(yesno,4,stdin); + } +#endif + + + return 0; +} diff --git a/rbutil/ipodpatcher/parttypes.h b/rbutil/ipodpatcher/parttypes.h new file mode 100644 index 0000000000..f8de303553 --- /dev/null +++ b/rbutil/ipodpatcher/parttypes.h @@ -0,0 +1,109 @@ +/* DOS partition types - taken from fdisk */ + +struct parttype { + unsigned char type; + char *name; +}; + +struct parttype parttypes[] = { + {0x00, "Empty"}, + {0x01, "FAT12"}, + {0x02, "XENIX root"}, + {0x03, "XENIX usr"}, + {0x04, "FAT16 <32M"}, + {0x05, "Extended"}, /* DOS 3.3+ extended partition */ + {0x06, "FAT16"}, /* DOS 16-bit >=32M */ + {0x07, "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */ + {0x08, "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */ + {0x09, "AIX bootable"}, /* AIX data or Coherent */ + {0x0a, "OS/2 Boot Manager"},/* OS/2 Boot Manager */ + {0x0b, "W95 FAT32"}, + {0x0c, "W95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */ + {0x0e, "W95 FAT16 (LBA)"}, + {0x0f, "W95 Ext'd (LBA)"}, + {0x10, "OPUS"}, + {0x11, "Hidden FAT12"}, + {0x12, "Compaq diagnostics"}, + {0x14, "Hidden FAT16 <32M"}, + {0x16, "Hidden FAT16"}, + {0x17, "Hidden HPFS/NTFS"}, + {0x18, "AST SmartSleep"}, + {0x1b, "Hidden W95 FAT32"}, + {0x1c, "Hidden W95 FAT32 (LBA)"}, + {0x1e, "Hidden W95 FAT16 (LBA)"}, + {0x24, "NEC DOS"}, + {0x39, "Plan 9"}, + {0x3c, "PartitionMagic recovery"}, + {0x40, "Venix 80286"}, + {0x41, "PPC PReP Boot"}, + {0x42, "SFS"}, + {0x4d, "QNX4.x"}, + {0x4e, "QNX4.x 2nd part"}, + {0x4f, "QNX4.x 3rd part"}, + {0x50, "OnTrack DM"}, + {0x51, "OnTrack DM6 Aux1"}, /* (or Novell) */ + {0x52, "CP/M"}, /* CP/M or Microport SysV/AT */ + {0x53, "OnTrack DM6 Aux3"}, + {0x54, "OnTrackDM6"}, + {0x55, "EZ-Drive"}, + {0x56, "Golden Bow"}, + {0x5c, "Priam Edisk"}, + {0x61, "SpeedStor"}, + {0x63, "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */ + {0x64, "Novell Netware 286"}, + {0x65, "Novell Netware 386"}, + {0x70, "DiskSecure Multi-Boot"}, + {0x75, "PC/IX"}, + {0x80, "Old Minix"}, /* Minix 1.4a and earlier */ + {0x81, "Minix / old Linux"},/* Minix 1.4b and later */ + {0x82, "Linux swap / Solaris"}, + {0x83, "Linux"}, + {0x84, "OS/2 hidden C: drive"}, + {0x85, "Linux extended"}, + {0x86, "NTFS volume set"}, + {0x87, "NTFS volume set"}, + {0x88, "Linux plaintext"}, + {0x8e, "Linux LVM"}, + {0x93, "Amoeba"}, + {0x94, "Amoeba BBT"}, /* (bad block table) */ + {0x9f, "BSD/OS"}, /* BSDI */ + {0xa0, "IBM Thinkpad hibernation"}, + {0xa5, "FreeBSD"}, /* various BSD flavours */ + {0xa6, "OpenBSD"}, + {0xa7, "NeXTSTEP"}, + {0xa8, "Darwin UFS"}, + {0xa9, "NetBSD"}, + {0xab, "Darwin boot"}, + {0xb7, "BSDI fs"}, + {0xb8, "BSDI swap"}, + {0xbb, "Boot Wizard hidden"}, + {0xbe, "Solaris boot"}, + {0xbf, "Solaris"}, + {0xc1, "DRDOS/sec (FAT-12)"}, + {0xc4, "DRDOS/sec (FAT-16 < 32M)"}, + {0xc6, "DRDOS/sec (FAT-16)"}, + {0xc7, "Syrinx"}, + {0xda, "Non-FS data"}, + {0xdb, "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or + Concurrent DOS or CTOS */ + {0xde, "Dell Utility"}, /* Dell PowerEdge Server utilities */ + {0xdf, "BootIt"}, /* BootIt EMBRM */ + {0xe1, "DOS access"}, /* DOS access or SpeedStor 12-bit FAT + extended partition */ + {0xe3, "DOS R/O"}, /* DOS R/O or SpeedStor */ + {0xe4, "SpeedStor"}, /* SpeedStor 16-bit FAT extended + partition < 1024 cyl. */ + {0xeb, "BeOS fs"}, + {0xee, "EFI GPT"}, /* Intel EFI GUID Partition Table */ + {0xef, "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */ + {0xf0, "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */ + {0xf1, "SpeedStor"}, + {0xf4, "SpeedStor"}, /* SpeedStor large partition */ + {0xf2, "DOS secondary"}, /* DOS 3.3+ secondary */ + {0xfd, "Linux raid autodetect"},/* New (2.2.x) raid partition with + autodetect using persistent + superblock */ + {0xfe, "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */ + {0xff, "BBT"}, /* Xenix Bad Block Table */ + { 0, 0 } +}; diff --git a/tools/ipodpatcher/Makefile b/tools/ipodpatcher/Makefile deleted file mode 100644 index f5a4d7cfb3..0000000000 --- a/tools/ipodpatcher/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -CFLAGS=-Wall - -BOOT_H = ipod3g.h ipod4g.h ipodcolor.h ipodmini.h ipodmini2g.h ipodnano.h ipodvideo.h - -# Uncomment the next two lines to build with embedded bootloaders and the -# --install option and interactive mode. You need the full set of Rockbox -# bootloaders in this directory - download them from -# http://download.rockbox.org/bootloader/ipod/bootloaders.zip - -#BOOTSRC = ipod3g.c ipod4g.c ipodcolor.c ipodmini.c ipodmini2g.c ipodnano.c ipodvideo.c -#CFLAGS += -DWITH_BOOTOBJS - -ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN) -OUTPUT=ipodpatcher.exe -CROSS= -CFLAGS+=-mno-cygwin -else -OUTPUT=ipodpatcher -CROSS=i586-mingw32msvc- -endif - -NATIVECC = gcc -CC = $(CROSS)gcc - -all: $(OUTPUT) - -ipodpatcher: main.c ipodpatcher.c ipodio-posix.c parttypes.h $(BOOTSRC) - gcc $(CFLAGS) -o ipodpatcher main.c ipodpatcher.c ipodio-posix.c $(BOOTSRC) - strip ipodpatcher - -ipodpatcher.exe: main.c ipodpatcher.c ipodio-win32.c parttypes.h $(BOOTSRC) - $(CC) $(CFLAGS) -o ipodpatcher.exe main.c ipodpatcher.c ipodio-win32.c $(BOOTSRC) - $(CROSS)strip ipodpatcher.exe - -ipod2c: ipod2c.c - $(NATIVECC) $(CFLAGS) -o ipod2c ipod2c.c - -ipod3g.c: bootloader-ipod3g.ipod ipod2c - ./ipod2c bootloader-ipod3g.ipod ipod3g - -ipod4g.c: bootloader-ipod4g.ipod ipod2c - ./ipod2c bootloader-ipod4g.ipod ipod4g - -ipodcolor.c: bootloader-ipodcolor.ipod ipod2c - ./ipod2c bootloader-ipodcolor.ipod ipodcolor - -ipodmini.c: bootloader-ipodmini.ipod ipod2c - ./ipod2c bootloader-ipodmini.ipod ipodmini - -ipodmini2g.c: bootloader-ipodmini2g.ipod ipod2c - ./ipod2c bootloader-ipodmini2g.ipod ipodmini2g - -ipodnano.c: bootloader-ipodnano.ipod ipod2c - ./ipod2c bootloader-ipodnano.ipod ipodnano - -ipodvideo.c: bootloader-ipodvideo.ipod ipod2c - ./ipod2c bootloader-ipodvideo.ipod ipodvideo - - -clean: - rm -f ipodpatcher.exe ipodpatcher ipod2c *~ $(BOOTSRC) $(BOOT_H) diff --git a/tools/ipodpatcher/ipod2c.c b/tools/ipodpatcher/ipod2c.c deleted file mode 100644 index af2e25dd09..0000000000 --- a/tools/ipodpatcher/ipod2c.c +++ /dev/null @@ -1,139 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id: ipodio-win32.c 12205 2007-02-05 01:20:20Z dave $ - * - * Copyright (C) 2007 Dave Chapman - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#ifndef O_BINARY -#define O_BINARY 0 -#endif - -static off_t filesize(int fd) -{ - struct stat buf; - - fstat(fd,&buf); - return buf.st_size; -} - -static int write_cfile(unsigned char* buf, off_t len, char* cname) -{ - char filename[256]; - FILE* fp; - int i; - - snprintf(filename,256,"%s.c",cname); - - fp = fopen(filename,"w+"); - if (fp == NULL) { - fprintf(stderr,"Couldn't open %s\n",filename); - return -1; - } - - fprintf(fp,"/* Generated by ipod2c */\n\n"); - fprintf(fp,"unsigned char %s[] = {",cname); - - for (i=0;i ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006-2007 Dave Chapman - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(linux) || defined (__linux) -#include -#define IPOD_SECTORSIZE_IOCTL BLKSSZGET -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ - || defined(__bsdi__) || defined(__DragonFly__) -#include -#define IPOD_SECTORSIZE_IOCTL DIOCGSECTORSIZE -#elif defined(__APPLE__) && defined(__MACH__) -#include -#define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE -#else - #error No sector-size detection implemented for this platform -#endif - -#include "ipodio.h" - -void print_error(char* msg) -{ - perror(msg); -} - -int ipod_open(struct ipod_t* ipod, int silent) -{ - ipod->dh=open(ipod->diskname,O_RDONLY); - if (ipod->dh < 0) { - if (!silent) perror(ipod->diskname); - return -1; - } - - if(ioctl(ipod->dh,IPOD_SECTORSIZE_IOCTL,&ipod->sector_size) < 0) { - ipod->sector_size=512; - if (!silent) { - fprintf(stderr,"[ERR] ioctl() call to get sector size failed, defaulting to %d\n" - ,ipod->sector_size); - } - } - return 0; -} - - -int ipod_reopen_rw(struct ipod_t* ipod) -{ - close(ipod->dh); - ipod->dh=open(ipod->diskname,O_RDWR); - if (ipod->dh < 0) { - perror(ipod->diskname); - return -1; - } - return 0; -} - -int ipod_close(struct ipod_t* ipod) -{ - close(ipod->dh); - return 0; -} - -int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize) -{ - *sectorbuf=malloc(bufsize); - if (*sectorbuf == NULL) { - return -1; - } - return 0; -} - -int ipod_seek(struct ipod_t* ipod, unsigned long pos) -{ - off_t res; - - res = lseek(ipod->dh, pos, SEEK_SET); - - if (res == -1) { - return -1; - } - return 0; -} - -int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes) -{ - return read(ipod->dh, buf, nbytes); -} - -int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes) -{ - return write(ipod->dh, buf, nbytes); -} diff --git a/tools/ipodpatcher/ipodio-win32.c b/tools/ipodpatcher/ipodio-win32.c deleted file mode 100644 index 83f00b8cd9..0000000000 --- a/tools/ipodpatcher/ipodio-win32.c +++ /dev/null @@ -1,190 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006-2007 Dave Chapman - * - * error(), lock_volume() and unlock_volume() functions and inspiration taken - * from: - * RawDisk - Direct Disk Read/Write Access for NT/2000/XP - * Copyright (c) 2003 Jan Kiszka - * http://www.stud.uni-hannover.de/user/73174/RawDisk/ - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#ifdef __WIN32__ -#include -#include -#endif - -#include "ipodio.h" - -static int lock_volume(HANDLE hDisk) -{ - DWORD dummy; - - return DeviceIoControl(hDisk, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, - &dummy, NULL); -} - -static int unlock_volume(HANDLE hDisk) -{ - DWORD dummy; - - return DeviceIoControl(hDisk, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, - &dummy, NULL); -} - -void print_error(char* msg) -{ - char* pMsgBuf; - - printf(msg); - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&pMsgBuf, - 0, NULL); - printf(pMsgBuf); - LocalFree(pMsgBuf); -} - -int ipod_open(struct ipod_t* ipod, int silent) -{ - DISK_GEOMETRY_EX diskgeometry_ex; - DISK_GEOMETRY diskgeometry; - unsigned long n; - - ipod->dh = CreateFile(ipod->diskname, GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); - - if (ipod->dh == INVALID_HANDLE_VALUE) { - if (!silent) print_error(" Error opening disk: "); - return -1; - } - - if (!lock_volume(ipod->dh)) { - if (!silent) print_error(" Error locking disk: "); - return -1; - } - - if (!DeviceIoControl(ipod->dh, - IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, - NULL, - 0, - &diskgeometry_ex, - sizeof(diskgeometry_ex), - &n, - NULL)) { - if (!DeviceIoControl(ipod->dh, - IOCTL_DISK_GET_DRIVE_GEOMETRY, - NULL, - 0, - &diskgeometry, - sizeof(diskgeometry), - &n, - NULL)) { - if (!silent) print_error(" Error reading disk geometry: "); - return -1; - } else { - ipod->sector_size=diskgeometry.BytesPerSector; - } - } else { - ipod->sector_size=diskgeometry_ex.Geometry.BytesPerSector; - } - - return 0; -} - -int ipod_reopen_rw(struct ipod_t* ipod) -{ - /* Close existing file and re-open for writing */ - unlock_volume(ipod->dh); - CloseHandle(ipod->dh); - - ipod->dh = CreateFile(ipod->diskname, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, - FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, NULL); - - if (ipod->dh == INVALID_HANDLE_VALUE) { - print_error(" Error opening disk: "); - return -1; - } - - if (!lock_volume(ipod->dh)) { - print_error(" Error locking disk: "); - return -1; - } - - return 0; -} - -int ipod_close(struct ipod_t* ipod) -{ - unlock_volume(ipod->dh); - CloseHandle(ipod->dh); - return 0; -} - -int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize) -{ - /* The ReadFile function requires a memory buffer aligned to a multiple of - the disk sector size. */ - *sectorbuf = (unsigned char*)VirtualAlloc(NULL, bufsize, MEM_COMMIT, PAGE_READWRITE); - if (*sectorbuf == NULL) { - print_error(" Error allocating a buffer: "); - return -1; - } - return 0; -} - -int ipod_seek(struct ipod_t* ipod, unsigned long pos) -{ - if (SetFilePointer(ipod->dh, pos, NULL, FILE_BEGIN)==0xffffffff) { - print_error(" Seek error "); - return -1; - } - return 0; -} - -int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes) -{ - unsigned long count; - - if (!ReadFile(ipod->dh, buf, nbytes, &count, NULL)) { - print_error(" Error reading from disk: "); - return -1; - } - - return count; -} - -int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes) -{ - unsigned long count; - - if (!WriteFile(ipod->dh, buf, nbytes, &count, NULL)) { - print_error(" Error writing to disk: "); - return -1; - } - - return count; -} diff --git a/tools/ipodpatcher/ipodio.h b/tools/ipodpatcher/ipodio.h deleted file mode 100644 index d0641faa2b..0000000000 --- a/tools/ipodpatcher/ipodio.h +++ /dev/null @@ -1,89 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006-2007 Dave Chapman - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef __IPODIO_H -#define __IPODIO_H - -#include - -#ifdef __WIN32__ -#include -#else -#define HANDLE int -#define O_BINARY 0 -#endif - -/* The maximum number of images in a firmware partition - a guess... */ -#define MAX_IMAGES 10 - -enum firmwaretype_t { - FTYPE_OSOS = 0, - FTYPE_RSRC, - FTYPE_AUPD, - FTYPE_HIBE -}; - -struct ipod_directory_t { - enum firmwaretype_t ftype; - int id; - uint32_t devOffset; /* Offset of image relative to one sector into bootpart*/ - uint32_t len; - uint32_t addr; - uint32_t entryOffset; - uint32_t chksum; - uint32_t vers; - uint32_t loadAddr; -}; - -struct partinfo_t { - unsigned long start; /* first sector (LBA) */ - unsigned long size; /* number of sectors */ - int type; -}; - -struct ipod_t { - HANDLE dh; - char diskname[4096]; - int sector_size; - struct ipod_directory_t ipod_directory[MAX_IMAGES]; - int nimages; - 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 */ - struct partinfo_t pinfo[4]; - int modelnum; - char* modelname; - char* modelstr; - int macpod; -#ifdef WITH_BOOTOBJS - unsigned char* bootloader; - int bootloader_len; -#endif -}; - -void print_error(char* msg); -int ipod_open(struct ipod_t* ipod, int silent); -int ipod_reopen_rw(struct ipod_t* ipod); -int ipod_close(struct ipod_t* ipod); -int ipod_seek(struct ipod_t* ipod, unsigned long pos); -int ipod_read(struct ipod_t* ipod, unsigned char* buf, int nbytes); -int ipod_write(struct ipod_t* ipod, unsigned char* buf, int nbytes); -int ipod_alloc_buffer(unsigned char** sectorbuf, int bufsize); - -#endif diff --git a/tools/ipodpatcher/ipodpatcher.c b/tools/ipodpatcher/ipodpatcher.c deleted file mode 100644 index 6c60bae38d..0000000000 --- a/tools/ipodpatcher/ipodpatcher.c +++ /dev/null @@ -1,1261 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2006-2007 Dave Chapman - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "parttypes.h" -#include "ipodio.h" -#include "ipodpatcher.h" - -#ifdef WITH_BOOTOBJS -#include "ipod3g.h" -#include "ipod4g.h" -#include "ipodmini.h" -#include "ipodmini2g.h" -#include "ipodcolor.h" -#include "ipodnano.h" -#include "ipodvideo.h" -#endif - -extern int verbose; - -unsigned char* sectorbuf; - -/* The following string appears at the start of the firmware partition */ -static const char *apple_stop_sign = "{{~~ /-----\\ "\ - "{{~~ / \\ "\ - "{{~~| | "\ - "{{~~| S T O P | "\ - "{{~~| | "\ - "{{~~ \\ / "\ - "{{~~ \\-----/ "\ - "Copyright(C) 200"\ - "1 Apple Computer"\ - ", Inc.----------"\ - "----------------"\ - "----------------"\ - "----------------"\ - "----------------"\ - "----------------"\ - "---------------"; - -/* Windows requires the buffer for disk I/O to be aligned in memory on a - multiple of the disk volume size - so we use a single global variable - and initialise it with ipod_alloc_buf() -*/ - -char* get_parttype(int pt) -{ - int i; - static char unknown[]="Unknown"; - - if (pt == -1) { - return "HFS/HFS+"; - } - - i=0; - while (parttypes[i].name != NULL) { - if (parttypes[i].type == pt) { - return (parttypes[i].name); - } - i++; - } - - return unknown; -} - -off_t filesize(int fd) { - struct stat buf; - - if (fstat(fd,&buf) < 0) { - perror("[ERR] Checking filesize of input file"); - return -1; - } else { - return(buf.st_size); - } -} - -/* Partition table parsing code taken from Rockbox */ - -#define MAX_SECTOR_SIZE 2048 -#define SECTOR_SIZE 512 - -unsigned short static inline le2ushort(unsigned char* buf) -{ - unsigned short res = (buf[1] << 8) | buf[0]; - - return res; -} - -int static inline le2int(unsigned char* buf) -{ - int32_t res = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; - - return res; -} - -int static inline be2int(unsigned char* buf) -{ - int32_t res = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; - - return res; -} - -int static inline getint16le(char* buf) -{ - int16_t res = (buf[1] << 8) | buf[0]; - - return res; -} - -void static inline short2le(unsigned short val, unsigned char* addr) -{ - addr[0] = val & 0xFF; - addr[1] = (val >> 8) & 0xff; -} - -void static inline int2le(unsigned int val, unsigned char* addr) -{ - addr[0] = val & 0xFF; - addr[1] = (val >> 8) & 0xff; - addr[2] = (val >> 16) & 0xff; - addr[3] = (val >> 24) & 0xff; -} - -void int2be(unsigned int val, unsigned char* addr) -{ - addr[0] = (val >> 24) & 0xff; - addr[1] = (val >> 16) & 0xff; - addr[2] = (val >> 8) & 0xff; - addr[3] = val & 0xFF; -} - - -#define BYTES2INT32(array,pos)\ - ((long)array[pos] | ((long)array[pos+1] << 8 ) |\ - ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 )) - -void display_partinfo(struct ipod_t* ipod) -{ - int i; - double sectors_per_MB = (1024.0*1024.0)/ipod->sector_size; - - printf("[INFO] Part Start Sector End Sector Size (MB) Type\n"); - for ( i = 0; i < 4; i++ ) { - if (ipod->pinfo[i].start != 0) { - printf("[INFO] %d %10ld %10ld %10.1f %s (0x%02x)\n", - i, - ipod->pinfo[i].start, - ipod->pinfo[i].start+ipod->pinfo[i].size-1, - ipod->pinfo[i].size/sectors_per_MB, - get_parttype(ipod->pinfo[i].type), - ipod->pinfo[i].type); - } - } -} - -int read_partinfo(struct ipod_t* ipod, int silent) -{ - int i; - unsigned long count; - - count = ipod_read(ipod,sectorbuf, ipod->sector_size); - - if (count <= 0) { - print_error(" Error reading from disk: "); - return -1; - } - - if ((sectorbuf[510] == 0x55) && (sectorbuf[511] == 0xaa)) { - /* DOS partition table */ - if ((memcmp(§orbuf[71],"iPod",4) != 0) && - (memcmp(§orbuf[0x40],"This is your Apple iPod. You probably do not want to boot from it!",66) != 0) ) { - if (!silent) fprintf(stderr,"[ERR] Drive is not an iPod, aborting\n"); - return -1; - } - - ipod->macpod = 0; - /* parse partitions */ - for ( i = 0; i < 4; i++ ) { - unsigned char* ptr = sectorbuf + 0x1be + 16*i; - ipod->pinfo[i].type = ptr[4]; - ipod->pinfo[i].start = BYTES2INT32(ptr, 8); - ipod->pinfo[i].size = BYTES2INT32(ptr, 12); - - /* extended? */ - if ( ipod->pinfo[i].type == 5 ) { - /* not handled yet */ - } - } - } else if ((sectorbuf[0] == 'E') && (sectorbuf[1] == 'R')) { - /* Apple Partition Map */ - - /* APM parsing code based on the check_mac_partitions() function in - ipodloader2 - written by Thomas Tempelmann and released - under the GPL. */ - - int blkNo = 1; - int partBlkCount = 1; - int partBlkSizMul = sectorbuf[2] / 2; - - int pmMapBlkCnt; /* # of blks in partition map */ - int pmPyPartStart; /* physical start blk of partition */ - int pmPartBlkCnt; /* # of blks in this partition */ - int i = 0; - - ipod->macpod = 1; - - memset(ipod->pinfo,0,sizeof(ipod->pinfo)); - - while (blkNo <= partBlkCount) { - if (ipod_seek(ipod, blkNo * partBlkSizMul * 512) < 0) { - fprintf(stderr,"[ERR] Seek failed whilst reading APM\n"); - return -1; - } - - count = ipod_read(ipod, sectorbuf, ipod->sector_size); - - if (count <= 0) { - print_error(" Error reading from disk: "); - return -1; - } - - /* see if it's a partition entry */ - if ((sectorbuf[0] != 'P') || (sectorbuf[1] != 'M')) { - /* end of partition table -> leave the loop */ - break; - } - - /* Extract the interesting entries */ - pmMapBlkCnt = be2int(sectorbuf + 4); - pmPyPartStart = be2int(sectorbuf + 8); - pmPartBlkCnt = be2int(sectorbuf + 12); - - /* update the number of part map blocks */ - partBlkCount = pmMapBlkCnt; - - if (strncmp((char*)(sectorbuf + 48), "Apple_MDFW", 32)==0) { - /* A Firmware partition */ - ipod->pinfo[i].start = pmPyPartStart; - ipod->pinfo[i].size = pmPartBlkCnt; - ipod->pinfo[i].type = 0; - i++; - } else if (strncmp((char*)(sectorbuf + 48), "Apple_HFS", 32)==0) { - /* A HFS partition */ - ipod->pinfo[i].start = pmPyPartStart; - ipod->pinfo[i].size = pmPartBlkCnt; - ipod->pinfo[i].type = -1; - i++; - } - - blkNo++; /* read next partition map entry */ - } - } else { - if (!silent) fprintf(stderr,"[ERR] Bad boot sector signature\n"); - return -1; - } - - ipod->start = ipod->pinfo[0].start*ipod->sector_size; - return 0; -} - -int read_partition(struct ipod_t* ipod, int outfile) -{ - int res; - unsigned long n; - int bytesleft; - int chunksize; - int count = ipod->pinfo[0].size; - - if (ipod_seek(ipod, ipod->start) < 0) { - return -1; - } - - fprintf(stderr,"[INFO] Writing %d sectors to output file\n",count); - - bytesleft = count * ipod->sector_size; - while (bytesleft > 0) { - if (bytesleft > BUFFER_SIZE) { - chunksize = BUFFER_SIZE; - } else { - chunksize = bytesleft; - } - - n = ipod_read(ipod, sectorbuf, chunksize); - - if (n < 0) { - return -1; - } - - if (n < chunksize) { - fprintf(stderr, - "[ERR] Short read in disk_read() - requested %d, got %lu\n", - chunksize,n); - return -1; - } - - bytesleft -= n; - - res = write(outfile,sectorbuf,n); - - if (res < 0) { - perror("[ERR] write in disk_read"); - return -1; - } - - if (res != n) { - fprintf(stderr, - "Short write - requested %lu, received %d - aborting.\n",n,res); - return -1; - } - } - - fprintf(stderr,"[INFO] Done.\n"); - return 0; -} - -int write_partition(struct ipod_t* ipod, int infile) -{ - unsigned long res; - int n; - int bytesread; - int byteswritten = 0; - int eof; - int padding = 0; - - if (ipod_seek(ipod, ipod->start) < 0) { - return -1; - } - - fprintf(stderr,"[INFO] Writing input file to device\n"); - bytesread = 0; - eof = 0; - while (!eof) { - n = read(infile,sectorbuf,BUFFER_SIZE); - - if (n < 0) { - perror("[ERR] read in disk_write"); - return -1; - } - - if (n < BUFFER_SIZE) { - eof = 1; - /* We need to pad the last write to a multiple of SECTOR_SIZE */ - if ((n % ipod->sector_size) != 0) { - padding = (ipod->sector_size-(n % ipod->sector_size)); - n += padding; - } - } - - bytesread += n; - - res = ipod_write(ipod, sectorbuf, n); - - if (res < 0) { - print_error(" Error writing to disk: "); - fprintf(stderr,"Bytes written: %d\n",byteswritten); - return -1; - } - - if (res != n) { - fprintf(stderr,"[ERR] Short write - requested %d, received %lu - aborting.\n",n,res); - return -1; - } - - byteswritten += res; - } - - fprintf(stderr,"[INFO] Wrote %d bytes plus %d bytes padding.\n", - byteswritten-padding,padding); - return 0; -} - -char* ftypename[] = { "OSOS", "RSRC", "AUPD", "HIBE" }; - -int diskmove(struct ipod_t* ipod, int delta) -{ - int src_start; - int src_end; - int bytesleft; - int chunksize; - int i; - int n; - - src_start = ipod->ipod_directory[1].devOffset + ipod->sector_size; - src_end = (ipod->ipod_directory[ipod->nimages-1].devOffset + ipod->sector_size + - ipod->ipod_directory[ipod->nimages-1].len + - (ipod->sector_size-1)) & ~(ipod->sector_size-1); - bytesleft = src_end - src_start; - - if (verbose) { - fprintf(stderr,"[INFO] Need to move images 2-%d forward %08x bytes\n", ipod->nimages,delta); - fprintf(stderr,"[VERB] src_start = %08x\n",src_start); - fprintf(stderr,"[VERB] src_end = %08x\n",src_end); - fprintf(stderr,"[VERB] dest_start = %08x\n",src_start+delta); - fprintf(stderr,"[VERB] dest_end = %08x\n",src_end+delta); - fprintf(stderr,"[VERB] bytes to copy = %08x\n",bytesleft); - } - - while (bytesleft > 0) { - if (bytesleft <= BUFFER_SIZE) { - chunksize = bytesleft; - } else { - chunksize = BUFFER_SIZE; - } - - if (verbose) { - fprintf(stderr,"[VERB] Copying %08x bytes from %08x to %08x (absolute %08x to %08x)\n", - chunksize, - src_end-chunksize, - src_end-chunksize+delta, - (unsigned int)(ipod->start+src_end-chunksize), - (unsigned int)(ipod->start+src_end-chunksize+delta)); - } - - - if (ipod_seek(ipod, ipod->start+src_end-chunksize) < 0) { - fprintf(stderr,"[ERR] Seek failed\n"); - return -1; - } - - if ((n = ipod_read(ipod,sectorbuf,chunksize)) < 0) { - perror("[ERR] Write failed\n"); - return -1; - } - - if (n < chunksize) { - fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n", - i,n); - return -1; - } - - if (ipod_seek(ipod, ipod->start+src_end-chunksize+delta) < 0) { - fprintf(stderr,"[ERR] Seek failed\n"); - return -1; - } - - if ((n = ipod_write(ipod,sectorbuf,chunksize)) < 0) { - perror("[ERR] Write failed\n"); - return -1; - } - - if (n < chunksize) { - fprintf(stderr,"[ERR] Short write - requested %d bytes, received %d\n" - ,i,n); - return -1; - } - - src_end -= chunksize; - bytesleft -= chunksize; - } - - return 0; -} - -int add_bootloader(struct ipod_t* ipod, char* filename, int type) -{ - int length; - int i; - int x; - int n; - int infile; - int paddedlength; - int entryOffset; - int delta = 0; - unsigned long chksum=0; - unsigned long filechksum=0; - unsigned char header[8]; /* Header for .ipod file */ - unsigned char* bootloader_buf; - - /* Calculate the position in the OSOS image where our bootloader will go. */ - if (ipod->ipod_directory[0].entryOffset>0) { - /* Keep the same entryOffset */ - entryOffset = ipod->ipod_directory[0].entryOffset; - } else { - entryOffset = (ipod->ipod_directory[0].len+ipod->sector_size-1)&~(ipod->sector_size-1); - } - -#ifdef WITH_BOOTOBJS - if (type == FILETYPE_INTERNAL) { - fprintf(stderr,"[INFO] Using internal bootloader - %d bytes\n",ipod->bootloader_len); - memcpy(sectorbuf+entryOffset,ipod->bootloader,ipod->bootloader_len); - length = ipod->bootloader_len; - paddedlength=(ipod->bootloader_len+ipod->sector_size-1)&~(ipod->sector_size-1); - } - else -#endif - { - infile=open(filename,O_RDONLY); - if (infile < 0) { - fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); - return -1; - } - - if (type==FILETYPE_DOT_IPOD) { - /* First check that the input file is the correct type for this ipod. */ - n = read(infile,header,8); - if (n < 8) { - fprintf(stderr,"[ERR] Failed to read header from %s\n",filename); - close(infile); - return -1; - } - - if (memcmp(header+4, ipod->modelname,4)!=0) { - fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n", - header[4],header[5],header[6],header[7], ipod->modelname); - close(infile); - return -1; - } - - filechksum = be2int(header); - - length=filesize(infile)-8; - } else { - length=filesize(infile); - } - paddedlength=(length+ipod->sector_size-1)&~(ipod->sector_size-1); - - bootloader_buf = malloc(length); - if (bootloader_buf == NULL) { - fprintf(stderr,"[ERR] Can not allocate memory for bootlaoder\n"); - } - /* Now read our bootloader - we need to check it before modifying the partition*/ - n = read(infile,bootloader_buf,length); - close(infile); - - if (n < 0) { - fprintf(stderr,"[ERR] Couldn't read input file\n"); - return -1; - } - - if (type==FILETYPE_DOT_IPOD) { - /* Calculate and confirm bootloader checksum */ - chksum = ipod->modelnum; - for (i = 0; i < length; i++) { - /* add 8 unsigned bits but keep a 32 bit sum */ - chksum += bootloader_buf[i]; - } - - if (chksum == filechksum) { - fprintf(stderr,"[INFO] Checksum OK in %s\n",filename); - } else { - fprintf(stderr,"[ERR] Checksum in %s failed check\n",filename); - return -1; - } - } - } - - if (entryOffset+paddedlength > BUFFER_SIZE) { - fprintf(stderr,"[ERR] Input file too big for buffer\n"); - return -1; - } - - if (verbose) { - fprintf(stderr,"[VERB] Original firmware begins at 0x%08x\n", ipod->ipod_directory[0].devOffset + ipod->sector_size); - fprintf(stderr,"[VERB] New entryOffset will be 0x%08x\n",entryOffset); - fprintf(stderr,"[VERB] End of bootloader will be at 0x%08x\n",entryOffset+paddedlength); - } - - /* Check if we have enough space */ - /* TODO: Check the size of the partition. */ - if (ipod->nimages > 1) { - if ((ipod->ipod_directory[0].devOffset+entryOffset+paddedlength) > - ipod->ipod_directory[1].devOffset) { - fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n"); - delta = ipod->ipod_directory[0].devOffset + entryOffset+paddedlength - - ipod->ipod_directory[1].devOffset; - - if (diskmove(ipod, delta) < 0) { - fprintf(stderr,"[ERR] Image movement failed.\n"); - return -1; - } - } - } - - - /* We have moved the partitions, now we can write our bootloader */ - - /* Firstly read the original firmware into sectorbuf */ - fprintf(stderr,"[INFO] Reading original firmware...\n"); - if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { - fprintf(stderr,"[ERR] Seek failed\n"); - return -1; - } - - if ((n = ipod_read(ipod,sectorbuf,entryOffset)) < 0) { - perror("[ERR] Read failed\n"); - return -1; - } - - if (n < entryOffset) { - fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n" - ,i,n); - return -1; - } - -#ifdef WITH_BOOTOBJS - if (type == FILETYPE_INTERNAL) { - memcpy(sectorbuf+entryOffset,ipod->bootloader,ipod->bootloader_len); - } - else -#endif - { - memcpy(sectorbuf+entryOffset,bootloader_buf,length); - free(bootloader_buf); - } - - /* Calculate new checksum for combined image */ - chksum = 0; - for (i=0;ifwoffset+ipod->ipod_directory[0].devOffset) < 0) { - fprintf(stderr,"[ERR] Seek failed\n"); - return -1; - } - - if ((n = ipod_write(ipod,sectorbuf,entryOffset+paddedlength)) < 0) { - perror("[ERR] Write failed\n"); - return -1; - } - - if (n < (entryOffset+paddedlength)) { - fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n" - ,i,n); - return -1; - } - - fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",entryOffset+paddedlength); - - x = ipod->diroffset % ipod->sector_size; - - /* Read directory */ - if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { - fprintf(stderr,"[ERR] Seek failed\n"); - return -1; - } - - n=ipod_read(ipod, sectorbuf, ipod->sector_size); - if (n < 0) { - fprintf(stderr,"[ERR] Directory read failed\n"); - return -1; - } - - /* Update entries for image 0 */ - int2le(entryOffset+length,sectorbuf+x+16); - int2le(entryOffset,sectorbuf+x+24); - int2le(chksum,sectorbuf+x+28); - int2le(0xffffffff,sectorbuf+x+36); /* loadAddr */ - - /* Update devOffset entries for other images, if we have moved them */ - if (delta > 0) { - for (i=1;inimages;i++) { - int2le(le2int(sectorbuf+x+i*40+12)+delta,sectorbuf+x+i*40+12); - } - } - - /* Write directory */ - if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { - fprintf(stderr,"[ERR] Seek to %d failed\n", (int)(ipod->start+ipod->diroffset-x)); - return -1; - } - n=ipod_write(ipod, sectorbuf, ipod->sector_size); - if (n < 0) { - fprintf(stderr,"[ERR] Directory write failed\n"); - return -1; - } - - return 0; -} - -int delete_bootloader(struct ipod_t* ipod) -{ - int length; - int i; - int x; - int n; - unsigned long chksum=0; /* 32 bit checksum - Rockbox .ipod style*/ - - /* Removing the bootloader involves adjusting the "length", - "chksum" and "entryOffset" values in the osos image's directory - entry. */ - - /* Firstly check we have a bootloader... */ - - if (ipod->ipod_directory[0].entryOffset == 0) { - fprintf(stderr,"[ERR] No bootloader found.\n"); - return -1; - } - - length = ipod->ipod_directory[0].entryOffset; - - /* Read the firmware so we can calculate the checksum */ - fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length); - - if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { - return -1; - } - - 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 ((n = ipod_read(ipod,sectorbuf,i)) < 0) { - return -1; - } - - if (n < i) { - fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n", - i,n); - return -1; - } - - chksum = 0; - for (i = 0; i < length; i++) { - /* add 8 unsigned bits but keep a 32 bit sum */ - chksum += sectorbuf[i]; - } - - /* Now write back the updated directory entry */ - - fprintf(stderr,"[INFO] Updating firmware checksum\n"); - - x = ipod->diroffset % ipod->sector_size; - - /* Read directory */ - if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; } - - n=ipod_read(ipod, sectorbuf, ipod->sector_size); - if (n < 0) { return -1; } - - /* Update entries for image 0 */ - int2le(length,sectorbuf+x+16); - int2le(0,sectorbuf+x+24); - int2le(chksum,sectorbuf+x+28); - - /* Write directory */ - if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; } - n=ipod_write(ipod, sectorbuf, ipod->sector_size); - if (n < 0) { return -1; } - - return 0; -} - -int write_firmware(struct ipod_t* ipod, char* filename, int type) -{ - int length; - int i; - int x; - int n; - int infile; - int newsize; - int bytesavailable; - unsigned long chksum=0; - unsigned long filechksum=0; - unsigned char header[8]; /* Header for .ipod file */ - - /* First check that the input file is the correct type for this ipod. */ - infile=open(filename,O_RDONLY); - if (infile < 0) { - fprintf(stderr,"[ERR] Couldn't open input file %s\n",filename); - return -1; - } - - if (type==FILETYPE_DOT_IPOD) { - n = read(infile,header,8); - if (n < 8) { - fprintf(stderr,"[ERR] Failed to read header from %s\n",filename); - close(infile); - return -1; - } - - if (memcmp(header+4, ipod->modelname,4)!=0) { - fprintf(stderr,"[ERR] Model name in input file (%c%c%c%c) doesn't match ipod model (%s)\n", - header[4],header[5],header[6],header[7], ipod->modelname); - close(infile); - return -1; - } - - filechksum = be2int(header); - - length = filesize(infile)-8; - } else { - length = filesize(infile); - } - newsize=(length+ipod->sector_size-1)&~(ipod->sector_size-1); - - fprintf(stderr,"[INFO] Padding input file from 0x%08x to 0x%08x bytes\n", - length,newsize); - - if (newsize > BUFFER_SIZE) { - fprintf(stderr,"[ERR] Input file too big for buffer\n"); - close(infile); - return -1; - } - - /* Check if we have enough space */ - /* TODO: Check the size of the partition. */ - if (ipod->nimages > 1) { - bytesavailable=ipod->ipod_directory[1].devOffset-ipod->ipod_directory[0].devOffset; - if (bytesavailable < newsize) { - fprintf(stderr,"[INFO] Moving images to create room for new firmware...\n"); - - /* TODO: Implement image movement */ - fprintf(stderr,"[ERR] Image movement not yet implemented.\n"); - close(infile); - return -1; - } - } - - fprintf(stderr,"[INFO] Reading input file...\n"); - /* We now know we have enough space, so write it. */ - memset(sectorbuf+length,0,newsize-length); - n = read(infile,sectorbuf,length); - if (n < 0) { - fprintf(stderr,"[ERR] Couldn't read input file\n"); - close(infile); - return -1; - } - close(infile); - - if (type==FILETYPE_DOT_IPOD) { - chksum = ipod->modelnum; - for (i = 0; i < length; i++) { - /* add 8 unsigned bits but keep a 32 bit sum */ - chksum += sectorbuf[i]; - } - - if (chksum == filechksum) { - fprintf(stderr,"[INFO] Checksum OK in %s\n",filename); - } else { - fprintf(stderr,"[ERR] Checksum in %s failed check\n",filename); - return -1; - } - } - - if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { - fprintf(stderr,"[ERR] Seek failed\n"); - return -1; - } - - if ((n = ipod_write(ipod,sectorbuf,newsize)) < 0) { - perror("[ERR] Write failed\n"); - return -1; - } - - if (n < newsize) { - fprintf(stderr,"[ERR] Short write - requested %d bytes, received %d\n" - ,i,n); - return -1; - } - fprintf(stderr,"[INFO] Wrote %d bytes to firmware partition\n",n); - - /* Now we need to update the "len", "entryOffset" and "chksum" fields */ - chksum = 0; - for (i = 0; i < length; i++) { - /* add 8 unsigned bits but keep a 32 bit sum */ - chksum += sectorbuf[i]; - } - - x = ipod->diroffset % ipod->sector_size; - - /* Read directory */ - if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; } - - n=ipod_read(ipod, sectorbuf, ipod->sector_size); - if (n < 0) { return -1; } - - /* Update entries for image 0 */ - int2le(length,sectorbuf+x+16); - int2le(0,sectorbuf+x+24); - int2le(chksum,sectorbuf+x+28); - - /* Write directory */ - if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { return -1; } - n=ipod_write(ipod, sectorbuf, ipod->sector_size); - if (n < 0) { return -1; } - - return 0; -} - -int read_firmware(struct ipod_t* ipod, char* filename) -{ - int length; - int i; - int outfile; - int n; - 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) { - /* We have a bootloader... */ - length = ipod->ipod_directory[0].entryOffset; - } else { - length = ipod->ipod_directory[0].len; - } - - fprintf(stderr,"[INFO] Reading firmware (%d bytes)\n",length); - - if (ipod_seek(ipod, ipod->fwoffset+ipod->ipod_directory[0].devOffset) < 0) { - return -1; - } - - 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 ((n = ipod_read(ipod,sectorbuf,i)) < 0) { - return -1; - } - - if (n < i) { - fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n", - i,n); - return -1; - } - - chksum = ipod->modelnum; - for (i = 0; i < length; i++) { - /* add 8 unsigned bits but keep a 32 bit sum */ - chksum += sectorbuf[i]; - } - - int2be(chksum,header); - memcpy(header+4, ipod->modelname,4); - - outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,0666); - if (outfile < 0) { - fprintf(stderr,"[ERR] Couldn't open file %s\n",filename); - return -1; - } - - write(outfile,header,8); - write(outfile,sectorbuf,length); - close(outfile); - - return 0; -} - -int read_directory(struct ipod_t* ipod) -{ - int n; - int x; - unsigned char* p; - unsigned short version; - - ipod->nimages=0; - - /* Read firmware partition header (first 512 bytes of disk - but - let's read a whole sector) */ - - if (ipod_seek(ipod, ipod->start) < 0) { - fprintf(stderr,"[ERR] Seek to 0x%08x in read_directory() failed.\n", - (unsigned int)(ipod->start)); - return -1; - } - - n=ipod_read(ipod, sectorbuf, ipod->sector_size); - if (n < 0) { - fprintf(stderr,"[ERR] ipod_read(ipod,buf,0x%08x) failed in read_directory()\n", ipod->sector_size); - return -1; - } - - if (memcmp(sectorbuf,apple_stop_sign,sizeof(apple_stop_sign))!=0) { - fprintf(stderr,"[ERR] Firmware partition doesn't contain Apple copyright, aborting.\n"); - return -1; - } - - if (memcmp(sectorbuf+0x100,"]ih[",4)!=0) { - fprintf(stderr,"[ERR] Bad firmware directory\n"); - return -1; - } - - version = le2ushort(sectorbuf+0x10a); - if ((version != 2) && (version != 3)) { - fprintf(stderr,"[ERR] Unknown firmware format version %04x\n", - version); - } - ipod->diroffset=le2int(sectorbuf+0x104) + 0x200; - - /* diroffset may not be sector-aligned */ - x = ipod->diroffset % ipod->sector_size; - - /* Read directory */ - if (ipod_seek(ipod, ipod->start + ipod->diroffset - x) < 0) { - fprintf(stderr,"[ERR] Seek to diroffset (%08x) failed.\n",(unsigned)ipod->diroffset); - return -1; - } - - n=ipod_read(ipod, sectorbuf, ipod->sector_size); - if (n < 0) { - fprintf(stderr,"[ERR] Read of directory failed.\n"); - return -1; - } - - p = sectorbuf + x; - - while ((ipod->nimages < MAX_IMAGES) && (p < (sectorbuf + x + 400)) && - (memcmp(p,"!ATA",4)==0)) { - p+=4; - if (memcmp(p,"soso",4)==0) { - ipod->ipod_directory[ipod->nimages].ftype=FTYPE_OSOS; - } else if (memcmp(p,"crsr",4)==0) { - ipod->ipod_directory[ipod->nimages].ftype=FTYPE_RSRC; - } else if (memcmp(p,"dpua",4)==0) { - ipod->ipod_directory[ipod->nimages].ftype=FTYPE_AUPD; - } else if (memcmp(p,"ebih",4)==0) { - ipod->ipod_directory[ipod->nimages].ftype=FTYPE_HIBE; - } else { - fprintf(stderr,"[ERR] Unknown image type %c%c%c%c\n", - p[0],p[1],p[2],p[3]); - } - p+=4; - ipod->ipod_directory[ipod->nimages].id=le2int(p); - p+=4; - ipod->ipod_directory[ipod->nimages].devOffset=le2int(p); - p+=4; - ipod->ipod_directory[ipod->nimages].len=le2int(p); - p+=4; - ipod->ipod_directory[ipod->nimages].addr=le2int(p); - p+=4; - ipod->ipod_directory[ipod->nimages].entryOffset=le2int(p); - p+=4; - ipod->ipod_directory[ipod->nimages].chksum=le2int(p); - p+=4; - ipod->ipod_directory[ipod->nimages].vers=le2int(p); - p+=4; - ipod->ipod_directory[ipod->nimages].loadAddr=le2int(p); - p+=4; - ipod->nimages++; - } - - 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; } - - ipod->fwoffset = ipod->start; - } else { - ipod->fwoffset = ipod->start + ipod->sector_size; - } - - return 0; -} - -int list_images(struct ipod_t* ipod) -{ - int i; - - if (verbose) { - printf(" Type id devOffset len addr entryOffset chksum vers loadAddr devOffset+len\n"); - for (i = 0 ; i < ipod->nimages; i++) { - printf("%d - %s 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",i, - ftypename[ipod->ipod_directory[i].ftype], - ipod->ipod_directory[i].id, - ipod->ipod_directory[i].devOffset, - ipod->ipod_directory[i].len, - ipod->ipod_directory[i].addr, - ipod->ipod_directory[i].entryOffset, - ipod->ipod_directory[i].chksum, - ipod->ipod_directory[i].vers, - ipod->ipod_directory[i].loadAddr, - ipod->ipod_directory[i].devOffset+((ipod->ipod_directory[i].len+ipod->sector_size-1)&~(ipod->sector_size-1))); - } - } - - printf("\n"); - printf("Listing firmware partition contents:\n"); - printf("\n"); - - for (i = 0 ; i < ipod->nimages; i++) { - printf("Image %d:\n",i+1); - switch(ipod->ipod_directory[i].ftype) { - case FTYPE_OSOS: - if (ipod->ipod_directory[i].entryOffset==0) { - printf(" Main firmware - %d bytes\n", - ipod->ipod_directory[i].len); - } else { - printf(" Main firmware - %d bytes\n", - ipod->ipod_directory[i].entryOffset); - printf(" Third-party bootloader - %d bytes\n", - ipod->ipod_directory[i].len-ipod->ipod_directory[i].entryOffset); - } - break; - default: - printf(" %s - %d bytes\n", - ftypename[ipod->ipod_directory[i].ftype], - ipod->ipod_directory[i].len); - } - } - printf("\n"); - - return 0; -} - -int getmodel(struct ipod_t* ipod, int ipod_version) -{ - switch (ipod_version) { - case 0x02: - ipod->modelstr="3rd Generation"; - ipod->modelnum = 7; - ipod->modelname = "ip3g"; -#ifdef WITH_BOOTOBJS - ipod->bootloader = ipod3g; - ipod->bootloader_len = LEN_ipod3g; -#endif - break; - case 0x40: - ipod->modelstr="1st Generation Mini"; - ipod->modelnum = 9; - ipod->modelname = "mini"; -#ifdef WITH_BOOTOBJS - ipod->bootloader = ipodmini; - ipod->bootloader_len = LEN_ipodmini; -#endif - break; - case 0x50: - ipod->modelstr="4th Generation"; - ipod->modelnum = 8; - ipod->modelname = "ip4g"; -#ifdef WITH_BOOTOBJS - ipod->bootloader = ipod4g; - ipod->bootloader_len = LEN_ipod4g; -#endif - break; - case 0x60: - ipod->modelstr="Photo/Color"; - ipod->modelnum = 3; - ipod->modelname = "ipco"; -#ifdef WITH_BOOTOBJS - ipod->bootloader = ipodcolor; - ipod->bootloader_len = LEN_ipodcolor; -#endif - break; - case 0x70: - ipod->modelstr="2nd Generation Mini"; - ipod->modelnum = 11; - ipod->modelname = "mn2g"; -#ifdef WITH_BOOTOBJS - ipod->bootloader = ipodmini2g; - ipod->bootloader_len = LEN_ipodmini2g; -#endif - break; - case 0xc0: - ipod->modelstr="1st Generation Nano"; - ipod->modelnum = 4; - ipod->modelname = "nano"; -#ifdef WITH_BOOTOBJS - ipod->bootloader = ipodnano; - ipod->bootloader_len = LEN_ipodnano; -#endif - break; - case 0xb0: - ipod->modelstr="Video (aka 5th Generation)"; - ipod->modelnum = 5; - ipod->modelname = "ipvd"; -#ifdef WITH_BOOTOBJS - ipod->bootloader = ipodvideo; - ipod->bootloader_len = LEN_ipodvideo; -#endif - break; - default: - ipod->modelname = NULL; - ipod->modelnum = 0; -#ifdef WITH_BOOTOBJS - ipod->bootloader = NULL; - ipod->bootloader_len = 0; -#endif - return -1; - } - return 0; -} - -int ipod_scan(struct ipod_t* ipod) -{ - int i; - int n = 0; - int ipod_version; - char last_ipod[4096]; - - printf("[INFO] Scanning disk devices...\n"); - - for (i = 0; i <= 25 ; i++) { -#ifdef __WIN32__ - sprintf(ipod->diskname,"\\\\.\\PhysicalDrive%d",i); -#elif defined(linux) || defined (__linux) - sprintf(ipod->diskname,"/dev/sd%c",'a'+i); -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \ - || defined(__bsdi__) || defined(__DragonFly__) - sprintf(ipod->diskname,"/dev/da%d",i); -#elif defined(__APPLE__) && defined(__MACH__) - sprintf(ipod->diskname,"/dev/disk%d",i); -#else - #error No disk paths defined for this platform -#endif - if (ipod_open(ipod, 1) < 0) { - continue; - } - - if (read_partinfo(ipod,1) < 0) { - continue; - } - - if ((ipod->pinfo[0].start==0) || (ipod->pinfo[0].type != 0)) { - continue; - } - - if (read_directory(ipod) < 0) { - continue; - } - - ipod_version=(ipod->ipod_directory[0].vers>>8); - if (getmodel(ipod,ipod_version) < 0) { - continue; - } - -#ifdef __WIN32__ - printf("[INFO] Ipod found - %s (\"%s\") - disk device %d\n", - ipod->modelstr,ipod->macpod ? "macpod" : "winpod",i); -#else - printf("[INFO] Ipod found - %s (\"%s\") - %s\n", - ipod->modelstr,ipod->macpod ? "macpod" : "winpod",ipod->diskname); -#endif - n++; - strcpy(last_ipod,ipod->diskname); - ipod_close(ipod); - } - - if (n==1) { - /* Remember the disk name */ - strcpy(ipod->diskname,last_ipod); - } - return n; -} diff --git a/tools/ipodpatcher/ipodpatcher.h b/tools/ipodpatcher/ipodpatcher.h deleted file mode 100644 index c533f4c2dc..0000000000 --- a/tools/ipodpatcher/ipodpatcher.h +++ /dev/null @@ -1,51 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id: ipodpatcher.c 12237 2007-02-08 21:31:38Z dave $ - * - * Copyright (C) 2006-2007 Dave Chapman - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#ifndef _IPODPATCHER_H -#define _IPODPATCHER_H - -#include "ipodio.h" - -/* Size of buffer for disk I/O - 8MB is large enough for any version - of the Apple firmware, but not the Nano's RSRC image. */ -#define BUFFER_SIZE 8*1024*1024 -extern unsigned char* sectorbuf; - -#define FILETYPE_DOT_IPOD 0 -#define FILETYPE_DOT_BIN 1 -#ifdef WITH_BOOTOBJS - #define FILETYPE_INTERNAL 2 -#endif - -void display_partinfo(struct ipod_t* ipod); -int read_partinfo(struct ipod_t* ipod, int silent); -int read_partition(struct ipod_t* ipod, int outfile); -int write_partition(struct ipod_t* ipod, int infile); -int diskmove(struct ipod_t* ipod, int delta); -int add_bootloader(struct ipod_t* ipod, char* filename, int type); -int delete_bootloader(struct ipod_t* ipod); -int write_firmware(struct ipod_t* ipod, char* filename, int type); -int read_firmware(struct ipod_t* ipod, char* filename); -int read_directory(struct ipod_t* ipod); -int list_images(struct ipod_t* ipod); -int getmodel(struct ipod_t* ipod, int ipod_version); -int ipod_scan(struct ipod_t* ipod); -off_t filesize(int fd); - -#endif diff --git a/tools/ipodpatcher/main.c b/tools/ipodpatcher/main.c deleted file mode 100644 index d183b9bc52..0000000000 --- a/tools/ipodpatcher/main.c +++ /dev/null @@ -1,429 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id: ipodpatcher.c 12237 2007-02-08 21:31:38Z dave $ - * - * Copyright (C) 2006-2007 Dave Chapman - * - * All files in this archive are subject to the GNU General Public License. - * See the file COPYING in the source tree root for full license agreement. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ipodpatcher.h" -#include "ipodio.h" - -#define VERSION "0.8 with r12194-070204 bootloaders" - -int verbose = 0; - -enum { - NONE, -#ifdef WITH_BOOTOBJS - INSTALL, -#endif - INTERACTIVE, - SHOW_INFO, - LIST_IMAGES, - DELETE_BOOTLOADER, - ADD_BOOTLOADER, - READ_FIRMWARE, - WRITE_FIRMWARE, - READ_PARTITION, - WRITE_PARTITION -}; - -void print_macpod_warning(void) -{ - printf("[INFO] ************************************************************************\n"); - printf("[INFO] *** WARNING FOR ROCKBOX USERS\n"); - printf("[INFO] *** You must convert this ipod to FAT32 format (aka a \"winpod\")\n"); - printf("[INFO] *** if you want to run Rockbox. Rockbox WILL NOT work on this ipod.\n"); - printf("[INFO] *** See http://www.rockbox.org/twiki/bin/view/Main/IpodConversionToFAT32\n"); - printf("[INFO] ************************************************************************\n"); -} - -void print_usage(void) -{ - fprintf(stderr,"Usage: ipodpatcher --scan\n"); -#ifdef __WIN32__ - fprintf(stderr," or ipodpatcher [DISKNO] [action]\n"); -#else - fprintf(stderr," or ipodpatcher [device] [action]\n"); -#endif - fprintf(stderr,"\n"); - fprintf(stderr,"Where [action] is one of the following options:\n"); -#ifdef WITH_BOOTOBJS - fprintf(stderr," --install\n"); -#endif - fprintf(stderr," -l, --list\n"); - fprintf(stderr," -r, --read-partition bootpartition.bin\n"); - fprintf(stderr," -w, --write-partition bootpartition.bin\n"); - fprintf(stderr," -rf, --read-firmware filename.ipod\n"); - fprintf(stderr," -wf, --write-firmware filename.ipod\n"); - fprintf(stderr," -wfb, --write-firmware-bin filename.bin\n"); - fprintf(stderr," -a, --add-bootloader filename.ipod\n"); - fprintf(stderr," -ab, --add-bootloader-bin filename.bin\n"); - fprintf(stderr," -d, --delete-bootloader\n"); - fprintf(stderr,"\n"); - -#ifdef __WIN32__ - fprintf(stderr,"DISKNO is the number (e.g. 2) Windows has assigned to your ipod's hard disk.\n"); - fprintf(stderr,"The first hard disk in your computer (i.e. C:\\) will be disk 0, the next disk\n"); - fprintf(stderr,"will be disk 1 etc. ipodpatcher will refuse to access a disk unless it\n"); - fprintf(stderr,"can identify it as being an ipod.\n"); - fprintf(stderr,"\n"); -#else -#if defined(linux) || defined (__linux) - fprintf(stderr,"\"device\" is the device node (e.g. /dev/sda) assigned to your ipod.\n"); -#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) - fprintf(stderr,"\"device\" is the device node (e.g. /dev/da1) assigned to your ipod.\n"); -#elif defined(__APPLE__) && defined(__MACH__) - fprintf(stderr,"\"device\" is the device node (e.g. /dev/disk1) assigned to your ipod.\n"); -#endif - fprintf(stderr,"ipodpatcher will refuse to access a disk unless it can identify it as being\n"); - fprintf(stderr,"an ipod.\n"); -#endif -} - -int main(int argc, char* argv[]) -{ -#ifdef WITH_BOOTOBJS - char yesno[4]; -#endif - int i; - int n; - int infile, outfile; - unsigned int inputsize; - char* filename; - int action = SHOW_INFO; - int type; - struct ipod_t ipod; - - fprintf(stderr,"ipodpatcher v" VERSION " - (C) Dave Chapman 2006-2007\n"); - fprintf(stderr,"This is free software; see the source for copying conditions. There is NO\n"); - fprintf(stderr,"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"); - - if ((argc > 1) && ((strcmp(argv[1],"-h")==0) || (strcmp(argv[1],"--help")==0))) { - print_usage(); - return 1; - } - - if (ipod_alloc_buffer(§orbuf,BUFFER_SIZE) < 0) { - fprintf(stderr,"Failed to allocate memory buffer\n"); - } - - if ((argc > 1) && (strcmp(argv[1],"--scan")==0)) { - if (ipod_scan(&ipod) == 0) - fprintf(stderr,"[ERR] No ipods found.\n"); - return 0; - } - - /* If the first parameter doesn't start with -, then we interpret it as a device */ - if ((argc > 1) && (argv[1][0] != '-')) { - ipod.diskname[0]=0; -#ifdef __WIN32__ - snprintf(ipod.diskname,sizeof(ipod.diskname),"\\\\.\\PhysicalDrive%s",argv[1]); -#else - strncpy(ipod.diskname,argv[1],sizeof(ipod.diskname)); -#endif - i = 2; - } else { - /* Autoscan for ipods */ - n = ipod_scan(&ipod); - if (n==0) { - fprintf(stderr,"[ERR] No ipods found, aborting\n"); - fprintf(stderr,"[ERR] Please connect your ipod and ensure it is in disk mode\n"); -#if defined(__APPLE__) && defined(__MACH__) - fprintf(stderr,"[ERR] Also ensure that itunes is closed, and that your ipod is not mounted.\n"); -#elif !defined(__WIN32__) - if (geteuid()!=0) { - fprintf(stderr,"[ERR] You may also need to run ipodpatcher as root.\n"); - } -#endif - fprintf(stderr,"[ERR] Please refer to the Rockbox manual if you continue to have problems.\n"); - } else if (n > 1) { - fprintf(stderr,"[ERR] %d ipods found, aborting\n",n); - fprintf(stderr,"[ERR] Please connect only one ipod and re-run ipodpatcher.\n"); - } - - if (n != 1) { -#ifdef WITH_BOOTOBJS - if (argc==1) { - printf("\nPress ENTER to exit ipodpatcher :"); - fgets(yesno,4,stdin); - } -#endif - return 0; - } - - i = 1; - } - -#ifdef WITH_BOOTOBJS - action = INTERACTIVE; -#else - action = NONE; -#endif - - while (i < argc) { - if ((strcmp(argv[i],"-l")==0) || (strcmp(argv[i],"--list")==0)) { - action = LIST_IMAGES; - i++; -#ifdef WITH_BOOTOBJS - } else if (strcmp(argv[i],"--install")==0) { - action = INSTALL; - i++; -#endif - } else if ((strcmp(argv[i],"-d")==0) || - (strcmp(argv[i],"--delete-bootloader")==0)) { - action = DELETE_BOOTLOADER; - i++; - } else if ((strcmp(argv[i],"-a")==0) || - (strcmp(argv[i],"--add-bootloader")==0)) { - action = ADD_BOOTLOADER; - type = FILETYPE_DOT_IPOD; - i++; - if (i == argc) { print_usage(); return 1; } - filename=argv[i]; - i++; - } else if ((strcmp(argv[i],"-ab")==0) || - (strcmp(argv[i],"--add-bootloader-bin")==0)) { - action = ADD_BOOTLOADER; - type = FILETYPE_DOT_BIN; - i++; - if (i == argc) { print_usage(); return 1; } - filename=argv[i]; - i++; - } else if ((strcmp(argv[i],"-rf")==0) || - (strcmp(argv[i],"--read-firmware")==0)) { - action = READ_FIRMWARE; - i++; - if (i == argc) { print_usage(); return 1; } - filename=argv[i]; - i++; - } else if ((strcmp(argv[i],"-wf")==0) || - (strcmp(argv[i],"--write-firmware")==0)) { - action = WRITE_FIRMWARE; - type = FILETYPE_DOT_IPOD; - i++; - if (i == argc) { print_usage(); return 1; } - filename=argv[i]; - i++; - } else if ((strcmp(argv[i],"-wfb")==0) || - (strcmp(argv[i],"--write-firmware-bin")==0)) { - action = WRITE_FIRMWARE; - type = FILETYPE_DOT_BIN; - i++; - if (i == argc) { print_usage(); return 1; } - filename=argv[i]; - i++; - } else if ((strcmp(argv[i],"-r")==0) || - (strcmp(argv[i],"--read-partition")==0)) { - action = READ_PARTITION; - i++; - if (i == argc) { print_usage(); return 1; } - filename=argv[i]; - i++; - } else if ((strcmp(argv[i],"-w")==0) || - (strcmp(argv[i],"--write-partition")==0)) { - action = WRITE_PARTITION; - i++; - if (i == argc) { print_usage(); return 1; } - filename=argv[i]; - i++; - } else if ((strcmp(argv[i],"-v")==0) || - (strcmp(argv[i],"--verbose")==0)) { - verbose++; - i++; - } else { - print_usage(); return 1; - } - } - - if (ipod.diskname[0]==0) { - print_usage(); - return 1; - } - - if (ipod_open(&ipod, 0) < 0) { - return 1; - } - - fprintf(stderr,"[INFO] Reading partition table from %s\n",ipod.diskname); - fprintf(stderr,"[INFO] Sector size is %d bytes\n",ipod.sector_size); - - if (read_partinfo(&ipod,0) < 0) { - return 2; - } - - display_partinfo(&ipod); - - if (ipod.pinfo[0].start==0) { - fprintf(stderr,"[ERR] No partition 0 on disk:\n"); - display_partinfo(&ipod); - return 3; - } - - read_directory(&ipod); - - if (ipod.nimages <= 0) { - fprintf(stderr,"[ERR] Failed to read firmware directory - nimages=%d\n",ipod.nimages); - return 1; - } - - if (getmodel(&ipod,(ipod.ipod_directory[0].vers>>8)) < 0) { - fprintf(stderr,"[ERR] Unknown version number in firmware (%08x)\n", - ipod.ipod_directory[0].vers); - return -1; - } - - printf("[INFO] Ipod model: %s (\"%s\")\n",ipod.modelstr, - ipod.macpod ? "macpod" : "winpod"); - - if (ipod.macpod) { - print_macpod_warning(); - } - - if (action==LIST_IMAGES) { - list_images(&ipod); -#ifdef WITH_BOOTOBJS - } else if (action==INTERACTIVE) { - - printf("Do you wish to install the rockbox bootloader? (y/n) :"); - if (fgets(yesno,4,stdin)) { - if (yesno[0]=='y') { - if (ipod_reopen_rw(&ipod) < 0) { - return 5; - } - - if (add_bootloader(&ipod, NULL, FILETYPE_INTERNAL)==0) { - fprintf(stderr,"[INFO] Bootloader installed successfully.\n"); - } else { - fprintf(stderr,"[ERR] --install failed.\n"); - } - } - } -#endif - } else if (action==DELETE_BOOTLOADER) { - if (ipod_reopen_rw(&ipod) < 0) { - return 5; - } - - if (ipod.ipod_directory[0].entryOffset==0) { - fprintf(stderr,"[ERR] No bootloader detected.\n"); - } else { - if (delete_bootloader(&ipod)==0) { - fprintf(stderr,"[INFO] Bootloader removed.\n"); - } else { - fprintf(stderr,"[ERR] --delete-bootloader failed.\n"); - } - } - } else if (action==ADD_BOOTLOADER) { - if (ipod_reopen_rw(&ipod) < 0) { - return 5; - } - - if (add_bootloader(&ipod, filename, type)==0) { - fprintf(stderr,"[INFO] Bootloader %s written to device.\n",filename); - } else { - fprintf(stderr,"[ERR] --add-bootloader failed.\n"); - } -#ifdef WITH_BOOTOBJS - } else if (action==INSTALL) { - if (ipod_reopen_rw(&ipod) < 0) { - return 5; - } - - if (add_bootloader(&ipod, NULL, FILETYPE_INTERNAL)==0) { - fprintf(stderr,"[INFO] Bootloader installed successfully.\n"); - } else { - fprintf(stderr,"[ERR] --install failed.\n"); - } -#endif - } else if (action==WRITE_FIRMWARE) { - if (ipod_reopen_rw(&ipod) < 0) { - return 5; - } - - if (write_firmware(&ipod, filename,type)==0) { - fprintf(stderr,"[INFO] Firmware %s written to device.\n",filename); - } else { - fprintf(stderr,"[ERR] --write-firmware failed.\n"); - } - } else if (action==READ_FIRMWARE) { - if (read_firmware(&ipod, filename)==0) { - fprintf(stderr,"[INFO] Firmware read to file %s.\n",filename); - } else { - fprintf(stderr,"[ERR] --read-firmware failed.\n"); - } - } else if (action==READ_PARTITION) { - outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IREAD|S_IWRITE); - if (outfile < 0) { - perror(filename); - return 4; - } - - if (read_partition(&ipod, outfile) < 0) { - fprintf(stderr,"[ERR] --read-partition failed.\n"); - } else { - fprintf(stderr,"[INFO] Partition extracted to %s.\n",filename); - } - close(outfile); - } else if (action==WRITE_PARTITION) { - if (ipod_reopen_rw(&ipod) < 0) { - return 5; - } - - infile = open(filename,O_RDONLY|O_BINARY); - if (infile < 0) { - perror(filename); - return 2; - } - - /* Check filesize is <= partition size */ - inputsize=filesize(infile); - if (inputsize > 0) { - if (inputsize <= (ipod.pinfo[0].size*ipod.sector_size)) { - fprintf(stderr,"[INFO] Input file is %u bytes\n",inputsize); - if (write_partition(&ipod,infile) < 0) { - fprintf(stderr,"[ERR] --write-partition failed.\n"); - } else { - fprintf(stderr,"[INFO] %s restored to partition\n",filename); - } - } else { - fprintf(stderr,"[ERR] File is too large for firmware partition, aborting.\n"); - } - } - - close(infile); - } - - ipod_close(&ipod); - -#ifdef WITH_BOOTOBJS - if (action==INTERACTIVE) { - printf("Press ENTER to exit ipodpatcher :"); - fgets(yesno,4,stdin); - } -#endif - - - return 0; -} diff --git a/tools/ipodpatcher/parttypes.h b/tools/ipodpatcher/parttypes.h deleted file mode 100644 index f8de303553..0000000000 --- a/tools/ipodpatcher/parttypes.h +++ /dev/null @@ -1,109 +0,0 @@ -/* DOS partition types - taken from fdisk */ - -struct parttype { - unsigned char type; - char *name; -}; - -struct parttype parttypes[] = { - {0x00, "Empty"}, - {0x01, "FAT12"}, - {0x02, "XENIX root"}, - {0x03, "XENIX usr"}, - {0x04, "FAT16 <32M"}, - {0x05, "Extended"}, /* DOS 3.3+ extended partition */ - {0x06, "FAT16"}, /* DOS 16-bit >=32M */ - {0x07, "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */ - {0x08, "AIX"}, /* AIX boot (AIX -- PS/2 port) or SplitDrive */ - {0x09, "AIX bootable"}, /* AIX data or Coherent */ - {0x0a, "OS/2 Boot Manager"},/* OS/2 Boot Manager */ - {0x0b, "W95 FAT32"}, - {0x0c, "W95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */ - {0x0e, "W95 FAT16 (LBA)"}, - {0x0f, "W95 Ext'd (LBA)"}, - {0x10, "OPUS"}, - {0x11, "Hidden FAT12"}, - {0x12, "Compaq diagnostics"}, - {0x14, "Hidden FAT16 <32M"}, - {0x16, "Hidden FAT16"}, - {0x17, "Hidden HPFS/NTFS"}, - {0x18, "AST SmartSleep"}, - {0x1b, "Hidden W95 FAT32"}, - {0x1c, "Hidden W95 FAT32 (LBA)"}, - {0x1e, "Hidden W95 FAT16 (LBA)"}, - {0x24, "NEC DOS"}, - {0x39, "Plan 9"}, - {0x3c, "PartitionMagic recovery"}, - {0x40, "Venix 80286"}, - {0x41, "PPC PReP Boot"}, - {0x42, "SFS"}, - {0x4d, "QNX4.x"}, - {0x4e, "QNX4.x 2nd part"}, - {0x4f, "QNX4.x 3rd part"}, - {0x50, "OnTrack DM"}, - {0x51, "OnTrack DM6 Aux1"}, /* (or Novell) */ - {0x52, "CP/M"}, /* CP/M or Microport SysV/AT */ - {0x53, "OnTrack DM6 Aux3"}, - {0x54, "OnTrackDM6"}, - {0x55, "EZ-Drive"}, - {0x56, "Golden Bow"}, - {0x5c, "Priam Edisk"}, - {0x61, "SpeedStor"}, - {0x63, "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */ - {0x64, "Novell Netware 286"}, - {0x65, "Novell Netware 386"}, - {0x70, "DiskSecure Multi-Boot"}, - {0x75, "PC/IX"}, - {0x80, "Old Minix"}, /* Minix 1.4a and earlier */ - {0x81, "Minix / old Linux"},/* Minix 1.4b and later */ - {0x82, "Linux swap / Solaris"}, - {0x83, "Linux"}, - {0x84, "OS/2 hidden C: drive"}, - {0x85, "Linux extended"}, - {0x86, "NTFS volume set"}, - {0x87, "NTFS volume set"}, - {0x88, "Linux plaintext"}, - {0x8e, "Linux LVM"}, - {0x93, "Amoeba"}, - {0x94, "Amoeba BBT"}, /* (bad block table) */ - {0x9f, "BSD/OS"}, /* BSDI */ - {0xa0, "IBM Thinkpad hibernation"}, - {0xa5, "FreeBSD"}, /* various BSD flavours */ - {0xa6, "OpenBSD"}, - {0xa7, "NeXTSTEP"}, - {0xa8, "Darwin UFS"}, - {0xa9, "NetBSD"}, - {0xab, "Darwin boot"}, - {0xb7, "BSDI fs"}, - {0xb8, "BSDI swap"}, - {0xbb, "Boot Wizard hidden"}, - {0xbe, "Solaris boot"}, - {0xbf, "Solaris"}, - {0xc1, "DRDOS/sec (FAT-12)"}, - {0xc4, "DRDOS/sec (FAT-16 < 32M)"}, - {0xc6, "DRDOS/sec (FAT-16)"}, - {0xc7, "Syrinx"}, - {0xda, "Non-FS data"}, - {0xdb, "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or - Concurrent DOS or CTOS */ - {0xde, "Dell Utility"}, /* Dell PowerEdge Server utilities */ - {0xdf, "BootIt"}, /* BootIt EMBRM */ - {0xe1, "DOS access"}, /* DOS access or SpeedStor 12-bit FAT - extended partition */ - {0xe3, "DOS R/O"}, /* DOS R/O or SpeedStor */ - {0xe4, "SpeedStor"}, /* SpeedStor 16-bit FAT extended - partition < 1024 cyl. */ - {0xeb, "BeOS fs"}, - {0xee, "EFI GPT"}, /* Intel EFI GUID Partition Table */ - {0xef, "EFI (FAT-12/16/32)"},/* Intel EFI System Partition */ - {0xf0, "Linux/PA-RISC boot"},/* Linux/PA-RISC boot loader */ - {0xf1, "SpeedStor"}, - {0xf4, "SpeedStor"}, /* SpeedStor large partition */ - {0xf2, "DOS secondary"}, /* DOS 3.3+ secondary */ - {0xfd, "Linux raid autodetect"},/* New (2.2.x) raid partition with - autodetect using persistent - superblock */ - {0xfe, "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */ - {0xff, "BBT"}, /* Xenix Bad Block Table */ - { 0, 0 } -}; -- cgit v1.2.3