/* ST20 Tools Standard Includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* GLC includes */
#include "types.h"
#include "target.h"
#include "ilut.h"
#include "auxdat.h"

#include "asc.h"

#include "error.h"
#include "os.h"
#include "cons.h"
#include "pio.h"
#include "eeprom.h"
#include "nvman.h"
#include "flash.h"

#include "ttool.h"
#include "i2c.h"
#include "idchip.h"
#include "tm.h"
#include "mtst.h"

#define MAX_BYTES_PER_ROW       32
#define MAX_STRING_LENGTH       104

#define AMD_BASE1       0x7FF00000 /* start of flash memory */
#define AMD_BASE2       0x7F700000 /* start of flash memory */
#define DATA32_A        0xaaaaaaaa
#define DATA32_5        0x55555555
#define MASK_BIT7       0x80808080
#define    MASK_A0         0xa0a0a0a0

typedef struct hex_rom_struct
{
    int          entries;
    unsigned int address;
    int          row[16];
} HEX_ROM_STRUCT;


int init_sys(void);
int flash_boot(char*);
int flash_app(FlashDevice_t, char*);
void program_row(HEX_ROM_STRUCT row, int);

NVMan_t        nvman;
FlashDevice_t  flashdevA;
FlashDevice_t  flashdevB;

unsigned long crc32(unsigned char*, unsigned long);

int main(int argc, char* argv[])
{
    int            errorwarn = NO_ERROR; /* Set to !NO_ERROR, if any error */
    int            i, result;
    char           flashpairAfilename[32];    /* boot file name       */
    char           flashpairBfilename[32];    /* boot file name       */
    char           app[32];      /* app file name        */
    BYTE           data[1024];
    SectorParams_t params;
    int            count;

    if ( init_sys() )
    {
        exit(-1);
    }

    printf("\n\n==============================================\n");
    printf("\n         Set-Top Box Flash Program.\n");
    printf("\n==============================================\n\n");

    flashpairAfilename[0] = '\0';
    flashpairBfilename[0] = '\0';
    app[0]   = '\0';

    /* Read the input filenames from the command line and store them
       in strings for fopen. */
    i = 1;
    while(i < argc)
    {
        if ( strcmp(argv[i], "-b1") == 0 && i+1 < argc )
        {
             sprintf(flashpairAfilename, "%s.hex", argv[i+1]);
             i += 2;
        }
        else if ( strcmp(argv[i], "-b2") == 0 && i+1 < argc )
        {
             sprintf(flashpairBfilename, "%s.hex", argv[i+1]);
             i += 2;
        }
        else if ( strcmp(argv[i], "-r") == 0 && i+1 < argc )
        {
             sprintf(app,  "%s.rsc", argv[i+1]);
             i += 2;
        }
        else
        {
            printf("------------------------------------------\n");
            printf("Usage: flash.lku -b1 <BankA Hex filename> -b2 <BankB Hex filename> -r <Resident App filename>\n");
            printf("(In the switches, do not type the extensions or the dot)\n");
            printf("------------------------------------------\n\n");
            exit(-1);
        }
    }

    memset(data, 0, 1024);
    printf("\nErase All EEPROM .....\n");
    nvman->eepromWrite(nvman, data, 0, 1024);

    printf("\nErasing all sectors in Flash Pair A.....");
    fflush(stdout);

    result = flashdevA->erase(flashdevA, 0xFF);

    if (result != NO_ERROR)
    {
        printf("****Error erasing flash****\n");
        errorwarn = !NO_ERROR;
    }

    /* In the 830, all Flash is in TP 3 Region 3 Bank 3 */
    printf("\nErasing all sectors in Flash Pair B.....");
    fflush(stdout);

    result = flashdevB->erase(flashdevB, 0xFF);

    if (result != NO_ERROR)
    {
        printf("****Error erasing flash****\n");
        errorwarn = !NO_ERROR;
    }


    if (strlen(flashpairBfilename))
    {
          /* In the 830, all Flash is in TP 3 Region 3 Bank 3 */
       printf("\nFlashing Pair A for boot .....");
       result = flash_boot(flashpairBfilename);
       if (result == NO_ERROR)
       {
           printf("\nPair A flashed for boot.");
       }
       else
       {
           printf("\nError flashing Pair A for boot.");
           errorwarn = !NO_ERROR;
       }
       fflush(stdout);
    }

    if ( strlen(flashpairAfilename) )
    {
       printf("\nFlashing Pair B for boot .....");
       result = flash_boot(flashpairAfilename);
       if (result == NO_ERROR)
       {
           printf("\nPair B flashed for boot.");
       }
       else
       {
           printf("\nError flashing Pair B for boot.");
           errorwarn = !NO_ERROR;
       }
       fflush(stdout);
    }

    if ( strlen(app) )
    {
       printf("\nFlashing resident application in Pair A.....");
       result = flash_app(flashdevA, app);
       if (result == NO_ERROR)
       {
           printf("\nResident application flashed in Pair A.");
       }
       else
       {
           printf("\nError flashing the Resident application in Pair A.");
           errorwarn = !NO_ERROR;
       }
       fflush(stdout);
    }

    if (errorwarn)
    {
        printf("\nDone. Error(s) occurred.\n");
    }
    else
    {
        printf("\nFlash complete. No errors detected.\n");
    }

    exit (result);
}

int init_sys(void)
{
    error_t        result;
    I2c_t          I2c;
    Asc_t          Asc;
    EepromDevice_t Eeprom;
    IdChip_t       IdChip;
    Os_t           Os;
    Tm_t           Tm;
    Cons_t         Cons;
    Ilut_t         Ilut;

    /*
    ** create the ILUT
    */
    result = IlutCreate(&Ilut);

    result = OsCreate(&Os, "FLASH OS", 1);
    Os->start(Os);

    /*
    ** create the ID chip, we may need info from it
    */
    result = IdChipCreate(&IdChip, IDCHIP_LOOKUP);

    result = TmCreate(&Tm, TM_LOOKUP);

    /*
    ** create an asc on the console port if not already done
    */
    result = AscCreate(&Asc,         /* asc instance name */
                       CONS_ASC_LOOKUP,
                       CONS_ASC_NUM,       /* Instance of ASC HW we control */
                       CONS_ASC_INTR_LEVEL,/* from glcemb\target.h */
                       CONS_BAUD_RATE,     /* baud rate */
                       CONS_DATA_BITS,     /* 8 data bits */
                       CONS_PARITY,        /* no parity */
                       CONS_STOP_BITS,     /* 1.0 stop bits */
                       FALSE,              /* do not use flow control */
                       CONS_BUFFER_SIZE);  /* 128 byte receive buffer */

    result = ConsCreate(&Cons, CLI_CONS_LOOKUP, CONS_IF_TYPE_ASC);

    /*
    ** default printing to the cliConsole
    */
    Cons->setPrint(Cons);

    I2cCreate(&I2c,
              "I2c0",
              I2C0,                     /* the one connected to micro */
              I2C0_INTR_LEVEL,          /* from glcemb\target.h */
              FALSE,                    /*  slow mode == 100kbps */
              3);                       /* max 3 retries */

    result = EepromCreate(&Eeprom, EEPROM_LOOKUP, 0);

    result = FlashCreate(&flashdevA, FLASH_LOOKUP, AMD_BASE1, TRUE);

    result = FlashCreate(&flashdevB, "flashdevB", AMD_BASE2, TRUE);

    result = NVManCreate(&nvman, NVMAN_LOOKUP);

    return 0;
}


/*
   Programs the flash banks. In the 830, both Flash addresses are
   in Region 3, Bank 3 of the TP3 Memory Map.
*/

int flash_boot(char* boot)
{
    FILE           *boot_fp;    /* boot file descriptor */
    HEX_ROM_STRUCT rom_data;
    char           raw_data[MAX_STRING_LENGTH];
    int            entries, rows;

    boot_fp = fopen(boot, "r");

    if (boot_fp == NULL)
    {
        fprintf(stderr, "boot flash: cannot open data file %s\n", boot);
        return -1;
    }

    printf("boot flash: data file %s opened\n",boot);

    /************************************************************************
    * read lines from the hex datafile, this has the following syntax:
    *
    *   address 1{byte}32
    *
    * where n{...}m means at least n terms and no more than m
    */

    rows = 0;

    while (1)
    {
        /* Design a loop to simply read in sixteen represented bytes and
           stuff in the addresses that sscanf expects. */

        inint = fgetc(boot_fp);

        if (inint == EOF)
        {
            fprintf(stderr, "boot flash: data file %s ended unexpectedly.\n", boot);
            return(-1);
        }

        inch = (unsigned char)inint;


fprintf(stderr, "boot flash: data file %s did not contain a quantity of bytes to be programmed divisible by sixteen.\n", boot);



        if (fgets(raw_data, MAX_STRING_LENGTH, boot_fp) == NULL)
        {
            /* Should only hit newlines, and not hit the end of the file,
               from checking the hex file we will be using. According to ANSI C,
               fgets does not return NULL due to hitting a newline.
               Thus variable length lines should not pose a problem.
               */
            break;
        }
        /* Some of the line lengths in the hex file might be shorter than
           32 depicted bytes of data. */
        /* According to ANSI C, if fgets reaches a newline within the length
           that it is told to get, it will include the newline at the end of
           the string and then stop there. */
        /* So, strip-off newline chars from the end of the string of raw data
           that fgets returns, if there were any. */

        i = strlen(raw_data)-1;
        while (
               (raw_data[i] == 0x0A)
               ||
               (raw_data[i] == 0x0D)
                 )
        {
               raw_data[i] = 0;
            i -= 1;
        }


        /* Add code to check for EOF from sscanf */
        entries = sscanf(raw_data,
                         "%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x",
                         &rom_data.address,
                         &rom_data.row[0],
                         &rom_data.row[1],
                         &rom_data.row[2],
                         &rom_data.row[3],
                         &rom_data.row[4],
                         &rom_data.row[5],
                         &rom_data.row[6],
                         &rom_data.row[7],
                         &rom_data.row[8],
                         &rom_data.row[9],
                         &rom_data.row[10],
                         &rom_data.row[11],
                         &rom_data.row[12],
                         &rom_data.row[13],
                         &rom_data.row[14],
                         &rom_data.row[15],
                         &rom_data.row[16],
                         &rom_data.row[17],
                         &rom_data.row[18],
                         &rom_data.row[19],
                         &rom_data.row[20],
                         &rom_data.row[21],
                         &rom_data.row[22],
                         &rom_data.row[23],
                         &rom_data.row[24],
                         &rom_data.row[25],
                         &rom_data.row[26],
                         &rom_data.row[27],
                         &rom_data.row[28],
                         &rom_data.row[29],
                         &rom_data.row[30],
                         &rom_data.row[31],
                         &rom_data.row[32]);

        /* don't count address, 0 <= rom_data.entries <= 32 */
        rom_data.entries = entries - 1;

        /**********************************************************************
         * If we read some data, either program or verify it
         */

        if (rom_data.entries > 0)
        {
            program_row(rom_data, bank);

            if ((rows++ % 0x100) == 0)
            {
               printf("flash: Programmed upto 0x%x\r", rom_data.address);
               fflush(stdout);
              }
        }
    }

    fclose(boot_fp);
    printf("\nflash: Operation complete\n");

    return 0;
}


/* programs a row from the bank?.hex file. The bank? file
   name is incorrect. The hardware banks are 3 and 1. So
   bank1 from command line refers to bank3 in hardware.
   Bank2 from command line refers to bank1 in hardware. */
void program_row(HEX_ROM_STRUCT row, int bank)
{
    int   i;
    long  data;
    long  *base;

    base = (long *)(row.address);  /* initialise address pointer */

    for (i = 0; i < (row.entries/4); i++)
    {
        data=(long)row.row[i*4]+
             ((long)(row.row[(i*4)+1])<<8)+
             ((long)(row.row[(i*4)+2])<<16)+
             ((long)(row.row[(i*4)+3])<<24);

        if ( bank == 1 )
        {
             /* program the flash word. Address offset is shifted 2 bits to
               the left to account for A0,A1 from bus not connected, A2 - A19
               from bus are connected to flash'es A0 - A17. 5555 -> 15555,
               2AAA -> AAAA */
             *((volatile unsigned long *) FLASH_BASEA + 0x15555) = DATA32_AA;
             *((volatile unsigned long *) FLASH_BASEA + 0xAAAA)  = DATA32_55;
             *((volatile unsigned long *) FLASH_BASEA + 0x15555) = DATA32_A0;
             *((volatile unsigned long *) base) = data;
        }
        else if (bank == 2 )
        {
             /* program the flash word. Address offset is shifted 2 bits to
               the left to account for A0,A1 from bus not connected, A2 - A19
               from bus are connected to flash'es A0 - A17. 5555 -> 15555,
               2AAA -> AAAA*/
             *((volatile unsigned long *) FLASH_BASEB0 + 0x15555) = DATA32_AA;
             *((volatile unsigned long *) FLASH_BASEB0 + 0xAAAA)  = DATA32_55;
             *((volatile unsigned long *) FLASH_BASEB0 + 0x15555) = DATA32_A0;
             *((volatile unsigned long *) base) = data;
        }
        else
        {
             /* program the flash word. Address offset is shifted 2 bits to
               the left to account for A0,A1 from bus not connected, A2 - A19
               from bus are connected to flash'es A0 - A17. 5555 -> 15555,
               2AAA -> AAAA*/
             *((volatile unsigned long *) FLASH_BASEB1 + 0x15555) = DATA32_AA;
             *((volatile unsigned long *) FLASH_BASEB1 + 0xAAAA)  = DATA32_55;
             *((volatile unsigned long *) FLASH_BASEB1 + 0x15555) = DATA32_A0;
             *((volatile unsigned long *) base) = data;
        }

        /* poll for completion */
        while ((*((volatile unsigned long *) base) & MASK_BIT7) != (data & MASK_BIT7))
        {
            ;
        }

        if (*((volatile unsigned long *)base) != data)
           printf("\nProgram failed at address %x : read %x but expected %x\n",(int)base,(int)*((volatile unsigned long *) base),(int)data);

        base++;
    }
}

int flash_app(FlashDevice_t fl_ptr, char* app)
{
    FILE           *app_fp;    /* boot file descriptor */
    long           *data;
    int            re, len;
    SectorParams_t params;
    int            count;
    unsigned long  crc1, crc2;
    int            len1;
    unsigned char  c1, c2, c3, c4;
    unsigned char* s;

    fl_ptr->getSectorParams(fl_ptr, &params, &count);

    app_fp = fopen(app, "rb");

    if (app_fp == NULL)
    {
        printf("flash: cannot open data file %s\n", app);
        return -1;
    }

    re = fseek(app_fp, 0L, SEEK_END);
    if (re)
    {
        printf("flash: cannot fseek data file %s\n", app);
        return -1;
    }

    len = (int) ftell(app_fp);
    if (len <=0)
    {
        printf("flash: cannot read data file %s\n", app);
        return -1;
    }

    re = fseek (app_fp, 0L, SEEK_SET);
    if (re)
    {
        printf("flash: cannot fseek data file %s\n", app);
        return -1;
    }

    s = (unsigned char*) malloc(len);
    re = fread(s, 1, len, app_fp);
    if ( re != len )
    {
        printf("flash: cannot read data file %s\n", app);
        return -1;
    }

    c1 = s[0]; c2 = s[1]; c3 = s[2]; c4 = s[3];
    crc1 = c1 << 24 | c2 << 16 | c3 << 8 | c4;

    c1 = s[4]; c2 = s[5]; c3 = s[6]; c4 = s[7];
    len1 = c1 << 24 | c2 << 16 | c3 << 8 | c4;

    if ( len1 != len-8 )
    {
        printf("flash: the resident (%s) image is NOT good!\n", app);
        return -1;
    }

    crc2 = crc32(s+8, len1);

    if ( crc1 != crc2 )
    {
        printf("flash: the resident (%s) image is NOT good!\n", app);
        return -1;
    }

    free(s);

    if ( len % 4 == 0 )
         len = len / 4;
    else
         len = len / 4 + 1;

    data = (long*) malloc(len*4);
    if (data == NULL)
    {
        printf("flash: cannot alloc memory for data file %s\n", app);
        return -1;
    }

    re = fseek (app_fp, 0L, SEEK_SET);
    if (re)
    {
        printf("flash: cannot fseek data file %s\n", app);
        return -1;
    }

    re = fread(data, 4, len, app_fp);
    if ( re != len )
    {
        printf("flash: cannot read data file %s\n", app);
        return -1;
    }

    /* addr = 0x7FF00000; */
    /* Flash resident application from the first sector */
    /* re = flash->program(flash, (long*)addr, data, len); */
    re = fl_ptr->program(fl_ptr, (long*)params->sctrAddr, data, len);
    if ( re != SUCCESS )
    {
        printf("flash: cannot write data file to FLASH %s\n", app);
        return -1;
    }

    free(data);

    fclose(app_fp);

    s = (unsigned char*)params->sctrAddr;

    c1 = s[0]; c2 = s[1]; c3 = s[2]; c4 = s[3];
    crc1 = c1 << 24 | c2 << 16 | c3 << 8 | c4;

    c1 = s[4]; c2 = s[5]; c3 = s[6]; c4 = s[7];
    len1 = c1 << 24 | c2 << 16 | c3 << 8 | c4;

    crc2 = crc32(s+8, len1);

    if ( crc1 != crc2 )
    {
        printf("flash: Flashing resident (%s) image failed!\n", app);
        return -1;
    }

    return 0;
}

#define CAL_CRC(A) crc = (crc << 4) ^ crc_mask[((crc >> 28) ^ \
                         ((unsigned long)A >> 4)) & 0x0f],    \
                   crc = (crc << 4) ^ crc_mask[((crc >> 28) ^ \
                         ((unsigned long)A)) & 0x0f]

unsigned long crc32(unsigned char* data, unsigned long length)
{
    unsigned long i;
    unsigned long crc;
    unsigned char *ptr;

    static const unsigned long crc_mask[] =
    {
        0x00000000L,
        0x04c11db7L,
        0x09823b6eL,
        0x0d4326d9L,
        0x130476dcL,
        0x17c56b6bL,
        0x1a864db2L,
        0x1e475005L,
        0x2608edb8L,
        0x22c9f00fL,
        0x2f8ad6d6L,
        0x2b4bcb61L,
        0x350c9b64L,
        0x31cd86d3L,
        0x3c8ea00aL,
        0x384fbdbdL
    };

    /* init the start value */
    crc = 0xffffffffL;

    ptr = data;
    for (i = 0; i<length; i++)
    {
         CAL_CRC(ptr[i]);
    }

    return crc;
}

back

First posted Oct 30, 2003

Hosted by www.Geocities.ws

1