int saveenv(void)
{
	unsigned long env_addr = CFG_ENV_ADDR;
	struct erase_info instr;
	int retlen;

	instr.len = CFG_ENV_SIZE;
	instr.addr = env_addr;
	instr.addr -= (unsigned long)onenand_chip.base;
	if (onenand_erase(&onenand_mtd, &instr)) {
		printf("OneNAND: erase failed at 0x%08x\n", env_addr);
		return 1;
	}

	/* update crc */
	env_ptr->crc =
	    crc32(0, env_ptr->data, onenand_mtd.oobblock - ENV_HEADER_SIZE);

	env_addr -= (unsigned long)onenand_chip.base;
	if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.oobblock, &retlen,
	     (u_char *) env_ptr)) {
		printf("OneNAND: write failed at 0x%08x\n", instr.addr);
		return 2;
	}

	return 0;
}
示例#2
0
int saveenv(void)
{
    unsigned long env_addr = CFG_ENV_ADDR;
    struct erase_info instr = {
        .callback	= NULL,
    };
    size_t retlen;

    instr.len = CFG_ENV_SIZE;
    instr.addr = env_addr;
    if (onenand_erase(&onenand_mtd, &instr)) {
        printf("OneNAND: erase failed at 0x%08lx\n", env_addr);
        return 1;
    }

    /* update crc */
    env_ptr->crc =
        crc32(0, env_ptr->data, ONENAND_ENV_SIZE(onenand_mtd));

    if (onenand_write(&onenand_mtd, env_addr, onenand_mtd.writesize, &retlen,
                      (u_char *) env_ptr)) {
        printf("OneNAND: write failed at 0x%08x\n", instr.addr);
        return 2;
    }

    return 0;
}
示例#3
0
int do_onenand(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
	int ret = 0;

	switch (argc) {
	case 0:
	case 1:
		printf("Usage:\n%s\n", cmdtp->usage);
		return 1;

	case 2:
		onenand_print_device_info(onenand_chip.device_id, 1);
		return 0;

	default:
		/* At least 4 args */
		if (strncmp(argv[1], "erase", 5) == 0) {
			struct erase_info instr;
			ulong start, end;
			char *endtail;
			ulong block;

			if (strncmp(argv[2], "block", 5) == 0) {
				start = simple_strtoul(argv[3], NULL, 10);
				endtail = strchr(argv[3], '-');
				end = simple_strtoul(endtail+1, NULL, 10);
			} else {
				start = simple_strtoul(argv[2], NULL, 10);
				end = simple_strtoul(argv[3], NULL, 10);
				start -= (unsigned long) onenand_chip.base;
				end -= (unsigned long) onenand_chip.base;
			}

			if (!end || end < 0)
				end = start;

			printf("Erase block from %d to %d\n", start, end);

			for (block = start; block <= end; block++) {
				instr.addr = block << onenand_chip.erase_shift;
				instr.len = 1 << onenand_chip.erase_shift;
				ret = onenand_erase(&onenand_mtd, &instr);
				if (ret) {
					printf("erase failed %d\n", block);
					break;
				}
			}

			return 0;
		}

		if (strncmp(argv[1], "read", 4) == 0) {
			ulong addr = simple_strtoul(argv[2], NULL, 16);
			ulong ofs  = simple_strtoul(argv[3], NULL, 16);
			size_t len = simple_strtoul(argv[4], NULL, 16);
			size_t retlen = 0;
			int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;


			if (oob)
				onenand_read_oob(&onenand_mtd, ofs, len, &retlen, (u_char *) addr);
			else
				onenand_read(&onenand_mtd, ofs, len, &retlen, (u_char *) addr);
			printf("Done\n");

			return 0;
		}

		if (strncmp(argv[1], "write", 5) == 0) {
			int ret ;
			ulong addr = simple_strtoul(argv[2], NULL, 16);
			ulong ofs  = simple_strtoul(argv[3], NULL, 16);
			size_t len = simple_strtoul(argv[4], NULL, 16);
			size_t retlen = 0;

			printf("onenadwrite: addr = 0x%x, ofs = 0x%x, len = 0x%x\n", addr, ofs, len);
			ret = onenand_write(&onenand_mtd, ofs, len, &retlen, (u_char *) addr);
			if (ret)
				printf("Error writing oneNAND: ret = %d\n", ret);
			else
				printf("Done. ret = %d\n", ret);

			return 0;
		}

		if (strncmp(argv[1], "block", 5) == 0) {
			ulong addr = simple_strtoul(argv[2], NULL, 16);
			ulong block = simple_strtoul(argv[3], NULL, 10);
			ulong page = simple_strtoul(argv[4], NULL, 10);
			size_t len = simple_strtol(argv[5], NULL, 10);
			size_t retlen = 0;
			ulong ofs;
			int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;

			ofs = block << onenand_chip.erase_shift;
			if (page)
				ofs += page << onenand_chip.page_shift;

			if (!len) {
				if (oob)
					len = 64;
				else
					len = 512;
			}

			if (oob)
				onenand_read_oob(&onenand_mtd, ofs, len, &retlen, (u_char *) addr);
			else
				onenand_read(&onenand_mtd, ofs, len, &retlen, (u_char *) addr);
			return 0;
		}

		if (strncmp(argv[1], "unlock", 6) == 0) {
			ulong start = simple_strtoul(argv[2], NULL, 10);
			ulong ofs = simple_strtoul(argv[3], NULL, 10);

			if (!ofs)
				ofs = (1 << onenand_chip.erase_shift);

			start = start << onenand_chip.erase_shift;
			printf("start = 0x%08x, ofs = 0x%08x\n",
				start, ofs);
			onenand_unlock(&onenand_mtd, start, start + ofs);
				
			return 0;
		}

		if (strncmp(argv[1], "save", 4) == 0 &&
		    strncmp(argv[2], "bootloader", 10) == 0) {
			ulong addr = simple_strtoul(argv[3], NULL, 16);
			struct erase_info instr;
			int ofs = 0;
			int len = 0x20000;
			size_t retlen;

			printf("save bootloader...\n");

			if (!addr)
				break;

			onenand_unlock(&onenand_mtd, ofs, len);

			instr.addr = 0 << onenand_chip.erase_shift;
			instr.len = 1 << onenand_chip.erase_shift;
			onenand_erase(&onenand_mtd, &instr);

			onenand_write(&onenand_mtd, ofs, len, &retlen, (u_char *) addr);
			onenand_unlock(&onenand_mtd, CFG_ENV_ADDR, onenand_mtd.size - CFG_ENV_ADDR);
			return 0;
		}

		break;
	}

	return 0;
}
int do_onenand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
    int ret = 0;

    switch (argc) {
    case 0:
    case 1:
        printf("Usage:\n%s\n", cmdtp->usage);
        return 1;

    case 2:
        if (strncmp(argv[1], "open", 4) == 0) {
            onenand_init();
            return 0;
        }
        printf("%s\n", onenand_mtd.name);
        return 0;

    default:
        /* At least 4 args */
        if (strncmp(argv[1], "erase", 5) == 0) {
            struct erase_info instr = {
                .callback	= NULL,
            };
            ulong start, size;
            ulong block;
            char *endtail;
            int clean = 0;
            struct jffs2_unknown_node cleanmarker;
            struct mtd_oob_ops ops = {
                .datbuf = NULL,
                .oobbuf = (uint8_t *)&cleanmarker,
                .ooblen = 8,
                .ooboffs= 0,
                .mode	= MTD_OOB_PLACE,
            };

            if (strncmp(argv[2], "block", 5) == 0) {
                start = simple_strtoul(argv[3], NULL, 10);
                endtail = strchr(argv[3], '-');
                size = simple_strtoul(endtail + 1, NULL, 10) - start;
            }
            else if (strncmp(argv[2], "clean", 5) == 0) {
                cleanmarker.magic = JFFS2_MAGIC_BITMASK;
                cleanmarker.nodetype = JFFS2_NODETYPE_CLEANMARKER;
                cleanmarker.totlen = 8;

                start = simple_strtoul(argv[3], NULL, 10);
                size = simple_strtoul(argv[4], NULL, 10);

                start >>= onenand_chip.erase_shift;
                size >>= onenand_chip.erase_shift;
                /* Don't include the end block */
                size--;

                clean = 1;
                printf("ready to erase with cleanmarker\n");
            } else {
                start = simple_strtoul(argv[2], NULL, 10);
                size = simple_strtoul(argv[3], NULL, 10);

                start >>= onenand_chip.erase_shift;
                size >>= onenand_chip.erase_shift;
                /* Don't include the end block */
                size--;
            }

            if (!size || size < 0)
                size = 0;

            printf("Erase begin with %luth block, erase size is %lu blocks\n", start, size);

            for (block = start; block <= start + size; block++) {
                instr.addr = block << onenand_chip.erase_shift;
                instr.len = 1 << onenand_chip.erase_shift;
                ret = onenand_erase(&onenand_mtd, &instr);

                if (ret) {
                    printf("erase failed %lu\n", block);
                    break;
                }

                if (clean == 1) {
                    ret = onenand_write_oob(&onenand_mtd, instr.addr, &ops);
                    if (ret) {
                        printf("write OOB failed %lu\n", block);
                        break;
                    }
                }
            }

            return 0;
        }

        if (strncmp(argv[1], "dump", 4) == 0) {
            ulong ofs = simple_strtoul(argv[2], NULL, 16);

            onenand_dump(&onenand_mtd, ofs);
            printf("Done\n");

            return 0;
        }

        if (strncmp(argv[1], "read", 4) == 0) {
            ulong addr = simple_strtoul(argv[2], NULL, 16);
            ulong ofs = simple_strtoul(argv[3], NULL, 16);
            size_t len = simple_strtoul(argv[4], NULL, 16);
            int oob = strncmp(argv[1], "read.oob", 8) ? 0 : 1;
            struct mtd_oob_ops ops;

            ops.mode = MTD_OOB_PLACE;

            if (oob) {
                ops.len = 0;
                ops.datbuf = NULL;
                ops.ooblen = len;
                ops.oobbuf = (u_char *) addr;
            } else {
                ops.len = len;
                ops.datbuf = (u_char *) addr;
                ops.ooblen = 0;
                ops.oobbuf = NULL;
            }
            ops.retlen = ops.oobretlen = 0;

            onenand_mtd.read_oob(&onenand_mtd, ofs, &ops);
            printf("Done\n");

            return 0;
        }

        if (strncmp(argv[1], "write", 5) == 0) {
            ulong addr = simple_strtoul(argv[2], NULL, 16);
            ulong ofs = simple_strtoul(argv[3], NULL, 16);
            size_t len = simple_strtoul(argv[4], NULL, 16);
            size_t retlen = 0;
            struct mtd_oob_ops ops = {
                .datbuf = (uint8_t *) addr,
                .len    = len,
                .oobbuf = (uint8_t *) addr,
                .ooblen = len,
                .mode	= MTD_OOB_PLACE,
            };

            onenand_mtd.owner = "UBOOT";
            if (strncmp(argv[1], "write.yaffs", 11) == 0) {
                onenand_write_oob(&onenand_mtd, ofs, &ops);
            }
            else
                onenand_write(&onenand_mtd, ofs, len, &retlen,
                              (u_char *) addr);
            printf("Done\n");

            return 0;
        }

        if (strncmp(argv[1], "block", 5) == 0) {
            ulong addr = simple_strtoul(argv[2], NULL, 16);
            ulong block = simple_strtoul(argv[3], NULL, 10);
            ulong page = simple_strtoul(argv[4], NULL, 10);
            size_t len = simple_strtol(argv[5], NULL, 10);
            ulong ofs;
            int oob = strncmp(argv[1], "block.oob", 9) ? 0 : 1;
            struct mtd_oob_ops ops;

            ops.mode = MTD_OOB_PLACE;


            ofs = block << onenand_chip.erase_shift;
            if (page)
                ofs += page << onenand_chip.page_shift;

            if (!len) {
                if (oob)
                    ops.ooblen = 64;
                else
                    ops.len = 512;
            }

            if (oob) {
                ops.datbuf = NULL;
                ops.oobbuf = (u_char *) addr;
            } else {
                ops.datbuf = (u_char *) addr;
                ops.oobbuf = NULL;
            }
            ops.retlen = ops.oobretlen = 0;

            onenand_read_oob(&onenand_mtd, ofs, &ops);
            return 0;
        }

        break;
    }
示例#5
0
int saveenv_onenand(void)
{
        size_t total;
        int ret = 0, i;
        u32 erasebase;
        u32 eraselength;
        u32 eraseblock;
        u32 erasesize = onenand_info[0].erasesize;
        uint8_t *data;
		struct mtd_info *onenand;

        puts("Erasing Onenand...\n");
		
			/* the following commands operate on the current device */
		if (onenand_curr_device < 0 ||
				onenand_curr_device >= CFG_MAX_ONENAND_DEVICE ||
				!onenand_info[onenand_curr_device].name) {
			puts("\nno devices available\n");
			return 1;
		}
		onenand = &onenand_info[onenand_curr_device];
        /* If the value of CFG_ENV_OFFSET is not a NAND block boundary, the
         * NAND erase operation will fail. So first check if the CFG_ENV_OFFSET
         * is equal to a NAND block boundary
         */
        if ((CFG_ENV_OFFSET % (erasesize - 1)) != 0 ) {
                /* CFG_ENV_OFFSET is not equal to block boundary address. So, read
                 * the read the NAND block (in which ENV has to be stored), and
                 * copy the ENV data into the copied block data.
                 */

                /* Step 1: Find out the starting address of the NAND block to
                 * be erased. Also allocate memory whose size is equal to tbe
                 * NAND block size (NAND erasesize).
                 */
                eraseblock = CFG_ENV_OFFSET / erasesize;
                erasebase = eraseblock * erasesize;
				printf("the baseaddr is 0x%08x ...\n", erasebase);
                data = (uint8_t*)malloc(erasesize);
                if (data == NULL) {
                        printf("Could not save enviroment variables\n");
                        return 1;
                }

                /* Step 2: Read the NAND block into which the ENV data has
                 * to be copied
                 */
                total = erasesize;
				printf("the total is 0x%08x ...\n", total);
		for (i = 0; i < CFG_MAX_NAND_DEVICE; i++) {
			if (onenand_scan(&onenand_info[i], 1) == 0) {
				ret = onenand_read(onenand, erasebase, &total, data);
			} else {
				printf("no devices available\n");
				return 1;
			}
		}
                if (ret || total != erasesize) {
                        printf("Could not save enviroment variables %d\n",ret);
                        return 1;
                }
				
                /* Step 3: Copy the ENV data into the local copy of the block
                 * contents.
                 */
                memcpy((data + (CFG_ENV_OFFSET - erasebase)), (void*)env_ptr, CFG_ENV_SIZE);
        } else {
                /* CFG_ENV_OFFSET is equal to a NAND block boundary. So
                 * no special care is required when erasing and writing NAND
                 * block
                 */
                data = env_ptr;
                erasebase = CFG_ENV_OFFSET;
                erasesize = CFG_ENV_SIZE;
        }

        /* Erase the NAND block which will hold the ENV data */
        if (onenand_erase(onenand, erasebase, erasesize))
                return 1;

        puts("Writing to onenand... \n");
        total = erasesize;

        /* Write the ENV data to the NAND block */
		printf("the baseaddr is 0x%08x ...\n", erasebase);
		printf("the baseaddr is 0x%08x ...\n", total);
        ret = onenand_write(onenand, erasebase, &total, (u_char*)data);
        if (ret || total != erasesize) {
                printf("Could not save enviroment variables\n");
                return 1;
        }

         if ((CFG_ENV_OFFSET % (erasesize - 1)) != 0 )
                free(data);

        puts("Saved enviroment variables\n");
        return ret;
        return 1;
}