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