+
+ ioctl (fd, MEMLOCK, &erase);
+
+ processed += blocklen;
+ block_seek = 0;
+ blockstart += blocklen;
+ }
+
+ if (write_total > count)
+ free (data);
+
+ return processed;
+}
+
+/*
+ * Set obsolete flag at offset - NOR flash only
+ */
+static int flash_flag_obsolete (int dev, int fd, off_t offset)
+{
+ int rc;
+
+ /* This relies on the fact, that obsolete_flag == 0 */
+ rc = lseek (fd, offset, SEEK_SET);
+ if (rc < 0) {
+ fprintf (stderr, "Cannot seek to set the flag on %s \n",
+ DEVNAME (dev));
+ return rc;
+ }
+ rc = write (fd, &obsolete_flag, sizeof (obsolete_flag));
+ if (rc < 0)
+ perror ("Could not set obsolete flag");
+
+ return rc;
+}
+
+static int flash_write (int fd_current, int fd_target, int dev_target)
+{
+ int rc;
+
+ switch (environment.flag_scheme) {
+ case FLAG_NONE:
+ break;
+ case FLAG_INCREMENTAL:
+ (*environment.flags)++;
+ break;
+ case FLAG_BOOLEAN:
+ *environment.flags = active_flag;
+ break;
+ default:
+ fprintf (stderr, "Unimplemented flash scheme %u \n",
+ environment.flag_scheme);
+ return -1;
+ }
+
+#ifdef DEBUG
+ printf ("Writing new environment at 0x%lx on %s\n",
+ DEVOFFSET (dev_target), DEVNAME (dev_target));
+#endif
+ rc = flash_write_buf (dev_target, fd_target, environment.image,
+ CFG_ENV_SIZE, DEVOFFSET (dev_target),
+ DEVTYPE(dev_target));
+ if (rc < 0)
+ return rc;
+
+ if (environment.flag_scheme == FLAG_BOOLEAN) {
+ /* Have to set obsolete flag */
+ off_t offset = DEVOFFSET (dev_current) +
+ offsetof (struct env_image_redundant, flags);
+#ifdef DEBUG
+ printf ("Setting obsolete flag in environment at 0x%lx on %s\n",
+ DEVOFFSET (dev_current), DEVNAME (dev_current));
+#endif
+ flash_flag_obsolete (dev_current, fd_current, offset);
+ }
+
+ return 0;
+}
+
+static int flash_read (int fd)
+{
+ struct mtd_info_user mtdinfo;
+ int rc;
+
+ rc = ioctl (fd, MEMGETINFO, &mtdinfo);
+ if (rc < 0) {
+ perror ("Cannot get MTD information");
+ return -1;
+ }
+
+ if (mtdinfo.type != MTD_NORFLASH && mtdinfo.type != MTD_NANDFLASH) {
+ fprintf (stderr, "Unsupported flash type %u\n", mtdinfo.type);
+ return -1;
+ }
+
+ DEVTYPE(dev_current) = mtdinfo.type;
+
+ rc = flash_read_buf (dev_current, fd, environment.image, CFG_ENV_SIZE,
+ DEVOFFSET (dev_current), mtdinfo.type);
+
+ return (rc != CFG_ENV_SIZE) ? -1 : 0;
+}
+
+static int flash_io (int mode)
+{
+ int fd_current, fd_target, rc, dev_target;
+
+ /* dev_current: fd_current, erase_current */
+ fd_current = open (DEVNAME (dev_current), mode);
+ if (fd_current < 0) {
+ fprintf (stderr,
+ "Can't open %s: %s\n",
+ DEVNAME (dev_current), strerror (errno));
+ return -1;
+ }
+
+ if (mode == O_RDWR) {