OpenCores
URL https://opencores.org/ocsvn/funbase_ip_library/funbase_ip_library/trunk

Subversion Repositories funbase_ip_library

[/] [funbase_ip_library/] [trunk/] [TUT/] [ip.swp.api/] [openmcapi/] [1.0/] [util/] [memtool.c] - Rev 145

Compare with Previous | Blame | View Log

/*
 * Copyright (c) 2011, Mentor Graphics Corporation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name of the <ORGANIZATION> nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * 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 HOLDER 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.
 */
 
/* XXX would be better to stay closer to dd(1) parameters and functionality */
 
#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <getopt.h>
#include <limits.h>
 
#define DEVMCOMM "/dev/mcomm"
 
typedef int (*command_t)(void *mem, size_t bytes, unsigned long base);
 
static ssize_t read_mcomm_size(void)
{
	ssize_t size;
	unsigned long val;
	FILE *f;
	int rc;
 
	f = fopen("/sys/devices/mcomm.0/size", "r");
	if (!f)
		return -ENOENT;
 
	rc = fscanf(f, "%lx", &val);
	size = val;
	if (rc < 0) {
		perror("fscanf");
		size = -EINVAL;
	}
 
	fclose(f);
 
	return size;
}
 
static void *map(int fd, ssize_t bytes, unsigned long off)
{
	void *mem = NULL;
 
	mem = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_SHARED, fd, off);
	if (mem == MAP_FAILED) {
		perror("mmap");
		return NULL;
	}
 
	return mem;
}
 
static void unmap(int fd, void *mem, int bytes)
{
	close(fd);
	munmap(mem, bytes);
}
 
void usage(char *name)
{
	printf("Usage: %s [options] <command>\n"
	       "Options:\n"
		   "  -d, --device=<path>\n"
		   "          Device to open.\n"
		   "\n"
		   "  -o, --offset=<offset>\n"
		   "          Offset (in bytes) at which to start. Must be page-aligned.\n"
		   "\n"
		   "  -l, --length=<length>\n"
		   "          Number of bytes on which to operate.\n"
		   "          Defaults to the entire mcomm region, or 4K for other devices.\n"
		   "\n"
	       "Commands:\n"
		   "  clear: zeroes memory\n"
		   "  dump:  dump memory contents as hex\n",
		   name);
	exit(1);
}
 
static int clear(void *mem, size_t bytes, unsigned long base)
{
	memset(mem, 0, bytes);
	return 0;
}
 
static int dump(void *addr, size_t bytes, unsigned long base)
{
	const int COLS = 4;
	unsigned int *data = addr;
	int pos, i;
 
    for (pos = 0; sizeof(int) * pos < bytes; pos += COLS) {
        printf("%08lx:", base + pos * sizeof(int));
        for (i = 0; i < COLS; i++)
            printf(" %08x", data[pos + i]);
        printf("\n");
    }
 
	return 0;
}
 
int main(int argc, char *argv[])
{
	unsigned long offset = 0;
	unsigned long length = ULONG_MAX;
	char *dev = "/dev/mem";
	unsigned int *mem;
	command_t command = NULL;
	ssize_t bytes;
	int dev_fd;
	int c;
	int rc = 0;
	unsigned int pagesize;
 
	while (1) {
		static struct option long_options[] = {
			{"device", 1, 0, 'd'},
			{"offset", 1, 0, 'o'},
			{"length", 1, 0, 'l'},
			{NULL, 0, 0, 0},
		};
		int option_index = 0;
 
		c = getopt_long(argc, argv, "d:o:l:", long_options, &option_index);
		if (c == -1)
			break;
 
		switch (c) {
		case 'd':
			dev = optarg;
			break;
 
		case 'o':
			offset = strtoul(optarg, NULL, 0);
			if (offset == ULONG_MAX) {
				printf("couldn't use offset\n");
				usage(argv[0]);
			}
			pagesize = getpagesize();
			if (offset & (pagesize-1)) {
				printf("offset must be a multiple of 0x%x\n", pagesize);
				usage(argv[0]);
			}
			break;
 
		case 'l':
			length = strtoul(optarg, NULL, 0);
			if (length == ULONG_MAX) {
				printf("couldn't use length\n");
				usage(argv[0]);
			}
			break;
 
		default:
			printf("%d\n", c);
			usage(argv[0]);
		}
	}
 
	if (optind < argc) {
		char *cmdstr = argv[optind];
 
		if (strcmp(cmdstr, "dump") == 0)
			command = dump;
		else if (strcmp(cmdstr, "clear") == 0)
			command = clear;
 
		optind++;
	}
 
	if ((optind < argc) || (command == NULL)) {
		usage(argv[0]);
	}
 
	dev_fd = open(dev, O_RDWR);
	if (dev_fd < 0) {
		rc = errno;
		perror("open");
		return rc;
	}
 
	if (strncmp(dev, DEVMCOMM, strlen(DEVMCOMM)) == 0) {
		bytes = read_mcomm_size();
		if (bytes <= 0) {
			perror("read mcomm size");
			goto out;
		}
	} else {
		bytes = 1<<12;
	}
 
	if (length < bytes)
		bytes = length;
 
	mem = map(dev_fd, bytes, offset);
	if (mem == NULL) {
		rc = -1;
		goto out;
	}
 
	rc = command(mem, bytes, offset);
 
	unmap(dev_fd, mem, bytes);
 
out:
	return rc;
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.