/*====================================================================* * * Copyright (c) 2013 Qualcomm Atheros, Inc. * * All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted (subject to the limitations * in the disclaimer below) provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * 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. * * * Neither the name of Qualcomm Atheros nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE * COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER * OR CONTRIBUTORS 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. * *--------------------------------------------------------------------*/ /*====================================================================* * * getpib.c - PIB Data Extractor * * Contributor(s): * Charles Maier <cmaier@qca.qualcomm.com> * *--------------------------------------------------------------------*/ /*====================================================================* * system header files; *--------------------------------------------------------------------*/ #include <unistd.h> #include <stdlib.h> #include <limits.h> #include <string.h> #include <ctype.h> /*====================================================================* * custom header files; *--------------------------------------------------------------------*/ #include "../tools/getoptv.h" #include "../tools/memory.h" #include "../tools/number.h" #include "../tools/error.h" #include "../tools/types.h" #include "../tools/flags.h" #include "../tools/files.h" #include "../pib/pib.h" #include "../nvm/nvm.h" /*====================================================================* * custom source files; *--------------------------------------------------------------------*/ #ifndef MAKEFILE #include "../tools/getoptv.c" #include "../tools/putoptv.c" #include "../tools/version.c" #include "../tools/uintspec.c" #include "../tools/basespec.c" #include "../tools/todigit.c" #include "../tools/hexout.c" #include "../tools/error.c" #include "../tools/checksum32.c" #include "../tools/fdchecksum32.c" #endif #ifndef MAKEFILE #include "../nvm/nvmseek2.c" #endif /*====================================================================* * constants; *--------------------------------------------------------------------*/ #define GETPIB_COMMA ' ' #define GETPIB_TOOBIG "object '%s' exceeds extent of " SIZE_T_SPEC " bytes" #define GETPIB_NOSIZE "object '%s' has no length" #define GETPIB_VERBOSE (1 << 0) #define GETPIB_SILENCE (1 << 1) #define GETPIB_NEWLINE (1 << 2) /*====================================================================* * * void getmemory (byte const * memory, size_t extent, char const * object, size_t length); * *--------------------------------------------------------------------*/ static void getmemory (byte const * memory, size_t extent, char const * object, size_t length) { if (length > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, length); } hexout (memory, length, ':', '\0', stdout); return; } /*====================================================================* * * void getstring (byte const * memory, size_t extent, char const * object, size_t length); * *--------------------------------------------------------------------*/ static void getstring (byte const * memory, size_t extent, char const * object, size_t length) { char const * string = (char const *) (memory); if (length > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, length); } while (isprint (* string) && (length--)) { putc (* string++, stdout); } return; } /*====================================================================* * * void snatch (int argc, char const * argv [], byte const * memory, size_t extent, char comma); * * extract and print the specified data objects from memory; comma * delimits consecutive objects on output; * *--------------------------------------------------------------------*/ static void snatch (int argc, char const * argv [], byte const * memory, size_t extent, char comma) { size_t length = 0; size_t offset = 0; if (! (argc) || ! (* argv)) { error (1, ECANCELED, "Need an offset"); } offset = (size_t) (basespec (* argv, 16, sizeof (uint32_t))); if (offset > extent) { error (1, ECANCELED, "offset " SIZE_T_SPEC " exceeds extent of " SIZE_T_SPEC " bytes", offset, extent); } memory += offset; extent -= offset; argc--; argv++; while ((argc) && (* argv)) { char const * object = * argv; argc--; argv++; if (! strcmp (object, "byte")) { uint8_t * number = (uint8_t *) (memory); if (sizeof (* number) > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } printf ("%u", * number); memory += sizeof (* number); extent -= sizeof (* number); } else if (! strcmp (object, "word")) { uint16_t * number = (uint16_t *) (memory); if (sizeof (* number) > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } printf ("%u", LE16TOH (* number)); memory += sizeof (* number); extent -= sizeof (* number); } else if (! strcmp (object, "long")) { uint32_t * number = (uint32_t *) (memory); if (sizeof (* number) > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } printf ("%u", LE32TOH (* number)); memory += sizeof (* number); extent -= sizeof (* number); } else if (! strcmp (object, "huge")) { uint64_t * number = (uint64_t *) (memory); if (sizeof (* number) > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } printf ("%llu", LE64TOH (* number)); memory += sizeof (* number); extent -= sizeof (* number); } #if 1 else if (! strcmp (object, "xbyte")) { uint8_t * number = (uint8_t *) (memory); if (sizeof (* number) > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } printf ("0x%02X", * number); memory += sizeof (* number); extent -= sizeof (* number); } else if (! strcmp (object, "xword")) { uint16_t * number = (uint16_t *) (memory); if (sizeof (* number) > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } printf ("0x%04X", LE16TOH (* number)); memory += sizeof (* number); extent -= sizeof (* number); } else if (! strcmp (object, "xlong")) { uint32_t * number = (uint32_t *) (memory); if (sizeof (* number) > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } printf ("0x%08X", LE32TOH (* number)); memory += sizeof (* number); extent -= sizeof (* number); } else if (! strcmp (object, "xhuge")) { uint64_t * number = (uint64_t *) (memory); if (sizeof (* number) > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } printf ("0x%016llX", LE64TOH (* number)); memory += sizeof (* number); extent -= sizeof (* number); } #endif else if (! strcmp (object, "mac")) { length = ETHER_ADDR_LEN; if (length > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } getmemory (memory, extent, object, length); memory += length; extent -= length; } else if (! strcmp (object, "key")) { length = PIB_KEY_LEN; if (length > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } getmemory (memory, extent, object, length); memory += length; extent -= length; } else if (! strcmp (object, "hfid")) { length = PIB_HFID_LEN; if (length > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } getstring (memory, extent, object, length); memory += length; extent -= length; } #if 1 else if (! strcmp (object, "adminusername") || ! strcmp (object, "adminpassword") || ! strcmp (object, "accessusername")) { length = PIB_NAME_LEN + 1; if (length > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } getstring (memory, extent, object, length); memory += length; extent -= length; } else if (! strcmp (object, "accesspassword")) { length = PIB_HFID_LEN + 1; if (length > extent) { error (1, ECANCELED, GETPIB_TOOBIG, object, extent); } getstring (memory, extent, object, length); memory += length; extent -= length; } else if (! strcmp (object, "username") || ! strcmp (object, "password") || ! strcmp (object, "url")) { length = PIB_TEXT_LEN + 1; getstring (memory, extent, object, length); memory += length; extent -= length; } #endif else if (! strcmp (object, "data")) { if (! * argv) { error (1, EINVAL, GETPIB_NOSIZE, object); } length = (unsigned) (uintspec (* argv, 1, extent)); hexout (memory, length, 0, 0, stdout); memory += length; extent -= length; argc--; argv++; } else if (! strcmp (object, "text")) { if (! * argv) { error (1, EINVAL, GETPIB_NOSIZE, object); } length = (unsigned) (uintspec (* argv, 1, extent)); getstring (memory, extent, object, length); memory += length; extent -= length; argc--; argv++; } else if (! strcmp (object, "skip")) { if (! * argv) { error (1, EINVAL, GETPIB_NOSIZE, object); } length = (unsigned) (uintspec (* argv, 1, extent)); memory += length; extent -= length; argc--; argv++; continue; } else { error (1, ENOTSUP, "%s", object); } if ((argc) && (* argv)) { putc (comma, stdout); } } return; } /*====================================================================* * * signed pibimage1 (int argc, char const * argv [], char comma); * * read an entire flat parameter file into memory, edit it, save * it and display it; * * Contributor(s): * Charles Maier <cmaier@qca.qualcomm.com> * *--------------------------------------------------------------------*/ static signed pibimage1 (int argc, char const * argv [], char comma) { signed fd; off_t extent; byte * memory; if ((fd = open (* argv, O_BINARY | O_RDWR)) == - 1) { error (1, errno, FILE_CANTOPEN, * argv); } if ((extent = lseek (fd, 0, SEEK_END)) == - 1) { error (1, errno, FILE_CANTSIZE, * argv); } if (lseek (fd, 0, SEEK_SET)) { error (1, errno, FILE_CANTHOME, * argv); } if (! (memory = malloc (extent))) { error (1, errno, FILE_CANTLOAD, * argv); } if (read (fd, memory, extent) != extent) { error (1, errno, FILE_CANTREAD, * argv); } close (fd); snatch (argc - 1, argv + 1, memory, extent, comma); free (memory); return (0); } /*====================================================================* * * signed pibimage2 (int argc, char const * argv [], char comma); * * read an entire flat parameter file into memory, edit it, save * it and display it; * * Contributor(s): * Charles Maier <cmaier@qca.qualcomm.com> * *--------------------------------------------------------------------*/ static signed pibimage2 (int argc, char const * argv [], char comma) { struct nvm_header2 header; signed fd; off_t extent; byte * memory; if ((fd = open (* argv, O_BINARY | O_RDWR)) == - 1) { error (1, errno, FILE_CANTOPEN, * argv); } if (nvmseek2 (fd, * argv, & header, NVM_IMAGE_PIB)) { error (1, errno, "Can't find PIB image in %s", * argv); } extent = LE32TOH (header.ImageLength); if (! (memory = malloc (extent))) { error (1, errno, FILE_CANTLOAD, * argv); } if (read (fd, memory, extent) != extent) { error (1, errno, FILE_CANTREAD, * argv); } close (fd); snatch (argc - 1, argv + 1, memory, extent, comma); free (memory); return (0); } /*====================================================================* * * signed function (int argc, char const * argv [], char comma); * * call an appropriate parameter edit function based on the file * header; * * older parameter files are flat with their own header; newer ones * are image chains where one of image contains the parameter block; * * * Contributor(s): * Charles Maier <cmaier@qca.qualcomm.com> * *--------------------------------------------------------------------*/ static signed function (int argc, char const * argv [], char comma) { uint32_t version; signed status; signed fd; if ((fd = open (* argv, O_BINARY | O_RDWR)) == - 1) { error (1, errno, FILE_CANTOPEN, * argv); } if (read (fd, & version, sizeof (version)) != sizeof (version)) { error (1, errno, FILE_CANTREAD, * argv); } close (fd); if (LE32TOH (version) == 0x00010001) { status = pibimage2 (argc, argv, comma); } else { status = pibimage1 (argc, argv, comma); } return (status); } /*====================================================================* * * int main (int argc, char const * argv []); * * *--------------------------------------------------------------------*/ int main (int argc, char const * argv []) { static char const * optv [] = { "c:qvn", "file offset type [size]\n\n\tstandard-length types are 'byte'|'word'|'long'|'huge'|'hfid'|'mac'|'key'\n\tvariable-length types are 'data'|'text'|'skip' and need a size", "PIB Data Extractor", "c c\tobject separator is (c) [" LITERAL (GETPIB_COMMA) "]", "n\tappend newline", "q\tquiet mode", "v\tverbose mode", (char const *) (0) }; flag_t flags = (flag_t) (0); char comma = GETPIB_COMMA; signed c; optind = 1; opterr = 1; while (~ (c = getoptv (argc, argv, optv))) { switch (c) { case 'c': comma = * optarg; break; case 'n': _setbits (flags, GETPIB_NEWLINE); break; case 'q': _setbits (flags, GETPIB_SILENCE); break; case 'v': _setbits (flags, GETPIB_VERBOSE); break; default: break; } } argc -= optind; argv += optind; if ((argc) && (* argv)) { function (argc, argv, comma); if (_anyset (flags, GETPIB_NEWLINE)) { putc ('\n', stdout); } } return (0); }