summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--adb/commandline.c2
-rw-r--r--fastboot/fastboot.c5
-rw-r--r--fastboot/usb.h2
-rw-r--r--fastboot/usb_linux.c20
-rw-r--r--fastboot/usb_osx.c3
-rw-r--r--fastboot/usb_windows.c1
-rwxr-xr-xinclude/cutils/adb_networking.h35
-rw-r--r--init/builtins.c16
-rw-r--r--init/devices.c3
-rwxr-xr-x[-rw-r--r--]init/init.c7
-rw-r--r--init/init.h1
-rw-r--r--init/keywords.h4
-rw-r--r--init/parser.c2
-rw-r--r--init/readme.txt6
-rw-r--r--libacc/tests/Android.mk6
-rw-r--r--libcutils/Android.mk1
-rw-r--r--libcutils/adb_networking.c172
-rw-r--r--libcutils/atomic-android-arm.S16
-rwxr-xr-xrootdir/etc/init.goldfish.sh14
-rw-r--r--toolbox/Android.mk3
-rw-r--r--toolbox/ls.c49
-rw-r--r--toolbox/nandread.c256
-rw-r--r--vold/blkdev.c4
-rw-r--r--vold/mmc.c7
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)) {