diff options
-rw-r--r-- | sys/boot/fdt/dts/sheevaplug.dts | 9 | ||||
-rw-r--r-- | sys/conf/files | 2 | ||||
-rw-r--r-- | sys/dev/fdt/fdt_common.h | 1 | ||||
-rw-r--r-- | sys/dev/fdt/fdt_slicer.c | 115 | ||||
-rw-r--r-- | sys/geom/geom_flashmap.c | 255 | ||||
-rw-r--r-- | sys/sys/slicer.h | 51 |
6 files changed, 433 insertions, 0 deletions
diff --git a/sys/boot/fdt/dts/sheevaplug.dts b/sys/boot/fdt/dts/sheevaplug.dts index 55ca032..3d347da 100644 --- a/sys/boot/fdt/dts/sheevaplug.dts +++ b/sys/boot/fdt/dts/sheevaplug.dts @@ -88,7 +88,16 @@ bank-width = <2>; device-width = <1>; + slice@0 { + reg = <0x0 0x200000>; + label = "u-boot"; + read-only; + }; + slice@200000 { + reg = <0x200000 0x1fe00000>; + label = "root"; + }; }; }; diff --git a/sys/conf/files b/sys/conf/files index aca59fb..288d5bc 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1223,6 +1223,7 @@ dev/fatm/if_fatm.c optional fatm pci dev/fb/splash.c optional splash dev/fdt/fdt_common.c optional fdt dev/fdt/fdt_pci.c optional fdt pci +dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static dev/fdt/fdtbus.c optional fdt dev/fdt/simplebus.c optional fdt @@ -2388,6 +2389,7 @@ geom/geom_disk.c standard geom/geom_dump.c standard geom/geom_event.c standard geom/geom_fox.c optional geom_fox +geom/geom_flashmap.c optional fdt cfi | fdt nand geom/geom_io.c standard geom/geom_kern.c standard geom/geom_map.c optional geom_map diff --git a/sys/dev/fdt/fdt_common.h b/sys/dev/fdt/fdt_common.h index 0bedb91..7947428 100644 --- a/sys/dev/fdt/fdt_common.h +++ b/sys/dev/fdt/fdt_common.h @@ -32,6 +32,7 @@ #ifndef _FDT_COMMON_H_ #define _FDT_COMMON_H_ +#include <sys/slicer.h> #include <contrib/libfdt/libfdt_env.h> #include <dev/ofw/ofw_bus.h> #include <machine/fdt.h> diff --git a/sys/dev/fdt/fdt_slicer.c b/sys/dev/fdt/fdt_slicer.c new file mode 100644 index 0000000..d32d159 --- /dev/null +++ b/sys/dev/fdt/fdt_slicer.c @@ -0,0 +1,115 @@ +/*- + * Copyright (c) 2012 Semihalf. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/slicer.h> + +#include <dev/fdt/fdt_common.h> + +#define DEBUG +#undef DEBUG + +#ifdef DEBUG +#define debugf(fmt, args...) do { printf("%s(): ", __func__); \ + printf(fmt,##args); } while (0) +#else +#define debugf(fmt, args...) +#endif + +int +flash_fill_slices(device_t dev, struct flash_slice *slices, int *slices_num) +{ + char *slice_name; + phandle_t dt_node, dt_child; + u_long base, size; + int i; + ssize_t name_len; + + /* + * We assume the caller provides buffer for FLASH_SLICES_MAX_NUM + * flash_slice structures. + */ + if (slices == NULL) { + *slices_num = 0; + return (ENOMEM); + } + + dt_node = ofw_bus_get_node(dev); + for (dt_child = OF_child(dt_node), i = 0; dt_child != 0; + dt_child = OF_peer(dt_child)) { + + if (i == FLASH_SLICES_MAX_NUM) { + debugf("not enough buffer for slice i=%d\n", i); + break; + } + + /* + * Retrieve start and size of the slice. + */ + if (fdt_regsize(dt_child, &base, &size) != 0) { + debugf("error during processing reg property, i=%d\n", + i); + continue; + } + + if (size == 0) { + debugf("slice i=%d with no size\n", i); + continue; + } + + /* + * Retrieve label. + */ + name_len = OF_getprop_alloc(dt_child, "label", sizeof(char), + (void **)&slice_name); + if (name_len <= 0) { + /* Use node name if no label defined */ + name_len = OF_getprop_alloc(dt_child, "name", sizeof(char), + (void **)&slice_name); + if (name_len <= 0) { + debugf("slice i=%d with no name\n", i); + slice_name = NULL; + } + } + + /* + * Fill slice entry data. + */ + slices[i].base = base; + slices[i].size = size; + slices[i].label = slice_name; + i++; + } + + *slices_num = i; + return (0); +} diff --git a/sys/geom/geom_flashmap.c b/sys/geom/geom_flashmap.c new file mode 100644 index 0000000..c657123 --- /dev/null +++ b/sys/geom/geom_flashmap.c @@ -0,0 +1,255 @@ +/*- + * Copyright (c) 2012 Semihalf + * Copyright (c) 2009 Jakub Klama <jakub.klama@uj.edu.pl> + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/endian.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/fcntl.h> +#include <sys/malloc.h> +#include <sys/bio.h> +#include <sys/bus.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/slicer.h> + +#include <geom/geom.h> +#include <geom/geom_slice.h> +#include <geom/geom_disk.h> +#include <dev/nand/nand_dev.h> + +#define FLASHMAP_CLASS_NAME "Flashmap" + +struct g_flashmap_slice { + off_t sl_start; + off_t sl_end; + const char *sl_name; + + STAILQ_ENTRY(g_flashmap_slice) sl_link; +}; + +STAILQ_HEAD(g_flashmap_head, g_flashmap_slice); + +static void g_flashmap_print(struct g_flashmap_slice *); +static int g_flashmap_modify(struct g_geom *, const char *, + int, struct g_flashmap_head *); +static int g_flashmap_start(struct bio *); +static int g_flashmap_ioctl(struct g_provider *, u_long, void *, + int, struct thread *); +static void g_flashmap_dumpconf(struct sbuf *, const char *, + struct g_geom *, struct g_consumer *, struct g_provider *); +static struct g_geom *g_flashmap_taste(struct g_class *, + struct g_provider *, int); +static void g_flashmap_config(struct gctl_req *, struct g_class *, + const char *); +static int g_flashmap_load(device_t, struct g_flashmap_head *); + +MALLOC_DECLARE(M_FLASHMAP); +MALLOC_DEFINE(M_FLASHMAP, "geom_flashmap", "GEOM flash memory slicer class"); + +static void +g_flashmap_print(struct g_flashmap_slice *slice) +{ + + printf("%08llx-%08llx: %s (%lluKB)\n", slice->sl_start, slice->sl_end, + slice->sl_name, (slice->sl_end - slice->sl_start) / 1024); +} + +static int +g_flashmap_modify(struct g_geom *gp, const char *devname, int secsize, + struct g_flashmap_head *slices) +{ + struct g_flashmap_slice *slice; + int i, error; + + g_topology_assert(); + + i = 0; + STAILQ_FOREACH(slice, slices, sl_link) { + if (bootverbose) { + printf("%s: slice ", devname); + g_flashmap_print(slice); + } + + error = g_slice_config(gp, i++, G_SLICE_CONFIG_CHECK, + slice->sl_start, + slice->sl_end - slice->sl_start + 1, + secsize, "%ss.%s", gp->name, slice->sl_name); + + if (error) + return (error); + } + + i = 0; + STAILQ_FOREACH(slice, slices, sl_link) { + error = g_slice_config(gp, i++, G_SLICE_CONFIG_SET, + slice->sl_start, + slice->sl_end - slice->sl_start + 1, + secsize, "%ss.%s", gp->name, slice->sl_name); + + if (error) + return (error); + } + + return (0); +} + +static int +g_flashmap_start(struct bio *bp) +{ + + return (0); +} + +static void +g_flashmap_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp, + struct g_consumer *cp __unused, struct g_provider *pp) +{ + struct g_slicer *gsp; + + gsp = gp->softc; + g_slice_dumpconf(sb, indent, gp, cp, pp); +} + +static int +g_flashmap_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, + struct thread *td) +{ + struct g_consumer *cp; + struct g_geom *gp; + + if (cmd != NAND_IO_GET_CHIP_PARAM) + return (ENOIOCTL); + + cp = LIST_FIRST(&pp->geom->consumer); + if (cp == NULL) + return (ENOIOCTL); + gp = cp->provider->geom; + if (gp->ioctl == NULL) + return (ENOIOCTL); + + return (gp->ioctl(cp->provider, cmd, data, fflag, td)); +} + + +static struct g_geom * +g_flashmap_taste(struct g_class *mp, struct g_provider *pp, int flags) +{ + struct g_geom *gp = NULL; + struct g_consumer *cp; + struct g_flashmap_head head; + struct g_flashmap_slice *slice, *slice_temp; + device_t dev; + int nslices, size; + + g_trace(G_T_TOPOLOGY, "flashmap_taste(%s,%s)", mp->name, pp->name); + g_topology_assert(); + + if (flags == G_TF_NORMAL && + !strcmp(pp->geom->class->name, FLASHMAP_CLASS_NAME)) + return (NULL); + + gp = g_slice_new(mp, FLASH_SLICES_MAX_NUM, pp, &cp, NULL, 0, + g_flashmap_start); + if (gp == NULL) + return (NULL); + + STAILQ_INIT(&head); + + do { + size = sizeof(device_t); + if (g_io_getattr("NAND::device", cp, &size, &dev)) + break; + + nslices = g_flashmap_load(dev, &head); + if (nslices == 0) + break; + + g_flashmap_modify(gp, cp->provider->name, + cp->provider->sectorsize, &head); + } while (0); + + g_access(cp, -1, 0, 0); + + STAILQ_FOREACH_SAFE(slice, &head, sl_link, slice_temp) { + free(slice, M_FLASHMAP); + } + + if (LIST_EMPTY(&gp->provider)) { + g_slice_spoiled(cp); + return (NULL); + } + return (gp); +} + +static void +g_flashmap_config(struct gctl_req *req, struct g_class *mp, const char *verb) +{ + + gctl_error(req, "unknown config verb"); +} + +static int +g_flashmap_load(device_t dev, struct g_flashmap_head *head) +{ + struct flash_slice *slices; + struct g_flashmap_slice *slice; + uint32_t i, buf_size; + int nslices = 0; + + buf_size = sizeof(struct flash_slice) * FLASH_SLICES_MAX_NUM; + slices = malloc(buf_size, M_FLASHMAP, M_WAITOK | M_ZERO); + if (flash_fill_slices(dev, slices, &nslices) == 0) { + for (i = 0; i < nslices; i++) { + slice = malloc(sizeof(struct g_flashmap_slice), + M_FLASHMAP, M_WAITOK); + + slice->sl_name = slices[i].label; + slice->sl_start = slices[i].base; + slice->sl_end = slices[i].base + slices[i].size - 1; + + STAILQ_INSERT_TAIL(head, slice, sl_link); + } + } + + free(slices, M_FLASHMAP); + return (nslices); +} + +static struct g_class g_flashmap_class = { + .name = FLASHMAP_CLASS_NAME, + .version = G_VERSION, + .taste = g_flashmap_taste, + .dumpconf = g_flashmap_dumpconf, + .ioctl = g_flashmap_ioctl, + .ctlreq = g_flashmap_config, +}; + +DECLARE_GEOM_CLASS(g_flashmap_class, g_flashmap); diff --git a/sys/sys/slicer.h b/sys/sys/slicer.h new file mode 100644 index 0000000..a41861e --- /dev/null +++ b/sys/sys/slicer.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 2012 Semihalf. + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _FLASH_SLICER_H_ +#define _FLASH_SLICER_H_ + +#include <sys/types.h> + +#define FLASH_SLICES_MAX_NUM 8 +#define FLASH_SLICES_MAX_NAME_LEN (32 + 1) + +#define FLASH_SLICES_FLAG_NONE 0 +#define FLASH_SLICES_FLAG_RO 1 /* Read only */ + +struct flash_slice { + off_t base; + off_t size; + char *label; + unsigned int flags; +}; + +#ifdef _KERNEL +int flash_fill_slices(device_t, struct flash_slice *, int *); +#endif /* _KERNEL */ + +#endif /* _FLASH_SLICER_H_ */ |