Openwrt下修改flash文件的例子

来源:互联网 发布:淘宝规格怎么设置 编辑:程序博客网 时间:2024/04/24 18:51

/*

steps:


* main() @mac.c
 * read_mac_all()
  * handle_mac_all(MAP_READ, mac_array)
   * scan_mtd_info(scriptname) // check /proc/yyy for word "xxxxx" and return the device name(scriptname) under /dev
   * map_file(scriptname, MAP_READ, &ptr, &len, &ifd)
      fstat(ifd, &sbuf)
      ptr = mmap(0, sbuf.st_size, prot, MAP_SHARED, ifd, 0) // map file ifd(scriptname) to memory
   * for each line in script file
    * do operation

 

*/

 

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <mtd-api.h>


#define MAP_READ  1
#define MAP_RDWR  2

#undef MAC_DEBUG
//#define MAC_DEBUG
#ifdef MAC_DEBUG
#define mac_debug(x...) fprintf(stderr,x)
#else
#define mac_debug(x...)
#endif

static int
map_file(char *filename, int opcode, char **pptr, int *plen, int *pfd)
{
    int ifd = -1;
    char *ptr;
    int flags;
    off_t offset;

    flags = (opcode == MAP_READ) ? O_RDONLY : O_RDWR;
    ifd = open(filename, flags);
    if (ifd < 0) {
        mac_debug("Can't open %s: %s/n", filename, strerror(errno));
        return MAC_ERROR_SYS;
    }

    /*returns mtd->size */
    offset = lseek(ifd, 0, SEEK_END);
    if (offset < 0) {
        mac_debug("Can't lseek %s: %s/n", filename, strerror(errno));
        close(ifd);
        return MAC_ERROR_SYS;
    }
    ptr = malloc(offset);
    if (ptr == NULL) {
        mac_debug("Can't alloc memory,%s/n", strerror(errno));
        close(ifd);
        return MAC_ERROR_SYS;
    }

    if (lseek(ifd, 0, SEEK_SET) == -1) {
        mac_debug("Can't alloc memory,%s/n", strerror(errno));
        close(ifd);
        return MAC_ERROR_SYS;
    }

    if (read(ifd, ptr, offset) != offset) {
        mac_debug("Can't read %s: %s/n", filename, strerror(errno));
        close(ifd);
        return MAC_ERROR_SYS;
    }

    *pptr = ptr;
    *plen = offset;
    *pfd = ifd;

    return MAC_ERROR_OK;
}

static int
unmap_file(int opcode, char *ptr, int len, int ifd)
{
    int ret = MAC_ERROR_OK;

    if (opcode == MAP_RDWR) {
        struct erase_info_user erase;
        erase.start = 0;
        erase.length = len;

        if (lseek(ifd, 0, SEEK_SET) == -1) {
            ret = MAC_ERROR_SYS;
            mac_debug("Can't seek the MTD device./n");
            goto done;
        }
        /* erase the blocks to write */
        if (ioctl(ifd, MEMERASE, &erase) < 0) {
            ret = MAC_ERROR_SYS;
            mac_debug("Can't erase the MTD device./n");
            goto done;
        }

        if (write(ifd, ptr, len) != len) {
            ret = MAC_ERROR_SYS;
            mac_debug(" Can't write %s/n", strerror(errno));
            goto done;
        }
    }

  done:
    return ret;
}

static void
close_file(char *ptr, int ifd)
{
    free(ptr);
    close(ifd);
}

static int
readline_from_buffer(char *s, int n, char *ptr, int *pos, int total)
{
    register char *cs;

    memset(s, 0, n);
    cs = s;
    while ((--n > 0) && (*pos < total)) {
        if ((*cs++ = *(ptr + (*pos)++)) == '/n')
            break;
    }
    *cs = '/0';
    return (*pos >= total && cs == s) ? 0 : 1;
}

static int
scan_mtd_info(char *filename)
{
    FILE *fp;
    char line[256];
    int i;
    int ret = MAC_ERROR_MTD_FILE;

    if ((fp = fopen("/proc/yyy", "r+")) == NULL) {
        return MAC_ERROR_SYS;
    }

    while (fgets(line, sizeof (line), fp) != NULL) {
        if (strstr(line, "xxxxxx") != NULL) {
            sscanf(line, "mtd%d: ", &i);
            sprintf(filename, "/dev/mtd%d", i);
            ret = MAC_ERROR_OK;
            break;
        }
    }
    fclose(fp);

    return ret;
}

static int
handle_mac_by_ifindex(int opcode, unsigned int ifindex, unsigned char mac_buf[])
{
    char line[256];
    unsigned int mac[6];
    char *ptr;
    int pos;
    int len;
    int ifd = -1;
    char *start;
    int unit;
    int oldlen, newlen;
    char scriptname[32];
    int ret;

    if (ifindex >= TSMAC_MAX_ETH_UNITS)
        return MAC_ERROR_ILLEGAL;

    if ((ret = scan_mtd_info(scriptname)) != MAC_ERROR_OK) {
        return ret;
    }
    if ((ret = map_file(scriptname, opcode, &ptr, &len, &ifd)) != MAC_ERROR_OK) {
        return ret;
    }

    pos = 0;
    start = ptr;
    ret = MAC_ERROR_NOT_FOUND;
    while (readline_from_buffer(line, sizeof (line), ptr, &pos, len)) {
        if (sscanf(line, " set ethaddr%d %02x:%02x:%02x:%02x:%02x:%02x",
                   &unit, &mac[0], &mac[1], &mac[2], &mac[3],
                   &mac[4], &mac[5]) == 7) {
            if (unit == ifindex) {
                switch (opcode) {
                case MAP_RDWR:
                    oldlen = strlen(line);
                    memset(line, ' ', oldlen);
                    sprintf(line,
                            "set ethaddr%d %02x:%02x:%02x:%02x:%02x:%02x",
                            unit, mac_buf[0], mac_buf[1], mac_buf[2],
                            mac_buf[3], mac_buf[4], mac_buf[5]);
                    newlen = strlen(line);
                    /*remove ending /n' */
                    *(line + newlen) = ' ';
                    /*add ending /n' */
                    *(line + oldlen - 1) = '/n';
                    memcpy(start, line, oldlen);
                    ret = MAC_ERROR_OK;
                    break;
                case MAP_READ:
                    /*implicit type conversion */
                    mac_buf[0] = mac[0];
                    mac_buf[1] = mac[1];
                    mac_buf[2] = mac[2];
                    mac_buf[3] = mac[3];
                    mac_buf[4] = mac[4];
                    mac_buf[5] = mac[5];
                    ret = MAC_ERROR_OK;
                    break;
                }
            }
        }
        start = ptr + pos;
    }
    if ((opcode == MAP_RDWR) && (ret == MAC_ERROR_OK))
        ret = unmap_file(opcode, ptr, len, ifd);

    close_file(ptr, ifd);

    return ret;
}

static int
handle_mac_all(int opcode, unsigned char mac_array[][6])
{
    char line[256];
    char scriptname[32];
    unsigned int mac[6];
    char *ptr;
    int pos;
    int len;
    int ifd = -1;
    char *start;
    int unit;
    int oldlen, newlen;
    int ret;
    int result[TSMAC_MAX_ETH_UNITS];

    if ((ret = scan_mtd_info(scriptname)) != MAC_ERROR_OK) {
        return ret;
    }

    if ((ret = map_file(scriptname, opcode, &ptr, &len, &ifd)) != MAC_ERROR_OK) {
        return ret;
    }

    pos = 0;
    start = ptr;

    for (unit = 0; unit < TSMAC_MAX_ETH_UNITS; ++unit) {
        result[unit] = 0;
    }

    while (readline_from_buffer(line, sizeof (line), ptr, &pos, len)) {
        if (sscanf(line, " set ethaddr%d %02x:%02x:%02x:%02x:%02x:%02x",
                   &unit, &mac[0], &mac[1], &mac[2], &mac[3],
                   &mac[4], &mac[5]) == 7) {
            if (unit < TSMAC_MAX_ETH_UNITS) {
                switch (opcode) {
                case MAP_RDWR:
                    oldlen = strlen(line);
                    memset(line, ' ', oldlen);
                    sprintf(line,
                            "set ethaddr%d %02x:%02x:%02x:%02x:%02x:%02x",
                            unit, mac_array[unit][0], mac_array[unit][1],
                            mac_array[unit][2], mac_array[unit][3],
                            mac_array[unit][4], mac_array[unit][5]);
                    newlen = strlen(line);
                    *(line + newlen) = ' ';
                    *(line + oldlen - 1) = '/n';
                    memcpy(start, line, oldlen);
                    result[unit] = 1;
                    break;
                case MAP_READ:
                    /*implicit type conversion */
                    mac_array[unit][0] = mac[0];
                    mac_array[unit][1] = mac[1];
                    mac_array[unit][2] = mac[2];
                    mac_array[unit][3] = mac[3];
                    mac_array[unit][4] = mac[4];
                    mac_array[unit][5] = mac[5];
                    result[unit] = 1;
                    break;
                }
            }
        }
        start = ptr + pos;
    }

    ret = MAC_ERROR_OK;
    for (unit = 0; unit < TSMAC_MAX_ETH_UNITS; ++unit) {
        if (result[unit] != 1) {
            ret = MAC_ERROR_NOT_FOUND;
            break;
        }
    }

    if ((opcode == MAP_RDWR) && (ret == MAC_ERROR_OK))
        ret = unmap_file(opcode, ptr, len, ifd);

    close_file(ptr, ifd);

    return ret;
}

/*
INPUT:
    ifindex(in) - index of interface.
    mac (out)   - mac address buffer. 6 byte unsigned char array.
Return:
    0       - ok
    <0      - error code
*/

int
read_mac_by_ifindex(unsigned int ifindex, unsigned char mac[])
{
    return handle_mac_by_ifindex(MAP_READ, ifindex, mac);
}

/*
INPUT:
    ifindex(in) - index of interface.
    mac (in)   - mac address buffer. 6 byte unsigned char array.
Return:
    0       - ok
    <0      - error code
*/
int
write_mac_by_ifindex(unsigned int ifindex, unsigned char mac[])
{
    return handle_mac_by_ifindex(MAP_RDWR, ifindex, mac);
}

/*
INPUT:
    mac_array (in)  - mac address array.
Return:
    0       - ok
    <0      - error code
*/
int
write_mac_all(unsigned char mac_array[][6])
{
    return handle_mac_all(MAP_RDWR, mac_array);
}

/*
INPUT:
    mac_array (out) - mac address array.
Return:
    0       - ok
    <0      - error code
*/
int
read_mac_all(unsigned char mac_array[][6])
{
    return handle_mac_all(MAP_READ, mac_array);
}

#undef TEST
#define TEST
#ifdef TEST
static void
print_mac(unsigned char *mac)
{
    printf("%02x:%02x:%02x:%02x:%02x:%02x/n",
           mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}

int
main()
{
    //read/write all
    {
        int i;
        unsigned char mac[TSMAC_MAX_ETH_UNITS][6];
        unsigned char new_mac[TSMAC_MAX_ETH_UNITS][6] = {
            {0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
            {0x00, 0x02, 0x02, 0x03, 0x04, 0x05},
            {0x00, 0x03, 0x02, 0x03, 0x04, 0x05}
        };

        if (read_mac_all(mac)) {
            printf("read all error/n");
            return -1;
        }
        printf("read all/n");
        for (i = 0; i < TSMAC_MAX_ETH_UNITS; ++i) {
            print_mac(mac[i]);
        }

        if (write_mac_all(new_mac)) {
            printf("write all error/n");
            return -1;
        }
        if (read_mac_all(mac)) {
            printf("write all error/n");
            return -1;
        }
        printf("after write all/n");
        for (i = 0; i < TSMAC_MAX_ETH_UNITS; ++i) {
            print_mac(mac[i]);
        }
    }
    // read/write by index
    {
        unsigned char mac[6];
        unsigned char new_mac[6] = { 0x00, 0x05, 0x05, 0x05, 0x05, 0x06 };

        printf("read by index/n");
        if (read_mac_by_ifindex(2, mac)) {
            printf(" read_mac_by_ifindex error/n");
            return -1;
        }
        print_mac(mac);

        if (write_mac_by_ifindex(2, new_mac)) {
            printf(" write_mac_by_ifindex error/n");
            return -1;
        }
        printf("after by index/n");
        if (read_mac_by_ifindex(2, mac)) {
            printf(" read_mac_by_ifindex error/n");
            return -1;
        }
        print_mac(mac);
    }

    return 0;
}
#endif

原创粉丝点击