diff options
-rw-r--r-- | adb/commandline.c | 2 | ||||
-rw-r--r-- | fastboot/fastboot.c | 5 | ||||
-rw-r--r-- | fastboot/usb.h | 2 | ||||
-rw-r--r-- | fastboot/usb_linux.c | 20 | ||||
-rw-r--r-- | fastboot/usb_osx.c | 3 | ||||
-rw-r--r-- | fastboot/usb_windows.c | 1 | ||||
-rwxr-xr-x | include/cutils/adb_networking.h | 35 | ||||
-rw-r--r-- | init/builtins.c | 16 | ||||
-rw-r--r-- | init/devices.c | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | init/init.c | 7 | ||||
-rw-r--r-- | init/init.h | 1 | ||||
-rw-r--r-- | init/keywords.h | 4 | ||||
-rw-r--r-- | init/parser.c | 2 | ||||
-rw-r--r-- | init/readme.txt | 6 | ||||
-rw-r--r-- | libacc/tests/Android.mk | 6 | ||||
-rw-r--r-- | libcutils/Android.mk | 1 | ||||
-rw-r--r-- | libcutils/adb_networking.c | 172 | ||||
-rw-r--r-- | libcutils/atomic-android-arm.S | 16 | ||||
-rwxr-xr-x | rootdir/etc/init.goldfish.sh | 14 | ||||
-rw-r--r-- | toolbox/Android.mk | 3 | ||||
-rw-r--r-- | toolbox/ls.c | 49 | ||||
-rw-r--r-- | toolbox/nandread.c | 256 | ||||
-rw-r--r-- | vold/blkdev.c | 4 | ||||
-rw-r--r-- | vold/mmc.c | 7 |
24 files changed, 391 insertions, 244 deletions
diff --git a/adb/commandline.c b/adb/commandline.c index 411bb82a3..f41146bf5 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -97,7 +97,7 @@ void help() " returns an error if more than one emulator is running.\n" " -s <serial number> - directs command to the USB device or emulator with\n" " the given serial number. Overrides ANDROID_SERIAL\n" - " envivornment variable.\n" + " environment variable.\n" " -p <product name or path> - simple product name like 'sooner', or\n" " a relative/absolute path to a product\n" " out directory like 'out/target/product/sooner'.\n" diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c index c81222a82..911c3f60c 100644 --- a/fastboot/fastboot.c +++ b/fastboot/fastboot.c @@ -165,6 +165,9 @@ int list_devices_callback(usb_ifc_info *info) { if (match_fastboot(info) == 0) { char* serial = info->serial_number; + if (!info->writable) { + serial = "no permissions"; // like "adb devices" + } if (!serial[0]) { serial = "????????????"; } @@ -554,6 +557,8 @@ int main(int argc, char **argv) return 0; } + serial = getenv("ANDROID_SERIAL"); + while (argc > 0) { if(!strcmp(*argv, "-w")) { wants_wipe = 1; diff --git a/fastboot/usb.h b/fastboot/usb.h index f3ec5bfda..cc157d56e 100644 --- a/fastboot/usb.h +++ b/fastboot/usb.h @@ -50,6 +50,8 @@ struct usb_ifc_info unsigned char has_bulk_in; unsigned char has_bulk_out; + unsigned char writable; + char serial_number[256]; }; diff --git a/fastboot/usb_linux.c b/fastboot/usb_linux.c index 3b40ba7f9..2ce53eb83 100644 --- a/fastboot/usb_linux.c +++ b/fastboot/usb_linux.c @@ -89,7 +89,8 @@ static int check(void *_desc, int len, unsigned type, int size) return 0; } -static int filter_usb_device(int fd, char *ptr, int len, ifc_match_func callback, +static int filter_usb_device(int fd, char *ptr, int len, int writable, + ifc_match_func callback, int *ept_in_id, int *ept_out_id, int *ifc_id) { struct usb_device_descriptor *dev; @@ -119,7 +120,8 @@ static int filter_usb_device(int fd, char *ptr, int len, ifc_match_func callback info.dev_class = dev->bDeviceClass; info.dev_subclass = dev->bDeviceSubClass; info.dev_protocol = dev->bDeviceProtocol; - + info.writable = writable; + // read device serial number (if there is one) info.serial_number[0] = 0; if (dev->iSerialNumber) { @@ -201,6 +203,7 @@ static usb_handle *find_usb_device(const char *base, ifc_match_func callback) DIR *busdir, *devdir; struct dirent *de; int fd; + int writable; busdir = opendir(base); if(busdir == 0) return 0; @@ -219,13 +222,20 @@ static usb_handle *find_usb_device(const char *base, ifc_match_func callback) sprintf(devname, "%s/%s", busname, de->d_name); // DBG("[ scanning %s ]\n", devname); + writable = 1; if((fd = open(devname, O_RDWR)) < 0) { - continue; + // Check if we have read-only access, so we can give a helpful + // diagnostic like "adb devices" does. + writable = 0; + if((fd = open(devname, O_RDONLY)) < 0) { + continue; + } } n = read(fd, desc, sizeof(desc)); - if(filter_usb_device(fd, desc, n, callback, &in, &out, &ifc) == 0){ + if(filter_usb_device(fd, desc, n, writable, callback, + &in, &out, &ifc) == 0) { usb = calloc(1, sizeof(usb_handle)); strcpy(usb->fname, devname); usb->ep_in = in; @@ -375,5 +385,3 @@ usb_handle *usb_open(ifc_match_func callback) { return find_usb_device("/dev/bus/usb", callback); } - - diff --git a/fastboot/usb_osx.c b/fastboot/usb_osx.c index d6a826094..0b0512d1c 100644 --- a/fastboot/usb_osx.c +++ b/fastboot/usb_osx.c @@ -351,6 +351,7 @@ static int try_device(io_service_t device, usb_handle *handle) { // device has no serial number handle->info.serial_number[0] = 0; } + handle->info.writable = 1; if (try_interfaces(dev, handle)) { goto error; @@ -416,8 +417,6 @@ static int init_usb(ifc_match_func callback, usb_handle **handle) { break; } - usb_ifc_info info; - if (try_device(device, &h) != 0) { IOObjectRelease(device); ret = -1; diff --git a/fastboot/usb_windows.c b/fastboot/usb_windows.c index 9c0a9cbf1..54008a423 100644 --- a/fastboot/usb_windows.c +++ b/fastboot/usb_windows.c @@ -301,6 +301,7 @@ int recognized_device(usb_handle* handle, ifc_match_func callback) { info.ifc_class = interf_desc.bInterfaceClass; info.ifc_subclass = interf_desc.bInterfaceSubClass; info.ifc_protocol = interf_desc.bInterfaceProtocol; + info.writable = 1; // read serial number (if there is one) unsigned long serial_number_len = sizeof(info.serial_number); diff --git a/include/cutils/adb_networking.h b/include/cutils/adb_networking.h deleted file mode 100755 index 409d577ec..000000000 --- a/include/cutils/adb_networking.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2006 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 _ADB_NETWORKING_H -#define _ADB_NETWORKING_H 1 -#include <netinet/in.h> -#include <arpa/inet.h> -#include <sys/socket.h> - -#ifdef __cplusplus -extern "C" { -#endif - -extern int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address); -extern int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr); - -#ifdef __cplusplus -} -#endif - -#endif /*_ADB_NETWORKING_H*/ - diff --git a/init/builtins.c b/init/builtins.c index 5a1b26378..b4af700bd 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -131,6 +131,18 @@ static void service_start_if_not_disabled(struct service *svc) } } +int do_chdir(int nargs, char **args) +{ + chdir(args[1]); + return 0; +} + +int do_chroot(int nargs, char **args) +{ + chroot(args[1]); + return 0; +} + int do_class_start(int nargs, char **args) { /* Starting a class does not start services @@ -206,7 +218,7 @@ int do_insmod(int nargs, char **args) int do_import(int nargs, char **args) { - return -1; + return parse_config_file(args[1]); } int do_mkdir(int nargs, char **args) @@ -400,6 +412,8 @@ int do_restart(int nargs, char **args) int do_trigger(int nargs, char **args) { + action_for_each_trigger(args[1], action_add_queue_tail); + drain_action_queue(); return 0; } diff --git a/init/devices.c b/init/devices.c index c2c9353c7..8f2f4efd6 100644 --- a/init/devices.c +++ b/init/devices.c @@ -125,6 +125,7 @@ static struct perms_ devperms[] = { { "/dev/pmem_camera", 0660, AID_SYSTEM, AID_CAMERA, 1 }, { "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 }, { "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 }, + { "/dev/snd/", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 }, { "/dev/msm_camera/", 0660, AID_SYSTEM, AID_SYSTEM, 1 }, { "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 }, @@ -312,7 +313,7 @@ static void make_device(const char *path, int block, int major, int minor) chown(path, uid, gid); } -#ifdef LOG_UEVENTS +#if LOG_UEVENTS static inline suseconds_t get_usecs(void) { diff --git a/init/init.c b/init/init.c index 8c2a0582e..f76eb36b5 100644..100755 --- a/init/init.c +++ b/init/init.c @@ -65,8 +65,6 @@ static struct input_keychord *keychords = 0; static int keychords_count = 0; static int keychords_length = 0; -static void drain_action_queue(void); - static void notify_service_state(const char *name, const char *state) { char pname[PROP_NAME_MAX]; @@ -391,12 +389,13 @@ static int wait_for_one_process(int block) } } + svc->flags |= SVC_RESTARTING; + /* Execute all onrestart commands for this service. */ list_for_each(node, &svc->onrestart.commands) { cmd = node_to_item(node, struct command, clist); cmd->func(cmd->nargs, cmd->args); } - svc->flags |= SVC_RESTARTING; notify_service_state(svc->name, "restarting"); return 0; } @@ -667,7 +666,7 @@ static void get_hardware_name(void) } } -static void drain_action_queue(void) +void drain_action_queue(void) { struct listnode *node; struct command *cmd; diff --git a/init/init.h b/init/init.h index f306b7bca..60c305559 100644 --- a/init/init.h +++ b/init/init.h @@ -165,6 +165,7 @@ void service_stop(struct service *svc); void service_start(struct service *svc, const char *dynamic_args); void property_changed(const char *name, const char *value); +void drain_action_queue(void); struct action *action_remove_queue_head(void); void action_add_queue_tail(struct action *act); void action_for_each_trigger(const char *trigger, diff --git a/init/keywords.h b/init/keywords.h index 641426caf..308118efd 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -1,5 +1,7 @@ #ifndef KEYWORD +int do_chroot(int nargs, char **args); +int do_chdir(int nargs, char **args); int do_class_start(int nargs, char **args); int do_class_stop(int nargs, char **args); int do_domainname(int nargs, char **args); @@ -32,6 +34,8 @@ enum { K_UNKNOWN, #endif KEYWORD(capability, OPTION, 0, 0) + KEYWORD(chdir, COMMAND, 1, do_chdir) + KEYWORD(chroot, COMMAND, 1, do_chroot) KEYWORD(class, OPTION, 0, 0) KEYWORD(class_start, COMMAND, 1, do_class_start) KEYWORD(class_stop, COMMAND, 1, do_class_stop) diff --git a/init/parser.c b/init/parser.c index affc80c9a..54622cce2 100644 --- a/init/parser.c +++ b/init/parser.c @@ -129,6 +129,8 @@ int lookup_keyword(const char *s) case 'c': if (!strcmp(s, "opy")) return K_copy; if (!strcmp(s, "apability")) return K_capability; + if (!strcmp(s, "hdir")) return K_chdir; + if (!strcmp(s, "hroot")) return K_chroot; if (!strcmp(s, "lass")) return K_class; if (!strcmp(s, "lass_start")) return K_class_start; if (!strcmp(s, "lass_stop")) return K_class_stop; diff --git a/init/readme.txt b/init/readme.txt index 665090bad..a185790ac 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -145,12 +145,18 @@ import <filename> hostname <name> Set the host name. +chdir <directory> + Change working directory. + chmod <octal-mode> <path> Change file access permissions. chown <owner> <group> <path> Change file owner and group. +chroot <directory> + Change process root directory. + class_start <serviceclass> Start all services of the specified class if they are not already running. diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk index e9fbe0319..b3af6f12a 100644 --- a/libacc/tests/Android.mk +++ b/libacc/tests/Android.mk @@ -25,7 +25,8 @@ LOCAL_SRC_FILES:= \ disassem.cpp LOCAL_SHARED_LIBRARIES := \ - libacc + libacc \ + libdl LOCAL_CFLAGS := -O0 -g @@ -57,7 +58,8 @@ LOCAL_SRC_FILES:= \ runtimeTest.cpp LOCAL_SHARED_LIBRARIES := \ - libacc + libacc \ + libdl LOCAL_CFLAGS := -O0 -g diff --git a/libcutils/Android.mk b/libcutils/Android.mk index 1d1e57603..afa64bc3f 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -65,7 +65,6 @@ else mspace.c \ selector.c \ tztime.c \ - adb_networking.c \ zygote.c commonHostSources += \ diff --git a/libcutils/adb_networking.c b/libcutils/adb_networking.c deleted file mode 100644 index d819d44c8..000000000 --- a/libcutils/adb_networking.c +++ /dev/null @@ -1,172 +0,0 @@ -/* libs/utils/adb_networking.c -** -** Copyright 2006, 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. -*/ - -#define ADB_PORT 5037 - -#define _GNU_SOURCE /* for asprintf */ -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <errno.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <string.h> - -#include <cutils/adb_networking.h> -#include <cutils/sockets.h> -#include <cutils/properties.h> - -#define ADB_RESPONSE_SIZE 4 - -/** - * Unfortunately, java.net.Socket wants to create it's filedescriptor early - * So, this function takes an fd that must be an unconnected - * PF_LOCAL SOCK_STREAM - */ -int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address) -{ - struct sockaddr_in local_addr; - socklen_t alen; - char *cmd; - char buf[ADB_RESPONSE_SIZE + 1]; - ssize_t count_read; - int ret; - int err; - /* for impl of inet_ntoa below*/ - union { - uint8_t b[4]; - uint32_t l; - } a; - - /* First, connect to adb */ - - memset(&local_addr, 0, sizeof(local_addr)); - local_addr.sin_family = AF_INET; - local_addr.sin_port = htons(ADB_PORT); - local_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - do { - err = connect(fd, (struct sockaddr *) &local_addr, sizeof(local_addr)); - } while (err < 0 && errno == EINTR); - - if (err < 0) { - return -1; - } - - a.l = p_address->sin_addr.s_addr; - - // compose the command - asprintf(&cmd, "tcp:%u:%u.%u.%u.%u", - (unsigned int)ntohs(p_address->sin_port), - a.b[0],a.b[1],a.b[2],a.b[3]); - - // buf is now the ascii hex length of cmd - snprintf(buf, sizeof(buf), "%04X", strlen(cmd)); - - // write the 4-byte length - do { - err = write(fd, buf, 4); - } while (err < 0 && errno == EINTR); - - // write the command - do { - err = write(fd, cmd, strlen(cmd)); - } while (err < 0 && errno == EINTR); - - // read the result - do { - count_read = read(fd, buf, sizeof(buf) - 1); - } while (count_read < 0 && errno != EINTR); - - if (count_read == ADB_RESPONSE_SIZE - && 0 == strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) { - ret = 0; - } else { - /* what errno here? <shrug? */ - errno = ENETUNREACH; - ret = -1; - } - - free(cmd); - - return ret; -} - -/** - * Fills in *p_out_addr and returns 0 on success - * Memset's *p_out_addr and returns -1 on fail - */ - -int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr) -{ - int fd; - char *cmd = NULL; - char buf[ADB_RESPONSE_SIZE + 1]; - int err; - ssize_t count_read; - - fd = socket_loopback_client(ADB_PORT, SOCK_STREAM); - - if (fd < 0) { - return -1; - } - - // compose the command - asprintf(&cmd, "dns:%s", name); - - // buf is now the ascii hex length of cmd - snprintf(buf, sizeof(buf), "%04X", strlen(cmd)); - - // write the 4-byte length - do { - err = write(fd, buf, 4); - } while (err < 0 && errno == EINTR); - - // write the command - do { - err = write(fd, cmd, strlen(cmd)); - } while (err < 0 && errno == EINTR); - - // read the result - do { - count_read = read(fd, buf, ADB_RESPONSE_SIZE); - } while (count_read < 0 && errno != EINTR); - - if (count_read != ADB_RESPONSE_SIZE - || 0 != strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) { - goto error; - } - - // read the actual IP address - do { - count_read = read(fd, &(p_out_addr->s_addr), sizeof(p_out_addr->s_addr)); - } while (count_read < 0 && errno != EINTR); - - if (count_read != 4) { - goto error; - } - - free(cmd); - close(fd); - return 0; -error: - free(cmd); - close(fd); - memset(p_out_addr, 0, sizeof(struct in_addr)); - return -1; -} - diff --git a/libcutils/atomic-android-arm.S b/libcutils/atomic-android-arm.S index f4299fded..4da619540 100644 --- a/libcutils/atomic-android-arm.S +++ b/libcutils/atomic-android-arm.S @@ -17,8 +17,7 @@ #include <machine/cpu-features.h> /* - * NOTE: these atomic operations are SMP safe on all architectures, - * except swap(), see below. + * NOTE: these atomic operations are SMP safe on all architectures. */ .text @@ -213,11 +212,18 @@ android_atomic_or: * output: r0 = old value */ -/* FIXME: this is not safe on SMP systems - * a general way to do it is to use kernel_cmpxchg */ - +/* replaced swp instruction with ldrex/strex for ARMv6 & ARMv7 */ android_atomic_swap: +#if defined (_ARM_HAVE_LDREX_STREX) +1: ldrex r2, [r1] + strex r3, r0, [r1] + teq r3, #0 + bne 1b + mov r0, r2 + mcr p15, 0, r0, c7, c10, 5 /* or, use dmb */ +#else swp r0, r0, [r1] +#endif bx lr /* diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh index f1b801d91..5ff0a3a4a 100755 --- a/rootdir/etc/init.goldfish.sh +++ b/rootdir/etc/init.goldfish.sh @@ -3,16 +3,20 @@ ifconfig eth0 10.0.2.15 netmask 255.255.255.0 up route add default gw 10.0.2.2 dev eth0 -qemud=`getprop.ro.kernel.android.qemud` -if test -z "$qemud"; then +qemud=`getprop ro.kernel.android.qemud` +case "$qemud" in + "") radio_ril=`getprop ro.kernel.android.ril` - if test -z "$radio_ril"; then + case "$radio_ril" in + "") # no need for the radio interface daemon # telephony is entirely emulated in Java setprop ro.radio.noril yes stop ril-daemon - fi -fi + ;; + esac + ;; +esac num_dns=`getprop ro.kernel.android.ndns` case "$num_dns" in diff --git a/toolbox/Android.mk b/toolbox/Android.mk index 70b13dcbc..122a5445e 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -50,7 +50,8 @@ TOOLS := \ top \ iftop \ id \ - vmstat + vmstat \ + nandread LOCAL_SRC_FILES:= \ toolbox.c \ diff --git a/toolbox/ls.c b/toolbox/ls.c index b221074ae..f340a8349 100644 --- a/toolbox/ls.c +++ b/toolbox/ls.c @@ -86,15 +86,50 @@ static void group2str(unsigned gid, char *out) } } -static int listfile_size(const char *path, int flags) +static int show_total_size(const char *dirname, DIR *d, int flags) { + struct dirent *de; + char tmp[1024]; struct stat s; + int sum = 0; + + /* run through the directory and sum up the file block sizes */ + while ((de = readdir(d)) != 0) { + if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) + continue; + if (de->d_name[0] == '.' && (flags & LIST_ALL) == 0) + continue; + + if (strcmp(dirname, "/") == 0) + snprintf(tmp, sizeof(tmp), "/%s", de->d_name); + else + snprintf(tmp, sizeof(tmp), "%s/%s", dirname, de->d_name); + + if (lstat(tmp, &s) < 0) { + fprintf(stderr, "stat failed on %s: %s\n", tmp, strerror(errno)); + rewinddir(d); + return -1; + } + + sum += s.st_blocks / 2; + } - if (lstat(path, &s) < 0) + printf("total %d\n", sum); + rewinddir(d); + return 0; +} + +static int listfile_size(const char *path, const char *filename, int flags) +{ + struct stat s; + + if (lstat(path, &s) < 0) { + fprintf(stderr, "lstat '%s' failed: %s\n", path, strerror(errno)); return -1; + } /* blocks are 512 bytes, we want output to be KB */ - printf("%lld %s\n", s.st_blocks / 2, path); + printf("%lld %s\n", s.st_blocks / 2, filename); return 0; } @@ -189,7 +224,7 @@ static int listfile(const char *dirname, const char *filename, int flags) if ((flags & LIST_LONG) != 0) { return listfile_long(pathname, flags); } else /*((flags & LIST_SIZE) != 0)*/ { - return listfile_size(pathname, flags); + return listfile_size(pathname, filename, flags); } } @@ -198,13 +233,17 @@ static int listdir(const char *name, int flags) char tmp[4096]; DIR *d; struct dirent *de; - + d = opendir(name); if(d == 0) { fprintf(stderr, "opendir failed, %s\n", strerror(errno)); return -1; } + if ((flags & LIST_SIZE) != 0) { + show_total_size(name, d, flags); + } + while((de = readdir(d)) != 0){ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; if(de->d_name[0] == '.' && (flags & LIST_ALL) == 0) continue; diff --git a/toolbox/nandread.c b/toolbox/nandread.c new file mode 100644 index 000000000..aacccdb26 --- /dev/null +++ b/toolbox/nandread.c @@ -0,0 +1,256 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> + +#include <mtd/mtd-user.h> +#include <sys/ioctl.h> + +int test_empty(const char *buf, size_t size) +{ + while(size--) { + if (*buf++ != 0xff) + return 0; + } + return 1; +} + +int nandread_main(int argc, char **argv) +{ + char *devname = NULL; + char *filename = NULL; + char *statusfilename = NULL; + char *statusext = ".stat"; + int fd; + int outfd = -1; + FILE *statusfile = NULL; + int ret; + int verbose = 0; + void *buffer; + loff_t pos, opos; + int c; + int i; + int empty_pages = 0; + int page_count = 0; + int bad_block; + uint32_t *oob_data; + uint8_t *oob_fixed; + size_t spare_size = 64; + struct mtd_info_user mtdinfo; + struct mtd_ecc_stats initial_ecc, last_ecc, ecc; + struct mtd_oob_buf oobbuf; + struct nand_ecclayout ecclayout; + + do { + c = getopt(argc, argv, "d:f:s:hv"); + if (c == EOF) + break; + switch (c) { + case 'd': + devname = optarg; + break; + case 'f': + filename = optarg; + break; + case 's': + spare_size = atoi(optarg); + break; + case 'v': + verbose++; + break; + case 'h': + fprintf(stderr, "%s [-d <dev>] [-f file] [-s sparesize] [-vh]\n" + " -d <dev> Read from <dev>\n" + " -f <file> Write to <file>\n" + " -s <size> Number of spare bytes in file (default 64)\n" + " -v Print info\n" + " -h Print help\n", argv[0]); + return -1; + case '?': + fprintf(stderr, "%s: invalid option -%c\n", + argv[0], optopt); + exit(1); + } + } while (1); + + if (optind < argc) { + fprintf(stderr, "%s: extra arguments\n", argv[0]); + return 1; + } + if (!devname) { + fprintf(stderr, "%s: specify device name\n", argv[0]); + return 1; + } + + fd = open(devname, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "cannot open %s, %s\n", devname, strerror(errno)); + return 1; + } + + if (filename) { + outfd = creat(filename, 0666); + if (outfd < 0) { + fprintf(stderr, "cannot open %s, %s\n", filename, strerror(errno)); + return 1; + } + statusfilename = malloc(strlen(filename) + strlen(statusext) + 1); + strcpy(statusfilename, filename); + strcat(statusfilename, statusext); + statusfile = fopen(statusfilename, "w+"); + if (!statusfile) { + fprintf(stderr, "cannot open %s, %s\n", statusfilename, strerror(errno)); + return 1; + } + } + + ret = ioctl(fd, MEMGETINFO, &mtdinfo); + if (ret) { + fprintf(stderr, "failed get mtd info for %s, %s\n", + devname, strerror(errno)); + return 1; + } + + if (verbose) { + printf("size: %u\n", mtdinfo.size); + printf("erase size: %u\n", mtdinfo.erasesize); + printf("write size: %u\n", mtdinfo.writesize); + printf("oob size: %u\n", mtdinfo.oobsize); + } + + buffer = malloc(mtdinfo.writesize + mtdinfo.oobsize + spare_size); + if (!buffer) { + fprintf(stderr, "failed allocate readbuffer size %u\n", + mtdinfo.writesize + mtdinfo.oobsize); + return 1; + } + + oobbuf.length = mtdinfo.oobsize; + oob_data = (uint32_t *)((uint8_t *)buffer + mtdinfo.writesize); + memset(oob_data, 0xff, spare_size); + oobbuf.ptr = (uint8_t *)oob_data + spare_size; + + ret = ioctl(fd, ECCGETLAYOUT, &ecclayout); + if (ret) { + fprintf(stderr, "failed get ecc layout for %s, %s\n", + devname, strerror(errno)); + return 1; + } + if (verbose) { + printf("ecc bytes: %u\n", ecclayout.eccbytes); + printf("oobavail: %u\n", ecclayout.oobavail); + } + if (ecclayout.oobavail > spare_size) + printf("oobavail, %d > image spare size, %d\n", ecclayout.oobavail, spare_size); + + ret = ioctl(fd, ECCGETSTATS, &initial_ecc); + if (ret) { + fprintf(stderr, "failed get ecc stats for %s, %s\n", + devname, strerror(errno)); + return 1; + } + last_ecc = initial_ecc; + + if (verbose) { + printf("initial ecc corrected: %u\n", initial_ecc.corrected); + printf("initial ecc failed: %u\n", initial_ecc.failed); + printf("initial ecc badblocks: %u\n", initial_ecc.badblocks); + printf("initial ecc bbtblocks: %u\n", initial_ecc.bbtblocks); + } + + for (pos = 0, opos = 0; pos < mtdinfo.size; pos += mtdinfo.writesize) { + bad_block = 0; + if (verbose > 3) + printf("reading at %llx\n", pos); + lseek64(fd, pos, SEEK_SET); + ret = read(fd, buffer, mtdinfo.writesize); + if (ret < (int)mtdinfo.writesize) { + fprintf(stderr, "short read at %llx, %d\n", pos, ret); + bad_block = 2; + } + oobbuf.start = pos; + ret = ioctl(fd, MEMREADOOB, &oobbuf); + if (ret) { + fprintf(stderr, "failed to read oob data at %llx, %d\n", pos, ret); + bad_block = 2; + } + ret = ioctl(fd, ECCGETSTATS, &ecc); + if (ret) { + fprintf(stderr, "failed get ecc stats for %s, %s\n", + devname, strerror(errno)); + return 1; + } + ret = ioctl(fd, MEMGETBADBLOCK, &pos); + if (ret && errno != EOPNOTSUPP) { + printf("badblock at %llx\n", pos); + bad_block = 1; + } + if (ecc.corrected != last_ecc.corrected) + printf("ecc corrected, %u, at %llx\n", ecc.corrected - last_ecc.corrected, pos); + if (ecc.failed != last_ecc.failed) + printf("ecc failed, %u, at %llx\n", ecc.failed - last_ecc.failed, pos); + if (ecc.badblocks != last_ecc.badblocks) + printf("ecc badblocks, %u, at %llx\n", ecc.badblocks - last_ecc.badblocks, pos); + if (ecc.bbtblocks != last_ecc.bbtblocks) + printf("ecc bbtblocks, %u, at %llx\n", ecc.bbtblocks - last_ecc.bbtblocks, pos); + + oob_fixed = (uint8_t *)oob_data; + for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) { + int len = ecclayout.oobfree[i].length; + if (oob_fixed + len > oobbuf.ptr) + len = oobbuf.ptr - oob_fixed; + if (len) { + memcpy(oob_fixed, oobbuf.ptr + ecclayout.oobfree[i].offset, len); + oob_fixed += len; + } + } + + if (outfd >= 0) { + ret = write(outfd, buffer, mtdinfo.writesize + spare_size); + if (ret < (int)(mtdinfo.writesize + spare_size)) { + fprintf(stderr, "short write at %llx, %d\n", pos, ret); + close(outfd); + outfd = -1; + } + if (ecc.corrected != last_ecc.corrected) + fprintf(statusfile, "%08llx: ecc corrected\n", opos); + if (ecc.failed != last_ecc.failed) + fprintf(statusfile, "%08llx: ecc failed\n", opos); + if (bad_block == 1) + fprintf(statusfile, "%08llx: badblock\n", opos); + if (bad_block == 2) + fprintf(statusfile, "%08llx: read error\n", opos); + opos += mtdinfo.writesize + spare_size; + } + + last_ecc = ecc; + page_count++; + if (test_empty(buffer, mtdinfo.writesize + mtdinfo.oobsize + spare_size)) + empty_pages++; + else if (verbose > 2 || (verbose > 1 && !(pos & (mtdinfo.erasesize - 1)))) + printf("page at %llx (%d oobbytes): %08x %08x %08x %08x " + "%08x %08x %08x %08x\n", pos, oobbuf.start, + oob_data[0], oob_data[1], oob_data[2], oob_data[3], + oob_data[4], oob_data[5], oob_data[6], oob_data[7]); + } + + if (outfd >= 0) { + fprintf(statusfile, "read %d pages, %d empty\n", page_count, empty_pages); + fprintf(statusfile, "total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected); + fprintf(statusfile, "total ecc failed, %u\n", ecc.failed - initial_ecc.failed); + fprintf(statusfile, "total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks); + fprintf(statusfile, "total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks); + } + if (verbose) { + printf("total ecc corrected, %u\n", ecc.corrected - initial_ecc.corrected); + printf("total ecc failed, %u\n", ecc.failed - initial_ecc.failed); + printf("total ecc badblocks, %u\n", ecc.badblocks - initial_ecc.badblocks); + printf("total ecc bbtblocks, %u\n", ecc.bbtblocks - initial_ecc.bbtblocks); + } + printf("read %d pages, %d empty\n", page_count, empty_pages); + + return 0; +} + diff --git a/vold/blkdev.c b/vold/blkdev.c index 22d000e5d..33fed1b83 100644 --- a/vold/blkdev.c +++ b/vold/blkdev.c @@ -113,7 +113,7 @@ int blkdev_refresh(blkdev_t *blk) goto out; } - for (i = 0; i < 4; i++) { + for (i = 0; i < NDOSPART; i++) { struct dos_partition part; dos_partition_dec(block + DOSPARTOFF + i * sizeof(struct dos_partition), &part); @@ -140,7 +140,7 @@ int blkdev_refresh(blkdev_t *blk) else part_no = blk->minor -1; - if (part_no < 4) { + if (part_no < NDOSPART) { dos_partition_dec(block + DOSPARTOFF + part_no * sizeof(struct dos_partition), &part); blk->part_type = part.dp_typ; } else { diff --git a/vold/mmc.c b/vold/mmc.c index b321c80f7..d90845d3a 100644 --- a/vold/mmc.c +++ b/vold/mmc.c @@ -25,6 +25,7 @@ #include "vold.h" #include "mmc.h" #include "media.h" +#include "diskmbr.h" /* for NDOSPART */ #define DEBUG_BOOTSTRAP 0 @@ -157,6 +158,10 @@ static int mmc_bootstrap_card(char *sysfs_path) sprintf(filename, "/sys%s/name", devpath); p = read_file(filename, &sz); + if (!p) { + LOGE("Unable to read MMC name: %s", filename); + return -errno; + } p[strlen(p) - 1] = '\0'; sprintf(tmp, "MMC_NAME=%s", p); free(p); @@ -233,7 +238,7 @@ static int mmc_bootstrap_mmcblk(char *devpath) *mmcblk_devname != '/'; mmcblk_devname--); mmcblk_devname++; - for (part_no = 0; part_no < 4; part_no++) { + for (part_no = 1; part_no <= NDOSPART; part_no++) { char part_file[255]; sprintf(part_file, "/sys%s/%sp%d", devpath, mmcblk_devname, part_no); if (!access(part_file, F_OK)) { |