diff options
author | Koushik Dutta <koushd@gmail.com> | 2010-12-18 17:42:31 -0800 |
---|---|---|
committer | Koushik Dutta <koushd@gmail.com> | 2010-12-18 17:42:31 -0800 |
commit | df1e4067821353af7a006ef4d70b7001ad3bd924 (patch) | |
tree | 874fd5be1d93fb75610bf1d14925799934127977 /mtdutils | |
parent | 5d6309e77f6055a9aec062dd991d071054726ebb (diff) | |
parent | 0b7bbf29d5864fc2939ab9b954c0e1d18a24bffd (diff) | |
download | bootable_recovery-df1e4067821353af7a006ef4d70b7001ad3bd924.zip bootable_recovery-df1e4067821353af7a006ef4d70b7001ad3bd924.tar.gz bootable_recovery-df1e4067821353af7a006ef4d70b7001ad3bd924.tar.bz2 |
Merge from ClockworkMod recovery
Change-Id: Id5b312147173ced559a62d97029acede6c2f8766
Diffstat (limited to 'mtdutils')
-rw-r--r-- | mtdutils/Android.mk | 10 | ||||
-rw-r--r-- | mtdutils/flash_image.c | 140 | ||||
-rw-r--r-- | mtdutils/mounts.c | 222 | ||||
-rw-r--r-- | mtdutils/mounts.h | 33 | ||||
-rw-r--r-- | mtdutils/mtdutils.c | 301 | ||||
-rw-r--r-- | mtdutils/mtdutils.h | 7 |
6 files changed, 301 insertions, 412 deletions
diff --git a/mtdutils/Android.mk b/mtdutils/Android.mk index 57ab579..90e97fd 100644 --- a/mtdutils/Android.mk +++ b/mtdutils/Android.mk @@ -5,20 +5,12 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ - mtdutils.c \ - mounts.c + mtdutils.c LOCAL_MODULE := libmtdutils include $(BUILD_STATIC_LIBRARY) -include $(CLEAR_VARS) -LOCAL_SRC_FILES := flash_image.c -LOCAL_MODULE := flash_image -LOCAL_MODULE_TAGS := eng -LOCAL_STATIC_LIBRARIES := libmtdutils -LOCAL_SHARED_LIBRARIES := libcutils libc -include $(BUILD_EXECUTABLE) endif # TARGET_ARCH == arm endif # !TARGET_SIMULATOR diff --git a/mtdutils/flash_image.c b/mtdutils/flash_image.c deleted file mode 100644 index c776876..0000000 --- a/mtdutils/flash_image.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "cutils/log.h" -#include "mtdutils.h" - -#define LOG_TAG "flash_image" - -#define HEADER_SIZE 2048 // size of header to compare for equality - -void die(const char *msg, ...) { - int err = errno; - va_list args; - va_start(args, msg); - char buf[1024]; - vsnprintf(buf, sizeof(buf), msg, args); - va_end(args); - - if (err != 0) { - strlcat(buf, ": ", sizeof(buf)); - strlcat(buf, strerror(err), sizeof(buf)); - } - - fprintf(stderr, "%s\n", buf); - LOGE("%s\n", buf); - exit(1); -} - -/* Read an image file and write it to a flash partition. */ - -int main(int argc, char **argv) { - const MtdPartition *ptn; - MtdWriteContext *write; - void *data; - unsigned sz; - - if (argc != 3) { - fprintf(stderr, "usage: %s partition file.img\n", argv[0]); - return 2; - } - - if (mtd_scan_partitions() <= 0) die("error scanning partitions"); - const MtdPartition *partition = mtd_find_partition_by_name(argv[1]); - if (partition == NULL) die("can't find %s partition", argv[1]); - - // If the first part of the file matches the partition, skip writing - - int fd = open(argv[2], O_RDONLY); - if (fd < 0) die("error opening %s", argv[2]); - - char header[HEADER_SIZE]; - int headerlen = read(fd, header, sizeof(header)); - if (headerlen <= 0) die("error reading %s header", argv[2]); - - MtdReadContext *in = mtd_read_partition(partition); - if (in == NULL) { - LOGW("error opening %s: %s\n", argv[1], strerror(errno)); - // just assume it needs re-writing - } else { - char check[HEADER_SIZE]; - int checklen = mtd_read_data(in, check, sizeof(check)); - if (checklen <= 0) { - LOGW("error reading %s: %s\n", argv[1], strerror(errno)); - // just assume it needs re-writing - } else if (checklen == headerlen && !memcmp(header, check, headerlen)) { - LOGI("header is the same, not flashing %s\n", argv[1]); - return 0; - } - mtd_read_close(in); - } - - // Skip the header (we'll come back to it), write everything else - LOGI("flashing %s from %s\n", argv[1], argv[2]); - - MtdWriteContext *out = mtd_write_partition(partition); - if (out == NULL) die("error writing %s", argv[1]); - - char buf[HEADER_SIZE]; - memset(buf, 0, headerlen); - int wrote = mtd_write_data(out, buf, headerlen); - if (wrote != headerlen) die("error writing %s", argv[1]); - - int len; - while ((len = read(fd, buf, sizeof(buf))) > 0) { - wrote = mtd_write_data(out, buf, len); - if (wrote != len) die("error writing %s", argv[1]); - } - if (len < 0) die("error reading %s", argv[2]); - - if (mtd_write_close(out)) die("error closing %s", argv[1]); - - // Now come back and write the header last - - out = mtd_write_partition(partition); - if (out == NULL) die("error re-opening %s", argv[1]); - - wrote = mtd_write_data(out, header, headerlen); - if (wrote != headerlen) die("error re-writing %s", argv[1]); - - // Need to write a complete block, so write the rest of the first block - size_t block_size; - if (mtd_partition_info(partition, NULL, &block_size, NULL)) - die("error getting %s block size", argv[1]); - - if (lseek(fd, headerlen, SEEK_SET) != headerlen) - die("error rewinding %s", argv[2]); - - int left = block_size - headerlen; - while (left < 0) left += block_size; - while (left > 0) { - len = read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left); - if (len <= 0) die("error reading %s", argv[2]); - if (mtd_write_data(out, buf, len) != len) - die("error writing %s", argv[1]); - left -= len; - } - - if (mtd_write_close(out)) die("error closing %s", argv[1]); - return 0; -} diff --git a/mtdutils/mounts.c b/mtdutils/mounts.c deleted file mode 100644 index c90fc8a..0000000 --- a/mtdutils/mounts.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <sys/mount.h> - -#include "mounts.h" - -struct MountedVolume { - const char *device; - const char *mount_point; - const char *filesystem; - const char *flags; -}; - -typedef struct { - MountedVolume *volumes; - int volumes_allocd; - int volume_count; -} MountsState; - -static MountsState g_mounts_state = { - NULL, // volumes - 0, // volumes_allocd - 0 // volume_count -}; - -static inline void -free_volume_internals(const MountedVolume *volume, int zero) -{ - free((char *)volume->device); - free((char *)volume->mount_point); - free((char *)volume->filesystem); - free((char *)volume->flags); - if (zero) { - memset((void *)volume, 0, sizeof(*volume)); - } -} - -#define PROC_MOUNTS_FILENAME "/proc/mounts" - -int -scan_mounted_volumes() -{ - char buf[2048]; - const char *bufp; - int fd; - ssize_t nbytes; - - if (g_mounts_state.volumes == NULL) { - const int numv = 32; - MountedVolume *volumes = malloc(numv * sizeof(*volumes)); - if (volumes == NULL) { - errno = ENOMEM; - return -1; - } - g_mounts_state.volumes = volumes; - g_mounts_state.volumes_allocd = numv; - memset(volumes, 0, numv * sizeof(*volumes)); - } else { - /* Free the old volume strings. - */ - int i; - for (i = 0; i < g_mounts_state.volume_count; i++) { - free_volume_internals(&g_mounts_state.volumes[i], 1); - } - } - g_mounts_state.volume_count = 0; - - /* Open and read the file contents. - */ - fd = open(PROC_MOUNTS_FILENAME, O_RDONLY); - if (fd < 0) { - goto bail; - } - nbytes = read(fd, buf, sizeof(buf) - 1); - close(fd); - if (nbytes < 0) { - goto bail; - } - buf[nbytes] = '\0'; - - /* Parse the contents of the file, which looks like: - * - * # cat /proc/mounts - * rootfs / rootfs rw 0 0 - * /dev/pts /dev/pts devpts rw 0 0 - * /proc /proc proc rw 0 0 - * /sys /sys sysfs rw 0 0 - * /dev/block/mtdblock4 /system yaffs2 rw,nodev,noatime,nodiratime 0 0 - * /dev/block/mtdblock5 /data yaffs2 rw,nodev,noatime,nodiratime 0 0 - * /dev/block/mmcblk0p1 /sdcard vfat rw,sync,dirsync,fmask=0000,dmask=0000,codepage=cp437,iocharset=iso8859-1,utf8 0 0 - * - * The zeroes at the end are dummy placeholder fields to make the - * output match Linux's /etc/mtab, but don't represent anything here. - */ - bufp = buf; - while (nbytes > 0) { - char device[64]; - char mount_point[64]; - char filesystem[64]; - char flags[128]; - int matches; - - /* %as is a gnu extension that malloc()s a string for each field. - */ - matches = sscanf(bufp, "%63s %63s %63s %127s", - device, mount_point, filesystem, flags); - - if (matches == 4) { - device[sizeof(device)-1] = '\0'; - mount_point[sizeof(mount_point)-1] = '\0'; - filesystem[sizeof(filesystem)-1] = '\0'; - flags[sizeof(flags)-1] = '\0'; - - MountedVolume *v = - &g_mounts_state.volumes[g_mounts_state.volume_count++]; - v->device = strdup(device); - v->mount_point = strdup(mount_point); - v->filesystem = strdup(filesystem); - v->flags = strdup(flags); - } else { -printf("matches was %d on <<%.40s>>\n", matches, bufp); - } - - /* Eat the line. - */ - while (nbytes > 0 && *bufp != '\n') { - bufp++; - nbytes--; - } - if (nbytes > 0) { - bufp++; - nbytes--; - } - } - - return 0; - -bail: -//TODO: free the strings we've allocated. - g_mounts_state.volume_count = 0; - return -1; -} - -const MountedVolume * -find_mounted_volume_by_device(const char *device) -{ - if (g_mounts_state.volumes != NULL) { - int i; - for (i = 0; i < g_mounts_state.volume_count; i++) { - MountedVolume *v = &g_mounts_state.volumes[i]; - /* May be null if it was unmounted and we haven't rescanned. - */ - if (v->device != NULL) { - if (strcmp(v->device, device) == 0) { - return v; - } - } - } - } - return NULL; -} - -const MountedVolume * -find_mounted_volume_by_mount_point(const char *mount_point) -{ - if (g_mounts_state.volumes != NULL) { - int i; - for (i = 0; i < g_mounts_state.volume_count; i++) { - MountedVolume *v = &g_mounts_state.volumes[i]; - /* May be null if it was unmounted and we haven't rescanned. - */ - if (v->mount_point != NULL) { - if (strcmp(v->mount_point, mount_point) == 0) { - return v; - } - } - } - } - return NULL; -} - -int -unmount_mounted_volume(const MountedVolume *volume) -{ - /* Intentionally pass NULL to umount if the caller tries - * to unmount a volume they already unmounted using this - * function. - */ - int ret = umount(volume->mount_point); - if (ret == 0) { - free_volume_internals(volume, 1); - return 0; - } - return ret; -} - -int -remount_read_only(const MountedVolume* volume) -{ - return mount(volume->device, volume->mount_point, volume->filesystem, - MS_NOATIME | MS_NODEV | MS_NODIRATIME | - MS_RDONLY | MS_REMOUNT, 0); -} diff --git a/mtdutils/mounts.h b/mtdutils/mounts.h deleted file mode 100644 index 30b2927..0000000 --- a/mtdutils/mounts.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MTDUTILS_MOUNTS_H_ -#define MTDUTILS_MOUNTS_H_ - -typedef struct MountedVolume MountedVolume; - -int scan_mounted_volumes(void); - -const MountedVolume *find_mounted_volume_by_device(const char *device); - -const MountedVolume * -find_mounted_volume_by_mount_point(const char *mount_point); - -int unmount_mounted_volume(const MountedVolume *volume); - -int remount_read_only(const MountedVolume* volume); - -#endif // MTDUTILS_MOUNTS_H_ diff --git a/mtdutils/mtdutils.c b/mtdutils/mtdutils.c index 198f498..c8dbba4 100644 --- a/mtdutils/mtdutils.c +++ b/mtdutils/mtdutils.c @@ -28,13 +28,6 @@ #include "mtdutils.h" -struct MtdPartition { - int device_index; - unsigned int size; - unsigned int erase_size; - char *name; -}; - struct MtdReadContext { const MtdPartition *partition; char *buffer; @@ -345,7 +338,7 @@ ssize_t mtd_read_data(MtdReadContext *ctx, char *data, size_t len) read += ctx->partition->erase_size; } - if (read >= len) { + if (read >= (int)len) { return read; } @@ -569,3 +562,295 @@ off_t mtd_find_write_start(MtdWriteContext *ctx, off_t pos) { } return pos; } + +#define BLOCK_SIZE 2048 +#define SPARE_SIZE (BLOCK_SIZE >> 5) +#define HEADER_SIZE 2048 + +int cmd_mtd_restore_raw_partition(const char *partition_name, const char *filename) +{ + const MtdPartition *ptn; + MtdWriteContext *write; + void *data; + unsigned sz; + + if (mtd_scan_partitions() <= 0) + { + printf("error scanning partitions"); + return -1; + } + const MtdPartition *partition = mtd_find_partition_by_name(partition_name); + if (partition == NULL) + { + printf("can't find %s partition", partition_name); + return -1; + } + + // If the first part of the file matches the partition, skip writing + + int fd = open(filename, O_RDONLY); + if (fd < 0) + { + printf("error opening %s", filename); + return -1; + } + + char header[HEADER_SIZE]; + int headerlen = read(fd, header, sizeof(header)); + if (headerlen <= 0) + { + printf("error reading %s header", filename); + return -1; + } + + MtdReadContext *in = mtd_read_partition(partition); + if (in == NULL) { + printf("error opening %s: %s\n", partition, strerror(errno)); + // just assume it needs re-writing + } else { + char check[HEADER_SIZE]; + int checklen = mtd_read_data(in, check, sizeof(check)); + if (checklen <= 0) { + printf("error reading %s: %s\n", partition_name, strerror(errno)); + // just assume it needs re-writing + } else if (checklen == headerlen && !memcmp(header, check, headerlen)) { + printf("header is the same, not flashing %s\n", partition_name); + return 0; + } + mtd_read_close(in); + } + + // Skip the header (we'll come back to it), write everything else + printf("flashing %s from %s\n", partition_name, filename); + + MtdWriteContext *out = mtd_write_partition(partition); + if (out == NULL) + { + printf("error writing %s", partition_name); + return -1; + } + + char buf[HEADER_SIZE]; + memset(buf, 0, headerlen); + int wrote = mtd_write_data(out, buf, headerlen); + if (wrote != headerlen) + { + printf("error writing %s", partition_name); + return -1; + } + + int len; + while ((len = read(fd, buf, sizeof(buf))) > 0) { + wrote = mtd_write_data(out, buf, len); + if (wrote != len) + { + printf("error writing %s", partition_name); + return -1; + } + } + if (len < 0) + { + printf("error reading %s", filename); + return -1; + } + + if (mtd_write_close(out)) + { + printf("error closing %s", partition_name); + return -1; + } + + // Now come back and write the header last + + out = mtd_write_partition(partition); + if (out == NULL) + { + printf("error re-opening %s", partition_name); + return -1; + } + + wrote = mtd_write_data(out, header, headerlen); + if (wrote != headerlen) + { + printf("error re-writing %s", partition_name); + return -1; + } + + // Need to write a complete block, so write the rest of the first block + size_t block_size; + if (mtd_partition_info(partition, NULL, &block_size, NULL)) + { + printf("error getting %s block size", partition_name); + return -1; + } + + if (lseek(fd, headerlen, SEEK_SET) != headerlen) + { + printf("error rewinding %s", filename); + return -1; + } + + int left = block_size - headerlen; + while (left < 0) left += block_size; + while (left > 0) { + len = read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left); + if (len <= 0){ + printf("error reading %s", filename); + return -1; + } + if (mtd_write_data(out, buf, len) != len) + { + printf("error writing %s", partition_name); + return -1; + } + + left -= len; + } + + if (mtd_write_close(out)) + { + printf("error closing %s", partition_name); + return -1; + } + return 0; +} + + +int cmd_mtd_backup_raw_partition(const char *partition_name, const char *filename) +{ + MtdReadContext *in; + const MtdPartition *partition; + char buf[BLOCK_SIZE + SPARE_SIZE]; + size_t partition_size; + size_t read_size; + size_t total; + int fd; + int wrote; + int len; + + if (mtd_scan_partitions() <= 0) + { + printf("error scanning partitions"); + return -1; + } + + partition = mtd_find_partition_by_name(partition_name); + if (partition == NULL) + { + printf("can't find %s partition", partition_name); + return -1; + } + + if (mtd_partition_info(partition, &partition_size, NULL, NULL)) { + printf("can't get info of partition %s", partition_name); + return -1; + } + + if (!strcmp(filename, "-")) { + fd = fileno(stdout); + } + else { + fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666); + } + + if (fd < 0) + { + printf("error opening %s", filename); + return -1; + } + + in = mtd_read_partition(partition); + if (in == NULL) { + close(fd); + unlink(filename); + printf("error opening %s: %s\n", partition_name, strerror(errno)); + return -1; + } + + total = 0; + while ((len = mtd_read_data(in, buf, BLOCK_SIZE)) > 0) { + wrote = write(fd, buf, len); + if (wrote != len) { + close(fd); + unlink(filename); + printf("error writing %s", filename); + return -1; + } + total += BLOCK_SIZE; + } + + mtd_read_close(in); + + if (close(fd)) { + unlink(filename); + printf("error closing %s", filename); + return -1; + } + return 0; +} + +int cmd_mtd_erase_raw_partition(const char *partition_name) +{ + MtdWriteContext *out; + size_t erased; + size_t total_size; + size_t erase_size; + + if (mtd_scan_partitions() <= 0) + { + printf("error scanning partitions"); + return -1; + } + const MtdPartition *p = mtd_find_partition_by_name(partition_name); + if (p == NULL) + { + printf("can't find %s partition", partition_name); + return -1; + } + + out = mtd_write_partition(p); + if (out == NULL) + { + printf("could not estabilish write context for %s", partition_name); + return -1; + } + + // do the actual erase, -1 = full partition erase + erased = mtd_erase_blocks(out, -1); + + // erased = bytes erased, if zero, something borked + if (!erased) + { + printf("error erasing %s", partition_name); + return -1; + } + + return 0; +} + +int cmd_mtd_erase_partition(const char *partition, const char *filesystem) +{ + return cmd_mtd_erase_raw_partition(partition); +} + + +int cmd_mtd_mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only) +{ + mtd_scan_partitions(); + const MtdPartition *p; + p = mtd_find_partition_by_name(partition); + if (p == NULL) { + return -1; + } + return mtd_mount_partition(p, mount_point, filesystem, read_only); +} + +int cmd_mtd_get_partition_device(const char *partition, char *device) +{ + mtd_scan_partitions(); + MtdPartition *p = mtd_find_partition_by_name(partition); + if (p == NULL) + return -1; + sprintf(device, "/dev/block/mtdblock%d", p->device_index); + return 0; +} diff --git a/mtdutils/mtdutils.h b/mtdutils/mtdutils.h index 45d3ebc..c57d45d 100644 --- a/mtdutils/mtdutils.h +++ b/mtdutils/mtdutils.h @@ -53,4 +53,11 @@ off_t mtd_erase_blocks(MtdWriteContext *, int blocks); /* 0 ok, -1 for all */ off_t mtd_find_write_start(MtdWriteContext *ctx, off_t pos); int mtd_write_close(MtdWriteContext *); +struct MtdPartition { + int device_index; + unsigned int size; + unsigned int erase_size; + char *name; +}; + #endif // MTDUTILS_H_ |