rbutil: Merge rbutil with utils folder.

rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.

This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.

Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
This commit is contained in:
Dominik Riebeling 2021-12-15 21:04:28 +01:00
parent 6c6f0757d7
commit c876d3bbef
494 changed files with 13 additions and 13 deletions

View file

@ -0,0 +1,53 @@
# __________ __ ___.
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
# \/ \/ \/ \/ \/
# $Id$
#
CFLAGS += -Wall -W
# Build with "make BOOTOBJS=1" 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
# Releases of ipodpatcher are created with "make RELEASE=1". This
# enables BOOTOBJS and uses the VERSION string defined in main.c
ifdef RELEASE
CFLAGS += -DRELEASE
BOOTOBJS=1
endif
ifdef BOOTOBJS
BOOTSRC = ipod1g2g.c ipod3g.c ipod4g.c ipodcolor.c ipodmini1g.c \
ipodmini2g.c ipodnano1g.c ipodvideo.c ipodnano2g.c
CFLAGS += -DWITH_BOOTOBJS
endif
# additional frameworks to link on on OS X
LDOPTS_OSX = -framework CoreFoundation -framework IOKit
LIBSOURCES = ipodpatcher.c fat32format.c arc4.c \
ipodio-posix.c ipodio-win32-scsi.c ipodio-win32.c
SOURCES = main.c $(BOOTSRC)
ipodpatcher: SOURCES+= ipodio-posix.c
OUTPUT = ipodpatcher
include ../libtools.make
ipodpatcher.exe: $(OBJDIR)ipodpatcher-rc.o
$(OBJDIR)ipodpatcher-rc.o: ipodpatcher.rc ipodpatcher.manifest
@echo WINDRES $(notdir $<)
$(SILENT)$(CROSS)$(WINDRES) -i $< -o $@
%.c: bootloader-%.ipod $(BIN2C)
@echo BIN2C $<
$(SILENT)$(BIN2C) -i $< $*
%.c: bootloader-%.ipodx $(BIN2C)
@echo BIN2C $<
$(SILENT)$(BIN2C) -i $< $*

108
utils/ipodpatcher/arc4.c Normal file
View file

@ -0,0 +1,108 @@
/*
* arc4.c
* Release $Name: MATRIXSSL_1_8_3_OPEN $
*
* ARC4 stream cipher implementation
*/
/*
* Copyright (c) PeerSec Networks, 2002-2007. All Rights Reserved.
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from PeerSec Networks
* at http://www.peersec.com
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#include "arc4.h"
/*
Some accounts, such as O'Reilly's Secure Programming Cookbook say that no
more than 2^30 bytes should be processed without rekeying, so we
enforce that limit here. FYI, this is equal to 1GB of data transferred.
*/
#define ARC4_MAX_BYTES 0x40000000
/******************************************************************************/
/*
SSL_RSA_WITH_RC4_* cipher callbacks
*/
void matrixArc4Init(struct rc4_key_t *ctx, unsigned char *key, int32_t keylen)
{
unsigned char index1, index2, tmp, *state;
int16_t counter;
ctx->byteCount = 0;
state = &ctx->state[0];
for (counter = 0; counter < 256; counter++) {
state[counter] = (unsigned char)counter;
}
ctx->x = 0;
ctx->y = 0;
index1 = 0;
index2 = 0;
for (counter = 0; counter < 256; counter++) {
index2 = (key[index1] + state[counter] + index2) & 0xff;
tmp = state[counter];
state[counter] = state[index2];
state[index2] = tmp;
index1 = (index1 + 1) % keylen;
}
}
int32_t matrixArc4(struct rc4_key_t *ctx, unsigned char *in,
unsigned char *out, int32_t len)
{
unsigned char x, y, *state, xorIndex, tmp;
int counter; /* NOTE BY DAVE CHAPMAN: This was a short in
the original code, which caused a segfault
when attempting to process data > 32767
bytes. */
ctx->byteCount += len;
if (ctx->byteCount > ARC4_MAX_BYTES) {
return -1;
}
x = ctx->x;
y = ctx->y;
state = &ctx->state[0];
for (counter = 0; counter < len; counter++) {
x = (x + 1) & 0xff;
y = (state[x] + y) & 0xff;
tmp = state[x];
state[x] = state[y];
state[y] = tmp;
xorIndex = (state[x] + state[y]) & 0xff;
tmp = in[counter];
tmp ^= state[xorIndex];
out[counter] = tmp;
}
ctx->x = x;
ctx->y = y;
return len;
}
/*****************************************************************************/

47
utils/ipodpatcher/arc4.h Normal file
View file

@ -0,0 +1,47 @@
/*
arc4.h - based on matrixssl-1-8-3-open
*/
/*
* Copyright (c) PeerSec Networks, 2002-2007. All Rights Reserved.
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from PeerSec Networks
* at http://www.peersec.com
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/*****************************************************************************/
#ifndef _ARC4_H
#include <stdint.h>
struct rc4_key_t
{
unsigned char state[256];
uint32_t byteCount;
unsigned char x;
unsigned char y;
};
void matrixArc4Init(struct rc4_key_t *ctx, unsigned char *key, int32_t keylen);
int32_t matrixArc4(struct rc4_key_t *ctx, unsigned char *in,
unsigned char *out, int32_t len);
#endif

View file

@ -0,0 +1,530 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
*
* FAT32 formatting functions. Based on:
*
* Fat32 formatter version 1.03
* (c) Tom Thornhill 2005
* This software is covered by the GPL.
* By using this tool, you agree to absolve Ridgecrop of an liabilities for
* lost data.
* Please backup any data you value before using this tool.
*
*
* Modified June 2007 by Dave Chapman for use in ipodpatcher
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <inttypes.h>
#include "ipodio.h"
static inline uint16_t swap16(uint16_t value)
{
return (value >> 8) | (value << 8);
}
static inline uint32_t swap32(uint32_t value)
{
uint32_t hi = swap16(value >> 16);
uint32_t lo = swap16(value & 0xffff);
return (lo << 16) | hi;
}
/* The following functions are not the most efficient, but are
self-contained and don't require needing to know endianness of CPU
at compile-time.
Note that htole16/htole32 exist on some platforms, so for
simplicity we use different names.
*/
static uint16_t rb_htole16(uint16_t x)
{
uint16_t test = 0x1234;
unsigned char* p = (unsigned char*)&test;
if (p[0]==0x12) {
/* Big-endian */
return swap16(x);
} else {
return x;
}
}
static uint32_t rb_htole32(uint32_t x)
{
uint32_t test = 0x12345678;
unsigned char* p = (unsigned char*)&test;
if (p[0]==0x12) {
/* Big-endian */
return swap32(x);
} else {
return x;
}
}
/* TODO: Pass these as parameters to the various create_ functions */
/* can be zero for default or 1,2,4,8,16,32 or 64 */
static int sectors_per_cluster = 0;
/* Recommended values */
static uint32_t ReservedSectCount = 32;
static uint32_t NumFATs = 2;
static uint32_t BackupBootSect = 6;
static uint32_t VolumeId=0; /* calculated before format */
/* Calculated later */
static uint32_t FatSize=0;
static uint32_t BytesPerSect=0;
static uint32_t SectorsPerCluster=0;
static uint32_t TotalSectors=0;
static uint32_t SystemAreaSize=0;
static uint32_t UserAreaSize=0;
static uint8_t VolId[12] = "NO NAME ";
struct FAT_BOOTSECTOR32
{
/* Common fields. */
uint8_t sJmpBoot[3];
char sOEMName[8];
uint16_t wBytsPerSec;
uint8_t bSecPerClus;
uint16_t wRsvdSecCnt;
uint8_t bNumFATs;
uint16_t wRootEntCnt;
uint16_t wTotSec16; /* if zero, use dTotSec32 instead */
uint8_t bMedia;
uint16_t wFATSz16;
uint16_t wSecPerTrk;
uint16_t wNumHeads;
uint32_t dHiddSec;
uint32_t dTotSec32;
/* Fat 32/16 only */
uint32_t dFATSz32;
uint16_t wExtFlags;
uint16_t wFSVer;
uint32_t dRootClus;
uint16_t wFSInfo;
uint16_t wBkBootSec;
uint8_t Reserved[12];
uint8_t bDrvNum;
uint8_t Reserved1;
uint8_t bBootSig; /* == 0x29 if next three fields are ok */
uint32_t dBS_VolID;
uint8_t sVolLab[11];
uint8_t sBS_FilSysType[8];
} __attribute__((packed));
struct FAT_FSINFO {
uint32_t dLeadSig; // 0x41615252
uint8_t sReserved1[480]; // zeros
uint32_t dStrucSig; // 0x61417272
uint32_t dFree_Count; // 0xFFFFFFFF
uint32_t dNxt_Free; // 0xFFFFFFFF
uint8_t sReserved2[12]; // zeros
uint32_t dTrailSig; // 0xAA550000
} __attribute__((packed));
/* Write "count" zero sectors, starting at sector "sector" */
static int zero_sectors(struct ipod_t* ipod, uint64_t sector, int count)
{
int n;
if (ipod_seek(ipod, sector * ipod->sector_size) < 0) {
fprintf(stderr,"[ERR] Seek failed\n");
return -1;
}
memset(ipod->sectorbuf, 0, 128 * ipod->sector_size);
/* Write 128 sectors at a time */
while (count) {
if (count >= 128)
n = 128;
else
n = count;
if (ipod_write(ipod,n * ipod->sector_size) < 0) {
perror("[ERR] Write failed in zero_sectors\n");
return -1;
}
count -= n;
}
return 0;
}
/*
28.2 CALCULATING THE VOLUME SERIAL NUMBER
For example, say a disk was formatted on 26 Dec 95 at 9:55 PM and 41.94
seconds. DOS takes the date and time just before it writes it to the
disk.
Low order word is calculated: Volume Serial Number is:
Month & Day 12/26 0c1ah
Sec & Hundrenths 41:94 295eh 3578:1d02
-----
3578h
High order word is calculated:
Hours & Minutes 21:55 1537h
Year 1995 07cbh
-----
1d02h
*/
static uint32_t get_volume_id ( )
{
/* TODO */
#if 0
SYSTEMTIME s;
uint32_t d;
uint16_t lo,hi,tmp;
GetLocalTime( &s );
lo = s.wDay + ( s.wMonth << 8 );
tmp = (s.wMilliseconds/10) + (s.wSecond << 8 );
lo += tmp;
hi = s.wMinute + ( s.wHour << 8 );
hi += s.wYear;
d = lo + (hi << 16);
return(d);
#endif
return(0);
}
/*
This is the Microsoft calculation from FATGEN
uint32_t RootDirSectors = 0;
uint32_t TmpVal1, TmpVal2, FATSz;
TmpVal1 = DskSize - ( ReservedSecCnt + RootDirSectors);
TmpVal2 = (256 * SecPerClus) + NumFATs;
TmpVal2 = TmpVal2 / 2;
FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
return( FatSz );
*/
static uint32_t get_fat_size_sectors(uint32_t DskSize, uint32_t ReservedSecCnt,
uint32_t SecPerClus, uint32_t NumFATs,
uint32_t BytesPerSect)
{
uint64_t Numerator, Denominator;
uint64_t FatElementSize = 4;
uint64_t FatSz;
/* This is based on
http://hjem.get2net.dk/rune_moeller_barnkob/filesystems/fat.html
I've made the obvious changes for FAT32
*/
Numerator = FatElementSize * ( DskSize - ReservedSecCnt );
Denominator = ( SecPerClus * BytesPerSect ) + ( FatElementSize * NumFATs );
FatSz = Numerator / Denominator;
/* round up */
FatSz += 1;
return((uint32_t)FatSz);
}
static uint8_t get_spc(uint32_t ClusterSizeKB, uint32_t BytesPerSect)
{
uint32_t spc = ( ClusterSizeKB * 1024 ) / BytesPerSect;
return( (uint8_t) spc );
}
static uint8_t get_sectors_per_cluster(uint32_t DiskSizeSectors,
uint32_t BytesPerSect)
{
uint8_t ret = 0x01; /* 1 sector per cluster */
uint64_t DiskSizeBytes = (uint64_t)DiskSizeSectors * (uint64_t)BytesPerSect;
int64_t DiskSizeMB = DiskSizeBytes / ( 1024*1024 );
/* 512 MB to 8,191 MB 4 KB */
if ( DiskSizeMB > 512 )
ret = get_spc( 4, BytesPerSect ); /* ret = 0x8; */
/* 8,192 MB to 16,383 MB 8 KB */
if ( DiskSizeMB > 8192 )
ret = get_spc( 8, BytesPerSect ); /* ret = 0x10; */
/* 16,384 MB to 32,767 MB 16 KB */
if ( DiskSizeMB > 16384 )
ret = get_spc( 16, BytesPerSect ); /* ret = 0x20; */
/* Larger than 32,768 MB 32 KB */
if ( DiskSizeMB > 32768 )
ret = get_spc( 32, BytesPerSect ); /* ret = 0x40; */
return( ret );
}
static void create_boot_sector(unsigned char* buf,
struct ipod_t* ipod, int partition)
{
struct FAT_BOOTSECTOR32* pFAT32BootSect = (struct FAT_BOOTSECTOR32*)buf;
/* fill out the boot sector and fs info */
pFAT32BootSect->sJmpBoot[0]=0xEB;
pFAT32BootSect->sJmpBoot[1]=0x5A;
pFAT32BootSect->sJmpBoot[2]=0x90;
memcpy(pFAT32BootSect->sOEMName, "MSWIN4.1", 8 );
pFAT32BootSect->wBytsPerSec = rb_htole16(BytesPerSect);
pFAT32BootSect->bSecPerClus = SectorsPerCluster ;
pFAT32BootSect->wRsvdSecCnt = rb_htole16(ReservedSectCount);
pFAT32BootSect->bNumFATs = NumFATs;
pFAT32BootSect->wRootEntCnt = rb_htole16(0);
pFAT32BootSect->wTotSec16 = rb_htole16(0);
pFAT32BootSect->bMedia = 0xF8;
pFAT32BootSect->wFATSz16 = rb_htole16(0);
pFAT32BootSect->wSecPerTrk = rb_htole16(ipod->sectors_per_track);
pFAT32BootSect->wNumHeads = rb_htole16(ipod->num_heads);
pFAT32BootSect->dHiddSec = rb_htole16(ipod->pinfo[partition].start);
pFAT32BootSect->dTotSec32 = rb_htole32(TotalSectors);
pFAT32BootSect->dFATSz32 = rb_htole32(FatSize);
pFAT32BootSect->wExtFlags = rb_htole16(0);
pFAT32BootSect->wFSVer = rb_htole16(0);
pFAT32BootSect->dRootClus = rb_htole32(2);
pFAT32BootSect->wFSInfo = rb_htole16(1);
pFAT32BootSect->wBkBootSec = rb_htole16(BackupBootSect);
pFAT32BootSect->bDrvNum = 0x80;
pFAT32BootSect->Reserved1 = 0;
pFAT32BootSect->bBootSig = 0x29;
pFAT32BootSect->dBS_VolID = rb_htole32(VolumeId);
memcpy(pFAT32BootSect->sVolLab, VolId, 11);
memcpy(pFAT32BootSect->sBS_FilSysType, "FAT32 ", 8 );
buf[510] = 0x55;
buf[511] = 0xaa;
}
static void create_fsinfo(unsigned char* buf)
{
struct FAT_FSINFO* pFAT32FsInfo = (struct FAT_FSINFO*)buf;
/* FSInfo sect */
pFAT32FsInfo->dLeadSig = rb_htole32(0x41615252);
pFAT32FsInfo->dStrucSig = rb_htole32(0x61417272);
pFAT32FsInfo->dFree_Count = rb_htole32((uint32_t) -1);
pFAT32FsInfo->dNxt_Free = rb_htole32((uint32_t) -1);
pFAT32FsInfo->dTrailSig = rb_htole32(0xaa550000);
pFAT32FsInfo->dFree_Count = rb_htole32((UserAreaSize/SectorsPerCluster)-1);
/* clusters 0-1 reserved, we used cluster 2 for the root dir */
pFAT32FsInfo->dNxt_Free = rb_htole32(3);
}
static void create_firstfatsector(unsigned char* buf)
{
uint32_t* p = (uint32_t*)buf; /* We know the buffer is aligned */
/* First FAT Sector */
p[0] = rb_htole32(0x0ffffff8); /* Reserved cluster 1 media id in low byte */
p[1] = rb_htole32(0x0fffffff); /* Reserved cluster 2 EOC */
p[2] = rb_htole32(0x0fffffff); /* end of cluster chain for root dir */
}
int format_partition(struct ipod_t* ipod, int partition)
{
uint32_t i;
uint64_t qTotalSectors=0;
uint64_t FatNeeded;
VolumeId = get_volume_id( );
/* Only support hard disks at the moment */
if ( ipod->sector_size != 512 )
{
fprintf(stderr,"[ERR] Only disks with 512 bytes per sector are supported.\n");
return -1;
}
BytesPerSect = ipod->sector_size;
/* Checks on Disk Size */
qTotalSectors = ipod->pinfo[partition].size;
/* low end limit - 65536 sectors */
if ( qTotalSectors < 65536 )
{
/* I suspect that most FAT32 implementations would mount this
volume just fine, but the spec says that we shouldn't do
this, so we won't */
fprintf(stderr,"[ERR] This drive is too small for FAT32 - there must be at least 64K clusters\n" );
return -1;
}
if ( qTotalSectors >= 0xffffffff )
{
/* This is a more fundamental limitation on FAT32 - the total
sector count in the root dir is 32bit. With a bit of
creativity, FAT32 could be extended to handle at least 2^28
clusters There would need to be an extra field in the
FSInfo sector, and the old sector count could be set to
0xffffffff. This is non standard though, the Windows FAT
driver FASTFAT.SYS won't understand this. Perhaps a future
version of FAT32 and FASTFAT will handle this. */
fprintf(stderr,"[ERR] This drive is too big for FAT32 - max 2TB supported\n");
}
if ( sectors_per_cluster ) {
SectorsPerCluster = sectors_per_cluster;
} else {
SectorsPerCluster = get_sectors_per_cluster(ipod->pinfo[partition].size,
BytesPerSect );
}
TotalSectors = (uint32_t) qTotalSectors;
FatSize = get_fat_size_sectors(TotalSectors, ReservedSectCount,
SectorsPerCluster, NumFATs, BytesPerSect );
UserAreaSize = TotalSectors - ReservedSectCount - (NumFATs*FatSize);
/* First zero out ReservedSect + FatSize * NumFats + SectorsPerCluster */
SystemAreaSize = (ReservedSectCount+(NumFATs*FatSize) + SectorsPerCluster);
/* Work out the Cluster count */
FatNeeded = UserAreaSize/SectorsPerCluster;
/* check for a cluster count of >2^28, since the upper 4 bits of
the cluster values in the FAT are reserved. */
if (FatNeeded > 0x0FFFFFFF) {
fprintf(stderr,"[ERR] This drive has more than 2^28 clusters, try to specify a larger cluster size\n" );
return -1;
}
/* Sanity check, make sure the fat is big enough.
Convert the cluster count into a Fat sector count, and check
the fat size value we calculated earlier is OK. */
FatNeeded *=4;
FatNeeded += (BytesPerSect-1);
FatNeeded /= BytesPerSect;
if ( FatNeeded > FatSize ) {
fprintf(stderr,"[ERR] Drive too big to format\n");
return -1;
}
/*
Write boot sector, fats
Sector 0 Boot Sector
Sector 1 FSInfo
Sector 2 More boot code - we write zeros here
Sector 3 unused
Sector 4 unused
Sector 5 unused
Sector 6 Backup boot sector
Sector 7 Backup FSInfo sector
Sector 8 Backup 'more boot code'
zero'd sectors upto ReservedSectCount
FAT1 ReservedSectCount to ReservedSectCount + FatSize
...
FATn ReservedSectCount to ReservedSectCount + FatSize
RootDir - allocated to cluster2
*/
fprintf(stderr,"[INFO] Heads - %d, sectors/track = %d\n",ipod->num_heads,ipod->sectors_per_track);
fprintf(stderr,"[INFO] Size : %" PRIu64 "GB %u sectors\n",
((uint64_t)ipod->pinfo[partition].size * (uint64_t)ipod->sector_size) / (1000*1000*1000), TotalSectors );
fprintf(stderr,"[INFO] %d Bytes Per Sector, Cluster size %d bytes\n", BytesPerSect, SectorsPerCluster*BytesPerSect );
fprintf(stderr,"[INFO] Volume ID is %x:%x\n", VolumeId>>16, VolumeId&0xffff );
fprintf(stderr,"[INFO] %d Reserved Sectors, %d Sectors per FAT, %d fats\n", ReservedSectCount, FatSize, NumFATs );
fprintf (stderr,"[INFO] %d Total clusters\n", UserAreaSize/SectorsPerCluster );
fprintf(stderr,"[INFO] Formatting partition %d:...\n",partition);
/* Once zero_sectors has run, any data on the drive is basically lost... */
fprintf(stderr,"[INFO] Clearing out %d sectors for Reserved sectors, fats and root cluster...\n", SystemAreaSize );
zero_sectors(ipod, ipod->pinfo[partition].start, SystemAreaSize);
fprintf(stderr,"[INFO] Initialising reserved sectors and FATs...\n" );
/* Create the boot sector structure */
create_boot_sector(ipod->sectorbuf, ipod, partition);
create_fsinfo(ipod->sectorbuf + 512);
/* Write boot sector and fsinfo at start of partition */
if (ipod_seek(ipod, ipod->pinfo[partition].start * ipod->sector_size) < 0) {
fprintf(stderr,"[ERR] Seek failed\n");
return -1;
}
if (ipod_write(ipod,512 * 2) < 0) {
perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n");
return -1;
}
/* Write backup copy of boot sector and fsinfo */
if (ipod_seek(ipod, (ipod->pinfo[partition].start + BackupBootSect) * ipod->sector_size) < 0) {
fprintf(stderr,"[ERR] Seek failed\n");
return -1;
}
if (ipod_write(ipod,512 * 2) < 0) {
perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n");
return -1;
}
/* Create the first FAT sector */
create_firstfatsector(ipod->sectorbuf);
/* Write the first fat sector in the right places */
for ( i=0; i<NumFATs; i++ ) {
int SectorStart = ReservedSectCount + (i * FatSize );
if (ipod_seek(ipod, (ipod->pinfo[partition].start + SectorStart) * ipod->sector_size) < 0) {
fprintf(stderr,"[ERR] Seek failed\n");
return -1;
}
if (ipod_write(ipod,512) < 0) {
perror("[ERR] Write failed (first copy of bootsect/fsinfo)\n");
return -1;
}
}
fprintf(stderr,"[INFO] Format successful\n");
return 0;
}

View file

@ -0,0 +1,409 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006-2007 Dave Chapman
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#if !defined(_WIN32) /* all non-Windows platforms are considered POSIX. */
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <errno.h>
#include "ipodio.h"
#if defined(linux) || defined (__linux)
#include <sys/mount.h>
#include <linux/hdreg.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/sg.h>
#define IPOD_SECTORSIZE_IOCTL BLKSSZGET
static void get_geometry(struct ipod_t* ipod)
{
struct hd_geometry geometry;
if (!ioctl(ipod->dh, HDIO_GETGEO, &geometry)) {
/* never use geometry.cylinders - it is truncated */
ipod->num_heads = geometry.heads;
ipod->sectors_per_track = geometry.sectors;
} else {
ipod->num_heads = 0;
ipod->sectors_per_track = 0;
}
}
/* Linux SCSI Inquiry code based on the documentation and example code from
http://www.ibm.com/developerworks/linux/library/l-scsi-api/index.html
*/
int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
unsigned char* buf, int bufsize)
{
unsigned char cdb[6];
struct sg_io_hdr hdr;
unsigned char sense_buffer[255];
memset(&hdr, 0, sizeof(hdr));
hdr.interface_id = 'S'; /* this is the only choice we have! */
hdr.flags = SG_FLAG_LUN_INHIBIT; /* this would put the LUN to 2nd byte of cdb*/
/* Set xfer data */
hdr.dxferp = buf;
hdr.dxfer_len = bufsize;
/* Set sense data */
hdr.sbp = sense_buffer;
hdr.mx_sb_len = sizeof(sense_buffer);
/* Set the cdb format */
cdb[0] = 0x12;
cdb[1] = 1; /* Enable Vital Product Data (EVPD) */
cdb[2] = page_code & 0xff;
cdb[3] = 0;
cdb[4] = 0xff;
cdb[5] = 0; /* For control filed, just use 0 */
hdr.dxfer_direction = SG_DXFER_FROM_DEV;
hdr.cmdp = cdb;
hdr.cmd_len = 6;
int ret = ioctl(ipod->dh, SG_IO, &hdr);
if (ret < 0) {
return -1;
} else {
return 0;
}
}
#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) \
|| defined(__bsdi__) || defined(__DragonFly__)
#include <sys/disk.h>
#define IPOD_SECTORSIZE_IOCTL DIOCGSECTORSIZE
/* TODO: Implement this function for BSD */
static void get_geometry(struct ipod_t* ipod)
{
/* Are these universal for all ipods? */
ipod->num_heads = 255;
ipod->sectors_per_track = 63;
}
int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
unsigned char* buf, int bufsize)
{
/* TODO: Implement for BSD */
(void)ipod;
(void)page_code;
(void)buf;
(void)bufsize;
return -1;
}
#elif defined(__APPLE__) && defined(__MACH__)
/* OS X IOKit includes don't like VERSION being defined! */
#undef VERSION
#include <sys/disk.h>
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/scsi/SCSITaskLib.h>
#include <IOKit/scsi/SCSICommandOperationCodes.h>
#define IPOD_SECTORSIZE_IOCTL DKIOCGETBLOCKSIZE
/* TODO: Implement this function for Mac OS X */
static void get_geometry(struct ipod_t* ipod)
{
/* Are these universal for all ipods? */
ipod->num_heads = 255;
ipod->sectors_per_track = 63;
}
int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
unsigned char* buf, int bufsize)
{
/* OS X doesn't allow to simply send out a SCSI inquiry request but
* requires registering an interface handler first.
* Currently this is done on each inquiry request which is somewhat
* inefficient but the current ipodpatcher API doesn't really fit here.
* Based on the documentation in Apple's document
* "SCSI Architecture Model Device Interface Guide".
*
* WARNING: this code currently doesn't take the selected device into
* account. It simply looks for an Ipod on the system and uses
* the first match.
*/
(void)ipod;
int result = 0;
/* first, create a dictionary to match the device. This is needed to get the
* service. */
CFMutableDictionaryRef match_dict;
match_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
if(match_dict == NULL)
return -1;
/* set value to match. In case of the Ipod this is "iPodUserClientDevice". */
CFMutableDictionaryRef sub_dict;
sub_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
if(sub_dict == NULL)
return -1;
CFDictionarySetValue(sub_dict, CFSTR(kIOPropertySCSITaskDeviceCategory),
CFSTR("iPodUserClientDevice"));
CFDictionarySetValue(match_dict, CFSTR(kIOPropertyMatchKey), sub_dict);
/* get an iterator for searching for the service. */
kern_return_t kr;
io_iterator_t iterator = IO_OBJECT_NULL;
/* get matching services from IO registry. Consumes one reference to
* the dictionary, so no need to release that. */
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, match_dict, &iterator);
if(!iterator | (kr != kIOReturnSuccess))
return -1;
/* get interface and obtain exclusive access */
SInt32 score;
HRESULT herr;
kern_return_t err;
IOCFPlugInInterface **plugin_interface = NULL;
SCSITaskDeviceInterface **interface = NULL;
io_service_t device = IO_OBJECT_NULL;
device = IOIteratorNext(iterator);
err = IOCreatePlugInInterfaceForService(device, kIOSCSITaskDeviceUserClientTypeID,
kIOCFPlugInInterfaceID, &plugin_interface,
&score);
if(err != noErr) {
return -1;
}
/* query the plugin interface for task interface */
herr = (*plugin_interface)->QueryInterface(plugin_interface,
CFUUIDGetUUIDBytes(kIOSCSITaskDeviceInterfaceID), (LPVOID*)&interface);
if(herr != S_OK) {
IODestroyPlugInInterface(plugin_interface);
return -1;
}
err = (*interface)->ObtainExclusiveAccess(interface);
if(err != noErr) {
(*interface)->Release(interface);
IODestroyPlugInInterface(plugin_interface);
return -1;
}
/* do the inquiry */
SCSITaskInterface **task = NULL;
task = (*interface)->CreateSCSITask(interface);
if(task != NULL) {
kern_return_t err;
SCSITaskStatus task_status;
IOVirtualRange* range;
SCSI_Sense_Data sense_data;
SCSICommandDescriptorBlock cdb;
UInt64 transfer_count = 0;
memset(buf, 0, bufsize);
/* allocate virtual range for buffer. */
range = (IOVirtualRange*) malloc(sizeof(IOVirtualRange));
memset(&sense_data, 0, sizeof(sense_data));
memset(cdb, 0, sizeof(cdb));
/* set up range. address is buffer address, length is request size. */
range->address = (IOVirtualAddress)buf;
range->length = bufsize;
/* setup CDB */
cdb[0] = 0x12; /* inquiry */
cdb[1] = 1;
cdb[2] = page_code;
cdb[4] = bufsize;
/* set cdb in task */
err = (*task)->SetCommandDescriptorBlock(task, cdb, kSCSICDBSize_6Byte);
if(err != kIOReturnSuccess) {
result = -1;
goto cleanup;
}
err = (*task)->SetScatterGatherEntries(task, range, 1, bufsize,
kSCSIDataTransfer_FromTargetToInitiator);
if(err != kIOReturnSuccess) {
result = -1;
goto cleanup;
}
/* set timeout */
err = (*task)->SetTimeoutDuration(task, 10000);
if(err != kIOReturnSuccess) {
result = -1;
goto cleanup;
}
/* request data */
err = (*task)->ExecuteTaskSync(task, &sense_data, &task_status, &transfer_count);
if(err != kIOReturnSuccess) {
result = -1;
goto cleanup;
}
/* cleanup */
free(range);
/* release task interface */
(*task)->Release(task);
}
else {
result = -1;
}
cleanup:
/* cleanup interface */
(*interface)->ReleaseExclusiveAccess(interface);
(*interface)->Release(interface);
IODestroyPlugInInterface(plugin_interface);
return result;
}
#else
#error No sector-size detection implemented for this platform
#endif
#if defined(__APPLE__) && defined(__MACH__)
static int ipod_unmount(struct ipod_t* ipod)
{
char cmd[4096];
int res;
sprintf(cmd, "/usr/sbin/diskutil unmount \"%ss2\"",ipod->diskname);
fprintf(stderr,"[INFO] ");
res = system(cmd);
if (res==0) {
return 0;
} else {
perror("Unmount failed");
return -1;
}
}
#endif
void ipod_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);
if(errno == EACCES) return -2;
else return -1;
}
/* Read information about the disk */
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);
}
}
get_geometry(ipod);
return 0;
}
int ipod_reopen_rw(struct ipod_t* ipod)
{
#if defined(__APPLE__) && defined(__MACH__)
if (ipod_unmount(ipod) < 0)
return -1;
#endif
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(struct ipod_t* ipod, int bufsize)
{
ipod->sectorbuf = malloc(bufsize);
if (ipod->sectorbuf== NULL) {
return -1;
}
return 0;
}
int ipod_dealloc_buffer(struct ipod_t* ipod)
{
if (ipod->sectorbuf == NULL) {
return -1;
}
free(ipod->sectorbuf);
ipod->sectorbuf = NULL;
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;
}
ssize_t ipod_read(struct ipod_t* ipod, int nbytes)
{
if(ipod->sectorbuf == NULL) {
return -1;
}
return read(ipod->dh, ipod->sectorbuf, nbytes);
}
ssize_t ipod_write(struct ipod_t* ipod, int nbytes)
{
if(ipod->sectorbuf == NULL) {
return -1;
}
return write(ipod->dh, ipod->sectorbuf, nbytes);
}
#endif

View file

@ -0,0 +1,147 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 Dave Chapman
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
*
* Based on the getCapsUsingSCSIPassThrough() function from "cddrv.cpp":
* - http://www.farmanager.com/svn/trunk/unicode_far/cddrv.cpp
*
* Copyright (c) 1996 Eugene Roshal
* Copyright (c) 2000 Far Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#if defined(_WIN32)
#include <windows.h>
#include <stddef.h>
#include <stdio.h>
#include "ipodio.h"
/* from ddk/ntddscsi.h */
#define SCSI_IOCTL_DATA_OUT 0
#define SCSI_IOCTL_DATA_IN 1
#define SCSI_IOCTL_DATA_UNSPECIFIED 2
#define IOCTL_SCSI_PASS_THROUGH \
CTL_CODE(FILE_DEVICE_CONTROLLER, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
typedef struct _SCSI_PASS_THROUGH {
USHORT Length;
UCHAR ScsiStatus;
UCHAR PathId;
UCHAR TargetId;
UCHAR Lun;
UCHAR CdbLength;
UCHAR SenseInfoLength;
UCHAR DataIn;
ULONG DataTransferLength;
ULONG TimeOutValue;
ULONG_PTR DataBufferOffset;
ULONG SenseInfoOffset;
UCHAR Cdb[16];
} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;
typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS {
SCSI_PASS_THROUGH Spt;
ULONG Filler; /* realign buffers to double word boundary */
UCHAR SenseBuf[32];
UCHAR DataBuf[512];
} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;
int ipod_scsi_inquiry(struct ipod_t* ipod, int page_code,
unsigned char* buf, int bufsize)
{
SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
ULONG length;
DWORD returned;
BOOL status;
if (bufsize > 255) {
fprintf(stderr,"[ERR] Invalid bufsize in ipod_scsi_inquiry\n");
return -1;
}
memset(&sptwb, 0, sizeof(sptwb));
sptwb.Spt.Length = sizeof(SCSI_PASS_THROUGH);
sptwb.Spt.PathId = 0;
sptwb.Spt.TargetId = 1;
sptwb.Spt.Lun = 0;
sptwb.Spt.CdbLength = 6;
sptwb.Spt.SenseInfoLength = 32; /* sbuf size */;
sptwb.Spt.DataIn = SCSI_IOCTL_DATA_IN;
sptwb.Spt.DataTransferLength = bufsize;
sptwb.Spt.TimeOutValue = 2; /* 2 seconds */
sptwb.Spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf);
sptwb.Spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, SenseBuf);
length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, DataBuf) +
sptwb.Spt.DataTransferLength;
/* Set cdb info */
sptwb.Spt.Cdb[0] = 0x12; /* SCSI Inquiry */
sptwb.Spt.Cdb[1] = 1;
sptwb.Spt.Cdb[2] = page_code;
sptwb.Spt.Cdb[3] = 0;
sptwb.Spt.Cdb[4] = bufsize;
sptwb.Spt.Cdb[5] = 0;
status = DeviceIoControl(ipod->dh,
IOCTL_SCSI_PASS_THROUGH,
&sptwb,
sizeof(SCSI_PASS_THROUGH),
&sptwb,
length,
&returned,
FALSE);
if (status) {
/* W32 sometimes returns more bytes with additional garbage.
* Make sure to not copy that garbage. */
memcpy(buf, sptwb.DataBuf,
(DWORD)bufsize >= returned ? returned : (DWORD)bufsize);
return 0;
} else {
return -1;
}
}
#endif

View file

@ -0,0 +1,226 @@
/***************************************************************************
* __________ __ ___.
* 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/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#if defined(_WIN32)
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <windows.h>
#include <stddef.h>
#include <winioctl.h>
#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 ipod_print_error(char* msg)
{
LPSTR pMsgBuf = NULL;
printf(msg);
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 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 = CreateFileA(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) ipod_print_error(" Error opening disk: ");
if(GetLastError() == ERROR_ACCESS_DENIED)
return -2;
else
return -1;
}
if (!lock_volume(ipod->dh)) {
if (!silent) ipod_print_error(" Error locking disk: ");
return -1;
}
/* Defaults */
ipod->num_heads = 0;
ipod->sectors_per_track = 0;
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) ipod_print_error(" Error reading disk geometry: ");
return -1;
} else {
ipod->sector_size = diskgeometry.BytesPerSector;
ipod->num_heads = diskgeometry.TracksPerCylinder;
ipod->sectors_per_track = diskgeometry.SectorsPerTrack;
}
} else {
ipod->sector_size = diskgeometry_ex.Geometry.BytesPerSector;
ipod->num_heads = diskgeometry_ex.Geometry.TracksPerCylinder;
ipod->sectors_per_track = diskgeometry_ex.Geometry.SectorsPerTrack;
}
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 = CreateFileA(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) {
ipod_print_error(" Error opening disk: ");
return -1;
}
if (!lock_volume(ipod->dh)) {
ipod_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(struct ipod_t* ipod, int bufsize)
{
/* The ReadFile function requires a memory buffer aligned to a multiple of
the disk sector size. */
ipod->sectorbuf = (unsigned char*)VirtualAlloc(NULL, bufsize, MEM_COMMIT, PAGE_READWRITE);
if (ipod->sectorbuf== NULL) {
ipod_print_error(" Error allocating a buffer: ");
return -1;
}
return 0;
}
int ipod_dealloc_buffer(struct ipod_t* ipod)
{
if (ipod->sectorbuf == NULL) {
return -1;
}
if(!VirtualFree(ipod->sectorbuf, 0, MEM_RELEASE)) {
ipod_print_error(" Error releasing buffer ");
return -1;
}
ipod->sectorbuf = NULL;
return 0;
}
int ipod_seek(struct ipod_t* ipod, unsigned long pos)
{
if (SetFilePointer(ipod->dh, pos, NULL, FILE_BEGIN)==0xffffffff) {
ipod_print_error(" Seek error ");
return -1;
}
return 0;
}
ssize_t ipod_read(struct ipod_t* ipod, int nbytes)
{
unsigned long count;
if(ipod->sectorbuf == NULL) {
return -1;
}
if (!ReadFile(ipod->dh, ipod->sectorbuf, nbytes, &count, NULL)) {
ipod_print_error(" Error reading from disk: ");
return -1;
}
return count;
}
ssize_t ipod_write(struct ipod_t* ipod, int nbytes)
{
unsigned long count;
if(ipod->sectorbuf == NULL) {
return -1;
}
if (!WriteFile(ipod->dh, ipod->sectorbuf, nbytes, &count, NULL)) {
ipod_print_error(" Error writing to disk: ");
return -1;
}
return count;
}
#endif

115
utils/ipodpatcher/ipodio.h Normal file
View file

@ -0,0 +1,115 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006-2007 Dave Chapman
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* 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 <stdint.h>
#if !defined(_WIN32)
#include <unistd.h>
#elif defined(_MSC_VER)
/* MSVC uses a different name for ssize_t */
#define ssize_t SSIZE_T
#endif
#if defined(__WIN32__) || defined(_WIN32)
#include <windows.h>
#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,
FTYPE_OSBK
};
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;
};
/* A fake partition type - DOS partition tables can't include HFS partitions */
#define PARTTYPE_HFS 0xffff
struct partinfo_t {
uint32_t start; /* first sector (LBA) */
uint32_t size; /* number of sectors */
uint32_t type;
};
struct ipod_t {
unsigned char* sectorbuf;
HANDLE dh;
char diskname[4096];
int sector_size;
int sectors_per_track;
int num_heads;
struct ipod_directory_t ipod_directory[MAX_IMAGES];
int nimages;
int ososimage;
off_t diroffset;
off_t start; /* Offset in bytes of firmware partition from start of disk */
off_t fwoffset; /* Offset in bytes of start of firmware images from start of disk */
struct partinfo_t pinfo[4];
int modelnum;
char* modelname;
char* modelstr;
char* targetname;
int macpod;
char* xmlinfo; /* The XML Device Information (if available) */
int xmlinfo_len;
int ramsize; /* The amount of RAM in the ipod (if available) */
#ifdef WITH_BOOTOBJS
unsigned char* bootloader;
int bootloader_len;
#endif
};
void ipod_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_scsi_inquiry(struct ipod_t* ipod, int page_code,
unsigned char* buf, int bufsize);
ssize_t ipod_read(struct ipod_t* ipod, int nbytes);
ssize_t ipod_write(struct ipod_t* ipod, int nbytes);
int ipod_alloc_buffer(struct ipod_t* ipod, int bufsize);
int ipod_dealloc_buffer(struct ipod_t* ipod);
/* In fat32format.c */
int format_partition(struct ipod_t* ipod, int partition);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,84 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006-2007 Dave Chapman
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef IPODPATCHER_H
#define IPODPATCHER_H
#ifdef __cplusplus
extern "C" {
#endif
#include "ipodio.h"
/* exit codes */
#define IPOD_OK 0
#define IPOD_WRONG_ARGUMENTS 1
#define IPOD_OPEN_INFILE_FAILED 2
#define IPOD_PARTITION_ERROR 3
#define IPOD_OPEN_OUTFILE_FAILED 4
#define IPOD_CANNOT_REOPEN 5
#define IPOD_ACCESS_DENIED 10
#define IPOD_NOT_FOUND 11
#define IPOD_WRONG_DEVICE_COUNT 12
#define IPOD_IMAGE_ERROR 13
#define IPOD_DUMP_FAILED 14
#define IPOD_MULTIPLE_DEVICES 15
#define IPOD_WRONG_TYPE 16
#define IPOD_UNKNOWN_FW_VERSION -1
/* 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 int ipod_verbose;
#define FILETYPE_DOT_IPOD 0
#define FILETYPE_DOT_BIN 1
#ifdef WITH_BOOTOBJS
#define FILETYPE_INTERNAL 2
#endif
char* get_parttype(unsigned int pt);
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 type);
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);
int write_dos_partition_table(struct ipod_t* ipod);
int ipod_get_xmlinfo(struct ipod_t* ipod);
void ipod_get_ramsize(struct ipod_t* ipod);
int read_aupd(struct ipod_t* ipod, char* filename);
int write_aupd(struct ipod_t* ipod, char* filename);
off_t filesize(int fd);
int ipod_has_bootloader(struct ipod_t* ipod);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="X86" name="ipodpatcher.exe" type="win32"/>
<!-- Identify the application security requirements. -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View file

@ -0,0 +1,47 @@
#
# __________ __ ___.
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
# \/ \/ \/ \/ \/
#
# 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.
#
TEMPLATE = app
TARGET = ipodpatcher
QT -= core
SOURCES += \
main.c \
ipodpatcher.c \
ipodio-posix.c \
ipodio-win32-scsi.c \
ipodio-win32.c \
fat32format.c \
arc4.c \
HEADERS += \
arc4.h \
ipodio.h \
ipodpatcher.h \
parttypes.h \
DEFINES += RELEASE=1 _LARGEFILE64_SOURCE
RC_FILE = ipodpatcher.rc
macx {
LIBS += -framework CoreFoundation -framework IOKit
}
unix {
target.path = /usr/local/bin
INSTALLS += target
}

View file

@ -0,0 +1 @@
1 24 MOVEABLE PURE "ipodpatcher.manifest"

622
utils/ipodpatcher/main.c Normal file
View file

@ -0,0 +1,622 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2006-2007 Dave Chapman
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "ipodpatcher.h"
#include "ipodio.h"
#ifdef RELEASE
#undef VERSION
#define VERSION "5.0 with v4.0 bootloaders (v1.0 for 2nd Gen Nano)"
#endif
enum {
NONE,
#ifdef WITH_BOOTOBJS
INSTALL,
#endif
INTERACTIVE,
SHOW_INFO,
LIST_IMAGES,
DELETE_BOOTLOADER,
ADD_BOOTLOADER,
READ_FIRMWARE,
WRITE_FIRMWARE,
READ_AUPD,
WRITE_AUPD,
READ_PARTITION,
WRITE_PARTITION,
FORMAT_PARTITION,
DUMP_XML,
CONVERT_TO_FAT32
};
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/wiki/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[x]\n");
fprintf(stderr," -rfb, --read-firmware-bin filename.bin\n");
fprintf(stderr," -wf, --write-firmware filename.ipod[x]\n");
fprintf(stderr," -wfb, --write-firmware-bin filename.bin\n");
#ifdef WITH_BOOTOBJS
fprintf(stderr," -we, --write-embedded\n");
#endif
fprintf(stderr," -a, --add-bootloader filename.ipod[x]\n");
fprintf(stderr," -ab, --add-bootloader-bin filename.bin\n");
fprintf(stderr," -d, --delete-bootloader\n");
fprintf(stderr," -f, --format\n");
fprintf(stderr," -c, --convert\n");
fprintf(stderr," --read-aupd filename.bin\n");
fprintf(stderr," --write-aupd filename.bin\n");
fprintf(stderr," -x --dump-xml filename.xml\n");
fprintf(stderr,"\n");
fprintf(stderr,"The .ipodx extension is used for encrypted images for the 2nd Gen Nano.\n\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
}
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,
(long int)ipod->pinfo[i].start,
(long int)ipod->pinfo[i].start+ipod->pinfo[i].size-1,
ipod->pinfo[i].size/sectors_per_MB,
get_parttype(ipod->pinfo[i].type),
(int)ipod->pinfo[i].type);
}
}
}
int main(int argc, char* argv[])
{
char yesno[4];
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 " VERSION "\n");
fprintf(stderr,"(C) Dave Chapman 2006-2009\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 IPOD_OK;
}
if (ipod_alloc_buffer(&ipod,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 IPOD_NOT_FOUND;
}
/* 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");
return IPOD_MULTIPLE_DEVICES;
} else if (n == 1 && ipod.macpod) {
return IPOD_WRONG_TYPE;
}
if (n != 1) {
#ifdef WITH_BOOTOBJS
if (argc==1) {
printf("\nPress ENTER to exit ipodpatcher :");
fgets(yesno,4,stdin);
}
#endif
return IPOD_NOT_FOUND;
}
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 IPOD_WRONG_ARGUMENTS; }
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 IPOD_WRONG_ARGUMENTS; }
filename=argv[i];
i++;
} else if ((strcmp(argv[i],"-rf")==0) ||
(strcmp(argv[i],"--read-firmware")==0)) {
action = READ_FIRMWARE;
type = FILETYPE_DOT_IPOD;
i++;
if (i == argc) { print_usage(); return IPOD_WRONG_ARGUMENTS; }
filename=argv[i];
i++;
} else if ((strcmp(argv[i],"-rfb")==0) ||
(strcmp(argv[i],"--read-firmware-bin")==0)) {
action = READ_FIRMWARE;
type = FILETYPE_DOT_BIN;
i++;
if (i == argc) { print_usage(); return IPOD_WRONG_ARGUMENTS; }
filename=argv[i];
i++;
#ifdef WITH_BOOTOBJS
} else if ((strcmp(argv[i],"-we")==0) ||
(strcmp(argv[i],"--write-embedded")==0)) {
action = WRITE_FIRMWARE;
type = FILETYPE_INTERNAL;
filename="[embedded bootloader]"; /* Only displayed for user */
i++;
#endif
} 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 IPOD_WRONG_ARGUMENTS; }
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 IPOD_WRONG_ARGUMENTS; }
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 IPOD_WRONG_ARGUMENTS; }
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 IPOD_WRONG_ARGUMENTS; }
filename=argv[i];
i++;
} else if ((strcmp(argv[i],"-v")==0) ||
(strcmp(argv[i],"--verbose")==0)) {
ipod_verbose++;
i++;
} else if ((strcmp(argv[i],"-f")==0) ||
(strcmp(argv[i],"--format")==0)) {
action = FORMAT_PARTITION;
i++;
} else if (strcmp(argv[i],"--read-aupd")==0) {
action = READ_AUPD;
i++;
if (i == argc) { print_usage(); return IPOD_WRONG_ARGUMENTS; }
filename=argv[i];
i++;
} else if (strcmp(argv[i],"--write-aupd")==0) {
action = WRITE_AUPD;
i++;
if (i == argc) { print_usage(); return IPOD_WRONG_ARGUMENTS; }
filename=argv[i];
i++;
} else if ((strcmp(argv[i],"-x")==0) ||
(strcmp(argv[i],"--dump-xml")==0)) {
action = DUMP_XML;
i++;
if (i == argc) { print_usage(); return IPOD_WRONG_ARGUMENTS; }
filename=argv[i];
i++;
} else if ((strcmp(argv[i],"-c")==0) ||
(strcmp(argv[i],"--convert")==0)) {
action = CONVERT_TO_FAT32;
i++;
} else {
print_usage(); return IPOD_WRONG_ARGUMENTS;
}
}
if (ipod.diskname[0]==0) {
print_usage();
return 1;
}
if (ipod_open(&ipod, 0) < 0) {
return IPOD_ACCESS_DENIED;
}
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 IPOD_PARTITION_ERROR;
}
display_partinfo(&ipod);
if (ipod.pinfo[0].start==0) {
fprintf(stderr,"[ERR] No partition 0 on disk:\n");
display_partinfo(&ipod);
return IPOD_PARTITION_ERROR;
}
read_directory(&ipod);
if (ipod.nimages <= 0) {
fprintf(stderr,"[ERR] Failed to read firmware directory - nimages=%d\n",ipod.nimages);
return IPOD_IMAGE_ERROR;
}
if (getmodel(&ipod,(ipod.ipod_directory[ipod.ososimage].vers>>8)) < 0) {
fprintf(stderr,"[ERR] Unknown version number in firmware (%08x)\n",
ipod.ipod_directory[ipod.ososimage].vers);
return IPOD_UNKNOWN_FW_VERSION;
}
#ifdef __WIN32__
/* Windows requires the ipod in R/W mode for SCSI Inquiry */
if (ipod_reopen_rw(&ipod) < 0) {
return IPOD_CANNOT_REOPEN;
}
#endif
/* Read the XML info, and if successful, look for the ramsize
(only available for some models - set to 0 if not known) */
ipod.ramsize = 0;
if (ipod_get_xmlinfo(&ipod) == 0) {
ipod_get_ramsize(&ipod);
}
printf("[INFO] Ipod model: %s ",ipod.modelstr);
if (ipod.ramsize > 0) { printf("(%dMB RAM) ",ipod.ramsize); }
printf("(\"%s\")\n",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("Enter i to install the Rockbox bootloader, u to uninstall\n or c to cancel and do nothing (i/u/c) :");
if (fgets(yesno,4,stdin)) {
if (yesno[0]=='i') {
if (ipod_reopen_rw(&ipod) < 0) {
return IPOD_CANNOT_REOPEN;
}
if (add_bootloader(&ipod, NULL, FILETYPE_INTERNAL)==0) {
fprintf(stderr,"[INFO] Bootloader installed successfully.\n");
} else {
fprintf(stderr,"[ERR] --install failed.\n");
}
} else if (yesno[0]=='u') {
if (ipod_reopen_rw(&ipod) < 0) {
return IPOD_CANNOT_REOPEN;
}
if (delete_bootloader(&ipod)==0) {
fprintf(stderr,"[INFO] Bootloader removed.\n");
} else {
fprintf(stderr,"[ERR] Bootloader removal failed.\n");
}
}
}
#endif
} else if (action==DELETE_BOOTLOADER) {
if (ipod_reopen_rw(&ipod) < 0) {
return IPOD_CANNOT_REOPEN;
}
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 IPOD_CANNOT_REOPEN;
}
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 IPOD_CANNOT_REOPEN;
}
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 IPOD_CANNOT_REOPEN;
}
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, type)==0) {
fprintf(stderr,"[INFO] Firmware read to file %s.\n",filename);
} else {
fprintf(stderr,"[ERR] --read-firmware failed.\n");
}
} else if (action==READ_AUPD) {
if (read_aupd(&ipod, filename)==0) {
fprintf(stderr,"[INFO] AUPD image read to file %s.\n",filename);
} else {
fprintf(stderr,"[ERR] --read-aupd failed.\n");
}
} else if (action==WRITE_AUPD) {
if (ipod_reopen_rw(&ipod) < 0) {
return IPOD_CANNOT_REOPEN;
}
if (write_aupd(&ipod, filename)==0) {
fprintf(stderr,"[INFO] AUPD image %s written to device.\n",filename);
} else {
fprintf(stderr,"[ERR] --write-aupd failed.\n");
}
} else if (action==DUMP_XML) {
if (ipod.xmlinfo == NULL) {
fprintf(stderr,"[ERR] No XML to write\n");
return IPOD_DUMP_FAILED;
}
outfile = open(filename,O_CREAT|O_TRUNC|O_WRONLY|O_BINARY,S_IREAD|S_IWRITE);
if (outfile < 0) {
perror(filename);
return IPOD_OPEN_OUTFILE_FAILED;
}
if (write(outfile, ipod.xmlinfo, ipod.xmlinfo_len) < 0) {
fprintf(stderr,"[ERR] --dump-xml failed.\n");
} else {
fprintf(stderr,"[INFO] XML info written to %s.\n",filename);
}
close(outfile);
} 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 IPOD_OPEN_OUTFILE_FAILED;
}
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 IPOD_CANNOT_REOPEN;
}
infile = open(filename,O_RDONLY|O_BINARY);
if (infile < 0) {
perror(filename);
return IPOD_OPEN_INFILE_FAILED;
}
/* 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);
} else if (action==FORMAT_PARTITION) {
printf("WARNING!!! YOU ARE ABOUT TO USE AN EXPERIMENTAL FEATURE.\n");
printf("ALL DATA ON YOUR IPOD WILL BE ERASED.\n");
printf("Are you sure you want to format your ipod? (y/n):");
if (fgets(yesno,4,stdin)) {
if (yesno[0]=='y') {
if (ipod_reopen_rw(&ipod) < 0) {
return IPOD_CANNOT_REOPEN;
}
if (format_partition(&ipod,1) < 0) {
fprintf(stderr,"[ERR] Format failed.\n");
}
} else {
fprintf(stderr,"[INFO] Format cancelled.\n");
}
}
} else if (action==CONVERT_TO_FAT32) {
if (!ipod.macpod) {
printf("[ERR] Ipod is already FAT32, aborting\n");
} else {
printf("WARNING!!! YOU ARE ABOUT TO USE AN EXPERIMENTAL FEATURE.\n");
printf("ALL DATA ON YOUR IPOD WILL BE ERASED.\n");
printf("Are you sure you want to convert your ipod to FAT32? (y/n):");
if (fgets(yesno,4,stdin)) {
if (yesno[0]=='y') {
if (ipod_reopen_rw(&ipod) < 0) {
return IPOD_CANNOT_REOPEN;
}
if (write_dos_partition_table(&ipod) < 0) {
fprintf(stderr,"[ERR] Partition conversion failed.\n");
}
if (format_partition(&ipod,1) < 0) {
fprintf(stderr,"[ERR] Format failed.\n");
}
} else {
fprintf(stderr,"[INFO] Format cancelled.\n");
}
}
}
}
ipod_close(&ipod);
#ifdef WITH_BOOTOBJS
if (action==INTERACTIVE) {
printf("Press ENTER to exit ipodpatcher :");
fgets(yesno,4,stdin);
}
#endif
ipod_dealloc_buffer(&ipod);
return IPOD_OK;
}

View file

@ -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 }
};