summaryrefslogtreecommitdiff
path: root/nor-utils/rfdformat.c
diff options
context:
space:
mode:
Diffstat (limited to 'nor-utils/rfdformat.c')
-rw-r--r--nor-utils/rfdformat.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/nor-utils/rfdformat.c b/nor-utils/rfdformat.c
new file mode 100644
index 0000000..17d9d2d
--- /dev/null
+++ b/nor-utils/rfdformat.c
@@ -0,0 +1,160 @@
+/*
+ * rfdformat.c
+ *
+ * Copyright (C) 2005 Sean Young <sean@mess.org>
+ *
+ * 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.
+ *
+ * This is very easy: just erase all the blocks and put the magic at
+ * the beginning of each block.
+ */
+
+#define PROGRAM_NAME "rfdformat"
+#define VERSION "$Revision 1.0 $"
+
+#define _XOPEN_SOURCE 500 /* For pread/pwrite */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include <mtd/mtd-user.h>
+#include <linux/types.h>
+
+void display_help(void)
+{
+ printf("Usage: %s [OPTIONS] MTD-device\n"
+ "Formats NOR flash for resident flash disk\n"
+ "\n"
+ "-h --help display this help and exit\n"
+ "-V --version output version information and exit\n",
+ PROGRAM_NAME);
+ exit(0);
+}
+
+void display_version(void)
+{
+ printf("%s " VERSION "\n"
+ "\n"
+ "This is free software; see the source for copying conditions. There is NO\n"
+ "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
+ PROGRAM_NAME);
+
+ exit(0);
+}
+
+void process_options(int argc, char *argv[], const char **mtd_filename)
+{
+ int error = 0;
+
+ for (;;) {
+ int option_index = 0;
+ static const char *short_options = "hV";
+ static const struct option long_options[] = {
+ { "help", no_argument, 0, 'h' },
+ { "version", no_argument, 0, 'V', },
+ { NULL, 0, 0, 0 }
+ };
+
+ int c = getopt_long(argc, argv, short_options,
+ long_options, &option_index);
+ if (c == EOF)
+ break;
+
+ switch (c) {
+ case 'h':
+ display_help();
+ break;
+ case 'V':
+ display_version();
+ break;
+ case '?':
+ error = 1;
+ break;
+ }
+ }
+
+ if ((argc - optind) != 1 || error)
+ display_help();
+
+ *mtd_filename = argv[optind];
+}
+
+int main(int argc, char *argv[])
+{
+ static const uint8_t magic[] = { 0x93, 0x91 };
+ int fd, block_count, i;
+ struct mtd_info_user mtd_info;
+ char buf[512];
+ const char *mtd_filename;
+
+ process_options(argc, argv, &mtd_filename);
+
+ fd = open(mtd_filename, O_RDWR);
+ if (fd == -1) {
+ perror(mtd_filename);
+ return 1;
+ }
+
+ if (ioctl(fd, MEMGETINFO, &mtd_info)) {
+ perror(mtd_filename);
+ close(fd);
+ return 1;
+ }
+
+ if (mtd_info.type != MTD_NORFLASH) {
+ fprintf(stderr, "%s: not NOR flash\n", mtd_filename);
+ close(fd);
+ return 2;
+ }
+
+ if (mtd_info.size > 32*1024*1024) {
+ fprintf(stderr, "%s: flash larger than 32MiB not supported\n",
+ mtd_filename);
+ close(fd);
+ return 2;
+ }
+
+ block_count = mtd_info.size / mtd_info.erasesize;
+
+ if (block_count < 2) {
+ fprintf(stderr, "%s: at least two erase units required\n",
+ mtd_filename);
+ close(fd);
+ return 2;
+ }
+
+ for (i=0; i<block_count; i++) {
+ struct erase_info_user erase_info;
+
+ erase_info.start = i * mtd_info.erasesize;
+ erase_info.length = mtd_info.erasesize;
+
+ if (ioctl(fd, MEMERASE, &erase_info) != 0) {
+ snprintf(buf, sizeof(buf), "%s: erase", mtd_filename);
+ perror(buf);
+ close(fd);
+ return 2;
+ }
+
+ if (pwrite(fd, magic, sizeof(magic), i * mtd_info.erasesize)
+ != sizeof(magic)) {
+ snprintf(buf, sizeof(buf), "%s: write", mtd_filename);
+ perror(buf);
+ close(fd);
+ return 2;
+ }
+ }
+
+ close(fd);
+
+ return 0;
+}