merge geom redboot and map

rozhuk.im at gmail.com rozhuk.im at gmail.com
Sun Apr 3 17:49:04 UTC 2011


Hi all!


I need Your help with testing and adding code to FreeBSD sources.

Not tested:
- redboot/FIS
- map search by key


Build options:
options	GEOM_MAP			# 
options	GEOM_MAP_NO_REDBOOT	# turn off redboot/fis support



Static mappings in hints:
===========================================================
# Area 0: 30000000 to 3002FFFF (0 - 196607, size: 196607) : "Bootloader":
u-boot
# Area 1: 30030000 to 3003FFFF (196608 - 262143, size: 65535) : "Factory":
u-boot env
# Area 2: 30040000 to 3023FFFF (262144 - 2359295, size: 2097151) : "Kernel"
# Area 3: 30240000 to 307FFFFF (2359296 - 8388607, size: 6029311) : "RootFS"

hint.map.0.at =	"flash/spi0"
hint.map.0.start =	0x00000000
hint.map.0.end =	0x00030000
hint.map.0.name =	"bootldr"
hint.map.0.readonly =1

hint.map.1.at =	"flash/spi0"
hint.map.1.start =	0x00030000
hint.map.1.end =	0x00040000
hint.map.1.name =	"bootldr_env"
hint.map.1.readonly =1

hint.map.2.at =	"flash/spi0"
hint.map.2.start =	0x00040000
hint.map.2.end =	0x00240000
hint.map.2.name =	"kernel"
hint.map.2.readonly =0

hint.map.3.at =	"flash/spi0"
hint.map.3.start =	0x00240000
hint.map.3.end =	0x00800000
hint.map.3.name =	"rootfs"
hint.map.3.readonly =0
===========================================================



Boot log:
===========================================================
...
GEOM_MAP: /dev/flash/spi0: 0x00000000-0x00030000, offset=0x0, R/O,
size=196608 bytes at: "/dev/map/spi0bootldr"
GEOM_MAP: /dev/flash/spi0: 0x00030000-0x00040000, offset=0x0, R/O,
size=65536 bytes at: "/dev/map/spi0bootldr_env"
GEOM_MAP: /dev/flash/spi0: 0x00040000-0x00240000, offset=0x0, R/W,
size=2097152 bytes at: "/dev/map/spi0kernel"
GEOM_MAP: /dev/flash/spi0: 0x00240000-0x00800000, offset=0x0, R/W,
size=6029312 bytes at: "/dev/map/spi0rootfs"
GEOM_MAP: /dev/flash/spi0: FIS/RedBoot not exist, incompatible blksize=0
GEOM_MAP: /dev/flash/spi0: mediasize=8388608, secsize=65536, blksize=0
...
GEOM_MAP: /dev/da0: FIS/RedBoot not exist, incompatible blksize=0
GEOM_MAP: /dev/da0p1: FIS/RedBoot not exist, incompatible blksize=0
GEOM_MAP: /dev/gpt/Documental: FIS/RedBoot not exist, incompatible blksize=0
GEOM_MAP: /dev/gptid/ca70d533-5759-11e0-b900-001a4d559a42: FIS/RedBoot not
exist, incompatible blksize=0
Mounting local file systems:GEOM_MAP: /dev/md0: FIS/RedBoot not exist,
incompatible blksize=0
GEOM_MAP: /dev/ufsid/4d98a59e587419bf: FIS/RedBoot not exist, incompatible
blksize=0
GEOM_MAP: /dev/md0: FIS/RedBoot not exist, incompatible blksize=0
GEOM_MAP: /dev/ufsid/4d98a967c292e50d: FIS/RedBoot not exist, incompatible
blksize=0
GEOM_MAP: /dev/md1: FIS/RedBoot not exist, incompatible blksize=0
GEOM_MAP: /dev/md1: FIS/RedBoot not exist, incompatible blksize=0
GEOM_MAP: /dev/ufsid/4d98a968674909d4: FIS/RedBoot not exist, incompatible
blksize=0
...
===========================================================



Files:
 - geom_map.c - source of geom node
 - options_add_geom_map.txt - patch to add build options
 - subr_hints.txt - kernel api to read 64bit values from hints
http://www.freebsd.org/cgi/query-pr.cgi?pr=156130



 
--
Rozhuk Ivan
  


> -----Original Message-----
> From: Aleksandr Rybalko [mailto:ray at ddteam.net]
> Sent: Thursday, March 31, 2011 5:28 AM
> To: Rozhuk.IM at gmail.com
> Cc: rozhuk.im at gmail.com; 'Warner Losh'; freebsd-arm at freebsd.org;
> freebsd-geom at freebsd.org
> Subject: Re: merge geom redboot and map
> 
> Hi all,
> 
> On Thu, 31 Mar 2011 04:19:11 +0900
> rozhuk.im at gmail.com wrote:
> 
> >
> > > > I need your opinions, suggestions and help with testing and
> > > > including
> > > code
> > > > to main stream source tree.
> > >
> > > I think this likely is a good refactoring.
> > >
> > > > PS: I can test only "map" part on my Agestar LB2.
> > >
> > > But please make sure FIS still works.
> >
> > I hope peoples with redboot hardware help with testing.
> >
> >
> > Another question is path to mapped block (partition)?
> >
> > Now
> > - redboot: /dev/redboot/%name
> > - map: /dev/map/%name
> >
> > Variants:
> > 1. stay as is
> > 2. /dev/flash/%name
> > 3. ?
> 
> 3. /dev/flash/spi0kernel, /dev/flash/spi0rootfs, ...
> 
> IMO, /dev/map/ more generic :)
> 
> >
> > _______________________________________________
> > freebsd-arm at freebsd.org mailing list
> > http://lists.freebsd.org/mailman/listinfo/freebsd-arm
> > To unsubscribe, send any mail to "freebsd-arm-
> unsubscribe at freebsd.org"
> 
> P.S.
> 
> I think GEOM_FLASH_NO_MAP not needed,
> because this modules differ only on configuration source,
> REDBOOT partition map and hints, so maybe only GEOM_FLASH_NO_REDBOOT to
> avoid unwanted read.
> 
> WBW
> --
> Aleksandr Rybalko <ray at ddteam.net>
-------------- next part --------------
--- /usr/src/sys/kern/subr_hints_orig.c 2009-08-03 17:13:06.000000000 +0900
+++ /usr/src/sys/kern/subr_hints.c      2011-04-03 18:10:57.000000000 +0900
@@ -273,6 +273,30 @@
        return 0;
 }
 
+
+int
+resource_quad_t_value(const char *name, int unit, const char *resname, quad_t *result)
+{
+       int error;
+       const char *str;
+       char *op;
+       quad_t val;
+       int line;
+
+       line = 0;
+       error = resource_find(&line, NULL, name, &unit, resname, NULL,
+           NULL, NULL, NULL, NULL, NULL, &str);
+       if (error)
+               return error;
+       if (*str == '\0') 
+               return EFTYPE;
+       val = strtoq(str, &op, 0);
+       if (*op != '\0') 
+               return EFTYPE;
+       *result = val;
+       return 0;
+}
+
 int
 resource_string_value(const char *name, int unit, const char *resname,
     const char **result)


--- /usr/src/sys/sys/bus.h_orig 2011-02-09 06:08:00.000000000 +0800
+++ /usr/src/sys/sys/bus.h      2011-04-03 18:13:07.000000000 +0900
@@ -470,6 +470,8 @@
                           int *result);
 int    resource_long_value(const char *name, int unit, const char *resname,
                            long *result);
+int    resource_quad_t_value(const char *name, int unit, const char *resname,
+                               quad_t *result);
 int    resource_string_value(const char *name, int unit, const char *resname,
                              const char **result);
 int    resource_disabled(const char *name, int unit);

-------------- next part --------------
/*-
 * Copyright (c) 2009 Aleksandr Rybalko AKA Alex RAY, DDTeam.net
 * based on geom_redboot.c
 * Copyright (c) 2009 Sam Leffler, Errno Consulting
 * 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,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
 *    redistribution must be conditioned upon including a substantially
 *    similar Disclaimer requirement for further binary redistribution.
 *
 * NO WARRANTY
 * 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 NONINFRINGEMENT, MERCHANTIBILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
 */


#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

#include <sys/param.h>
#include <sys/bus.h>
#include <sys/errno.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/lock.h>
#include <sys/mutex.h>

#include <sys/sbuf.h>
#include <geom/geom.h>
#include <geom/geom_slice.h>
#include "opt_geom.h"


#define MAP_CLASS_NAME		"MAP"
#define MAP_MAXSLICE			64
#define MAP_SEARCH_KEY_LEN_MAX	255
#define MAP_SEARCH_STEP_DEF		0x10000U


struct g_map_softc {
	g_access_t	*parent_access;
	off_t		entry[MAP_MAXSLICE];		/* offset in image for entry point */
	off_t		dsize[MAP_MAXSLICE];		/* data size in bytes */
	u_int		readonly[MAP_MAXSLICE];
};



#if !defined(GEOM_MAP_NO_REDBOOT)

struct fis_image_desc {
	uint8_t	name   [16];	/* null-terminated name */
	uint32_t	offset;	/* offset in flash */
	uint32_t	addr;		/* address in memory */
	uint32_t	size;		/* image size in bytes */
	uint32_t	entry;		/* offset in image for entry point */
	uint32_t	dsize;		/* data size in bytes */
	uint8_t	pad[256-(16+7*sizeof(uint32_t)+sizeof(void*))];
	struct fis_image_desc *next;	/* linked list (in memory) */
	uint32_t	dsum;		/* descriptor checksum */
	uint32_t	fsum;		/* checksum over image data */
};

#define FISDIR_NAME			"FIS directory"
#define REDBCFG_NAME			"RedBoot config"
#define REDBOOT_NAME			"RedBoot"

#endif /* !defined(GEOM_MAP_NO_REDBOOT) */




static int
g_map_ioctl(struct g_provider *pp, u_long cmd, void *data, int fflag, struct thread *td)
{
	return (ENOIOCTL);
}

static int
g_map_access(struct g_provider *pp, int dread, int dwrite, int dexcl)
{
	struct g_geom *gp = pp->geom;
	struct g_slicer *gsp = gp->softc;
	struct g_map_softc *sc = gsp->softc;

	if (dwrite > 0 && sc->readonly[pp->index])
		return (EPERM);
	return (sc->parent_access(pp, dread, dwrite, dexcl)); 
}

static int
g_map_start(struct bio *bp)
{
	struct g_provider *pp;
	struct g_geom *gp;
	struct g_map_softc *sc;
	struct g_slicer *gsp;
	int idx;

	pp = bp->bio_to;
	idx = pp->index;
	gp = pp->geom;
	gsp = gp->softc;
	sc = gsp->softc;
	if (bp->bio_cmd == BIO_GETATTR) {
		if (g_handleattr_off_t(bp, MAP_CLASS_NAME "::entry", sc->entry[idx]))
			return (1);
		if (g_handleattr_off_t(bp, MAP_CLASS_NAME "::dsize", sc->dsize[idx]))
			return (1);
	}
	return (0);
}

static void
g_map_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
	       struct g_consumer *cp __unused, struct g_provider *pp)
{
	struct g_map_softc *sc;
	struct g_slicer *gsp;

	gsp = gp->softc;
	sc = gsp->softc;
	g_slice_dumpconf(sb, indent, gp, cp, pp);
	if (pp != NULL) {
		if (indent == NULL) {
			sbuf_printf(sb, " entry %jd", sc->entry[pp->index]);
			sbuf_printf(sb, " dsize %jd", sc->dsize[pp->index]);
			sbuf_printf(sb, " readonly %u", sc->readonly[pp->index]);
		} else {
			sbuf_printf(sb, "%s<entry>%jd</entry>\n", indent, sc->entry[pp->index]);
			sbuf_printf(sb, "%s<dsize>%jd</dsize>\n", indent, sc->dsize[pp->index]);
			sbuf_printf(sb, "%s<readonly>%u</readonly>\n", indent, sc->readonly[pp->index]);
		}
	}
}



#include <sys/ctype.h>



#if !defined(GEOM_MAP_NO_REDBOOT)

static void
g_map_print_redboot(int i, struct fis_image_desc *fd)
{
	printf("[%2d] \"%-15.15s\" %08x:%08x", i, fd->name, fd->offset, fd->size);
	printf(" addr %08x entry %08x\n", fd->addr, fd->entry);
	printf("     dsize 0x%x dsum 0x%x fsum 0x%x\n", fd->dsize, fd->dsum, fd->fsum);
}


static int
nameok(const char name[16])
{
	int i;

	/* descriptor names are null-terminated printable ascii */
	for (i = 0; i < 15; i++)
		if (!isprint(name[i]))
			break;
	return (name[i] == '\0');
}


static struct fis_image_desc *
parse_fis_directory(u_char *buf, size_t bufsize, off_t offset, uint32_t offmask)
{
#define	match(a,b)	(bcmp(a, b, sizeof(b)-1) == 0)
	struct fis_image_desc *fd, *efd;
	struct fis_image_desc *fisdir, *redbcfg;
	struct fis_image_desc *head, **tail;
	int i;

	fd = (struct fis_image_desc *)buf;
	efd = fd + (bufsize / sizeof(struct fis_image_desc));
#if 0
	/*
	 * Find the start of the FIS table.
	 */
	while (fd < efd && fd->name[0] != 0xff)
		fd++;
	if (fd == efd)
		return (NULL);
	if (bootverbose)
		printf("RedBoot FIS table starts at 0x%jx\n",
		    offset + fd - (struct fis_image_desc *) buf);
#endif
	/*
	 * Scan forward collecting entries in a list.
	 */
	fisdir = redbcfg = NULL;
	*(tail = &head) = NULL;
	for (i = 0; fd < efd; i++, fd++) {
		if (fd->name[0] == 0xff)
			continue;
		if (match(fd->name, FISDIR_NAME))
			fisdir = fd;
		else if (match(fd->name, REDBCFG_NAME))
			redbcfg = fd;
		if (nameok(fd->name)) {
			/*
			 * NB: flash address includes platform mapping;
			 *     strip it so we have only a flash offset.
			 */
			fd->offset &= offmask;
			if (bootverbose)
				g_map_print_redboot(i, fd);
			*tail = fd;
			*(tail = &fd->next) = NULL;
		}
	}
	if (fisdir == NULL) {
		if (bootverbose)
			printf("No RedBoot FIS table located at %ju\n", offset);
		return (NULL);
	}
	if (redbcfg != NULL &&
	    fisdir->offset + fisdir->size == redbcfg->offset) {
		/*
		 * Merged FIS/RedBoot config directory.
		 */
		if (bootverbose)
			printf("FIS/RedBoot merged at 0x%jx (not yet)\n",
			    offset + fisdir->offset);
		/* XXX */
	}
	return head;
#undef match
}


/* load maps from hints */
static u_int
g_map_load_fis(struct g_consumer *cp, u_int idx)
{
	struct g_geom *gp;
	struct g_provider *pp;
	struct g_slicer *gsp;
	struct g_map_softc *sc;
	struct fis_image_desc *fd, *head;
	u_char *buf;
	int error;
	u_int sectorsize, blksize;	/* NB: flash block size stored as stripesize */
	uint32_t offmask;
	off_t offset;


	gp = cp->geom;
	pp = cp->provider;
	gsp = gp->softc;
	sc = gsp->softc;

	sectorsize = cp->provider->sectorsize;
	if (sectorsize < sizeof(struct fis_image_desc) ||
	    (sectorsize % sizeof(struct fis_image_desc))) {
		if (bootverbose)
			printf("GEOM_MAP: /dev/%s: FIS/RedBoot not exist, incompatible sectorsize=%u\n", pp->name, sectorsize);
		return (0);
	}

	blksize = cp->provider->stripesize;
	if (blksize == 0) {
		if (bootverbose)
			printf("GEOM_MAP: /dev/%s: FIS/RedBoot not exist, incompatible blksize=%u\n", pp->name, blksize);
		return (0);
	}

	if (powerof2(cp->provider->mediasize))
		offmask = cp->provider->mediasize-1;
	else
		offmask = 0xffffffff;	/* XXX */
	offset = (cp->provider->mediasize - blksize);
	g_topology_unlock();
again:
	head = NULL;
	buf = g_read_data(cp, offset, blksize, NULL);
	if (buf != NULL)
		head = parse_fis_directory(buf, blksize, offset, offmask);
	if (head == NULL && offset != 0) {
		if (bootverbose)
			printf("GEOM_MAP: /dev/%s: FIS/RedBoot table not found in last block, try firast block\n", pp->name);
		if (buf != NULL)
			g_free(buf);
		offset = 0; /* check the front */
		goto again;
	}
	g_topology_lock();
	if (head == NULL) {
		if (bootverbose)
			printf("GEOM_MAP: /dev/%s: FIS/RedBoot not found on device\n", pp->name);
		if (buf != NULL)
			g_free(buf);
		return (0);
	}

	/* Craft a slice for each entry. */
	for (fd = head; fd != NULL; fd = fd->next) {
		if (fd->name[0] == '\0')
			continue;
		error = g_slice_config(gp, idx, G_SLICE_CONFIG_SET, fd->offset, fd->size, sectorsize, "redboot/%s", fd->name);
		if (error) {
			printf("GEOM_MAP: /dev/%s: g_slice_config returns %d for \"%s\"\n", pp->name, error, fd->name);
		}else{
			sc->entry[idx] = fd->entry;
			sc->dsize[idx] = fd->dsize;
			/* disallow writing hard-to-recover entries */
			sc->readonly[idx] = (strcmp(fd->name, FISDIR_NAME) == 0) || (strcmp(fd->name, REDBOOT_NAME) == 0);
			idx ++;

			printf("GEOM_MAP: /dev/%s: 0x%08x-0x%08x, offset=0x%x, %s, size=%ul bytes at: \"/dev/redboot/%s\"\n",
				pp->name, fd->addr, (fd->addr + fd->size), fd->entry, (sc->readonly[idx]? "R/O":"R/W"), fd->size, fd->name);
		}
	}
	g_free(buf);

	return(idx);
}

#endif /* !defined(GEOM_MAP_NO_REDBOOT) */



/* search given key on some geom */
static off_t
g_map_search_key(struct g_consumer *cp, u_int sectorsize, off_t from, off_t step, const char *key, u_int key_len)
{
	struct g_provider *pp;
	off_t ret = 0, i, mediasize, read_len;
	u_int c;
	char key_mask[MAP_SEARCH_KEY_LEN_MAX];
	u_char *buf;


	pp = cp->provider;
	key_len = min(MAP_SEARCH_KEY_LEN_MAX, key_len);
	read_len = roundup(key_len, sectorsize);
	mediasize = cp->provider->mediasize;

	if (bootverbose)
		printf("GEOM_MAP: /dev/%s: searchkey=\"%s\", from=0x%jx, step=0x%jx...", pp->name, key, from, step);

	g_topology_unlock();
	for (i = from; i < mediasize && ret == 0; i += step) {
		buf = g_read_data(cp, rounddown(i, sectorsize), read_len, NULL);
		/* read ok? */
		if (buf == NULL)
			break;

		/* Wildcard, replace '.' with byte from data */
		bcopy(key, key_mask, key_len);
		for (c = 0; c < key_len; c++)
			if (key_mask[c] == '.')
				key_mask[c] = ((char *)(buf + (i % sectorsize)))[c];

		if (bcmp( (buf + (i % sectorsize)), key_mask, key_len) == 0)
			ret = i;
		g_free(buf);
	}
	g_topology_lock();
	
	if (bootverbose) {
		if (ret)
			printf("found at 0x%jx\n", ret);
		else
			printf("NOT found!\n");
	}

	return(ret);
}


/* load maps from hints */
static u_int
g_map_load_hints(struct g_consumer *cp, u_int idx)
{
	struct g_geom *gp;
	struct g_provider *pp;
	struct g_slicer *gsp;
	struct g_map_softc *sc;
	const char *map_name, *tmpstr, *search_key;
	off_t map_start, map_end, map_size, map_offset, search_start, search_step;
	u_int i, sectorsize, map_readonly, map_start_searched;
	int ret;

	gp = cp->geom;
	pp = cp->provider;
	gsp = gp->softc;
	sc = gsp->softc;

	sectorsize = cp->provider->sectorsize;

	for (i = 0; i < MAP_MAXSLICE; i++) {
		map_start = map_end = map_size = map_offset = map_readonly = map_start_searched = 0;

		ret = resource_string_value("map", i, "at", &tmpstr);
		/* Check if my provider */
		if (ret || strcmp(pp->name, tmpstr))
			continue;

		ret = resource_string_value("map", i, "name", &map_name);
		/* No name or error read name */
		if (ret)
			continue;

		ret = resource_string_value("map", i, "start", &tmpstr);
		/* No start or error read */
		if (ret)
			continue;
		if (strncmp(tmpstr, "search", 6) == 0) {
			ret = resource_string_value("map", i, "searchkey", &search_key);
			if (ret)
				continue;

			search_start = 0;
			search_step = MAP_SEARCH_STEP_DEF;
			resource_quad_t_value("map", i, "searchstart", &search_start);
			resource_quad_t_value("map", i, "searchstep", &search_step);
			map_start_searched = 1;

			map_start = g_map_search_key(cp, sectorsize, search_start, search_step, search_key, strlen(search_key));
			/* is search failed? */
			if (search_start > map_start)
				ret = 1;
		} else
			ret = resource_quad_t_value("map", i, "start", &map_start);
		if (ret)
			continue;


		ret = resource_string_value("map", i, "end", &tmpstr);
		/* No start or error read */
		if (ret)
			continue;
		if (strncmp(tmpstr, "search", 6) == 0) {
			ret = resource_string_value("map", i, "searchkey", &search_key);
			if (ret)
				continue;

			search_step = MAP_SEARCH_STEP_DEF;
			if (map_start_searched) {
				/* we found key for start, end will see in next "step" offset */
				search_start = (map_start + search_step);
			}else{
				search_start = 0;
				resource_quad_t_value("map", i, "searchstart", &search_start);
			}
			resource_quad_t_value("map", i, "searchstep", &search_step);

			map_end = g_map_search_key(cp, sectorsize, search_start, search_step, search_key, strlen(search_key));
			/* is search failed? */
			if (search_start > map_start)
				ret = 1;
		} else
			ret = resource_quad_t_value("map", i, "end", &map_end);

		map_size = (map_end - map_start);

		/* end is 0 or size is 0, No MAP - so next */
		if (ret || map_end == 0 || map_size == 0)
			continue;
		if (map_offset > map_size) {
			printf("GEOM_MAP: /dev/%s: offset(%jx) > size(%jx) for \"%s\"\n", pp->name, map_offset, map_size, map_name);
			continue;
		}

		resource_quad_t_value("map", i, "offset", &map_offset);
		resource_int_value("map", i, "readonly", &map_readonly);

		/* strip dev name: pp->name = "flash/spi0" -> tmpstr = "spi0" */
		for (tmpstr = (pp->name + strlen(pp->name)); tmpstr > pp->name && tmpstr[0] != '/'; tmpstr --);
		if (tmpstr[0] == '/')
			tmpstr ++;

		ret = g_slice_config(gp, idx, G_SLICE_CONFIG_SET, (map_start + map_offset), (map_size - map_offset), sectorsize, "map/%s%s", tmpstr, map_name);
		if (ret) {
			printf("GEOM_MAP: /dev/%s: g_slice_config returns %d for \"%s\"\n", pp->name, ret, map_name);
		}else{
			sc->entry[idx] = map_offset;
			sc->dsize[idx] = (map_size - map_offset);
			sc->readonly[idx] = map_readonly;
			idx ++;

			printf("GEOM_MAP: /dev/%s: 0x%08jx-0x%08jx, offset=0x%jx, %s, size=%ju bytes at: \"/dev/map/%s%s\"\n",
				pp->name, map_start, map_end, map_offset, (map_readonly? "R/O":"R/W"), map_size, tmpstr, map_name);
		}
	}/* for (i = 0; i < MAP_MAXSLICE; i++) */

	return(idx);
}



static struct g_geom *
g_map_taste(struct g_class *mp, struct g_provider *pp, int insist)
{
	struct g_geom *gp;
	struct g_consumer *cp;
	struct g_map_softc *sc;
	u_int idx = 0;


	g_trace(G_T_TOPOLOGY, "map_taste(%s,%s)", mp->name, pp->name);
	g_topology_assert();
	if (!strcmp(pp->geom->class->name, MAP_CLASS_NAME))
		return (NULL);

	gp = g_slice_new(mp, MAP_MAXSLICE, pp, &cp, &sc, sizeof(*sc), g_map_start);
	if (gp == NULL)
		return (NULL);

	/* interpose our access method */
	sc->parent_access = gp->access;
	gp->access = g_map_access;

	idx += g_map_load_hints(cp, idx);

#if !defined(GEOM_MAP_NO_REDBOOT)
	idx += g_map_load_fis(cp, idx);
#endif

	if (idx && bootverbose)
		printf("GEOM_MAP: /dev/%s: mediasize=%ju, secsize=%d, blksize=%d\n",
		    pp->name, pp->mediasize, pp->sectorsize, pp->stripesize);


	g_access(cp, -1, 0, 0);
	if (LIST_EMPTY(&gp->provider)) {
		g_slice_spoiled(cp);
		return (NULL);
	}
	return (gp);
}

static void
g_map_config(struct gctl_req *req, struct g_class *mp, const char *verb)
{
	struct g_geom  *gp;

	g_topology_assert();
	gp = gctl_get_geom(req, mp, "geom");
	if (gp == NULL)
		return;
	gctl_error(req, "Unknown verb");
}

static struct g_class g_map_class = {
	.name		= MAP_CLASS_NAME,
	.version	= G_VERSION,
	.taste		= g_map_taste,
	.dumpconf	= g_map_dumpconf,
	.ctlreq	= g_map_config,
	.ioctl		= g_map_ioctl,
};
DECLARE_GEOM_CLASS(g_map_class, g_map);
-------------- next part --------------
--- /usr/src/sys/conf/options_orig      2011-04-04 02:38:46.000000000 +0900
+++ /usr/src/sys/conf/options   2011-04-03 06:18:26.000000000 +0900
@@ -1,4 +1,4 @@
-# $FreeBSD: src/sys/conf/options,v 1.687.2.11 2011/03/27 00:42:28 kib Exp $
+# $FreeBSD: src/sys/conf/options,v 1.687.2.10 2010/07/09 08:48:51 ae Exp $
 #
 #        On the handling of kernel options
 #
@@ -99,6 +99,8 @@
 GEOM_PART_MBR  opt_geom.h
 GEOM_PART_PC98 opt_geom.h
 GEOM_PART_VTOC8        opt_geom.h
+GEOM_MAP       opt_geom.h
+GEOM_MAP_NO_REDBOOT opt_geom.h
 GEOM_PC98      opt_geom.h
 GEOM_RAID3     opt_geom.h
 GEOM_SHSEC     opt_geom.h



More information about the freebsd-arm mailing list