From: Wolfgang Denk <wd@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 6/6] Support environment in NAND
Date: Sun, 31 Aug 2008 20:57:38 +0200 [thread overview]
Message-ID: <20080831185738.90681242FF@gemini.denx.de> (raw)
In-Reply-To: <Pine.LNX.4.64.0808271748520.6718@axis700.grange>
Dear Guennadi Liakhovetski,
In message <Pine.LNX.4.64.0808271748520.6718@axis700.grange> you wrote:
>
> --- a/tools/env/fw_env.c
> +++ b/tools/env/fw_env.c
> @@ -44,6 +44,12 @@
> #define CMD_GETENV "fw_printenv"
> #define CMD_SETENV "fw_setenv"
>
> +#define min(x, y) ({ \
> + typeof(x) _min1 = (x); \
> + typeof(y) _min2 = (y); \
> + (void) (&_min1 == &_min2); \
What does this do?
> + _min1 < _min2 ? _min1 : _min2; })
> typedef struct envdev_s {
> char devname[16]; /* Device name */
> ulong devoff; /* Device offset */
> @@ -413,179 +419,290 @@ int fw_setenv (int argc, char *argv[])
> return 0;
> }
>
> +static int flash_bad_block (int dev, int fd, struct mtd_info_user *mtdinfo,
> + loff_t *blockstart, size_t blocklen)
> +{
> + if (mtdinfo->type == MTD_NANDFLASH) {
> + int badblock = ioctl (fd, MEMGETBADBLOCK, blockstart);
> +
> + if (badblock < 0) {
> + perror ("Cannot read bad block mark");
It would be probably helpful to print the block address.
> + return badblock;
> + }
> +
> + if (badblock) {
> + fprintf (stderr, "Bad block at 0x%llx, "
> + "skipping\n", *blockstart);
> + *blockstart += blocklen;
> + return badblock;
> + }
> + }
> +
> + return 0;
> +}
> +
> +/*
> + * We are called with count == 0 for backing up as much data from the
> + * range as possible
> + */
Backing up?
> static int flash_read_buf (int dev, int fd, void *buf, size_t count,
> - off_t offset)
> + off_t offset, size_t range)
> {
> + struct mtd_info_user mtdinfo;
> + size_t blocklen, processed = 0;
> + size_t readlen = count ? : range;
> + off_t erase_offset, block_seek;
> + loff_t blockstart;
> int rc;
> + int backup_mode = !count;
backup_mode ?
I think there should be an explanation what exactly you are trying to
do.
> - rc = lseek (fd, offset, SEEK_SET);
> - if (rc == -1) {
> - fprintf (stderr,
> - "seek error on %s: %s\n",
> - DEVNAME (dev), strerror (errno));
> + if (!count)
> + count = range;
> +
> + rc = ioctl (fd, MEMGETINFO, &mtdinfo);
> + if (rc < 0) {
> + perror ("Cannot get MTD information");
> return rc;
> }
Did you verify that the code still builds when MTD_OLD is set?
>
> - rc = read (fd, buf, count);
> - if (rc != count) {
> - fprintf (stderr,
> - "Read error on %s: %s\n",
> - DEVNAME (dev), strerror (errno));
> - return -1;
> + /* Erase sector size is always a power of 2 */
> + erase_offset = offset & ~(mtdinfo.erasesize - 1);
Please explain this logic.
> + blockstart = erase_offset;
> + /* Offset inside a block */
> + block_seek = offset - erase_offset;
> +
> + if (mtdinfo.type == MTD_NANDFLASH) {
> + /*
> + * NAND: calculate which blocks we are reading. We have
> + * to read one block at a time to skip bad blocks.
> + */
> + blocklen = mtdinfo.erasesize;
> + /* Limit to one block for the first read */
> + if (readlen > blocklen - block_seek)
> + readlen = blocklen - block_seek;
> + } else {
> + blocklen = 0;
> }
>
> - return rc;
> + /* This only runs once for NOR flash */
> + while (processed < count) {
> + rc = flash_bad_block (dev, fd, &mtdinfo, &blockstart, blocklen);
But - NOR flash does not have bad block, so all of this is not needed
at all?
> + if (rc < 0)
> + return -1;
> + else if (blockstart + block_seek + readlen > offset + range) {
I do not understand what you are doing here. Comment?
> + /* End of range is reached */
> + if (backup_mode) {
> + return processed;
> + } else {
> + fprintf (stderr,
> + "Too few good blocks within range\n");
> + return -1;
> + }
> + } else if (rc)
> + continue;
> +
> + /*
> + * If a block is bad, we retry in the next block
> + * at the same offset - see common/env_nand.c::
> + * writeenv()
> + */
> + lseek (fd, blockstart + block_seek, SEEK_SET);
I don't see that you remember which blocks were bad. Does that mean
that you will attemopt to write the environment to known bad blocks?
Sonds not like a good idea to me.
> + rc = read (fd, buf + processed, readlen);
> + if (rc != readlen) {
> + fprintf (stderr,
> + "Read error on %s: %s\n",
> + DEVNAME (dev), strerror (errno));
> + return -1;
> + }
> + processed += readlen;
> + readlen = min(blocklen, count - processed);
> + block_seek = 0;
> + blockstart += blocklen;
> + }
> +
> + return processed;
> }
>
> -static int flash_write (void)
> +static int flash_write_buf (int dev, int fd, void *buf, size_t count,
> + off_t offset)
> {
> - int fd_current, fd_target, rc, dev_target;
> - erase_info_t erase_current = {}, erase_target;
> char *data = NULL;
> - off_t erase_offset;
> - struct mtd_info_user mtdinfo_target;
> + erase_info_t erase;
> + struct mtd_info_user mtdinfo;
> + size_t blocklen, erase_len, processed = 0;
> + size_t writelen, write_total = DEVESIZE (dev);
> + off_t erase_offset, block_seek;
> + loff_t blockstart;
> + int rc;
>
> - /* dev_current: fd_current, erase_current */
> - if ((fd_current = open (DEVNAME (dev_current), O_RDWR)) < 0) {
> - fprintf (stderr,
> - "Can't open %s: %s\n",
> - DEVNAME (dev_current), strerror (errno));
> + rc = ioctl (fd, MEMGETINFO, &mtdinfo);
> + if (rc < 0) {
> + perror ("Cannot get MTD information");
> return -1;
> }
>
> - if (HaveRedundEnv) {
> - /* switch to next partition for writing */
> - dev_target = !dev_current;
> - /* dev_target: fd_target, erase_target */
> - if ((fd_target = open (DEVNAME (dev_target), O_RDWR)) < 0) {
> - fprintf (stderr,
> - "Can't open %s: %s\n",
> - DEVNAME (dev_target),
> - strerror (errno));
> - return -1;
> - }
> - } else {
> - dev_target = dev_current;
> - fd_target = fd_current;
> - }
> + /* Erase sector size is always a power of 2 */
> + erase_offset = offset & ~(mtdinfo.erasesize - 1);
> + /* Maximum area we may use */
> + erase_len = (offset - erase_offset + DEVESIZE (dev) +
> + mtdinfo.erasesize - 1) & ~(mtdinfo.erasesize - 1);
> +
> + blockstart = erase_offset;
> + /* Offset inside a block */
> + block_seek = offset - erase_offset;
>
> /*
> * Support environment anywhere within erase sectors: read out the
> * complete area to be erased, replace the environment image, write
> * the whole block back again.
> */
> - if (DEVESIZE (dev_target) > CFG_ENV_SIZE) {
> - data = malloc (DEVESIZE (dev_target));
> + if (erase_len > DEVESIZE (dev)) {
> + data = malloc (erase_len);
> if (!data) {
> fprintf (stderr,
> - "Cannot malloc %lu bytes: %s\n",
> - DEVESIZE (dev_target),
> - strerror (errno));
> + "Cannot malloc %u bytes: %s\n",
> + erase_len, strerror (errno));
> return -1;
> }
>
> - rc = ioctl (fd_target, MEMGETINFO, &mtdinfo_target);
> - if (rc < 0) {
> - perror ("Cannot get MTD information");
> + /*
> + * This is different from a normal read. We have to read as much
> + * as we can from a certain area, and it should be at least X
> + * bytes, instead of having to read a fixed number of bytes as
> + * usual. This also tells us how much data "fits" in the good
> + * blocks in the area.
> + */
> + write_total = flash_read_buf (dev, fd, data, 0,
> + erase_offset, erase_len);
> + if (write_total < block_seek + CFG_ENV_SIZE)
Ummm...this is flash_write_buf(), and we start reading data?
Please explain your code.
Best regards,
Wolfgang Denk
--
DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
It would seem that evil retreats when forcibly confronted
-- Yarnek of Excalbia, "The Savage Curtain", stardate 5906.5
next prev parent reply other threads:[~2008-08-31 18:57 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-27 15:52 [U-Boot] [PATCH 0/6] Support NAND in fw_printenv/fw_setenv Guennadi Liakhovetski
2008-08-27 15:52 ` [U-Boot] [PATCH 1/6] Convert fw_env.c to use a single environment image union Guennadi Liakhovetski
2008-08-31 14:36 ` Wolfgang Denk
2008-08-31 15:57 ` Guennadi Liakhovetski
2008-08-31 18:57 ` Wolfgang Denk
2008-08-27 15:52 ` [U-Boot] [PATCH 2/6] Separate flash read and write operations Guennadi Liakhovetski
2008-08-31 14:58 ` Wolfgang Denk
2008-08-31 16:04 ` Guennadi Liakhovetski
2008-08-31 18:57 ` Wolfgang Denk
2008-08-31 19:45 ` Guennadi Liakhovetski
2008-08-31 19:56 ` Wolfgang Denk
2008-08-27 15:52 ` [U-Boot] [PATCH 3/6] "return" is not a function Guennadi Liakhovetski
2008-08-31 14:59 ` Wolfgang Denk
2008-08-31 16:10 ` Guennadi Liakhovetski
2008-08-31 18:57 ` Wolfgang Denk
2008-08-31 19:17 ` Guennadi Liakhovetski
2008-08-27 15:52 ` [U-Boot] [PATCH 4/6] Unify active vs. redundant environment variable naming Guennadi Liakhovetski
2008-08-31 15:04 ` Wolfgang Denk
2008-08-31 16:18 ` Guennadi Liakhovetski
2008-08-31 18:57 ` Wolfgang Denk
2008-08-31 19:27 ` Guennadi Liakhovetski
2008-08-31 19:44 ` Wolfgang Denk
2008-08-27 15:52 ` [U-Boot] [PATCH 5/6] Support environment anywhere within erase area Guennadi Liakhovetski
2008-08-31 18:57 ` Wolfgang Denk
2008-08-31 19:39 ` Guennadi Liakhovetski
2008-08-31 19:53 ` Wolfgang Denk
2008-08-27 15:52 ` [U-Boot] [PATCH 6/6] Support environment in NAND Guennadi Liakhovetski
2008-08-29 9:29 ` [U-Boot] [PATCH 6/6 v2] " Guennadi Liakhovetski
2008-08-31 18:57 ` Wolfgang Denk [this message]
2008-08-31 21:53 ` [U-Boot] [PATCH 6/6] " Guennadi Liakhovetski
2008-08-31 20:21 ` [U-Boot] [PATCH 0/6] Support NAND in fw_printenv/fw_setenv Wolfgang Denk
2008-08-31 20:37 ` Guennadi Liakhovetski
2008-08-31 20:55 ` Wolfgang Denk
2008-09-01 9:08 ` Guennadi Liakhovetski
2008-09-01 9:31 ` Guennadi Liakhovetski
2008-09-01 22:42 ` Wolfgang Denk
2008-09-01 22:41 ` Wolfgang Denk
2008-09-01 23:33 ` Guennadi Liakhovetski
2008-09-02 0:13 ` Wolfgang Denk
2008-09-02 16:00 ` Guennadi Liakhovetski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080831185738.90681242FF@gemini.denx.de \
--to=wd@denx.de \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.