r4288 - in trunk/src/target: . dynenv

werner at sita.openmoko.org werner at sita.openmoko.org
Tue Apr 1 07:35:35 CEST 2008


Author: werner
Date: 2008-04-01 07:35:32 +0200 (Tue, 01 Apr 2008)
New Revision: 4288

Added:
   trunk/src/target/dynenv/
   trunk/src/target/dynenv/Makefile
   trunk/src/target/dynenv/README
   trunk/src/target/dynenv/dynenv.c
   trunk/src/target/dynenv/mtd-abi.h
Log:
"dynenv" is a utility to read or write the u-boot environment pointer stored
in the OOB area of NAND.



Added: trunk/src/target/dynenv/Makefile
===================================================================
--- trunk/src/target/dynenv/Makefile	2008-04-01 04:36:34 UTC (rev 4287)
+++ trunk/src/target/dynenv/Makefile	2008-04-01 05:35:32 UTC (rev 4288)
@@ -0,0 +1,14 @@
+CC=arm-angstrom-linux-gnueabi-gcc
+
+CFLAGS=-Wall -g
+
+.PHONY:		all clean spotless
+
+all:		dynenv
+
+dynenv:	 	dynenv.c
+
+clean:
+
+spotless:
+		rm -f dynenv

Added: trunk/src/target/dynenv/README
===================================================================
--- trunk/src/target/dynenv/README	2008-04-01 04:36:34 UTC (rev 4287)
+++ trunk/src/target/dynenv/README	2008-04-01 05:35:32 UTC (rev 4288)
@@ -0,0 +1,29 @@
+dynenv - Read and write the Dynamic Environment Pointer
+=======================================================
+
+*
+* Copyright (C) 2008 by OpenMoko, Inc.
+* Written by Werner Almesberger <werner at openmoko.org>
+* All Rights Reserved
+*
+* mtd-abi.h is a verbatim copy from mtd-utils.
+*
+
+
+usage: dynenv device [pointer]
+
+"dynenv" reads or writes the pointer that indicates to u-boot from which
+NAND location to load the environment. This pointer is stored in the OOB
+area of the first page of the NAND Flash.
+
+"device" is the device containing the first page of the NAND. "pointer"
+is the new value to write. "pointer" follows the usual C notation.
+
+Examples:
+
+# dynenv /dev/mtd1
+# dynenv /dev/mtd1 0x40000
+# dynenv /dev/mtd1 0x`awk '/mtd1/{print $2}' </proc/mtd`
+
+(Note that the NAND Flash starts with /dev/mtd1 on GTA02 but with
+/dev/mtd0 on GTA01.)

Added: trunk/src/target/dynenv/dynenv.c
===================================================================
--- trunk/src/target/dynenv/dynenv.c	2008-04-01 04:36:34 UTC (rev 4287)
+++ trunk/src/target/dynenv/dynenv.c	2008-04-01 05:35:32 UTC (rev 4288)
@@ -0,0 +1,147 @@
+/*
+ * dynenv - Read and write the Dynamic Environment Pointer
+ *
+ * Copyright (C) 2008 by OpenMoko, Inc.
+ * Written by Werner Almesberger <werner at openmoko.org>
+ * All Rights Reserved
+ *  
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include "mtd-abi.h"
+
+
+static void get_buf(int fd, uint8_t *buf)
+{
+	struct mtd_oob_buf oob = {
+		.start	= 8,
+		.length	= 8,
+		.ptr	= buf,
+	};
+
+	if (ioctl(fd, MEMREADOOB, &oob) != 0) {
+		perror("ioctl(MEMREADOOB)");
+		exit(1);
+	}
+
+}
+
+
+static int erased_q(int fd)
+{
+	uint8_t buf[8];
+
+	get_buf(fd, buf);
+	return !memcmp(buf, "\xff\xff\xff\xff\xff\xff\xff\xff", 8);
+}
+
+
+static uint32_t get_ptr(int fd)
+{
+	uint8_t buf[8];
+
+	get_buf(fd, buf);
+	if (memcmp(buf, "ENV0", 4)) {
+		fprintf(stderr, "environment pointer marker is absent\n");
+		exit(1);
+	}
+	return buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
+}
+
+
+static void set_ptr(int fd, uint32_t ptr)
+{
+	uint8_t buf[8] = "ENV0";
+	struct mtd_oob_buf oob = {
+		.start	= 8,
+		.length	= 8,
+		.ptr	= buf,
+	};
+
+	buf[4] = ptr;
+	buf[5] = ptr >> 8;
+	buf[6] = ptr >> 16;
+	buf[7] = ptr >> 24;
+	if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
+		perror("ioctl(MEMWRITEOOB)");
+		exit(1);
+	}
+}
+
+
+static void usage(const char *name)
+{
+	fprintf(stderr, "usage: %s device [pointer]\n", name);
+	exit(1);
+}
+
+
+int main(int argc, char **argv)
+{
+	char *end;
+	int wr = 0;
+	unsigned long ptr;
+	int fd;
+
+	switch (argc) {
+	case 2:
+		break;
+	case 3:
+		wr = 1;
+		ptr = strtoul(argv[2], &end, 0);
+		if (*end || (ptr & ~0xffffffffUL))
+			usage(*argv);
+		break;
+	default:
+		usage(*argv);
+	}
+
+	fd = open(argv[1], wr ? O_RDWR : O_RDONLY);
+	if (fd < 0) {
+		perror(argv[1]);
+		exit(1);
+	}
+	if (wr) {
+		uint32_t got;
+
+		if (!erased_q(fd)) {
+			got = get_ptr(fd);
+			if (ptr == got)
+				return 0;
+/*
+ * We could use the following check instead of the stricter check for either
+ * identity or complete erasure (this is what u-boot does). However, it's quite
+ * unlikely that anything good would come from this, so we don't.
+ *
+ *		if (ptr & ~got) {
+ */
+			fprintf(stderr, "please erase OOB block first\n");
+			exit(1);
+		}
+		set_ptr(fd, ptr);
+		got = get_ptr(fd);
+		if (ptr != got) {
+			fprintf(stderr, "write failed (0x%lx != 0x%lx)\n",
+			    (unsigned long) got, (unsigned long) ptr);
+			exit(1);
+
+		}
+	}
+	else {
+		printf("0x%lx\n", (unsigned long) get_ptr(fd));
+		exit(1);
+	}
+	return 0;
+}

Added: trunk/src/target/dynenv/mtd-abi.h
===================================================================
--- trunk/src/target/dynenv/mtd-abi.h	2008-04-01 04:36:34 UTC (rev 4287)
+++ trunk/src/target/dynenv/mtd-abi.h	2008-04-01 05:35:32 UTC (rev 4288)
@@ -0,0 +1,158 @@
+/*
+ * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $
+ *
+ * Portions of MTD ABI definition which are shared by kernel and user space
+ */
+
+#ifndef __MTD_ABI_H__
+#define __MTD_ABI_H__
+
+#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into
+		    separate files was to avoid #ifdef __KERNEL__ */
+#define __user
+#endif
+
+struct erase_info_user {
+	uint32_t start;
+	uint32_t length;
+};
+
+struct mtd_oob_buf {
+	uint32_t start;
+	uint32_t length;
+	unsigned char __user *ptr;
+};
+
+#define MTD_ABSENT		0
+#define MTD_NORFLASH		3
+#define MTD_NANDFLASH		4
+#define MTD_DATAFLASH		6
+#define MTD_GENERIC_TYPE	7
+
+#define MTD_WRITEABLE		0x400	/* Device is writeable */
+#define MTD_BIT_WRITEABLE	0x800	/* Single bits can be flipped */
+#define MTD_NO_ERASE		0x1000	/* No erase necessary */
+
+// Some common devices / combinations of capabilities
+#define MTD_CAP_ROM		0
+#define MTD_CAP_RAM		(MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE)
+#define MTD_CAP_NORFLASH	(MTD_WRITEABLE | MTD_BIT_WRITEABLE)
+#define MTD_CAP_NANDFLASH	(MTD_WRITEABLE)
+
+
+// Types of automatic ECC/Checksum available
+#define MTD_ECC_NONE		0 	// No automatic ECC available
+#define MTD_ECC_RS_DiskOnChip	1	// Automatic ECC on DiskOnChip
+#define MTD_ECC_SW		2	// SW ECC for Toshiba & Samsung devices
+
+/* ECC byte placement */
+#define MTD_NANDECC_OFF		0	// Switch off ECC (Not recommended)
+#define MTD_NANDECC_PLACE	1	// Use the given placement in the structure (YAFFS1 legacy mode)
+#define MTD_NANDECC_AUTOPLACE	2	// Use the default placement scheme
+#define MTD_NANDECC_PLACEONLY	3	// Use the given placement in the structure (Do not store ecc result on read)
+#define MTD_NANDECC_AUTOPL_USR 	4	// Use the given autoplacement scheme rather than using the default
+
+/* OTP mode selection */
+#define MTD_OTP_OFF		0
+#define MTD_OTP_FACTORY		1
+#define MTD_OTP_USER		2
+
+struct mtd_info_user {
+	uint8_t type;
+	uint32_t flags;
+	uint32_t size;	 // Total size of the MTD
+	uint32_t erasesize;
+	uint32_t writesize;
+	uint32_t oobsize;   // Amount of OOB data per block (e.g. 16)
+	uint32_t ecctype;
+	uint32_t eccsize;
+};
+
+struct region_info_user {
+	uint32_t offset;		/* At which this region starts,
+					 * from the beginning of the MTD */
+	uint32_t erasesize;		/* For this region */
+	uint32_t numblocks;		/* Number of blocks in this region */
+	uint32_t regionindex;
+};
+
+struct otp_info {
+	uint32_t start;
+	uint32_t length;
+	uint32_t locked;
+};
+
+#define MEMGETINFO		_IOR('M', 1, struct mtd_info_user)
+#define MEMERASE		_IOW('M', 2, struct erase_info_user)
+#define MEMWRITEOOB		_IOWR('M', 3, struct mtd_oob_buf)
+#define MEMREADOOB		_IOWR('M', 4, struct mtd_oob_buf)
+#define MEMLOCK			_IOW('M', 5, struct erase_info_user)
+#define MEMUNLOCK		_IOW('M', 6, struct erase_info_user)
+#define MEMGETREGIONCOUNT	_IOR('M', 7, int)
+#define MEMGETREGIONINFO	_IOWR('M', 8, struct region_info_user)
+#define MEMSETOOBSEL		_IOW('M', 9, struct nand_oobinfo)
+#define MEMGETOOBSEL		_IOR('M', 10, struct nand_oobinfo)
+#define MEMGETBADBLOCK		_IOW('M', 11, loff_t)
+#define MEMSETBADBLOCK		_IOW('M', 12, loff_t)
+#define OTPSELECT		_IOR('M', 13, int)
+#define OTPGETREGIONCOUNT	_IOW('M', 14, int)
+#define OTPGETREGIONINFO	_IOW('M', 15, struct otp_info)
+#define OTPLOCK			_IOR('M', 16, struct otp_info)
+#define ECCGETLAYOUT		_IOR('M', 17, struct nand_ecclayout)
+#define ECCGETSTATS		_IOR('M', 18, struct mtd_ecc_stats)
+#define MTDFILEMODE		_IO('M', 19)
+
+/*
+ * Obsolete legacy interface. Keep it in order not to break userspace
+ * interfaces
+ */
+struct nand_oobinfo {
+	uint32_t useecc;
+	uint32_t eccbytes;
+	uint32_t oobfree[8][2];
+	uint32_t eccpos[32];
+};
+
+struct nand_oobfree {
+	uint32_t offset;
+	uint32_t length;
+};
+
+#define MTD_MAX_OOBFREE_ENTRIES	8
+/*
+ * ECC layout control structure. Exported to userspace for
+ * diagnosis and to allow creation of raw images
+ */
+struct nand_ecclayout {
+	uint32_t eccbytes;
+	uint32_t eccpos[64];
+	uint32_t oobavail;
+	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
+};
+
+/**
+ * struct mtd_ecc_stats - error correction status
+ *
+ * @corrected:	number of corrected bits
+ * @failed:	number of uncorrectable errors
+ * @badblocks:	number of bad blocks in this partition
+ * @bbtblocks:	number of blocks reserved for bad block tables
+ */
+struct mtd_ecc_stats {
+	uint32_t corrected;
+	uint32_t failed;
+	uint32_t badblocks;
+	uint32_t bbtblocks;
+};
+
+/*
+ * Read/write file modes for access to MTD
+ */
+enum mtd_file_modes {
+	MTD_MODE_NORMAL = MTD_OTP_OFF,
+	MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY,
+	MTD_MODE_OTP_USER = MTD_OTP_USER,
+	MTD_MODE_RAW,
+};
+
+#endif /* __MTD_ABI_H__ */





More information about the commitlog mailing list