From 665291e693efd1fd2955c6f8bfb89956711b0aef Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Sun, 15 Jul 2007 13:50:04 +0200 Subject: [PATCH] implement memmap(). With this function we can get a pointer to directly memory mapped devices like nor flash or RAM. Useful for bootm where we save one memcopy when the image is mappable --- commands/partition.c | 1 + common/partition.c | 17 +++++++++++++++++ drivers/cfi_flash.c | 1 + fs/devfs.c | 8 ++++++++ fs/fs.c | 19 +++++++++++++++++++ include/driver.h | 5 +++++ include/fs.h | 6 ++++++ lib/driver.c | 22 ++++++++++++++++++++++ 8 files changed, 79 insertions(+) diff --git a/commands/partition.c b/commands/partition.c index 0a363c0cc..42f487009 100644 --- a/commands/partition.c +++ b/commands/partition.c @@ -41,6 +41,7 @@ static void dev_del_partitions(struct device_d *physdev) dev = device_from_spec_str(buf, NULL); if (dev) { struct partition *part = dev->type_data; + printf("unregister %s %s\n", dev->name, dev->id); unregister_device(dev); free(part); } else diff --git a/common/partition.c b/common/partition.c index 5e9297df8..b3b27d5de 100644 --- a/common/partition.c +++ b/common/partition.c @@ -44,6 +44,22 @@ static int part_erase(struct device_d *dev, size_t count, unsigned long offset) return -1; } +static int part_memmap(struct device_d *dev, void **map, int flags) +{ + struct partition *part = dev->type_data; + int ret; + + if (part->physdev->driver->memmap) { + ret = part->physdev->driver->memmap(part->physdev, map, flags); + if (ret) + return ret; + *map = (void *)((unsigned long)*map + part->offset); + return 0; + } + + return -1; +} + static ssize_t part_read(struct device_d *dev, void *buf, size_t count, unsigned long offset, ulong flags) { struct partition *part = dev->type_data; @@ -82,6 +98,7 @@ struct driver_d part_driver = { .read = part_read, .write = part_write, .erase = part_erase, + .memmap = part_memmap, }; static int partition_init(void) diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c index 4e6820db1..ed08b1049 100644 --- a/drivers/cfi_flash.c +++ b/drivers/cfi_flash.c @@ -518,6 +518,7 @@ static struct driver_d cfi_driver = { .read = mem_read, .write = cfi_write, .erase = cfi_erase, + .memmap = generic_memmap_ro, .info = cfi_info, }; diff --git a/fs/devfs.c b/fs/devfs.c index 5e60362f3..aafcc3443 100644 --- a/fs/devfs.c +++ b/fs/devfs.c @@ -50,6 +50,13 @@ static int devfs_erase(struct device_d *_dev, FILE *f, size_t count, unsigned lo return dev_erase(dev, count, offset); } +static int devfs_memmap(struct device_d *_dev, FILE *f, void **map, int flags) +{ + struct device_d *dev = f->inode; + + return dev_memmap(dev, map, flags); +} + static int devfs_open(struct device_d *_dev, FILE *file, const char *filename) { struct device_d *dev = get_device_by_id(filename + 1); @@ -146,6 +153,7 @@ static struct fs_driver_d devfs_driver = { .closedir = devfs_closedir, .stat = devfs_stat, .erase = devfs_erase, + .memmap = devfs_memmap, .flags = FS_DRIVER_NO_DEV, .drv = { .type = DEVICE_TYPE_FS, diff --git a/fs/fs.c b/fs/fs.c index 51e59309d..57d75ddb3 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -516,6 +516,25 @@ int erase(int fd, size_t count, unsigned long offset) return errno; } +void *memmap(int fd, int flags) +{ + struct device_d *dev; + struct fs_driver_d *fsdrv; + FILE *f = &files[fd]; + void *ret = NULL; + + dev = f->dev; + + fsdrv = (struct fs_driver_d *)dev->driver->type_data; + + if (fsdrv->memmap) + errno = fsdrv->memmap(dev, f, &ret, flags); + else + errno = -EINVAL; + + return ret; +} + int close(int fd) { struct device_d *dev; diff --git a/include/driver.h b/include/driver.h index e360778c0..1be59100d 100644 --- a/include/driver.h +++ b/include/driver.h @@ -53,6 +53,7 @@ struct driver_d { ssize_t (*read) (struct device_d*, void* buf, size_t count, ulong offset, ulong flags); ssize_t (*write) (struct device_d*, const void* buf, size_t count, ulong offset, ulong flags); ssize_t (*erase) (struct device_d*, size_t count, unsigned long offset); + int (*memmap)(struct device_d*, void **map, int flags); void (*info) (struct device_d *); void (*shortinfo) (struct device_d *); @@ -100,6 +101,7 @@ struct driver_d *get_driver_by_name(const char *name); ssize_t dev_read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags); ssize_t dev_write(struct device_d *dev, const void *buf, size_t count, ulong offset, ulong flags); ssize_t dev_erase(struct device_d *dev, size_t count, unsigned long offset); +int dev_memmap(struct device_d *dev, void **map, int flags); /* These are used by drivers which work with direct memory accesses */ ssize_t mem_read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags); @@ -108,5 +110,8 @@ ssize_t mem_write(struct device_d *dev, const void *buf, size_t count, ulong off /* Use this if you have nothing to do in your drivers probe function */ int dummy_probe(struct device_d *); +int generic_memmap_ro(struct device_d *dev, void **map, int flags); +int generic_memmap_rw(struct device_d *dev, void **map, int flags); + #endif /* DRIVER_H */ diff --git a/include/fs.h b/include/fs.h index f0d63bfd6..752aca5fe 100644 --- a/include/fs.h +++ b/include/fs.h @@ -67,6 +67,8 @@ struct fs_driver_d { int (*erase)(struct device_d *dev, FILE *f, size_t count, unsigned long offset); + int (*memmap)(struct device_d *dev, FILE *f, void **map, int flags); + struct driver_d drv; unsigned long flags; @@ -110,6 +112,10 @@ int umount(const char *pathname); /* not-so-standard erase */ int erase(int fd, size_t count, unsigned long offset); +void *memmap(int fd, int flags); + +#define PROT_READ 1 +#define PROT_WRITE 2 #define LS_RECURSIVE 1 #define LS_SHOWARG 2 diff --git a/lib/driver.c b/lib/driver.c index 5ec67b491..8f6c2ffaa 100644 --- a/lib/driver.c +++ b/lib/driver.c @@ -292,6 +292,28 @@ ssize_t dev_erase(struct device_d *dev, size_t count, unsigned long offset) return -ENOSYS; } +ssize_t dev_memmap(struct device_d *dev, void **map, int flags) +{ + if (dev->driver->memmap) + return dev->driver->memmap(dev, map, flags); + errno = -ENOSYS; + return -ENOSYS; +} + +int generic_memmap_ro(struct device_d *dev, void **map, int flags) +{ + if (flags & PROT_WRITE) + return -EACCES; + *map = (void *)dev->map_base; + return 0; +} + +int generic_memmap_rw(struct device_d *dev, void **map, int flags) +{ + *map = (void *)dev->map_base; + return 0; +} + int dummy_probe(struct device_d *dev) { return 0;