diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2019-02-04 14:00:50 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2019-02-06 08:31:13 +0100 |
commit | d60e9aa5f5a21374950dfd15bedafeccf76c3b1d (patch) | |
tree | e50c6df4a5f508ecfcd8fe727b5c23a397ec4189 /drivers/misc | |
parent | 1455e221ae3023270a4716be6b47c038249955fd (diff) | |
download | barebox-d60e9aa5f5a21374950dfd15bedafeccf76c3b1d.tar.gz barebox-d60e9aa5f5a21374950dfd15bedafeccf76c3b1d.tar.xz |
misc: fix /dev/mem size
The size of /dev/mem was limited to the lower half of the 64bit address
range. This is unfortunate since on some architectures (MIPS64, namely)
the upper half contains meaningful addresses. We can't just set /dev/mem
to its real size since that's bigger than the maximum loff_t. Set the
DEVFS_IS_CHARACTER_DEV flag instead for /dev/mem which will cause the
size checks in lseek and friends to be bypassed.
Also fix the size the memory device is registered with. We used to set
the size to ~0, but the real size is one higher. To do this explicitly
register the device with specifying the end address rather than the
size. This will make /dev/mem appear with filesize 0, but so does
/dev/zero already.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/mem.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/drivers/misc/mem.c b/drivers/misc/mem.c index 60981a3e98..6dd7f687c9 100644 --- a/drivers/misc/mem.c +++ b/drivers/misc/mem.c @@ -21,8 +21,18 @@ static int mem_probe(struct device_d *dev) dev->priv = cdev; cdev->name = (char*)dev->resource[0].name; - cdev->size = min_t(unsigned long long, resource_size(&dev->resource[0]), - S64_MAX); + if (dev->resource[0].start == 0 && dev->resource[0].end == ~0) { + /* + * Special case for /dev/mem. We can't express it's size as it's + * outside of our address range. Set DEVFS_IS_CHARACTER_DEV to + * bypass size checks. + */ + cdev->size = 0; + cdev->flags = DEVFS_IS_CHARACTER_DEV; + } else { + cdev->size = resource_size(&dev->resource[0]); + } + cdev->ops = &memops; cdev->dev = dev; @@ -38,7 +48,26 @@ static struct driver_d mem_drv = { static int mem_init(void) { - add_mem_device("mem", 0, ~0, IORESOURCE_MEM_WRITEABLE); + struct device_d *dev; + struct resource res = { + .start = 0, + .end = ~0, + .flags = IORESOURCE_MEM, + .name = "mem", + }; + int ret; + + dev = device_alloc("mem", DEVICE_ID_DYNAMIC); + if (!dev) + return -ENOMEM; + + dev->resource = xmemdup(&res, sizeof(res)); + dev->num_resources = 1; + + ret = platform_device_register(dev); + if (ret) + return ret; + return platform_driver_register(&mem_drv); } device_initcall(mem_init); |