> andy:~$ gcc -o firmware firmware.c -DSTANDALONE_EXTRACTER
> firmware.c:43:17: crc.h: No such file or directory
> firmware.c:529:17: crc.c: No such file or directory
> andy:~$
> 
> Looks like it needs crc.c and crc.h.

Yes, sorry about that.  I've included all needed files at the
end of this email.

> So I untarred the speedtouch-1.3.1,  
> cd'd into speedtouch-1.3.1/src and then did
> 
> gcc -o firmware firmware.c -DSTANDALONE_EXTRACTER
> 
> That worked fine.


Except that it's not quite the same firmware.c...

> > Then do
> > 
> >     ./firmware KQD6_3.012
> > 
> > This will create speedtch-1.bin and speedtch-2.bin.
> > 
> 
> I copied the KQD6_3.012 into speedtouch-1.3.1/src and then did
> 
> andy:~/Desktop/speedtouch-1.3.1/src$ ./firmware KQD6_3.012
> Firmware info (CRC:0xd80bf9f7, Size:991, Checked: Yes, Alcatel/Thomson 
> Boot block (old))
> Firmware info (CRC:0x78039fed, Size:762650, Checked: Yes, 3.0.6 - MacOSX 
> - Win32)
> ** Boot block from KQD6_3.012:
>     CRC: 0xd80bf9f7
>     Length: 991
> ** Firmware block from KQD6_3.012:
>     CRC: 0x78039fed
>     Length: 762650
> andy:~/Desktop/speedtouch-1.3.1/src$
> 
> 
> 
> That made two files, boot.bin and firmware.bin. Were these the 
> speedtch-1.bin and speedtch-2.bin that you were referring to?

Yes.  The difference between the firmware.c I supplied and the one from
the user space driver is simply that it names the files speedtch-1.bin etc.

> I renamed  
> them speedtch-1.bin (the small one, 991 bytes) and speedtch-2.bin and 
> copied them to /lib/firmware. But when I reboot, no joy, the firmware 
> doesn't load. I think I'm getting close here but I'm not sure. Perhaps 
> the problem is with hotplug?

If you compile your kernel with CONFIG_USB_DEBUG=y then you will get a
pile of maybe helpful messages in your system logs.  Even without this
config setting, various messages are printed so please check the logs.

Ciao,

Duncan.

===> crc.h

/*
*  ALCATEL SpeedTouch USB modem utility : CRC lib
*  Copyright (C) 2001 Edouard Gomez
* 
*  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 program is distributed in the hope that it will be useful,
*  but 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.
*
*  Author : Edouard Gomez ([EMAIL PROTECTED])
*  Creation : 08/08/2001
*
* $Id: crc.h,v 1.1 2004/10/15 15:00:56 duncan Exp $
*/

#ifndef _CRC_H_
#define _CRC_H_

/******************************************************************************
* Constants
******************************************************************************/

#define AAL5_CRC32_REMAINDER 0xCBF43926
#define AAL5_CRC32_INITIAL 0xffffffff

#define ATM_HEADER_REMAINDER 0x107
#define ATM_HEADER_COSET_LEADER 0x055

/******************************************************************************
* Prototype
******************************************************************************/

extern unsigned int  aal5_calc_crc(unsigned char *mem, int len, unsigned int 
initial);
extern unsigned char atm_calc_hec(unsigned char *header);

#endif


===> crc.c

/*
*  ALCATEL SpeedTouch USB modem utility : CRC lib
*  Copyright (C) 2001 Edouard Gomez
* 
*  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 program is distributed in the hope that it will be useful,
*  but 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.
*
*  Author : Edouard Gomez ([EMAIL PROTECTED])
*  Creation : 08/08/2001
*
* $Id: crc.c,v 1.1 2004/10/15 15:00:56 duncan Exp $
*/

#ifndef _CRC_C_
#define _CRC_C_

/* Some stuff */
#include "crc.h"

/******************************************************************************
* Macros (This is used to speedup code in the calc_crc first while loop)
******************************************************************************/

#define DO1(c, crc) ((crc) = crc32tab[((unsigned int)((crc)>>24) ^ (*c++)) & 
0xff] ^ ((crc) << 8))
#define DO2(c, crc)  DO1(c, crc); DO1(c, crc);
#define DO4(c, crc)  DO2(c, crc); DO2(c, crc);
#define DO8(c, crc)  DO4(c, crc); DO4(c, crc);

/******************************************************************************
* Precomputed AAL5 CRC32 lookup table
******************************************************************************/

static unsigned long crc32tab[256] = {

        0x00000000L, 0x04C11DB7L, 0x09823B6EL, 0x0D4326D9L,
        0x130476DCL, 0x17C56B6BL, 0x1A864DB2L, 0x1E475005L,
        0x2608EDB8L, 0x22C9F00FL, 0x2F8AD6D6L, 0x2B4BCB61L,
        0x350C9B64L, 0x31CD86D3L, 0x3C8EA00AL, 0x384FBDBDL,
        0x4C11DB70L, 0x48D0C6C7L, 0x4593E01EL, 0x4152FDA9L,
        0x5F15ADACL, 0x5BD4B01BL, 0x569796C2L, 0x52568B75L,
        0x6A1936C8L, 0x6ED82B7FL, 0x639B0DA6L, 0x675A1011L,
        0x791D4014L, 0x7DDC5DA3L, 0x709F7B7AL, 0x745E66CDL,
        0x9823B6E0L, 0x9CE2AB57L, 0x91A18D8EL, 0x95609039L,
        0x8B27C03CL, 0x8FE6DD8BL, 0x82A5FB52L, 0x8664E6E5L,
        0xBE2B5B58L, 0xBAEA46EFL, 0xB7A96036L, 0xB3687D81L,
        0xAD2F2D84L, 0xA9EE3033L, 0xA4AD16EAL, 0xA06C0B5DL,
        0xD4326D90L, 0xD0F37027L, 0xDDB056FEL, 0xD9714B49L,
        0xC7361B4CL, 0xC3F706FBL, 0xCEB42022L, 0xCA753D95L,
        0xF23A8028L, 0xF6FB9D9FL, 0xFBB8BB46L, 0xFF79A6F1L,
        0xE13EF6F4L, 0xE5FFEB43L, 0xE8BCCD9AL, 0xEC7DD02DL,
        0x34867077L, 0x30476DC0L, 0x3D044B19L, 0x39C556AEL,
        0x278206ABL, 0x23431B1CL, 0x2E003DC5L, 0x2AC12072L,
        0x128E9DCFL, 0x164F8078L, 0x1B0CA6A1L, 0x1FCDBB16L,
        0x018AEB13L, 0x054BF6A4L, 0x0808D07DL, 0x0CC9CDCAL,
        0x7897AB07L, 0x7C56B6B0L, 0x71159069L, 0x75D48DDEL,
        0x6B93DDDBL, 0x6F52C06CL, 0x6211E6B5L, 0x66D0FB02L,
        0x5E9F46BFL, 0x5A5E5B08L, 0x571D7DD1L, 0x53DC6066L,
        0x4D9B3063L, 0x495A2DD4L, 0x44190B0DL, 0x40D816BAL,
        0xACA5C697L, 0xA864DB20L, 0xA527FDF9L, 0xA1E6E04EL,
        0xBFA1B04BL, 0xBB60ADFCL, 0xB6238B25L, 0xB2E29692L,
        0x8AAD2B2FL, 0x8E6C3698L, 0x832F1041L, 0x87EE0DF6L,
        0x99A95DF3L, 0x9D684044L, 0x902B669DL, 0x94EA7B2AL,
        0xE0B41DE7L, 0xE4750050L, 0xE9362689L, 0xEDF73B3EL,
        0xF3B06B3BL, 0xF771768CL, 0xFA325055L, 0xFEF34DE2L,
        0xC6BCF05FL, 0xC27DEDE8L, 0xCF3ECB31L, 0xCBFFD686L,
        0xD5B88683L, 0xD1799B34L, 0xDC3ABDEDL, 0xD8FBA05AL,
        0x690CE0EEL, 0x6DCDFD59L, 0x608EDB80L, 0x644FC637L,
        0x7A089632L, 0x7EC98B85L, 0x738AAD5CL, 0x774BB0EBL,
        0x4F040D56L, 0x4BC510E1L, 0x46863638L, 0x42472B8FL,
        0x5C007B8AL, 0x58C1663DL, 0x558240E4L, 0x51435D53L,
        0x251D3B9EL, 0x21DC2629L, 0x2C9F00F0L, 0x285E1D47L,
        0x36194D42L, 0x32D850F5L, 0x3F9B762CL, 0x3B5A6B9BL,
        0x0315D626L, 0x07D4CB91L, 0x0A97ED48L, 0x0E56F0FFL,
        0x1011A0FAL, 0x14D0BD4DL, 0x19939B94L, 0x1D528623L,
        0xF12F560EL, 0xF5EE4BB9L, 0xF8AD6D60L, 0xFC6C70D7L,
        0xE22B20D2L, 0xE6EA3D65L, 0xEBA91BBCL, 0xEF68060BL,
        0xD727BBB6L, 0xD3E6A601L, 0xDEA580D8L, 0xDA649D6FL,
        0xC423CD6AL, 0xC0E2D0DDL, 0xCDA1F604L, 0xC960EBB3L,
        0xBD3E8D7EL, 0xB9FF90C9L, 0xB4BCB610L, 0xB07DABA7L,
        0xAE3AFBA2L, 0xAAFBE615L, 0xA7B8C0CCL, 0xA379DD7BL,
        0x9B3660C6L, 0x9FF77D71L, 0x92B45BA8L, 0x9675461FL,
        0x8832161AL, 0x8CF30BADL, 0x81B02D74L, 0x857130C3L,
        0x5D8A9099L, 0x594B8D2EL, 0x5408ABF7L, 0x50C9B640L,
        0x4E8EE645L, 0x4A4FFBF2L, 0x470CDD2BL, 0x43CDC09CL,
        0x7B827D21L, 0x7F436096L, 0x7200464FL, 0x76C15BF8L,
        0x68860BFDL, 0x6C47164AL, 0x61043093L, 0x65C52D24L,
        0x119B4BE9L, 0x155A565EL, 0x18197087L, 0x1CD86D30L,
        0x029F3D35L, 0x065E2082L, 0x0B1D065BL, 0x0FDC1BECL,
        0x3793A651L, 0x3352BBE6L, 0x3E119D3FL, 0x3AD08088L,
        0x2497D08DL, 0x2056CD3AL, 0x2D15EBE3L, 0x29D4F654L,
        0xC5A92679L, 0xC1683BCEL, 0xCC2B1D17L, 0xC8EA00A0L,
        0xD6AD50A5L, 0xD26C4D12L, 0xDF2F6BCBL, 0xDBEE767CL,
        0xE3A1CBC1L, 0xE760D676L, 0xEA23F0AFL, 0xEEE2ED18L,
        0xF0A5BD1DL, 0xF464A0AAL, 0xF9278673L, 0xFDE69BC4L,
        0x89B8FD09L, 0x8D79E0BEL, 0x803AC667L, 0x84FBDBD0L,
        0x9ABC8BD5L, 0x9E7D9662L, 0x933EB0BBL, 0x97FFAD0CL,
        0xAFB010B1L, 0xAB710D06L, 0xA6322BDFL, 0xA2F33668L,
        0xBCB4666DL, 0xB8757BDAL, 0xB5365D03L, 0xB1F740B4L

};

/******************************************************************************
* Precomputed ATM CRC8 lookup table
******************************************************************************/

unsigned char hec_table[256]=
{

        0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, 
        0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, 
        0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, 
        0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, 
        0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, 
        0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, 
        0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, 
        0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, 
        0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, 
        0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, 
        0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, 
        0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, 
        0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, 
        0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, 
        0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, 
        0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, 
        0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, 
        0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, 
        0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, 
        0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, 
        0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, 
        0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, 
        0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, 
        0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, 
        0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, 
        0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, 
        0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, 
        0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, 
        0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, 
        0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, 
        0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 
        0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3

};

/******************************************************************************
* Functions
******************************************************************************/

/*
* Function     : aal5_calc_crc
* Return Value : crc calculated for the given buffer ( needs to be xor'ed)
* Description  : none
*/

unsigned int aal5_calc_crc(unsigned char *mem, int len, unsigned int initial)
{

        register unsigned int crc;

        crc = initial;

        while( len >= 8) {
                DO8(mem, crc);
                len -= 8;
        }

        while( len ) {
                DO1(mem, crc);
                len--;
        }

        return(crc);

}

unsigned char atm_calc_hec(unsigned char *header)
{

        register unsigned char hec,i;

        hec = 0;

        for(i=0; i<4; i++)
                hec = hec_table[hec^header[i]];

        return(hec^ATM_HEADER_COSET_LEADER);

}

#endif


===> firmware.h


#ifndef __FIRMWARE_H__
#define __FIRMWARE_H__

typedef struct
{
        unsigned long crc;
        unsigned long length;
        const char *id;
} stusb_firmware_id_t;


typedef struct
{
        unsigned char *phase1;
        unsigned char *phase2;
        unsigned long phase1_length;
        unsigned long phase2_length;
} stusb_firmware_t;

stusb_firmware_t *
extract_firmware(const char *boot_file, const char *firm_file, int rev4);

void
free_firmware(stusb_firmware_t *f);

#endif


===> firmware.c

/*
*  ALCATEL SpeedTouch USB modem microcode extract utility
*  Copyright (C) 2001 Benoit PAPILLAULT
*  
*  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 program is distributed in the hope that it will be useful,
*  but 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.
*
*  Author   : Edouard Gomez <[EMAIL PROTECTED]>
*  Creation : 14/02/2004
*
*  Searching for the microcode is done in a two step process:
*   - the boot code.
*   - the main firmware.
*
*  The bootcode is always loaded at 0x00000000 in the modem RAM, so we look for
*  this base address mixed in a special file format signature. The end of the
*  boot code is marked by a command that tells the ARM to jump at the base
*  address and execute (aka boot)
*
*  The base address of the main firmware depends on the modem revision (as of
*  2004-02-14, only rev4 is different). The end pattern is also a jump command.
*
* $Id: firmware.c,v 1.1 2004/10/15 15:00:56 duncan Exp $
*/

#ifndef _FIRMWARE_C_
#define _FIRMWARE_C_

#ifndef STANDALONE_EXTRACTER
#include "pppoa3.h"
#endif
#include "crc.h"
#include "firmware.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

/*****************************************************************************
* Local Prototypes
*****************************************************************************/

static stusb_firmware_t *
extract_firmware_phase(const char *file,
                       const unsigned char *start_pattern,
                       const unsigned char *end_pattern,
                       const int pattern_length,
                       const stusb_firmware_id_t *ids);
static int
search_pattern(const unsigned char *buffer,
               const unsigned char *pattern,
               const int buffer_length,
               const int pattern_length);

static unsigned char *
load_file(const char * file, int * size);

/******************************************************************************
*       Main Lib Function
******************************************************************************/

/*
 * Function    : check_firmware
 * Results     : return 1 if the firmware is OK, 0 otherwise.
 * Description : check that the firmware found is valid
 */

int check_firmware(unsigned char * buf, int len)
{
        unsigned char * current_block;
        int remaining_len;

        unsigned int addr;
        unsigned int size, extra_size;

        int boot_block_seen = 0;
        int last_block_seen = 0;

        current_block = buf;
        remaining_len = len;

        while (remaining_len > 0) {
                if (remaining_len < 8) {
                        /* not enougth data to make a block, abort */
                        return(0);
                }

                addr =   current_block[2]      | (current_block[3]<<8) |
                        (current_block[4]<<16) | (current_block[5]<<24);

                size       = current_block[6] | (current_block[7]<<8);
                extra_size = current_block[1] | ((current_block[0]&0x80)<<1);

                switch (current_block[0]) {
                case 0x08:
                case 0x88:
                        /* determine the type of block */
                        if (extra_size <= 0x1f8 && extra_size > 6) {
                                /* last data block & last data block */
                                if (boot_block_seen || last_block_seen)
                                        return 0;

                                if (extra_size < 0x1f8)
                                        last_block_seen = 1;

                                if (extra_size != size + 6)
                                        return 0;

                                /* skip over header */
                                current_block += 2;
                                remaining_len -= 2;
                
                                if (remaining_len < extra_size)
                                        return(0);
                
                                /* skip over data */
                                current_block += extra_size;
                                remaining_len -= extra_size;
                
                                if (remaining_len < 3)
                                        return(0);
                
                                if (current_block[0] != 0x40 ||
                                    current_block[1] != 0x01 ||
                                    current_block[2] != 0x12)
                                        return(0);
                
                                /* skip over trailer */
                                current_block += 3;
                                remaining_len -= 3;
                        } else if (extra_size == 4) {
                                /* boot block */
                                if (boot_block_seen)
                                        return(0);

                                boot_block_seen = 1;

                                /* skip over header */
                                current_block += 2;
                                remaining_len -= 2;
                
                                if (remaining_len < extra_size)
                                        return(0);
                
                                /* skip over data */
                                current_block += extra_size;
                                remaining_len -= extra_size;
                
                                if (remaining_len < 3)
                                        return(0);
                
                                if (current_block[0] != 0x00 ||
                                    current_block[1] != 0x01 ||
                                    current_block[2] != 0x14)
                                        return(0);
                
                                /* skip over trailer */
                                current_block += 3;
                                remaining_len -= 3;
                        } else {
                                /* unknown block again, abort */
                                return(0);
                        }

                        break;
                default:
                        /* unknown block, abort */
                        return(0);
                }
        }

        return(1);
}

/*
* Function     : extract_microcode
* Return Value : NULL on error
*                valid pointer to the microcode on success
* Description  : We are searching for the best match of a start and end
*                sequence.
*                Those sequence delimits the microcode. You won't get 100%
*                probability, but it will work anyway, for all the microcode
*                I've tested.
*/

#define PATTERN_LENGTH 8

stusb_firmware_t *
extract_firmware(const char *file1, const char *file2, int rev4)
{
        /* Specific byte sequences that mark the start/end of the encapsulated 
ARM code in firmware files */
        const unsigned char boot_patterns[2][PATTERN_LENGTH] = {
                /* The base address is always 0x00000000 */
                {0x88, 0xf8, 0x00, 0x00, 0x00, 0x00, 0xf2, 0x01}, /* start */
                {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x14}  /* stop */
        };

        const unsigned char firm_patterns[2][2][PATTERN_LENGTH] = {
                {    /* The base address is 0x00400000 */
                        {0x88, 0xf8, 0x00, 0x40, 0x00, 0x00, 0xf2, 0x01},  /* 
start for stusb rev 1,2,3 */
                        {0x04, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x14}  /* 
stop for stusb rev 1,2,3 */
                }, { /* The base address is 0x00000010 */
                        {0x88, 0xf8, 0x00, 0x00, 0x00, 0x10, 0xf2, 0x01},  /* 
start for stusb rev 4 */
                        {0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x14}  /* 
stop for stusb rev 4 */
                }
        };

        const stusb_firmware_id_t stusb_phase1_ids[] = {
                {0xd3e33990, 883, "Ian's Free Software Boot block"},
                {0xd80bf9f7, 991, "Alcatel/Thomson Boot block (old)"},
                {0x69636579, 935, "Alcatel/Thomson Boot block (new)"},
                {0x00000000, 0, NULL}
        };

        const stusb_firmware_id_t stusb_phase2_ids[] = {
                {0xae3ff81f, 526239, "1.3.1 - GNU/Linux"},
                {0xa719bc0e, 523436, "1.3.1 - Win32"},
                {0x94a45435, 526187, "1.3.3 - GNU/Linux - Win32"},
                {0x61914198, 527093, "1.4.0 - Win32(3.0.1800)"},
                {0x37c189ed, 527752, "1.4.0 - Win32(4.0.100)"},
                {0x99cc1c1a, 528738, "1.4.2 - Win32(2.0.500)"},
                {0xe0251a5e, 671665, "1.6.1 - Win32(5.0.1801)"},
                {0x3b4a5854, 671653, "1.6.1 - MacOSX - Win32(1.0.1800)"},
                {0xd673923f, 672264, "2.0.0 - Win32(07)"},
                {0x5bca7d16, 677641, "2.0.1 - MacOSX - Win32(2.0.0)"},
                {0x78039fed, 762650, "3.0.6 - MacOSX - Win32"},
                {0x698eb734, 761389, "3.0.0 - Win32"},
                {0xd7864c39, 774192, "3.0.0 - Win32 (rev 4)"},
                {0x0223733c, 775509, "1.0.10 - Win32 Rev 0400 SACHU3"},
                {0x41d4143c, 775545, "0.0.0 - testing firmware from Thomson"},
                {0x00000000, 0, NULL}
        };

        stusb_firmware_t *boot, *firmware;

        if (file2 == NULL) return(NULL);

        /* If we are not passed a phase1 file, try to find it in the phase2
         * file. It was the usual way firmwares were packed together in olds
         * alcatel/thomson drivers */
        if (file1 == NULL) file1 = file2;

        /* Extract the phase1 (boot block) part */
        boot = extract_firmware_phase(file1,
                                      boot_patterns[0],
                                      boot_patterns[1],
                                      PATTERN_LENGTH,
                                      stusb_phase1_ids);

        /* Extract the modem's firmware now */
        firmware =  extract_firmware_phase(file2,
                                           firm_patterns[(rev4)?1:0][0],
                                           firm_patterns[(rev4)?1:0][1],
                                           PATTERN_LENGTH,
                                           stusb_phase2_ids);

        /* firmware is used as the returned value, it MUST be valid */
        if (firmware == NULL) {
                free_firmware(boot);
                return(NULL);
        }

        /* Data is now loaded, put it where it belongs to
         * NB: - phase1 slot may be empty, it's up to the caller to fill it with
         *       default boot block
         *     - phase2 slot is mandatory and triggers an error if it's missing 
*/
        firmware->phase2 = firmware->phase1;
        firmware->phase2_length = firmware->phase1_length;
        firmware->phase1 = (boot!=NULL)?boot->phase1:NULL;
        firmware->phase1_length = (boot!=NULL)?boot->phase1_length:0;

        /* Free allocated structure (if any) but not the its fields */
        if (boot) free(boot);

        return(firmware);
}

static stusb_firmware_t *
extract_firmware_phase(const char *file,
                       const unsigned char *start_pattern,
                       const unsigned char *stop_pattern,
                       const int pattern_length,
                       const stusb_firmware_id_t *ids)
{
        unsigned char *buf;
        int start_offset, length;
        stusb_firmware_t *firmware;

        length = 0;
        start_offset = 0;

        /* Loads the file into memory (yes, it's a lame, why not a mmap ?) */
        if ((buf = load_file(file, &length)) == NULL)
                return(NULL);

        /* Searches the start and end offsets */
        start_offset = search_pattern(buf,
                                      start_pattern,
                                      length,
                                      pattern_length);
        if (start_offset < 0) {
                free(buf);
                return(NULL);
        }

        length  = search_pattern(buf + start_offset,
                                 stop_pattern,
                                 length - start_offset,
                                 pattern_length);
        if (length < 0) {
                free(buf);
                return(NULL);
        }

        /* We must add the pattern length to obtain the real length */
        length += PATTERN_LENGTH;

        /* Initialize the returned firmware struct */
        if ((firmware = malloc(sizeof(stusb_firmware_t))) == NULL) {
                free(buf);
                return(NULL);
        }
        memset(firmware, 0, sizeof(stusb_firmware_t));

        if ((firmware->phase1 = malloc(length)) == NULL) {
                free(firmware);
                free(buf);
                return(NULL);
        }

        /* Copy the data into the returned firmware
         * Data is put into phase1 fields -- The caller function may then do
         * whatever it likes with this data. */
        memcpy(firmware->phase1, buf+start_offset, length);
        firmware->phase1_length = length;

        /* We don't need the file buffer anymore */
        free(buf);

        {
                unsigned long crc;
                const stusb_firmware_id_t *id = ids;
                const char *idstr =
                        "Unknown revision - Please report the CRC "
                        "and length with the revision number to "
                        "[EMAIL PROTECTED]";
                int checked;

                /* Computes this value once */
                crc = ~aal5_calc_crc(firmware->phase1, 
firmware->phase1_length,~0);

                /* Browse the "known" firmware array */
                while (id->length != 0) {
                        if(id->length == length && id->crc == crc) {
                                idstr = id->id;
                                break;
                        }
                        id++;
                }

                checked = check_firmware(firmware->phase1,
                                         firmware->phase1_length);

#ifndef STANDALONE_EXTRACTER
                report(1, REPORT_INFO,
                       "Firmware info (CRC:0x%08x, Size:%d, Checked: %s, %s)\n",
                       crc, length, checked?"Yes":"No",idstr);
#else
                printf("Firmware info (CRC:0x%08x, Size:%d, Checked: %s, %s)\n",
                       crc, length, checked?"Yes":"No",idstr);
#endif
        }
        /* Returns a pointer to the start adress */
        return(firmware);
}

/*****************************************************************************
*       Local sub routines
*****************************************************************************/

/*
* Function     : load_file
* Return Value : null in case of error
*                a pointer to a buffer allocated using malloc() on success
* NB           : *size contains the returned buffer size
*/

static unsigned char *
load_file(const char * file, int * size)
{
        struct stat statbuf;
        int len;
        unsigned char * buf;
        int fd;

        *size = 0;

        /* Opens the file */
        if ((fd = open(file, O_RDONLY)) < 0) {
                perror(file);
                return(NULL);
        }

        /* Retrieves file informations */
         if (fstat(fd, &statbuf) != 0) {
                perror("stat");
                return(NULL);
        }

        /* Gets length */
        len = statbuf.st_size;

        /* Allocates the buffer */
        if((buf = (unsigned char *)malloc(len)) == NULL) {
                perror("malloc");
                close (fd);
                return(NULL);
        }

        /* Read all contents in buffer */
        if (read(fd, buf, len) != len) {
                perror(file);
                free (buf);
                close (fd);
                return(NULL);
        }

        /* Closes the file */
        close(fd);

        /* Sets size */
        *size = len;

        return(buf);

}

/*
* Function     : search_match
* Return value : -1 in case of error
*                best match offset on success
* Description  : Search for the longest match of buf2 inside buf1.
*
*/
static int
search_pattern(const unsigned char *buffer,
               const unsigned char *pattern,
               const int buffer_length,
               const int pattern_length)
{
        /* Number of bytes match with pattern */
        int best_match = 0;

        /* Best offset*/
        int best_offset = -1;

        /* Zone where the pattern can reside */
        int potential_length = (buffer_length - pattern_length + 1);

        /* Loop counter */
        int cur_offset;

        for(cur_offset=0; cur_offset< potential_length; cur_offset++) {
                int i;
                int cur_match;

                /* Compute the matching number of bytes at this offset */
                for(i=0, cur_match=0;i<pattern_length;i++)
                        if (buffer[cur_offset+i] == pattern[i])
                                cur_match++;

                /* Compare to the best known matching offset */
                if(cur_match > best_match) {
                        best_offset = cur_offset;
                        best_match  = cur_match;

                        /* Stops as soon as a perfect match is found */
                        if (best_match == pattern_length)
                                break;
                }
        }

#ifndef STANDALONE_EXTRACTER
        report(1, REPORT_INFO, "Best offset %6d with probability %3d%%\n",
               best_offset,
               (100*best_match)/pattern_length);
#endif
        return((best_match == pattern_length)?best_offset:-1);
}

void
free_firmware(stusb_firmware_t *f)
{
        if (f) {
                if (f->phase1) {
                        free(f->phase1);
                        f->phase1 = NULL;
                        f->phase1_length = 0;
                }
                if (f->phase2) {
                        free(f->phase2);
                        f->phase2 = NULL;
                        f->phase2_length = 0;
                }
                free(f);
        }
}

/******************************************************************************
* A main function to test the extract function
******************************************************************************/

#ifdef STANDALONE_EXTRACTER

#include "crc.c"

void usage(char *progname)
{
        fprintf(stderr, "Usage: %s [boot file] <firmware file>\n\n", progname);
}

void extract_new(char *file);

int
main(int argc, char *argv[])
{
        char *file1 = NULL;
        char *file2 = NULL;
        stusb_firmware_t *firmware;

        if (argc != 2 && argc != 3) {
                usage(argv[0]);
                return(-1);
        }

        /* Binds filenames where they belong */
        file2 = argv[argc-1];
        file1 = (argc==2)? file2 : argv[argc-2];

        /* Get the firmware */
        firmware = extract_firmware(file1, file2, 0);
        if (firmware == NULL) firmware = extract_firmware(file1, file2, 1);

        /* Report to user all informations that can be useful */
        printf("** Boot block from %s:\n", file1);
        if (firmware && firmware->phase1) {
                int o;
                printf("   CRC: 0x%08x\n", ~aal5_calc_crc(firmware->phase1, 
firmware->phase1_length,~0));
                printf("   Length: %d\n", (int)firmware->phase1_length);
                o = open("boot.bin", O_CREAT|O_WRONLY|O_TRUNC, 0644);
                if (o != -1) {
                        write(o, firmware->phase1, firmware->phase1_length);
                        close(o);
                }
        } else {
                printf("   Not found\n");
        }

        printf("** Firmware block from %s:\n", file2);
        if (firmware && firmware->phase2) {
                int o;
                printf("   CRC: 0x%08x\n", ~aal5_calc_crc(firmware->phase2, 
firmware->phase2_length,~0));
                printf("   Length: %d\n", (int)firmware->phase2_length);
                o = open("firmware.bin", O_CREAT|O_WRONLY|O_TRUNC, 0644);
                if (o != -1) {
                        write(o, firmware->phase2, firmware->phase2_length);
                        close(o);
                }
        } else {
                printf("   Not found\n");
        }

        /* Free the firmware */
        free_firmware(firmware);

        return(0);
}

#endif /* STANDALONE_EXTRACTER */

#endif /* #ifndef _FIRMWARE_C_ */

Liste de diffusion modem ALCATEL SpeedTouch USB
Pour se désinscrire : mailto:[EMAIL PROTECTED]

        

Reply via email to