mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-04-12 00:47:49 -04:00
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:
parent
6c6f0757d7
commit
c876d3bbef
494 changed files with 13 additions and 13 deletions
53
utils/ipodpatcher/Makefile
Normal file
53
utils/ipodpatcher/Makefile
Normal 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
108
utils/ipodpatcher/arc4.c
Normal 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
47
utils/ipodpatcher/arc4.h
Normal 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
|
||||
530
utils/ipodpatcher/fat32format.c
Normal file
530
utils/ipodpatcher/fat32format.c
Normal 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;
|
||||
}
|
||||
409
utils/ipodpatcher/ipodio-posix.c
Normal file
409
utils/ipodpatcher/ipodio-posix.c
Normal 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
|
||||
|
||||
147
utils/ipodpatcher/ipodio-win32-scsi.c
Normal file
147
utils/ipodpatcher/ipodio-win32-scsi.c
Normal 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
|
||||
|
||||
226
utils/ipodpatcher/ipodio-win32.c
Normal file
226
utils/ipodpatcher/ipodio-win32.c
Normal 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
115
utils/ipodpatcher/ipodio.h
Normal 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
|
||||
2350
utils/ipodpatcher/ipodpatcher.c
Normal file
2350
utils/ipodpatcher/ipodpatcher.c
Normal file
File diff suppressed because it is too large
Load diff
84
utils/ipodpatcher/ipodpatcher.h
Normal file
84
utils/ipodpatcher/ipodpatcher.h
Normal 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
|
||||
|
||||
13
utils/ipodpatcher/ipodpatcher.manifest
Normal file
13
utils/ipodpatcher/ipodpatcher.manifest
Normal 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>
|
||||
47
utils/ipodpatcher/ipodpatcher.pro
Normal file
47
utils/ipodpatcher/ipodpatcher.pro
Normal 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
|
||||
}
|
||||
1
utils/ipodpatcher/ipodpatcher.rc
Normal file
1
utils/ipodpatcher/ipodpatcher.rc
Normal file
|
|
@ -0,0 +1 @@
|
|||
1 24 MOVEABLE PURE "ipodpatcher.manifest"
|
||||
622
utils/ipodpatcher/main.c
Normal file
622
utils/ipodpatcher/main.c
Normal 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;
|
||||
}
|
||||
109
utils/ipodpatcher/parttypes.h
Normal file
109
utils/ipodpatcher/parttypes.h
Normal 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 }
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue