All pastes #880541 Raw Edit

Stuff

public c v1 · immutable
#880541 ·published 2008-01-29 20:31 UTC
rendered paste body
//// revision history:// this program is based on pe.c and modified to parse the command line.// if no arguments are present, the parameters are simply dumped.//// NOTE: the caller must put complex values in "" or '' when changing //   environment values.//#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdlib.h>#include <stdio.h>//// our environment structure, local to our program only//struct envvar {  char name[32];  char value[256];};// #define DATAFLASH_SIZE      0x21000// #define DATAFLASH_ALIGNMENT 0x00200#define START_OF_UBOOT_ENV  0x20000#define SIZE_OF_UBOOT_ENV   0x01000//// a buffer to hold the entire dataflash// ok, well, if you remove the __attribute__ for the forced alignment,//  bad things happen to the CRC when it's written back://    it could be skipped, or it could be missing one byte.//unsigned char uboot_env[SIZE_OF_UBOOT_ENV] __attribute__((aligned (4)));//// function to read nbuf bytes into buf in one pass for the caller.//int blockread (int fd, unsigned char *buf, int nbuf){  int nleft = nbuf;  int nread;  int offs = 0;  while (nleft > 0 && ((nread = read (fd, buf + offs, nleft)) > 0))  {    nleft -= nread;    offs += nread;  }  return nbuf - nleft;}//// from the crc32.c in this directory//extern unsigned long crc32 (unsigned long crc,                             const unsigned char *buf,                             unsigned int len);//// function to dump the current environment.//void dumpVars (struct envvar env[], int nenv){  int i;  for (i = 0; i < nenv; i++)  {    printf ("%s = %s\n", env[i].name, env[i].value);  }}//// parse: open the named file 'name' and fill in up to 'nenv' records// from the u-boot environment file.//// note: the environment file is expected to be NO MORE THAN 4K (0x1000) bytes!//int parse (const char *name, struct envvar env[], int nenv){  int fd;  int rc = 0;  off_t offs;  if ((fd = open (name, O_RDONLY)) > -1)  {    int nr;    if ((offs = lseek (fd, START_OF_UBOOT_ENV, SEEK_SET)) == START_OF_UBOOT_ENV)    {      //       // we're going to assume the read will complete in one pass.      //      if ((nr = blockread (fd, uboot_env, sizeof uboot_env)) == sizeof uboot_env)      {        int r, p, i;        unsigned long crc;        printf ("Current CRC = 0x%08x\n", * (unsigned long *) uboot_env);        p = 4;    // skip the CRC        r = 0;        crc = crc32 (0, uboot_env + sizeof crc, sizeof uboot_env - sizeof crc);        printf ("Calculated CRC = 0x%08x\n", crc);        // go until we hit the end of the buffer or the max # of env vars        while ((uboot_env[p] != '\0') && (r < nenv))        {          i = 0;          // parse the name          do          {            if (i < sizeof env[r].name / sizeof env[r].name[0])              env[r].name[i++] = uboot_env[p];            else            {              fprintf (stderr, "Invalid environment partition.  "                      "Try a different raw device (0, i = %d).\n", i);              exit (-1);            }          }          while (uboot_env[p++] != '=');          // terminate the name          env[r].name[i-1] = '\0';          // printf ("parsed environment name: %s\n", env[r].name);          i = 0;          // parse the value          do          {            if (i < sizeof env[r].value / sizeof env[r].value[0])              env[r].value[i++] = uboot_env[p];            else            {              fprintf (stderr, "Invalid environment partition.  "                      "Try a different raw device (1, i = %d).\n", i);              exit (-1);            }          }          while (uboot_env[p++] != '\0');          // terminate the value          env[r].value[i] = '\0';          // printf ("parsed environment value: %s\n", env[r].value);          // move to the next var          r++;        }        rc = r;      }          else      {        rc = -1;      }    }    else    {      rc = -1;    }    close (fd);  }  else    rc = -1;  return rc;}//// write the modified environment back to the file.//int write_env (const char *name, struct envvar env[], int nenv){  int fd;  off_t offs;  int rc = 0;  unsigned long crc;  if ((fd = open (name, O_WRONLY)) > -1)  {    int nw;    //    // position the file to the spot we will write to.    // note this is the aligned block offset.  it will contain the area    //  we modified, plus some that we didn't.    //    if ((offs = lseek (fd, START_OF_UBOOT_ENV, SEEK_SET)) == START_OF_UBOOT_ENV)    {      int i;      int bufoff = sizeof crc;      //      // clear the buffer where we're going to start writing.      // remember that this is past 'block_offs' into the dataflash memory      //  space.      //      memset (uboot_env, 0, sizeof uboot_env);      //       // write out all the variables.      // the format is      //  name=value\0      //  ...      //  \0      //      for (i = 0; i < nenv; i++)      {        nw = sprintf (uboot_env + bufoff, "%s=%s", env[i].name, env[i].value);        //         // the '+1' is because of the memset above:        //  since the buffer already has all zeros in it, it's not        //   necessary to put another one.        //        // recall that sprintf does NOT include the NUL byte in it's        //  return value.        //        bufoff += nw + 1;      }      //      // compute the CRC and then store it.      //      crc = crc32 (0, uboot_env + sizeof crc, sizeof uboot_env - sizeof crc);      memcpy (uboot_env, &crc, sizeof crc);      printf ("New CRC = 0x%08x\n", crc);      //       // we're all done.      // write the partial buffer back to the file.      // we don't want to write the whole thing because we don't      //  want to have to write over part of u-boot.  so do the      //  minimal write we can and still write back the whole thing.      //      rc = write (fd, uboot_env, sizeof uboot_env);      //      // temp      //      close (fd);      fd = open ("u-boot_env.dat", O_CREAT | O_WRONLY, 0666);      rc = write (fd, uboot_env, sizeof uboot_env);      close (fd);    }    else    {      rc = -1;    }  }  else  {    rc = -1;  }  return rc;}//// findVar looks for 'name' as the .name field in the env[] array.// nvars is the number of elements in env[].//int findVar (const char *name, struct envvar env[], int nenv){  int rc = -1;  int i;  //   // loop over env[] and find where name == env[i].name.  // terminate if we find a match, at which time we terminate the loop.  //  for (i = 0; i < nenv && rc == -1; i++)    if (strcmp (name, env[i].name) == 0)      rc = i;  return rc;}int main (int argc, char *argv[]){  if (argc >= 2)  {    struct envvar env[128];    int i, nenv;    nenv = parse (argv[1], env, sizeof env / sizeof env[0]);    if (nenv > 0)    {      //       // successfully parse the list.      // rc is the number of elements in the list.      //      // see if the user wants to modify anything (in which case argc > 2) or      //  just wants a dump (argc == 2)      //      if (argc > 2)      {        if (argc % 2 == 0)        {          //          // for argv[i] (i even && i >= 2):          //    argv[i] is the name of a parameter          //    argv[i+1] is the value to be set.          //          int i, idx;          for (i = 2; i < argc; i += 2)          {            idx = findVar (argv[i], env, nenv);            if (idx >= 0)            {              strcpy (env[idx].value, argv[i+1]);            }            else            {              //               // we add a new variable.              //              strcpy (env[nenv].name, argv[i]);              strcpy (env[nenv].value, argv[i+1]);              //              // add one to the variable count.              //              nenv++;            }          }          i = write_env (argv[1], env, nenv);        }        else        {          printf ("Error: argc not an even number: argc == %d\n", argc);        }      }      else      {        dumpVars (env, nenv);      }    }    else    {      printf ("Error: empty environment list\n");    }  }  return EXIT_SUCCESS;}