sansapatcher: move sectorbuf pointer into sansa_t structure.

Similar as the ipod_t structure for ipodpatcher the sansa_t structure holds all
relevant information for sansapatcher. Put the global sansa_sectorbuf pointer
into it as well.

Change-Id: Iad08ef6aafc49609c3d0d556914246f230ee0179
This commit is contained in:
Dominik Riebeling 2012-12-23 23:36:00 +01:00
parent 24e37ddf57
commit 9c1ed84d28
9 changed files with 77 additions and 97 deletions

View file

@ -167,9 +167,8 @@ bool Autodetection::detect()
// try sansapatcher
// initialize sector buffer. Needed.
sansa_sectorbuf = NULL;
sansa_alloc_buffer(&sansa_sectorbuf, BUFFER_SIZE);
struct sansa_t sansa;
sansa_alloc_buffer(&sansa, BUFFER_SIZE);
n = sansa_scan(&sansa);
if(n == 1) {
qDebug() << "[Autodetect] Sansa found:" << sansa.targetname << "at" << sansa.diskname;
@ -187,8 +186,8 @@ bool Autodetection::detect()
else {
qDebug() << "[Autodetect] sansapatcher: no Sansa found." << n;
}
free(sansa_sectorbuf);
sansa_sectorbuf = NULL;
free(sansa.sectorbuf);
sansa.sectorbuf = NULL;
if(m_mountpoint.isEmpty() && m_device.isEmpty()
&& m_errdev.isEmpty() && m_incompat.isEmpty())

View file

@ -27,22 +27,17 @@ BootloaderInstallSansa::BootloaderInstallSansa(QObject *parent)
: BootloaderInstallBase(parent)
{
(void)parent;
// initialize sector buffer. sansa_sectorbuf is instantiated by
// sansapatcher.
// The buffer itself is only present once, so make sure to not allocate
// it if it was already allocated. The application needs to take care
// no concurrent (i.e. multiple objects of this class running) requests
// are done.
if(sansa_sectorbuf == NULL)
sansa_alloc_buffer(&sansa_sectorbuf, BUFFER_SIZE);
// initialize sector buffer. The sector buffer is part of the sansa_t
// structure, so a second instance of this class will have its own buffer.
sansa_alloc_buffer(&sansa, BUFFER_SIZE);
}
BootloaderInstallSansa::~BootloaderInstallSansa()
{
if(sansa_sectorbuf) {
free(sansa_sectorbuf);
sansa_sectorbuf = NULL;
if(sansa.sectorbuf) {
free(sansa.sectorbuf);
sansa.sectorbuf = NULL;
}
}
@ -51,7 +46,7 @@ BootloaderInstallSansa::~BootloaderInstallSansa()
*/
bool BootloaderInstallSansa::install(void)
{
if(sansa_sectorbuf == NULL) {
if(sansa.sectorbuf == NULL) {
emit logItem(tr("Error: can't allocate buffer memory!"), LOGERROR);
return false;
emit done(true);
@ -59,8 +54,6 @@ bool BootloaderInstallSansa::install(void)
emit logItem(tr("Searching for Sansa"), LOGINFO);
struct sansa_t sansa;
int n = sansa_scan(&sansa);
if(n == -1) {
emit logItem(tr("Permission for disc access denied!\n"
@ -95,7 +88,6 @@ bool BootloaderInstallSansa::install(void)
*/
void BootloaderInstallSansa::installStage2(void)
{
struct sansa_t sansa;
unsigned char* buf = NULL;
unsigned int len;
@ -174,8 +166,6 @@ void BootloaderInstallSansa::installStage3(bool mounted)
*/
bool BootloaderInstallSansa::uninstall(void)
{
struct sansa_t sansa;
emit logItem(tr("Uninstalling bootloader"), LOGINFO);
QCoreApplication::processEvents();
@ -222,7 +212,6 @@ bool BootloaderInstallSansa::uninstall(void)
*/
BootloaderInstallBase::BootloaderType BootloaderInstallSansa::installed(void)
{
struct sansa_t sansa;
int num;
if(!sansaInitialize(&sansa)) {

View file

@ -21,6 +21,7 @@
#include <QtCore>
#include "bootloaderinstallbase.h"
#include "sansapatcher.h"
// bootloader installation class for devices handled by sansapatcher.
@ -38,6 +39,7 @@ class BootloaderInstallSansa : public BootloaderInstallBase
private:
bool sansaInitialize(struct sansa_t *);
struct sansa_t sansa;
private slots:
void installStage2(void);

View file

@ -155,7 +155,7 @@ int main(int argc, char* argv[])
return 1;
}
if (sansa_alloc_buffer(&sansa_sectorbuf,BUFFER_SIZE) < 0) {
if (sansa_alloc_buffer(&sansa, BUFFER_SIZE) < 0) {
fprintf(stderr,"Failed to allocate memory buffer\n");
}

View file

@ -113,10 +113,10 @@ int sansa_close(struct sansa_t* sansa)
return 0;
}
int sansa_alloc_buffer(unsigned char** sectorbuf, int bufsize)
int sansa_alloc_buffer(struct sansa_t *sansa, int bufsize)
{
*sectorbuf=malloc(bufsize);
if (*sectorbuf == NULL) {
sansa->sectorbuf=malloc(bufsize);
if (sansa->sectorbuf == NULL) {
return -1;
}
return 0;
@ -139,9 +139,9 @@ int sansa_read(struct sansa_t* sansa, unsigned char* buf, int nbytes)
return read(sansa->dh, buf, nbytes);
}
int sansa_write(struct sansa_t* sansa, unsigned char* buf, int nbytes)
int sansa_write(struct sansa_t* sansa, int nbytes)
{
return write(sansa->dh, buf, nbytes);
return write(sansa->dh, sansa->sectorbuf, nbytes);
}
#endif

View file

@ -150,12 +150,12 @@ int sansa_close(struct sansa_t* sansa)
return 0;
}
int sansa_alloc_buffer(unsigned char** sectorbuf, int bufsize)
int sansa_alloc_buffer(struct sansa_t* sansa, int bufsize)
{
/* The ReadFile function requires a memory buffer aligned to a multiple of
the disk sector size. */
*sectorbuf = (unsigned char*)VirtualAlloc(NULL, bufsize, MEM_COMMIT, PAGE_READWRITE);
if (*sectorbuf == NULL) {
sansa->sectorbuf = (unsigned char*)VirtualAlloc(NULL, bufsize, MEM_COMMIT, PAGE_READWRITE);
if (sansa->sectorbuf == NULL) {
sansa_print_error(" Error allocating a buffer: ");
return -1;
}
@ -189,11 +189,11 @@ int sansa_read(struct sansa_t* sansa, unsigned char* buf, int nbytes)
return count;
}
int sansa_write(struct sansa_t* sansa, unsigned char* buf, int nbytes)
int sansa_write(struct sansa_t* sansa, int nbytes)
{
unsigned long count;
if (!WriteFile(sansa->dh, buf, nbytes, &count, NULL)) {
if (!WriteFile(sansa->dh, sansa->sectorbuf, nbytes, &count, NULL)) {
sansa_print_error(" Error writing to disk: ");
return -1;
}

View file

@ -63,6 +63,7 @@ struct mi4header_t {
struct sansa_t {
HANDLE dh;
unsigned char* sectorbuf;
char diskname[4096];
int sector_size;
struct sansa_partinfo_t pinfo[4];
@ -77,8 +78,8 @@ int sansa_reopen_rw(struct sansa_t* sansa);
int sansa_close(struct sansa_t* sansa);
int sansa_seek(struct sansa_t* sansa, loff_t pos);
int sansa_read(struct sansa_t* sansa, unsigned char* buf, int nbytes);
int sansa_write(struct sansa_t* sansa, unsigned char* buf, int nbytes);
int sansa_alloc_buffer(unsigned char** sectorbuf, int bufsize);
int sansa_write(struct sansa_t* sansa, int nbytes);
int sansa_alloc_buffer(struct sansa_t* sansa, int bufsize);
#ifdef __cplusplus
}

View file

@ -43,8 +43,6 @@ int sansa_verbose = 0;
and initialise it with sansa_alloc_buf() in main().
*/
unsigned char* sansa_sectorbuf = NULL;
static off_t filesize(int fd) {
struct stat buf;
@ -92,17 +90,17 @@ int sansa_read_partinfo(struct sansa_t* sansa, int silent)
int i;
unsigned long count;
count = sansa_read(sansa,sansa_sectorbuf, sansa->sector_size);
count = sansa_read(sansa,sansa->sectorbuf, sansa->sector_size);
if (count <= 0) {
sansa_print_error(" Error reading from disk: ");
return -1;
}
if ((sansa_sectorbuf[510] == 0x55) && (sansa_sectorbuf[511] == 0xaa)) {
if ((sansa->sectorbuf[510] == 0x55) && (sansa->sectorbuf[511] == 0xaa)) {
/* parse partitions */
for ( i = 0; i < 4; i++ ) {
unsigned char* ptr = sansa_sectorbuf + 0x1be + 16*i;
unsigned char* ptr = sansa->sectorbuf + 0x1be + 16*i;
sansa->pinfo[i].type = ptr[4];
sansa->pinfo[i].start = BYTES2INT32(ptr, 8);
sansa->pinfo[i].size = BYTES2INT32(ptr, 12);
@ -112,7 +110,7 @@ int sansa_read_partinfo(struct sansa_t* sansa, int silent)
/* not handled yet */
}
}
} else if ((sansa_sectorbuf[0] == 'E') && (sansa_sectorbuf[1] == 'R')) {
} else if ((sansa->sectorbuf[0] == 'E') && (sansa->sectorbuf[1] == 'R')) {
if (!silent) fprintf(stderr,"[ERR] Bad boot sector signature\n");
return -1;
}
@ -406,14 +404,14 @@ int is_sansa(struct sansa_t* sansa)
}
/* Check Bootloader header */
if (sansa_seek_and_read(sansa, sansa->start, sansa_sectorbuf, 0x200) < 0) {
if (sansa_seek_and_read(sansa, sansa->start, sansa->sectorbuf, 0x200) < 0) {
return -2;
}
if (memcmp(sansa_sectorbuf,"PPBL",4)!=0) {
if (memcmp(sansa->sectorbuf,"PPBL",4)!=0) {
/* No bootloader header, abort */
return -4;
}
ppbl_length = (le2int(sansa_sectorbuf+4) + 0x1ff) & ~0x1ff;
ppbl_length = (le2int(sansa->sectorbuf+4) + 0x1ff) & ~0x1ff;
/* Sanity/safety check - the bootloader can't be larger than PPMI_OFFSET */
if (ppbl_length > PPMI_OFFSET)
@ -422,12 +420,12 @@ int is_sansa(struct sansa_t* sansa)
}
/* Load Sansa bootloader and check for "Sansa C200" magic string */
if (sansa_seek_and_read(sansa, sansa->start + 0x200, sansa_sectorbuf, ppbl_length) < 0) {
if (sansa_seek_and_read(sansa, sansa->start + 0x200, sansa->sectorbuf, ppbl_length) < 0) {
fprintf(stderr,"[ERR] Seek and read to 0x%08llx in is_sansa failed.\n",
sansa->start+0x200);
return -6;
}
if (sansa_memmem(sansa_sectorbuf, ppbl_length, "Sansa C200", 10) != NULL) {
if (sansa_memmem(sansa->sectorbuf, ppbl_length, "Sansa C200", 10) != NULL) {
/* C200 */
sansa->targetname="c200";
} else {
@ -436,25 +434,25 @@ int is_sansa(struct sansa_t* sansa)
}
/* Check Main firmware header */
if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET, sansa_sectorbuf, 0x200) < 0) {
if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET, sansa->sectorbuf, 0x200) < 0) {
fprintf(stderr,"[ERR] Seek to 0x%08llx in is_sansa failed.\n",
sansa->start+PPMI_OFFSET);
return -5;
}
if (memcmp(sansa_sectorbuf,"PPMI",4)!=0) {
if (memcmp(sansa->sectorbuf,"PPMI",4)!=0) {
/* No bootloader header, abort */
return -7;
}
ppmi_length = le2int(sansa_sectorbuf+4);
ppmi_length = le2int(sansa->sectorbuf+4);
/* Check main mi4 file header */
if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET+0x200, sansa_sectorbuf, 0x200) < 0) {
if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET+0x200, sansa->sectorbuf, 0x200) < 0) {
fprintf(stderr,"[ERR] Seek to 0x%08llx in is_sansa failed.\n",
sansa->start+PPMI_OFFSET+0x200);
return -5;
}
if (get_mi4header(sansa_sectorbuf,&mi4header) < 0) {
if (get_mi4header(sansa->sectorbuf,&mi4header) < 0) {
fprintf(stderr,"[ERR] Invalid mi4header\n");
return -6;
}
@ -466,15 +464,15 @@ int is_sansa(struct sansa_t* sansa)
*/
sansa->hasoldbootloader = 0;
if (memcmp(sansa_sectorbuf+0x1f8,"RBBL",4)==0) {
if (memcmp(sansa->sectorbuf+0x1f8,"RBBL",4)==0) {
/* Look for an original firmware after the first image */
if (sansa_seek_and_read(sansa,
sansa->start + PPMI_OFFSET + 0x200 + ppmi_length,
sansa_sectorbuf, 512) < 0) {
sansa->sectorbuf, 512) < 0) {
return -7;
}
if (get_mi4header(sansa_sectorbuf,&mi4header)!=0) {
if (get_mi4header(sansa->sectorbuf,&mi4header)!=0) {
fprintf(stderr,"[ERR] No original firmware found\n");
sansa->hasoldbootloader = 1;
}
@ -659,7 +657,7 @@ int sansa_read_firmware(struct sansa_t* sansa, const char* filename)
int outfile;
struct mi4header_t mi4header;
res = load_original_firmware(sansa,sansa_sectorbuf,&mi4header);
res = load_original_firmware(sansa,sansa->sectorbuf,&mi4header);
if (res < 0)
return res;
@ -669,7 +667,7 @@ int sansa_read_firmware(struct sansa_t* sansa, const char* filename)
return -1;
}
res = write(outfile,sansa_sectorbuf,mi4header.mi4size);
res = write(outfile,sansa->sectorbuf,mi4header.mi4size);
if (res != (int)mi4header.mi4size) {
fprintf(stderr,"[ERR] Write error - %d\n", res);
return -1;
@ -730,16 +728,16 @@ int sansa_add_bootloader(struct sansa_t* sansa, const unsigned char* bootloader,
int n;
/* Create PPMI header */
memset(sansa_sectorbuf,0,0x200);
memcpy(sansa_sectorbuf,"PPMI",4);
int2le(bl_length, sansa_sectorbuf+4);
int2le(0x00020000, sansa_sectorbuf+8);
memset(sansa->sectorbuf,0,0x200);
memcpy(sansa->sectorbuf,"PPMI",4);
int2le(bl_length, sansa->sectorbuf+4);
int2le(0x00020000, sansa->sectorbuf+8);
/* copy bootloader to sansa_sectorbuf+0x200 */
memcpy(sansa_sectorbuf+0x200,bootloader,bl_length);
/* copy bootloader to sansa->sectorbuf+0x200 */
memcpy(sansa->sectorbuf+0x200,bootloader,bl_length);
/* Load original firmware from Sansa to the space after the bootloader */
res = load_original_firmware(sansa,sansa_sectorbuf+0x200+bl_length,&mi4header);
res = load_original_firmware(sansa,sansa->sectorbuf+0x200+bl_length,&mi4header);
if (res < 0)
return res;
@ -753,7 +751,7 @@ int sansa_add_bootloader(struct sansa_t* sansa, const unsigned char* bootloader,
length = 0x200 + bl_length + mi4header.mi4size;
n=sansa_write(sansa, sansa_sectorbuf, length);
n=sansa_write(sansa, length);
if (n < length) {
fprintf(stderr,"[ERR] Short write in add_bootloader\n");
return -6;
@ -769,16 +767,16 @@ int sansa_delete_bootloader(struct sansa_t* sansa)
int n;
int length;
/* Load original firmware from Sansa to sansa_sectorbuf+0x200 */
res = load_original_firmware(sansa,sansa_sectorbuf+0x200,&mi4header);
/* Load original firmware from Sansa to sansa->sectorbuf+0x200 */
res = load_original_firmware(sansa,sansa->sectorbuf+0x200,&mi4header);
if (res < 0)
return res;
/* Create PPMI header */
memset(sansa_sectorbuf,0,0x200);
memcpy(sansa_sectorbuf,"PPMI",4);
int2le(mi4header.mi4size, sansa_sectorbuf+4);
int2le(0x00020000, sansa_sectorbuf+8);
memset(sansa->sectorbuf,0,0x200);
memcpy(sansa->sectorbuf,"PPMI",4);
int2le(mi4header.mi4size, sansa->sectorbuf+4);
int2le(0x00020000, sansa->sectorbuf+8);
/* Now write the whole thing back to the Sansa */
@ -790,7 +788,7 @@ int sansa_delete_bootloader(struct sansa_t* sansa)
length = 0x200 + mi4header.mi4size;
n=sansa_write(sansa, sansa_sectorbuf, length);
n=sansa_write(sansa, length);
if (n < length) {
fprintf(stderr,"[ERR] Short write in delete_bootloader\n");
return -6;
@ -808,21 +806,21 @@ int sansa_list_images(struct sansa_t* sansa)
int num = 0;
/* Check Main firmware header */
if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET, sansa_sectorbuf, 0x200) < 0) {
if (sansa_seek_and_read(sansa, sansa->start+PPMI_OFFSET, sansa->sectorbuf, 0x200) < 0) {
return 0;
}
ppmi_length = le2int(sansa_sectorbuf+4);
ppmi_length = le2int(sansa->sectorbuf+4);
printf("[INFO] Image 1 - %llu bytes\n",ppmi_length);
num = 1;
/* Look for an original firmware after the first image */
if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, sansa_sectorbuf, 512) < 0) {
if (sansa_seek_and_read(sansa, sansa->start + PPMI_OFFSET + 0x200 + ppmi_length, sansa->sectorbuf, 512) < 0) {
return 0;
}
if (get_mi4header(sansa_sectorbuf,&mi4header)==0) {
if (get_mi4header(sansa->sectorbuf,&mi4header)==0) {
printf("[INFO] Image 2 - %d bytes\n",mi4header.mi4size);
num = 2;
}
@ -874,8 +872,8 @@ int sansa_update_of(struct sansa_t* sansa, const char* filename)
of_length = filesize(infile);
/* Load original firmware from file */
memset(sansa_sectorbuf,0,0x200);
n = read(infile,sansa_sectorbuf,of_length);
memset(sansa->sectorbuf,0,0x200);
n = read(infile,sansa->sectorbuf,of_length);
close(infile);
if (n < of_length) {
fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n"
@ -884,13 +882,13 @@ int sansa_update_of(struct sansa_t* sansa, const char* filename)
}
/* Check we have a valid MI4 file. */
if (get_mi4header(sansa_sectorbuf,&mi4header)!=0) {
if (get_mi4header(sansa->sectorbuf,&mi4header)!=0) {
fprintf(stderr,"[ERR] %s is not a valid mi4 file\n",filename);
return -1;
}
/* Decrypt and build the header */
if(prepare_original_firmware(sansa, sansa_sectorbuf, &mi4header)!=0){
if(prepare_original_firmware(sansa, sansa->sectorbuf, &mi4header)!=0){
fprintf(stderr,"[ERR] Unable to build decrypted mi4 from %s\n"
,filename);
return -1;
@ -903,7 +901,7 @@ int sansa_update_of(struct sansa_t* sansa, const char* filename)
return -1;
}
n=sansa_write(sansa, sansa_sectorbuf, of_length);
n=sansa_write(sansa, of_length);
if (n < of_length) {
fprintf(stderr,"[ERR] Short write in sansa_update_of\n");
return -1;
@ -920,8 +918,8 @@ int sansa_update_of(struct sansa_t* sansa, const char* filename)
return -1;
}
memset(sansa_sectorbuf,0,NVPARAMS_SIZE);
n=sansa_write(sansa, sansa_sectorbuf, NVPARAMS_SIZE);
memset(sansa->sectorbuf,0,NVPARAMS_SIZE);
n=sansa_write(sansa, NVPARAMS_SIZE);
if (n < NVPARAMS_SIZE) {
fprintf(stderr,"[ERR] Short write in sansa_update_of\n");
return -1;
@ -947,7 +945,7 @@ int sansa_update_ppbl(struct sansa_t* sansa, const char* filename)
ppbl_length = filesize(infile);
n = read(infile,sansa_sectorbuf+0x200,ppbl_length);
n = read(infile,sansa->sectorbuf+0x200,ppbl_length);
close(infile);
if (n < ppbl_length) {
fprintf(stderr,"[ERR] Short read - requested %d bytes, received %d\n", ppbl_length, n);
@ -955,10 +953,10 @@ int sansa_update_ppbl(struct sansa_t* sansa, const char* filename)
}
/* Step 2 - Build the header */
memset(sansa_sectorbuf,0,0x200);
memcpy(sansa_sectorbuf,"PPBL",4);
int2le(ppbl_length, sansa_sectorbuf+4);
int2le(0x00010000, sansa_sectorbuf+8);
memset(sansa->sectorbuf,0,0x200);
memcpy(sansa->sectorbuf,"PPBL",4);
int2le(ppbl_length, sansa->sectorbuf+4);
int2le(0x00010000, sansa->sectorbuf+8);
/* Step 3 - write the bootloader to the Sansa */
if (sansa_seek(sansa, sansa->start) < 0) {
@ -966,7 +964,7 @@ int sansa_update_ppbl(struct sansa_t* sansa, const char* filename)
return -1;
}
n=sansa_write(sansa, sansa_sectorbuf, ppbl_length + 0x200);
n=sansa_write(sansa, ppbl_length + 0x200);
if (n < (ppbl_length+0x200)) {
fprintf(stderr,"[ERR] Short write in sansa_update_ppbl\n");
return -1;

View file

@ -32,15 +32,6 @@ extern int sansa_verbose;
/* 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
#ifndef _MSC_VER
extern unsigned char* sansa_sectorbuf;
#else
/* MSVC needs to use dllimport to allow using it directly from a DLL.
* See http://support.microsoft.com/kb/90530
* Building with MSVC is only when using as DLL.
*/
_declspec(dllimport) unsigned char* sansa_sectorbuf;
#endif
int sansa_read_partinfo(struct sansa_t* sansa, int silent);
int is_sansa(struct sansa_t* sansa);