diff options
-rw-r--r-- | commands/flash.c | 63 | ||||
-rw-r--r-- | common/partition.c | 11 | ||||
-rw-r--r-- | drivers/cfi_flash.c | 32 | ||||
-rw-r--r-- | fs/devfs.c | 8 | ||||
-rw-r--r-- | fs/fs.c | 21 | ||||
-rw-r--r-- | include/driver.h | 2 | ||||
-rw-r--r-- | include/fs.h | 5 | ||||
-rw-r--r-- | lib/driver.c | 8 |
8 files changed, 124 insertions, 26 deletions
diff --git a/commands/flash.c b/commands/flash.c index 1aa00187e1..68b85495aa 100644 --- a/commands/flash.c +++ b/commands/flash.c @@ -90,36 +90,67 @@ U_BOOT_CMD_END int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - int p; - int rcode = 0; - struct memarea_info mem_info; + int opt, fd; + char *filename = NULL; + struct stat s; + int prot = 1; + unsigned long start = 0, size = ~0; + + getopt_reset(); + + while((opt = getopt(argc, argv, "f:")) > 0) { + switch(opt) { + case 'f': + filename = optarg; + break; + } + } + + if (*argv[0] == 'u') + prot = 0; - if (argc < 3) { - printf ("Usage:\n%s\n", cmdtp->usage); + if (stat(filename, &s)) { + printf("stat %s: %s\n", filename, errno_str()); return 1; } - if (strcmp(argv[1], "off") == 0) { - p = 0; - } else if (strcmp(argv[1], "on") == 0) { - p = 1; - } else { - printf ("Usage:\n%s\n", cmdtp->usage); + size = s.st_size; + + if (!filename) { + printf("missing filename\n"); + return 1; + } + + fd = open(filename, O_WRONLY); + if (fd < 0) { + printf("open %s:", filename, errno_str()); return 1; } - if (spec_str_to_info(argv[2], &mem_info)) { - printf ("-EPARSE\n"); + if (optind < argc) + parse_area_spec(argv[optind], &start, &size); + + if(protect(fd, size, start, prot)) { + perror("protect"); return 1; } -// rcode = flash_sect_protect (p, addr_first, addr_last); - return rcode; + close(fd); + + return 0; } U_BOOT_CMD_START(protect) .maxargs = 4, .cmd = do_protect, - .usage = "enable or disable FLASH write protection", + .usage = "enable FLASH write protection", U_BOOT_CMD_HELP("write me\n") U_BOOT_CMD_END + +U_BOOT_CMD_START(unprotect) + .maxargs = 4, + .cmd = do_protect, + .usage = "disable FLASH write protection", + U_BOOT_CMD_HELP("write me\n") +U_BOOT_CMD_END + diff --git a/common/partition.c b/common/partition.c index b3b27d5ded..d420592863 100644 --- a/common/partition.c +++ b/common/partition.c @@ -44,6 +44,16 @@ static int part_erase(struct device_d *dev, size_t count, unsigned long offset) return -1; } +static int part_protect(struct device_d *dev, size_t count, unsigned long offset, int prot) +{ + struct partition *part = dev->type_data; + + if (part->physdev->driver->protect) + return part->physdev->driver->protect(part->physdev, count, offset + part->offset, prot); + + return -1; +} + static int part_memmap(struct device_d *dev, void **map, int flags) { struct partition *part = dev->type_data; @@ -98,6 +108,7 @@ struct driver_d part_driver = { .read = part_read, .write = part_write, .erase = part_erase, + .protect= part_protect, .memmap = part_memmap, }; diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c index ed08b1049f..1bb6533fab 100644 --- a/drivers/cfi_flash.c +++ b/drivers/cfi_flash.c @@ -411,6 +411,27 @@ out: return ret; } +int cfi_protect(struct device_d *dev, size_t count, unsigned long offset, int prot) +{ + flash_info_t *finfo = (flash_info_t *)dev->priv; + unsigned long start, end; + int i, ret = 0; + + printf("%s: protect 0x%08x (size %d)\n", __FUNCTION__, offset, count); + + start = flash_find_sector(finfo, dev->map_base + offset); + end = flash_find_sector(finfo, dev->map_base + offset + count - 1); + + for (i = start; i <= end; i++) { + ret = flash_real_protect (finfo, i, prot); + if (ret) + goto out; + } +out: + putc('\n'); + return ret; +} + static ssize_t cfi_write(struct device_d* dev, const void* buf, size_t count, unsigned long offset, ulong flags) { flash_info_t *finfo = (flash_info_t *)dev->priv; @@ -518,6 +539,7 @@ static struct driver_d cfi_driver = { .read = mem_read, .write = cfi_write, .erase = cfi_erase, + .protect= cfi_protect, .memmap = generic_memmap_ro, .info = cfi_info, }; @@ -628,10 +650,6 @@ int write_buff (flash_info_t * info, const uchar * src, ulong addr, ulong cnt) return flash_write_cfiword (info, wp, cword); } -/*----------------------------------------------------------------------- - */ -#ifdef CFG_FLASH_PROTECTION - int flash_real_protect (flash_info_t * info, long sector, int prot) { int retcode = 0; @@ -695,7 +713,7 @@ void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset, flash_write_cmd (info, 0, 0, info->cmd_reset); } -#endif /* CFG_FLASH_PROTECTION */ + /* * flash_is_busy - check to see if the flash is busy @@ -1125,9 +1143,7 @@ ulong flash_get_size (flash_info_t *info, ulong base) info->ext_addr = 0; info->cfi_version = 0; -#ifdef CFG_FLASH_PROTECTION info->legacy_unlock = 0; -#endif /* first only malloc space for the first sector */ info->start = malloc(sizeof(ulong)); @@ -1158,13 +1174,11 @@ ulong flash_get_size (flash_info_t *info, ulong base) case CFI_CMDSET_INTEL_EXTENDED: default: info->cmd_reset = FLASH_CMD_RESET; -#ifdef CFG_FLASH_PROTECTION /* read legacy lock/unlock bit from intel flash */ if (info->ext_addr) { info->legacy_unlock = flash_read_uchar (info, info->ext_addr + 5) & 0x08; } -#endif break; case CFI_CMDSET_AMD_STANDARD: case CFI_CMDSET_AMD_EXTENDED: diff --git a/fs/devfs.c b/fs/devfs.c index aafcc34439..4fc0dbb91b 100644 --- a/fs/devfs.c +++ b/fs/devfs.c @@ -50,6 +50,13 @@ static int devfs_erase(struct device_d *_dev, FILE *f, size_t count, unsigned lo return dev_erase(dev, count, offset); } +static int devfs_protect(struct device_d *_dev, FILE *f, size_t count, unsigned long offset, int prot) +{ + struct device_d *dev = f->inode; + + return dev_protect(dev, count, offset, prot); +} + static int devfs_memmap(struct device_d *_dev, FILE *f, void **map, int flags) { struct device_d *dev = f->inode; @@ -153,6 +160,7 @@ static struct fs_driver_d devfs_driver = { .closedir = devfs_closedir, .stat = devfs_stat, .erase = devfs_erase, + .protect = devfs_protect, .memmap = devfs_memmap, .flags = FS_DRIVER_NO_DEV, .drv = { @@ -516,6 +516,27 @@ int erase(int fd, size_t count, unsigned long offset) return errno; } +int protect(int fd, size_t count, unsigned long offset, int prot) +{ + struct device_d *dev; + struct fs_driver_d *fsdrv; + FILE *f = &files[fd]; + + dev = f->dev; + + fsdrv = (struct fs_driver_d *)dev->driver->type_data; + + if (f->pos + count > f->size) + count = f->size - f->pos; + + if (fsdrv->protect) + errno = fsdrv->protect(dev, f, count, offset, prot); + else + errno = -EINVAL; + + return errno; +} + void *memmap(int fd, int flags) { struct device_d *dev; diff --git a/include/driver.h b/include/driver.h index 1be59100d6..293a265045 100644 --- a/include/driver.h +++ b/include/driver.h @@ -53,6 +53,7 @@ struct driver_d { ssize_t (*read) (struct device_d*, void* buf, size_t count, ulong offset, ulong flags); ssize_t (*write) (struct device_d*, const void* buf, size_t count, ulong offset, ulong flags); ssize_t (*erase) (struct device_d*, size_t count, unsigned long offset); + int (*protect)(struct device_d*, size_t count, unsigned long offset, int prot); int (*memmap)(struct device_d*, void **map, int flags); void (*info) (struct device_d *); @@ -101,6 +102,7 @@ struct driver_d *get_driver_by_name(const char *name); ssize_t dev_read(struct device_d *dev, void *buf, size_t count, ulong offset, ulong flags); ssize_t dev_write(struct device_d *dev, const void *buf, size_t count, ulong offset, ulong flags); ssize_t dev_erase(struct device_d *dev, size_t count, unsigned long offset); +ssize_t dev_protect(struct device_d *dev, size_t count, unsigned long offset, int prot); int dev_memmap(struct device_d *dev, void **map, int flags); /* These are used by drivers which work with direct memory accesses */ diff --git a/include/fs.h b/include/fs.h index 752aca5fea..f2a9f49859 100644 --- a/include/fs.h +++ b/include/fs.h @@ -66,6 +66,8 @@ struct fs_driver_d { int (*erase)(struct device_d *dev, FILE *f, size_t count, unsigned long offset); + int (*protect)(struct device_d *dev, FILE *f, size_t count, + unsigned long offset, int prot); int (*memmap)(struct device_d *dev, FILE *f, void **map, int flags); @@ -110,8 +112,9 @@ int closedir(DIR *dir); int mount (const char *device, const char *fsname, const char *path); int umount(const char *pathname); -/* not-so-standard erase */ +/* not-so-standard functions */ int erase(int fd, size_t count, unsigned long offset); +int protect(int fd, size_t count, unsigned long offset, int prot); void *memmap(int fd, int flags); #define PROT_READ 1 diff --git a/lib/driver.c b/lib/driver.c index 8f6c2ffaa6..0d28b0fe6e 100644 --- a/lib/driver.c +++ b/lib/driver.c @@ -292,6 +292,14 @@ ssize_t dev_erase(struct device_d *dev, size_t count, unsigned long offset) return -ENOSYS; } +int dev_protect(struct device_d *dev, size_t count, unsigned long offset, int prot) +{ + if (dev->driver->protect) + return dev->driver->protect(dev, count, offset, prot); + errno = -ENOSYS; + return -ENOSYS; +} + ssize_t dev_memmap(struct device_d *dev, void **map, int flags) { if (dev->driver->memmap) |